You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sentry.apache.org by sd...@apache.org on 2015/08/14 09:28:53 UTC

[19/50] [abbrv] incubator-sentry git commit: SENTRY-804: Add Audit Log Support for Solr Sentry Handlers (Gregory Chanan, Reviewed by: Vamsee Yarlagadda)

SENTRY-804: Add Audit Log Support for Solr Sentry Handlers (Gregory Chanan, Reviewed by: Vamsee Yarlagadda)


Project: http://git-wip-us.apache.org/repos/asf/incubator-sentry/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-sentry/commit/f5445bbc
Tree: http://git-wip-us.apache.org/repos/asf/incubator-sentry/tree/f5445bbc
Diff: http://git-wip-us.apache.org/repos/asf/incubator-sentry/diff/f5445bbc

Branch: refs/heads/hive_plugin_v2
Commit: f5445bbc602ede901ed4cc707e2ce11ee8961a31
Parents: 7eb7c7d
Author: Vamsee Yarlagadda <va...@cloudera.com>
Authored: Mon Jul 20 15:20:00 2015 -0700
Committer: Vamsee Yarlagadda <va...@cloudera.com>
Committed: Mon Jul 20 15:20:00 2015 -0700

----------------------------------------------------------------------
 sentry-solr/solr-sentry-handlers/pom.xml        |   1 -
 .../SecureDocumentAnalysisRequestHandler.java   |   2 +-
 .../SecureFieldAnalysisRequestHandler.java      |   2 +-
 .../solr/handler/SecureReplicationHandler.java  |   2 +-
 .../solr/handler/SecureRequestHandlerUtil.java  |  17 +-
 .../solr/handler/admin/SecureAdminHandlers.java |  16 +-
 .../handler/admin/SecureCollectionsHandler.java |   2 +-
 .../handler/admin/SecureCoreAdminHandler.java   |  34 +++-
 .../QueryIndexAuthorizationComponent.java       |   5 +-
 .../org/apache/solr/sentry/AuditLogger.java     |  97 ++++++++++
 .../RollingFileWithoutDeleteAppender.java       | 176 +++++++++++++++++++
 .../SentryIndexAuthorizationSingleton.java      |  40 ++++-
 .../UpdateIndexAuthorizationProcessor.java      |  26 +--
 .../src/main/resources/log4j.properties         |  13 ++
 .../SentryIndexAuthorizationSingletonTest.java  |  11 +-
 .../UpdateIndexAuthorizationProcessorTest.java  |  36 ++--
 16 files changed, 416 insertions(+), 64 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/f5445bbc/sentry-solr/solr-sentry-handlers/pom.xml
----------------------------------------------------------------------
diff --git a/sentry-solr/solr-sentry-handlers/pom.xml b/sentry-solr/solr-sentry-handlers/pom.xml
index 7acdd40..d6db69f 100644
--- a/sentry-solr/solr-sentry-handlers/pom.xml
+++ b/sentry-solr/solr-sentry-handlers/pom.xml
@@ -47,7 +47,6 @@ limitations under the License.
     <dependency>
       <groupId>log4j</groupId>
       <artifactId>log4j</artifactId>
-      <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>commons-logging</groupId>

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/f5445bbc/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/SecureDocumentAnalysisRequestHandler.java
----------------------------------------------------------------------
diff --git a/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/SecureDocumentAnalysisRequestHandler.java b/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/SecureDocumentAnalysisRequestHandler.java
index 23886fe..9ecf139 100644
--- a/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/SecureDocumentAnalysisRequestHandler.java
+++ b/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/SecureDocumentAnalysisRequestHandler.java
@@ -26,7 +26,7 @@ import org.apache.solr.response.SolrQueryResponse;
 public class SecureDocumentAnalysisRequestHandler extends DocumentAnalysisRequestHandler {
   @Override
   public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception {
-    SecureRequestHandlerUtil.checkSentryCollection(req, SecureRequestHandlerUtil.QUERY_ONLY);
+    SecureRequestHandlerUtil.checkSentryCollection(req, SecureRequestHandlerUtil.QUERY_ONLY, getClass().getName());
     super.handleRequestBody(req, rsp);
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/f5445bbc/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/SecureFieldAnalysisRequestHandler.java
----------------------------------------------------------------------
diff --git a/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/SecureFieldAnalysisRequestHandler.java b/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/SecureFieldAnalysisRequestHandler.java
index 4a8809a..819227b 100644
--- a/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/SecureFieldAnalysisRequestHandler.java
+++ b/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/SecureFieldAnalysisRequestHandler.java
@@ -26,7 +26,7 @@ import org.apache.solr.response.SolrQueryResponse;
 public class SecureFieldAnalysisRequestHandler extends FieldAnalysisRequestHandler {
   @Override
   public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception {
-    SecureRequestHandlerUtil.checkSentryCollection(req, SecureRequestHandlerUtil.QUERY_ONLY);
+    SecureRequestHandlerUtil.checkSentryCollection(req, SecureRequestHandlerUtil.QUERY_ONLY, getClass().getName());
     super.handleRequestBody(req, rsp);
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/f5445bbc/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/SecureReplicationHandler.java
----------------------------------------------------------------------
diff --git a/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/SecureReplicationHandler.java b/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/SecureReplicationHandler.java
index 70e5c83..42213ae 100644
--- a/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/SecureReplicationHandler.java
+++ b/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/SecureReplicationHandler.java
@@ -31,7 +31,7 @@ public class SecureReplicationHandler extends ReplicationHandler {
       // request handler
       collection = core.getCoreDescriptor().getCloudDescriptor().getCollectionName();
     }
-    SecureRequestHandlerUtil.checkSentryAdmin(req, SecureRequestHandlerUtil.QUERY_AND_UPDATE, true, collection);
+    SecureRequestHandlerUtil.checkSentryAdmin(req, SecureRequestHandlerUtil.QUERY_AND_UPDATE, getClass().getName(), true, collection);
     super.handleRequestBody(req, rsp);
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/f5445bbc/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/SecureRequestHandlerUtil.java
----------------------------------------------------------------------
diff --git a/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/SecureRequestHandlerUtil.java b/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/SecureRequestHandlerUtil.java
index 7ae5391..94341b3 100644
--- a/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/SecureRequestHandlerUtil.java
+++ b/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/SecureRequestHandlerUtil.java
@@ -43,17 +43,18 @@ public class SecureRequestHandlerUtil {
    * @param collection only relevant if checkCollection==true,
    *   use collection (if non-null) instead pulling collection name from req (if null)
    */
-  public static void checkSentryAdmin(SolrQueryRequest req, Set<SearchModelAction> andActions, boolean checkCollection, String collection) {
-    checkSentry(req, andActions, true, checkCollection, collection);
+  public static void checkSentryAdmin(SolrQueryRequest req, Set<SearchModelAction> andActions,
+      String operation, boolean checkCollection, String collection) {
+    checkSentry(req, andActions, operation, true, checkCollection, collection);
   }
 
   /**
    * Attempt to authorize a collection action.  The collection
    * name will be pulled from the request.
    */
-  public static void checkSentryCollection(SolrQueryRequest req, Set<SearchModelAction> andActions) {
-    checkSentry(req, andActions, false, false, null);
-  }
+  public static void checkSentryCollection(SolrQueryRequest req, Set<SearchModelAction> andActions, String operation) {
+    checkSentry(req, andActions, operation, false, false, null);
+   }
 
   /**
    * Attempt to sync collection privileges with Sentry when the metadata has changed.
@@ -68,16 +69,16 @@ public class SecureRequestHandlerUtil {
   }
 
   private static void checkSentry(SolrQueryRequest req, Set<SearchModelAction> andActions,
-      boolean admin, boolean checkCollection, String collection) {
+      String operation, boolean admin, boolean checkCollection, String collection) {
     // Sentry currently does have AND support for actions; need to check
     // actions one at a time
     final SentryIndexAuthorizationSingleton sentryInstance =
       (testOverride == null)?SentryIndexAuthorizationSingleton.getInstance():testOverride;
     for (SearchModelAction action : andActions) {
       if (admin) {
-        sentryInstance.authorizeAdminAction(req, EnumSet.of(action), checkCollection, collection);
+        sentryInstance.authorizeAdminAction(req, EnumSet.of(action), operation, checkCollection, collection);
       } else {
-        sentryInstance.authorizeCollectionAction(req, EnumSet.of(action));
+        sentryInstance.authorizeCollectionAction(req, EnumSet.of(action), operation);
       }
     }
   }

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/f5445bbc/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/admin/SecureAdminHandlers.java
----------------------------------------------------------------------
diff --git a/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/admin/SecureAdminHandlers.java b/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/admin/SecureAdminHandlers.java
index 5463754..88016ea 100644
--- a/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/admin/SecureAdminHandlers.java
+++ b/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/admin/SecureAdminHandlers.java
@@ -112,7 +112,7 @@ public class SecureAdminHandlers extends AdminHandlers {
     @Override
     public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception {
       // logging handler can be used both to read and change logs
-      SecureRequestHandlerUtil.checkSentryAdmin(req, SecureRequestHandlerUtil.QUERY_AND_UPDATE, false, null);
+      SecureRequestHandlerUtil.checkSentryAdmin(req, SecureRequestHandlerUtil.QUERY_AND_UPDATE, getClass().getName(), false, null);
       super.handleRequestBody(req, rsp);
     }
   }
@@ -120,7 +120,7 @@ public class SecureAdminHandlers extends AdminHandlers {
   public static class SecureLukeRequestHandler extends LukeRequestHandler {
     @Override
     public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception {
-      SecureRequestHandlerUtil.checkSentryAdmin(req, SecureRequestHandlerUtil.QUERY_ONLY, true, null);
+      SecureRequestHandlerUtil.checkSentryAdmin(req, SecureRequestHandlerUtil.QUERY_ONLY, getClass().getName(), true, null);
       super.handleRequestBody(req, rsp);
     }
   }
@@ -128,7 +128,7 @@ public class SecureAdminHandlers extends AdminHandlers {
   public static class SecurePluginInfoHandler extends PluginInfoHandler {
     @Override
     public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception {
-      SecureRequestHandlerUtil.checkSentryAdmin(req, SecureRequestHandlerUtil.QUERY_ONLY, true, null);
+      SecureRequestHandlerUtil.checkSentryAdmin(req, SecureRequestHandlerUtil.QUERY_ONLY, getClass().getName(), true, null);
       super.handleRequestBody(req, rsp);
     }
   }
@@ -136,7 +136,7 @@ public class SecureAdminHandlers extends AdminHandlers {
   public static class SecurePropertiesRequestHandler extends PropertiesRequestHandler {
     @Override
     public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws IOException {
-      SecureRequestHandlerUtil.checkSentryAdmin(req, SecureRequestHandlerUtil.QUERY_ONLY, false, null);
+      SecureRequestHandlerUtil.checkSentryAdmin(req, SecureRequestHandlerUtil.QUERY_ONLY, getClass().getName(), false, null);
       super.handleRequestBody(req, rsp);
     }
   }
@@ -145,7 +145,7 @@ public class SecureAdminHandlers extends AdminHandlers {
     @Override
     public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp)
      throws IOException, KeeperException, InterruptedException {
-      SecureRequestHandlerUtil.checkSentryAdmin(req, SecureRequestHandlerUtil.QUERY_ONLY, true, null);
+      SecureRequestHandlerUtil.checkSentryAdmin(req, SecureRequestHandlerUtil.QUERY_ONLY, getClass().getName(), true, null);
       super.handleRequestBody(req, rsp);
     }
   }
@@ -153,7 +153,7 @@ public class SecureAdminHandlers extends AdminHandlers {
   public static class SecureSolrInfoMBeanHandler extends SolrInfoMBeanHandler {
     @Override
     public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception {
-      SecureRequestHandlerUtil.checkSentryAdmin(req, SecureRequestHandlerUtil.QUERY_ONLY, true, null);
+      SecureRequestHandlerUtil.checkSentryAdmin(req, SecureRequestHandlerUtil.QUERY_ONLY, getClass().getName(), true, null);
       super.handleRequestBody(req, rsp);
     }
   }
@@ -171,7 +171,7 @@ public class SecureAdminHandlers extends AdminHandlers {
     public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception {
       // this may or may not have the core
       SolrCore core = req.getCore();
-      SecureRequestHandlerUtil.checkSentryAdmin(req, SecureRequestHandlerUtil.QUERY_ONLY, core != null, null);
+      SecureRequestHandlerUtil.checkSentryAdmin(req, SecureRequestHandlerUtil.QUERY_ONLY, getClass().getName(), core != null, null);
       super.handleRequestBody(req, rsp);
     }
   }
@@ -179,7 +179,7 @@ public class SecureAdminHandlers extends AdminHandlers {
   public static class SecureThreadDumpHandler extends ThreadDumpHandler {
     @Override
     public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws IOException {
-      SecureRequestHandlerUtil.checkSentryAdmin(req, SecureRequestHandlerUtil.QUERY_ONLY, false, null);
+      SecureRequestHandlerUtil.checkSentryAdmin(req, SecureRequestHandlerUtil.QUERY_ONLY, getClass().getName(), false, null);
       super.handleRequestBody(req, rsp);
     }
   }

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/f5445bbc/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/admin/SecureCollectionsHandler.java
----------------------------------------------------------------------
diff --git a/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/admin/SecureCollectionsHandler.java b/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/admin/SecureCollectionsHandler.java
index 0a471a4..15a6ba0 100644
--- a/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/admin/SecureCollectionsHandler.java
+++ b/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/admin/SecureCollectionsHandler.java
@@ -75,7 +75,7 @@ public class SecureCollectionsHandler extends CollectionsHandler {
     }
     // all actions require UPDATE privileges
     SecureRequestHandlerUtil.checkSentryAdmin(req, SecureRequestHandlerUtil.UPDATE_ONLY,
-      true, collection);
+      (action != null ? "CollectionAction." + action.toString() : getClass().getName() + "/" + a), true, collection);
     super.handleRequestBody(req, rsp);
 
     /**

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/f5445bbc/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/admin/SecureCoreAdminHandler.java
----------------------------------------------------------------------
diff --git a/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/admin/SecureCoreAdminHandler.java b/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/admin/SecureCoreAdminHandler.java
index 36ef6d0..77548b9 100644
--- a/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/admin/SecureCoreAdminHandler.java
+++ b/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/admin/SecureCoreAdminHandler.java
@@ -17,16 +17,14 @@ package org.apache.solr.handler.admin;
  * limitations under the License.
  */
 
-import java.util.EnumSet;
-import org.apache.solr.core.SolrCore;
-import org.apache.sentry.core.model.search.SearchModelAction;
 import org.apache.solr.common.params.CoreAdminParams;
 import org.apache.solr.common.params.CoreAdminParams.CoreAdminAction;
 import org.apache.solr.common.params.SolrParams;
+import org.apache.solr.core.CoreContainer;
+import org.apache.solr.core.SolrCore;
 import org.apache.solr.handler.SecureRequestHandlerUtil;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.response.SolrQueryResponse;
-import org.apache.solr.core.CoreContainer;
 
 /**
  * Secure (sentry-aware) version of CoreAdminHandler
@@ -67,7 +65,12 @@ public class SecureCoreAdminHandler extends CoreAdminHandler {
       action = CoreAdminAction.get(a);
       if (action == null) {
         // some custom action -- let's reqiure QUERY and UPDATE
-        SecureRequestHandlerUtil.checkSentryAdmin(req, SecureRequestHandlerUtil.QUERY_AND_UPDATE, true, null);
+        SecureRequestHandlerUtil.checkSentryAdmin(
+            req,
+            SecureRequestHandlerUtil.QUERY_AND_UPDATE,
+            "CoreAdminAction." + a,
+            true,
+            null);
       }
     }
     String collection = null;
@@ -117,7 +120,12 @@ public class SecureCoreAdminHandler extends CoreAdminHandler {
       switch (action) {
         case STATUS:
         case REQUESTSTATUS: {
-          SecureRequestHandlerUtil.checkSentryAdmin(req, SecureRequestHandlerUtil.QUERY_ONLY, checkCollection, collection);
+          SecureRequestHandlerUtil.checkSentryAdmin(
+              req,
+              SecureRequestHandlerUtil.QUERY_ONLY,
+              "CoreAdminAction." + action.toString(),
+              checkCollection,
+              collection);
           break;
         }
         case LOAD:
@@ -141,12 +149,22 @@ public class SecureCoreAdminHandler extends CoreAdminHandler {
         case TRANSIENT:
         case REQUESTBUFFERUPDATES:
         case OVERSEEROP: {
-          SecureRequestHandlerUtil.checkSentryAdmin(req, SecureRequestHandlerUtil.UPDATE_ONLY, checkCollection, collection);
+          SecureRequestHandlerUtil.checkSentryAdmin(
+              req,
+              SecureRequestHandlerUtil.UPDATE_ONLY,
+              "CoreAdminAction." + action.toString(),
+              checkCollection,
+              collection);
           break;
         }
         default: {
           // some custom action -- let's reqiure QUERY and UPDATE
-          SecureRequestHandlerUtil.checkSentryAdmin(req, SecureRequestHandlerUtil.QUERY_AND_UPDATE, checkCollection, collection);
+          SecureRequestHandlerUtil.checkSentryAdmin(
+              req,
+              SecureRequestHandlerUtil.QUERY_AND_UPDATE,
+              "CoreAdminAction." + action.toString(),
+              checkCollection,
+              collection);
           break;
         }
       }

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/f5445bbc/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/component/QueryIndexAuthorizationComponent.java
----------------------------------------------------------------------
diff --git a/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/component/QueryIndexAuthorizationComponent.java b/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/component/QueryIndexAuthorizationComponent.java
index e4b5741..8f68f40 100644
--- a/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/component/QueryIndexAuthorizationComponent.java
+++ b/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/component/QueryIndexAuthorizationComponent.java
@@ -29,6 +29,7 @@ import java.util.List;
 
 public class QueryIndexAuthorizationComponent extends SearchComponent
 {
+  private static final String OPERATION_NAME = "query";
   private static Logger log =
     LoggerFactory.getLogger(QueryIndexAuthorizationComponent.class);
   private SentryIndexAuthorizationSingleton sentryInstance;
@@ -46,7 +47,7 @@ public class QueryIndexAuthorizationComponent extends SearchComponent
   @Override
   public void prepare(ResponseBuilder rb) throws IOException {
     sentryInstance.authorizeCollectionAction(
-      rb.req, EnumSet.of(SearchModelAction.QUERY));
+      rb.req, EnumSet.of(SearchModelAction.QUERY), OPERATION_NAME);
     String collections = rb.req.getParams().get("collection");
     if (collections != null) {
       List<String> collectionList = StrUtils.splitSmart(collections, ",", true);
@@ -61,7 +62,7 @@ public class QueryIndexAuthorizationComponent extends SearchComponent
       // correct sentry check
       for (String coll : collectionList) {
         sentryInstance.authorizeCollectionAction(rb.req, EnumSet.of(SearchModelAction.QUERY),
-          coll, true);
+          OPERATION_NAME, coll, true);
       }
     }
   }

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/f5445bbc/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/sentry/AuditLogger.java
----------------------------------------------------------------------
diff --git a/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/sentry/AuditLogger.java b/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/sentry/AuditLogger.java
new file mode 100644
index 0000000..7f3e391
--- /dev/null
+++ b/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/sentry/AuditLogger.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.sentry;
+
+
+import org.apache.lucene.util.Version;
+import org.noggit.CharArr;
+import org.noggit.JSONWriter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * Writes audit events to the audit log. This helps answer questions such as:
+ * Who did what action when from where, and what values were changed from what
+ * to what as a result?
+ */
+final class AuditLogger {
+
+  public static final int ALLOWED = 1;
+  public static final int UNAUTHORIZED = 0;
+
+  private final Logger logger;
+
+  private static final boolean IS_ENABLED =
+    Boolean.valueOf(
+      System.getProperty(AuditLogger.class.getName() + ".isEnabled", "true"));
+
+  private static final String SOLR_VERSION = Version.LATEST.toString();
+
+
+  public AuditLogger() {
+    this.logger = LoggerFactory.getLogger(getClass());
+  }
+
+  public boolean isLogEnabled() {
+    return IS_ENABLED && logger.isInfoEnabled();
+  }
+
+  public void log(
+    String userName,
+    String impersonator,
+    String ipAddress,
+    String operation,
+    String operationParams,
+    long eventTime,
+    int allowed,
+    String collectionName) {
+
+    if (!isLogEnabled()) {
+      return;
+    }
+    CharArr chars = new CharArr(512);
+    JSONWriter writer = new JSONWriter(chars, -1);
+    writer.startObject();
+    writeField("solrVersion", SOLR_VERSION, writer);
+    writer.writeValueSeparator();
+    writeField("eventTime", eventTime, writer);
+    writer.writeValueSeparator();
+    writeField("allowed", allowed, writer);
+    writer.writeValueSeparator();
+    writeField("collectionName", collectionName, writer);
+    writer.writeValueSeparator();
+    writeField("operation", operation, writer);
+    writer.writeValueSeparator();
+    writeField("operationParams", operationParams, writer);
+    writer.writeValueSeparator();
+    writeField("ipAddress", ipAddress, writer);
+    writer.writeValueSeparator();
+    writeField("username", userName, writer);
+    writer.writeValueSeparator();
+    writeField("impersonator", impersonator, writer);
+    writer.endObject();
+    logger.info("{}", chars);
+  }
+
+  private void writeField(String key, Object value, JSONWriter writer) {
+    writer.writeString(key);
+    writer.writeNameSeparator();
+    writer.write(value);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/f5445bbc/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/sentry/RollingFileWithoutDeleteAppender.java
----------------------------------------------------------------------
diff --git a/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/sentry/RollingFileWithoutDeleteAppender.java b/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/sentry/RollingFileWithoutDeleteAppender.java
new file mode 100644
index 0000000..ec26ef3
--- /dev/null
+++ b/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/sentry/RollingFileWithoutDeleteAppender.java
@@ -0,0 +1,176 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.sentry;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.io.Writer;
+import java.nio.file.Files;
+
+import org.apache.log4j.FileAppender;
+import org.apache.log4j.Layout;
+import org.apache.log4j.helpers.CountingQuietWriter;
+import org.apache.log4j.helpers.LogLog;
+import org.apache.log4j.helpers.OptionConverter;
+import org.apache.log4j.spi.LoggingEvent;
+
+public class RollingFileWithoutDeleteAppender extends FileAppender {
+  /**
+   * The default maximum file size is 10MB.
+   */
+  protected long maxFileSize = 10 * 1024 * 1024;
+
+  private long nextRollover = 0;
+
+  /**
+   * The default constructor simply calls its {@link FileAppender#FileAppender
+   * parents constructor}.
+   */
+  public RollingFileWithoutDeleteAppender() {
+    super();
+  }
+
+  /**
+   * Instantiate a RollingFileAppender and open the file designated by
+   * <code>filename</code>. The opened filename will become the ouput
+   * destination for this appender.
+   * <p>
+   * If the <code>append</code> parameter is true, the file will be appended to.
+   * Otherwise, the file desginated by <code>filename</code> will be truncated
+   * before being opened.
+   */
+  public RollingFileWithoutDeleteAppender(Layout layout, String filename,
+      boolean append) throws IOException {
+    super(layout, getLogFileName(filename), append);
+  }
+
+  /**
+   * Instantiate a FileAppender and open the file designated by
+   * <code>filename</code>. The opened filename will become the output
+   * destination for this appender.
+   * <p>
+   * The file will be appended to.
+   */
+  public RollingFileWithoutDeleteAppender(Layout layout, String filename)
+      throws IOException {
+    super(layout, getLogFileName(filename));
+  }
+
+  /**
+   * Get the maximum size that the output file is allowed to reach before being
+   * rolled over to backup files.
+   */
+  public long getMaximumFileSize() {
+    return maxFileSize;
+  }
+
+  /**
+   * Implements the usual roll over behaviour.
+   * <p>
+   * <code>File</code> is renamed <code>File.yyyyMMddHHmmss</code> and closed. A
+   * new <code>File</code> is created to receive further log output.
+   */
+  // synchronization not necessary since doAppend is alreasy synched
+  public void rollOver() {
+    if (qw != null) {
+      long size = ((CountingQuietWriter) qw).getCount();
+      LogLog.debug("rolling over count=" + size);
+      // if operation fails, do not roll again until
+      // maxFileSize more bytes are written
+      nextRollover = size + maxFileSize;
+    }
+
+    this.closeFile(); // keep windows happy.
+
+    String newFileName = getLogFileName(fileName);
+    try {
+      // This will also close the file. This is OK since multiple
+      // close operations are safe.
+      this.setFile(newFileName, false, bufferedIO, bufferSize);
+      nextRollover = 0;
+    } catch (IOException e) {
+      if (e instanceof InterruptedIOException) {
+        Thread.currentThread().interrupt();
+      }
+      LogLog.error("setFile(" + newFileName + ", false) call failed.", e);
+    }
+  }
+
+  public synchronized void setFile(String fileName, boolean append,
+      boolean bufferedIO, int bufferSize) throws IOException {
+    super.setFile(fileName, append, this.bufferedIO, this.bufferSize);
+    if (append) {
+      File f = new File(fileName);
+      ((CountingQuietWriter) qw).setCount(f.length());
+    }
+  }
+
+  /**
+   * Set the maximum size that the output file is allowed to reach before being
+   * rolled over to backup files.
+   * <p>
+   * This method is equivalent to {@link #setMaxFileSize} except that it is
+   * required for differentiating the setter taking a <code>long</code> argument
+   * from the setter taking a <code>String</code> argument by the JavaBeans
+   * {@link java.beans.Introspector Introspector}.
+   *
+   * @see #setMaxFileSize(String)
+   */
+  public void setMaximumFileSize(long maxFileSize) {
+    this.maxFileSize = maxFileSize;
+  }
+
+  /**
+   * Set the maximum size that the output file is allowed to reach before being
+   * rolled over to backup files.
+   * <p>
+   * In configuration files, the <b>MaxFileSize</b> option takes an long integer
+   * in the range 0 - 2^63. You can specify the value with the suffixes "KB",
+   * "MB" or "GB" so that the integer is interpreted being expressed
+   * respectively in kilobytes, megabytes or gigabytes. For example, the value
+   * "10KB" will be interpreted as 10240.
+   */
+  public void setMaxFileSize(String value) {
+    maxFileSize = OptionConverter.toFileSize(value, maxFileSize + 1);
+  }
+
+  protected void setQWForFiles(Writer writer) {
+    this.qw = new CountingQuietWriter(writer, errorHandler);
+  }
+
+  /**
+   * This method differentiates RollingFileAppender from its super class.
+   */
+  protected void subAppend(LoggingEvent event) {
+    super.subAppend(event);
+
+    if (fileName != null && qw != null) {
+      long size = ((CountingQuietWriter) qw).getCount();
+      if (size >= maxFileSize && size >= nextRollover) {
+        rollOver();
+      }
+    }
+  }
+
+  // Mangled file name. Append the current timestamp
+  private static String getLogFileName(String oldFileName) {
+    return oldFileName + "." + Long.toString(System.currentTimeMillis());
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/f5445bbc/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/sentry/SentryIndexAuthorizationSingleton.java
----------------------------------------------------------------------
diff --git a/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/sentry/SentryIndexAuthorizationSingleton.java b/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/sentry/SentryIndexAuthorizationSingleton.java
index 53c8946..185884b 100644
--- a/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/sentry/SentryIndexAuthorizationSingleton.java
+++ b/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/sentry/SentryIndexAuthorizationSingleton.java
@@ -46,6 +46,7 @@ public class SentryIndexAuthorizationSingleton {
     new SentryIndexAuthorizationSingleton(System.getProperty(propertyName));
 
   private final SolrAuthzBinding binding;
+  private final AuditLogger auditLogger = new AuditLogger();
 
   private SentryIndexAuthorizationSingleton(String sentrySiteLocation) {
     SolrAuthzBinding tmpBinding = null;
@@ -85,15 +86,15 @@ public class SentryIndexAuthorizationSingleton {
    *   use collection (if non-null) instead pulling collection name from req (if null)
    */
   public void authorizeAdminAction(SolrQueryRequest req,
-      Set<SearchModelAction> actions, boolean checkCollection, String collection)
+      Set<SearchModelAction> actions, String operation, boolean checkCollection, String collection)
       throws SolrException {
-    authorizeCollectionAction(req, actions, "admin", true);
+    authorizeCollectionAction(req, actions, operation, "admin", true);
     if (checkCollection) {
       // Let's not error out if we can't find the collection associated with an
       // admin action, it's pretty complicated to get all the possible administrative
       // actions correct.  Instead, let's warn in the log and address any issues we
       // find.
-      authorizeCollectionAction(req, actions, collection, false);
+      authorizeCollectionAction(req, actions, operation, collection, false);
     }
   }
 
@@ -102,8 +103,8 @@ public class SentryIndexAuthorizationSingleton {
    * name will be pulled from the request.
    */
   public void authorizeCollectionAction(SolrQueryRequest req,
-      Set<SearchModelAction> actions) throws SolrException {
-    authorizeCollectionAction(req, actions, null, true);
+      Set<SearchModelAction> actions, String operation) throws SolrException {
+    authorizeCollectionAction(req, actions, operation, null, true);
   }
 
   /**
@@ -117,34 +118,61 @@ public class SentryIndexAuthorizationSingleton {
    *   cannot be located
    */
   public void authorizeCollectionAction(SolrQueryRequest req,
-      Set<SearchModelAction> actions, String collectionName, boolean errorIfNoCollection)
+      Set<SearchModelAction> actions, String operation, String collectionName,
+      boolean errorIfNoCollection)
       throws SolrException {
 
     Subject superUser = new Subject(System.getProperty("solr.authorization.superuser", "solr"));
     Subject userName = new Subject(getUserName(req));
+    long eventTime = req.getStartTime();
+    String paramString = req.getParamString();
+    String impersonator = null; // FIXME
+
+    String ipAddress = null;
+    HttpServletRequest sreq = (HttpServletRequest) req.getContext().get("httpRequest");
+    if (sreq != null) {
+      try {
+        ipAddress = sreq.getRemoteAddr();
+      } catch (AssertionError e) {
+        ; // ignore
+        // This is a work-around for "Unexpected method call getRemoteAddr()"
+        // exception during unit test mocking at
+        // com.sun.proxy.$Proxy28.getRemoteAddr(Unknown Source)
+      }
+    }
+
     if (collectionName == null) {
       SolrCore solrCore = req.getCore();
       if (solrCore == null) {
         String msg = "Unable to locate collection for sentry to authorize because "
           + "no SolrCore attached to request";
         if (errorIfNoCollection) {
+          auditLogger.log(userName.getName(), impersonator, ipAddress,
+              operation, paramString, eventTime, AuditLogger.UNAUTHORIZED, collectionName);
           throw new SolrException(SolrException.ErrorCode.UNAUTHORIZED, msg);
         } else { // just warn
           log.warn(msg);
+          auditLogger.log(userName.getName(), impersonator, ipAddress,
+              operation, paramString, eventTime, AuditLogger.ALLOWED, collectionName);
           return;
         }
       }
       collectionName = solrCore.getCoreDescriptor().getCloudDescriptor().getCollectionName();
     }
+
     Collection collection = new Collection(collectionName);
     try {
       if (!superUser.getName().equals(userName.getName())) {
         binding.authorizeCollection(userName, collection, actions);
       }
     } catch (SentrySolrAuthorizationException ex) {
+      auditLogger.log(userName.getName(), impersonator, ipAddress,
+          operation, paramString, eventTime, AuditLogger.UNAUTHORIZED, collectionName);
       throw new SolrException(SolrException.ErrorCode.UNAUTHORIZED, ex);
     }
 
+    auditLogger.log(userName.getName(), impersonator, ipAddress,
+        operation, paramString, eventTime, AuditLogger.ALLOWED, collectionName);
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/f5445bbc/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/update/processor/UpdateIndexAuthorizationProcessor.java
----------------------------------------------------------------------
diff --git a/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/update/processor/UpdateIndexAuthorizationProcessor.java b/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/update/processor/UpdateIndexAuthorizationProcessor.java
index 8cd53d3..5e60645 100644
--- a/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/update/processor/UpdateIndexAuthorizationProcessor.java
+++ b/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/update/processor/UpdateIndexAuthorizationProcessor.java
@@ -27,9 +27,8 @@ import org.apache.solr.update.DeleteUpdateCommand;
 import org.apache.solr.update.MergeIndexesCommand;
 import org.apache.solr.update.RollbackUpdateCommand;
 import org.apache.sentry.core.model.search.SearchModelAction;
+
 import com.google.common.annotations.VisibleForTesting;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import java.io.IOException;
 import java.util.EnumSet;
@@ -52,46 +51,53 @@ public class UpdateIndexAuthorizationProcessor extends UpdateRequestProcessor {
     this.req = req;
   }
 
-  public void authorizeCollectionAction() throws SolrException {
+  private void authorizeCollectionAction(String operation) throws SolrException {
     sentryInstance.authorizeCollectionAction(
-      req, EnumSet.of(SearchModelAction.UPDATE));
+      req, EnumSet.of(SearchModelAction.UPDATE), operation);
   }
 
   @Override
   public void processAdd(AddUpdateCommand cmd) throws IOException {
-    authorizeCollectionAction();
+    authorizeCollectionAction(cmd.name());
     super.processAdd(cmd);
   }
 
   @Override
   public void processDelete(DeleteUpdateCommand cmd) throws IOException {
-    authorizeCollectionAction();
+    String operation = cmd.name();
+    if (cmd.isDeleteById()) {
+      operation += "ById";
+    } else {
+      operation += "ByQuery";
+    }
+    authorizeCollectionAction(operation);
     super.processDelete(cmd);
   }
 
   @Override
   public void processMergeIndexes(MergeIndexesCommand cmd) throws IOException {
-    authorizeCollectionAction();
+    authorizeCollectionAction(cmd.name());
     super.processMergeIndexes(cmd);
   }
 
   @Override
   public void processCommit(CommitUpdateCommand cmd) throws IOException
   {
-    authorizeCollectionAction();
+    authorizeCollectionAction(cmd.name());
     super.processCommit(cmd);
   }
 
   @Override
   public void processRollback(RollbackUpdateCommand cmd) throws IOException
   {
-    authorizeCollectionAction();
+    authorizeCollectionAction(cmd.name());
     super.processRollback(cmd);
   }
 
   @Override
   public void finish() throws IOException {
-    authorizeCollectionAction();
+    authorizeCollectionAction("finish");
     super.finish();
   }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/f5445bbc/sentry-solr/solr-sentry-handlers/src/main/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/sentry-solr/solr-sentry-handlers/src/main/resources/log4j.properties b/sentry-solr/solr-sentry-handlers/src/main/resources/log4j.properties
index 62fdcd4..0e61f4a 100644
--- a/sentry-solr/solr-sentry-handlers/src/main/resources/log4j.properties
+++ b/sentry-solr/solr-sentry-handlers/src/main/resources/log4j.properties
@@ -20,6 +20,19 @@
 #  Logging level
 log4j.rootLogger=INFO, CONSOLE
 
+log4j.logger.org.apache.solr.sentry.AuditLogger=INFO, solrAudit
+#log4j.logger.org.apache.solr.sentry.AuditLogger=OFF
+
+# turn off appending to A1:
+#log4j.additivity.org.apache.solr.sentry.AuditLogger=false
+
+log4j.appender.solrAudit=org.apache.solr.sentry.RollingFileWithoutDeleteAppender
+log4j.appender.solrAudit.layout=org.apache.log4j.PatternLayout
+log4j.appender.solrAudit.layout.ConversionPattern=%m%n
+log4j.appender.solrAudit.File=target/temp/SOLR-1-SOLR_SERVER-d554cdf32962542b8c887a4f9fcbc079
+#log4j.appender.solrAudit.File=/var/log/solr/audit/SENTRY-1-SENTRY_SERVER-d554cdf32962542b8c887a4f9fcbc079
+log4j.appender.solrAudit.MaxFileSize=100MB
+
 log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
 log4j.appender.CONSOLE.Target=System.err
 log4j.appender.CONSOLE.layout=org.apache.solr.util.SolrLogLayout

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/f5445bbc/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/sentry/SentryIndexAuthorizationSingletonTest.java
----------------------------------------------------------------------
diff --git a/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/sentry/SentryIndexAuthorizationSingletonTest.java b/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/sentry/SentryIndexAuthorizationSingletonTest.java
index 4bea251..a3d7d19 100644
--- a/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/sentry/SentryIndexAuthorizationSingletonTest.java
+++ b/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/sentry/SentryIndexAuthorizationSingletonTest.java
@@ -23,11 +23,10 @@ import java.util.Set;
 
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.sentry.core.model.search.SearchModelAction;
+import org.apache.solr.cloud.CloudDescriptor;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.params.ModifiableSolrParams;
-import org.apache.solr.cloud.CloudDescriptor;
 import org.apache.solr.core.SolrCore;
-// import org.apache.solr.servlet.SolrHadoopAuthenticationFilter;
 import org.apache.solr.request.LocalSolrQueryRequest;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.request.SolrQueryRequestBase;
@@ -47,6 +46,8 @@ public class SentryIndexAuthorizationSingletonTest extends SentryTestBase {
   private static CloudDescriptor cloudDescriptor;
   private static SentryIndexAuthorizationSingleton sentryInstance;
 
+  private static final String OPERATION_NAME = "myOperation";
+
   @BeforeClass
   public static void beforeClass() throws Exception {
     core = createCore("solrconfig.xml", "schema-minimal.xml");
@@ -80,7 +81,7 @@ public class SentryIndexAuthorizationSingletonTest extends SentryTestBase {
   private void doExpectUnauthorized(SentryIndexAuthorizationSingleton singleton, SolrQueryRequest request,
       Set<SearchModelAction> actions, String msgContains) throws Exception {
     try {
-      singleton.authorizeCollectionAction(request, actions);
+      singleton.authorizeCollectionAction(request, actions, OPERATION_NAME);
       Assert.fail("Expected SolrException");
     } catch (SolrException ex) {
       assertEquals(ex.code(), SolrException.ErrorCode.UNAUTHORIZED.code);
@@ -144,7 +145,7 @@ public class SentryIndexAuthorizationSingletonTest extends SentryTestBase {
     prepareCollAndUser(core, request, "collection1", "junit");
 
     sentryInstance.authorizeCollectionAction(
-      request, EnumSet.of(SearchModelAction.ALL));
+      request, EnumSet.of(SearchModelAction.ALL), OPERATION_NAME);
   }
 
   /**
@@ -157,7 +158,7 @@ public class SentryIndexAuthorizationSingletonTest extends SentryTestBase {
     prepareCollAndUser(core, request, "bogusCollection", "junit");
 
     sentryInstance.authorizeCollectionAction(
-      request, EnumSet.of(SearchModelAction.ALL));
+      request, EnumSet.of(SearchModelAction.ALL), OPERATION_NAME);
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/f5445bbc/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/update/processor/UpdateIndexAuthorizationProcessorTest.java
----------------------------------------------------------------------
diff --git a/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/update/processor/UpdateIndexAuthorizationProcessorTest.java b/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/update/processor/UpdateIndexAuthorizationProcessorTest.java
index e297232..8feb5a7 100644
--- a/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/update/processor/UpdateIndexAuthorizationProcessorTest.java
+++ b/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/update/processor/UpdateIndexAuthorizationProcessorTest.java
@@ -19,18 +19,25 @@ package org.apache.solr.update.processor;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.List;
 import java.util.TreeSet;
 
 import org.apache.commons.lang.mutable.MutableInt;
 import org.apache.solr.cloud.CloudDescriptor;
 import org.apache.solr.common.SolrException;
+import org.apache.solr.common.params.MapSolrParams;
 import org.apache.solr.core.SolrCore;
 import org.apache.solr.request.SolrQueryRequest;
-import org.apache.solr.sentry.SentryTestBase;
+import org.apache.solr.request.SolrQueryRequestBase;
 import org.apache.solr.sentry.SentrySingletonTestInstance;
+import org.apache.solr.sentry.SentryTestBase;
+import org.apache.solr.update.AddUpdateCommand;
+import org.apache.solr.update.CommitUpdateCommand;
+import org.apache.solr.update.DeleteUpdateCommand;
+import org.apache.solr.update.MergeIndexesCommand;
+import org.apache.solr.update.RollbackUpdateCommand;
 import org.junit.AfterClass;
-import org.junit.Assert;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
@@ -66,11 +73,15 @@ public class UpdateIndexAuthorizationProcessorTest extends SentryTestBase {
   }
 
   private void verifyAuthorized(String collection, String user) throws Exception {
-    getProcessor(collection, user).processAdd(null);
-    getProcessor(collection, user).processDelete(null);
-    getProcessor(collection, user).processMergeIndexes(null);
-    getProcessor(collection, user).processCommit(null);
-    getProcessor(collection, user).processRollback(null);
+    SolrQueryRequestBase req = new SolrQueryRequestBase(core, new MapSolrParams(new HashMap())) {};
+    getProcessor(collection, user).processAdd(new AddUpdateCommand(req));
+    getProcessor(collection, user).processDelete(new DeleteUpdateCommand(req));
+    DeleteUpdateCommand deleteByQueryCommand = new DeleteUpdateCommand(req);
+    deleteByQueryCommand.setQuery("*:*");
+    getProcessor(collection, user).processDelete(deleteByQueryCommand);
+    getProcessor(collection, user).processMergeIndexes(new MergeIndexesCommand(null, req));
+    getProcessor(collection, user).processCommit(new CommitUpdateCommand(req, false));
+    getProcessor(collection, user).processRollback(new RollbackUpdateCommand(req));
     getProcessor(collection, user).finish();
   }
 
@@ -83,29 +94,30 @@ public class UpdateIndexAuthorizationProcessorTest extends SentryTestBase {
   private void verifyUnauthorized(String collection, String user) throws Exception {
     MutableInt numExceptions = new MutableInt(0);
     String contains = "User " + user + " does not have privileges for " + collection;
+    SolrQueryRequestBase req = new SolrQueryRequestBase(core, new MapSolrParams(new HashMap())) {};
 
     try {
-      getProcessor(collection, user).processAdd(null);
+      getProcessor(collection, user).processAdd(new AddUpdateCommand(req));
     } catch(SolrException ex) {
       verifyUnauthorizedException(ex, contains, numExceptions);
     }
     try {
-      getProcessor(collection, user).processDelete(null);
+      getProcessor(collection, user).processDelete(new DeleteUpdateCommand(req));
     } catch(SolrException ex) {
       verifyUnauthorizedException(ex, contains, numExceptions);
     }
     try {
-      getProcessor(collection, user).processMergeIndexes(null);
+      getProcessor(collection, user).processMergeIndexes(new MergeIndexesCommand(null, req));
     } catch(SolrException ex) {
       verifyUnauthorizedException(ex, contains, numExceptions);
     }
     try {
-      getProcessor(collection, user).processCommit(null);
+      getProcessor(collection, user).processCommit(new CommitUpdateCommand(req, false));
     } catch(SolrException ex) {
       verifyUnauthorizedException(ex, contains, numExceptions);
     }
     try {
-      getProcessor(collection, user).processRollback(null);
+      getProcessor(collection, user).processRollback(new RollbackUpdateCommand(req));
     } catch(SolrException ex) {
       verifyUnauthorizedException(ex, contains, numExceptions);
     }