Repository: incubator-sentry
Updated Branches:
  refs/heads/master f1a2efac1 -> aca4d0e9c


SENTRY-987: Move general (non specific handler) solr-sentry code to 
solr-sentry-core package


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

Branch: refs/heads/master
Commit: aca4d0e9ca2c5956a8f59ee3885f92a63af2f65e
Parents: f1a2efa
Author: Gregory Chanan <[email protected]>
Authored: Tue Dec 15 15:33:07 2015 -0800
Committer: Gregory Chanan <[email protected]>
Committed: Tue Dec 22 13:04:50 2015 -0800

----------------------------------------------------------------------
 pom.xml                                         |   5 +
 sentry-dist/pom.xml                             |   4 +
 sentry-solr/pom.xml                             |   1 +
 sentry-solr/solr-sentry-core/pom.xml            |  58 +++++
 .../org/apache/solr/sentry/AuditLogger.java     |  97 ++++++++
 .../RollingFileWithoutDeleteAppender.java       | 176 ++++++++++++++
 .../solr/sentry/SecureRequestHandlerUtil.java   |  84 +++++++
 .../SentryIndexAuthorizationSingleton.java      | 234 +++++++++++++++++++
 sentry-solr/solr-sentry-handlers/pom.xml        |  10 +-
 .../SecureDocumentAnalysisRequestHandler.java   |   1 +
 .../SecureFieldAnalysisRequestHandler.java      |   1 +
 .../solr/handler/SecureReplicationHandler.java  |   1 +
 .../solr/handler/SecureRequestHandlerUtil.java  |  85 -------
 .../solr/handler/admin/SecureAdminHandlers.java |   2 +-
 .../handler/admin/SecureCollectionsHandler.java |   2 +-
 .../handler/admin/SecureCoreAdminHandler.java   |   2 +-
 .../org/apache/solr/sentry/AuditLogger.java     |  97 --------
 .../RollingFileWithoutDeleteAppender.java       | 176 --------------
 .../SentryIndexAuthorizationSingleton.java      | 234 -------------------
 .../sentry/SentrySingletonTestInstance.java     |   2 +-
 20 files changed, 667 insertions(+), 605 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/aca4d0e9/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 9495286..6210454 100644
--- a/pom.xml
+++ b/pom.xml
@@ -253,6 +253,11 @@ limitations under the License.
       </dependency>
       <dependency>
         <groupId>org.apache.sentry</groupId>
+        <artifactId>solr-sentry-core</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.sentry</groupId>
         <artifactId>solr-sentry-handlers</artifactId>
         <version>${project.version}</version>
       </dependency>

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/aca4d0e9/sentry-dist/pom.xml
----------------------------------------------------------------------
diff --git a/sentry-dist/pom.xml b/sentry-dist/pom.xml
index daa2a5a..4e078f0 100644
--- a/sentry-dist/pom.xml
+++ b/sentry-dist/pom.xml
@@ -60,6 +60,10 @@ limitations under the License.
     </dependency>
     <dependency>
       <groupId>org.apache.sentry</groupId>
+      <artifactId>solr-sentry-core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.sentry</groupId>
       <artifactId>solr-sentry-handlers</artifactId>
     </dependency>
     <dependency>

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/aca4d0e9/sentry-solr/pom.xml
----------------------------------------------------------------------
diff --git a/sentry-solr/pom.xml b/sentry-solr/pom.xml
index c3e22c4..43798c9 100644
--- a/sentry-solr/pom.xml
+++ b/sentry-solr/pom.xml
@@ -31,6 +31,7 @@ limitations under the License.
 
   <modules>
     <module>solr-sentry-handlers</module>
+    <module>solr-sentry-core</module>
   </modules>
 
 </project>

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/aca4d0e9/sentry-solr/solr-sentry-core/pom.xml
----------------------------------------------------------------------
diff --git a/sentry-solr/solr-sentry-core/pom.xml 
b/sentry-solr/solr-sentry-core/pom.xml
new file mode 100644
index 0000000..44fbb86
--- /dev/null
+++ b/sentry-solr/solr-sentry-core/pom.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0"?>
+<!--
+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.
+-->
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd"; 
xmlns="http://maven.apache.org/POM/4.0.0";
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";>
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.sentry</groupId>
+    <artifactId>sentry-solr</artifactId>
+    <version>1.7.0-incubating-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>solr-sentry-core</artifactId>
+  <name>Solr Sentry Core</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>log4j</groupId>
+      <artifactId>log4j</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.sentry</groupId>
+      <artifactId>sentry-core-common</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.sentry</groupId>
+      <artifactId>sentry-core-model-search</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.sentry</groupId>
+      <artifactId>sentry-binding-solr</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.solr</groupId>
+      <artifactId>solr-solrj</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.solr</groupId>
+      <artifactId>solr-core</artifactId>
+    </dependency>
+  </dependencies>
+
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/aca4d0e9/sentry-solr/solr-sentry-core/src/main/java/org/apache/solr/sentry/AuditLogger.java
----------------------------------------------------------------------
diff --git 
a/sentry-solr/solr-sentry-core/src/main/java/org/apache/solr/sentry/AuditLogger.java
 
b/sentry-solr/solr-sentry-core/src/main/java/org/apache/solr/sentry/AuditLogger.java
new file mode 100644
index 0000000..7f3e391
--- /dev/null
+++ 
b/sentry-solr/solr-sentry-core/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/aca4d0e9/sentry-solr/solr-sentry-core/src/main/java/org/apache/solr/sentry/RollingFileWithoutDeleteAppender.java
----------------------------------------------------------------------
diff --git 
a/sentry-solr/solr-sentry-core/src/main/java/org/apache/solr/sentry/RollingFileWithoutDeleteAppender.java
 
b/sentry-solr/solr-sentry-core/src/main/java/org/apache/solr/sentry/RollingFileWithoutDeleteAppender.java
new file mode 100644
index 0000000..ec26ef3
--- /dev/null
+++ 
b/sentry-solr/solr-sentry-core/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/aca4d0e9/sentry-solr/solr-sentry-core/src/main/java/org/apache/solr/sentry/SecureRequestHandlerUtil.java
----------------------------------------------------------------------
diff --git 
a/sentry-solr/solr-sentry-core/src/main/java/org/apache/solr/sentry/SecureRequestHandlerUtil.java
 
b/sentry-solr/solr-sentry-core/src/main/java/org/apache/solr/sentry/SecureRequestHandlerUtil.java
new file mode 100644
index 0000000..1f46835
--- /dev/null
+++ 
b/sentry-solr/solr-sentry-core/src/main/java/org/apache/solr/sentry/SecureRequestHandlerUtil.java
@@ -0,0 +1,84 @@
+/*
+ * 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.util.EnumSet;
+import java.util.Set;
+import org.apache.sentry.core.model.search.SearchModelAction;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.response.SolrQueryResponse;
+
+/**
+ * Utility functions for Secure (sentry-aware) versions of RequestHandlers
+ */
+public class SecureRequestHandlerUtil {
+  public static final Set<SearchModelAction> QUERY_ONLY = 
EnumSet.of(SearchModelAction.QUERY);
+  public static final Set<SearchModelAction> UPDATE_ONLY = 
EnumSet.of(SearchModelAction.UPDATE);
+  public static final Set<SearchModelAction> QUERY_AND_UPDATE = 
EnumSet.of(SearchModelAction.QUERY, SearchModelAction.UPDATE);
+
+  // Hack to provide a test-only version of SentryIndexAuthorizationSingleton
+  public static SentryIndexAuthorizationSingleton testOverride = null;
+
+  /**
+   * Attempt to authorize an administrative action.
+   *
+   * @param req request to check
+   * @param andActions set of actions to check
+   * @param checkCollection check the collection the action is on, or only 
"admin"?
+   * @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,
+      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, String operation) {
+    checkSentry(req, andActions, operation, false, false, null);
+   }
+
+  /**
+   * Attempt to sync collection privileges with Sentry when the metadata has 
changed.
+   * ex: When the collection has been deleted, the privileges related to the 
collection
+   * were also needed to drop. When the collection has been renamed, the 
privileges must been
+   * renamed too.
+   */
+  public static void syncDeleteCollection(String collection) {
+    final SentryIndexAuthorizationSingleton sentryInstance =
+        (testOverride == 
null)?SentryIndexAuthorizationSingleton.getInstance():testOverride;
+    sentryInstance.deleteCollection(collection);
+  }
+
+  private static void checkSentry(SolrQueryRequest req, Set<SearchModelAction> 
andActions,
+      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), 
operation, checkCollection, collection);
+      } else {
+        sentryInstance.authorizeCollectionAction(req, EnumSet.of(action), 
operation);
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/aca4d0e9/sentry-solr/solr-sentry-core/src/main/java/org/apache/solr/sentry/SentryIndexAuthorizationSingleton.java
----------------------------------------------------------------------
diff --git 
a/sentry-solr/solr-sentry-core/src/main/java/org/apache/solr/sentry/SentryIndexAuthorizationSingleton.java
 
b/sentry-solr/solr-sentry-core/src/main/java/org/apache/solr/sentry/SentryIndexAuthorizationSingleton.java
new file mode 100644
index 0000000..185884b
--- /dev/null
+++ 
b/sentry-solr/solr-sentry-core/src/main/java/org/apache/solr/sentry/SentryIndexAuthorizationSingleton.java
@@ -0,0 +1,234 @@
+/*
+ * 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.net.URL;
+import java.util.Set;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.sentry.binding.solr.authz.SentrySolrAuthorizationException;
+import org.apache.sentry.binding.solr.authz.SolrAuthzBinding;
+import org.apache.sentry.binding.solr.conf.SolrAuthzConf;
+import org.apache.sentry.core.common.Subject;
+import org.apache.sentry.core.model.search.Collection;
+import org.apache.sentry.core.model.search.SearchModelAction;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.request.LocalSolrQueryRequest;
+import org.apache.solr.request.SolrQueryRequest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SentryIndexAuthorizationSingleton {
+
+  private static Logger log =
+    LoggerFactory.getLogger(SentryIndexAuthorizationSingleton.class);
+
+  public static final String propertyName = "solr.authorization.sentry.site";
+  private static final String USER_NAME = "solr.user.name";
+
+  private static final SentryIndexAuthorizationSingleton INSTANCE =
+    new SentryIndexAuthorizationSingleton(System.getProperty(propertyName));
+
+  private final SolrAuthzBinding binding;
+  private final AuditLogger auditLogger = new AuditLogger();
+
+  private SentryIndexAuthorizationSingleton(String sentrySiteLocation) {
+    SolrAuthzBinding tmpBinding = null;
+    try {
+      if (sentrySiteLocation != null && sentrySiteLocation.length() > 0) {
+        tmpBinding =
+          new SolrAuthzBinding(new SolrAuthzConf(new URL("file://" + 
sentrySiteLocation)));
+        log.info("SolrAuthzBinding created successfully");
+      } else {
+        log.info("SolrAuthzBinding not created because " + propertyName
+          + " not set, sentry not enabled");
+      }
+    } catch (Exception ex) {
+      log.error("Unable to create SolrAuthzBinding", ex);
+    }
+    binding = tmpBinding;
+  }
+
+  public static SentryIndexAuthorizationSingleton getInstance() {
+    return INSTANCE;
+  }
+
+  /**
+   * Returns true iff Sentry index authorization checking is enabled
+   */
+  public boolean isEnabled() {
+    return binding != null;
+  }
+
+  /**
+   * Attempt to authorize an administrative action.
+   *
+   * @param req request to check
+   * @param actions set of actions to check
+   * @param checkCollection check the collection the action is on, or only 
"admin"?
+   * @param collection only relevant if checkCollection==true,
+   *   use collection (if non-null) instead pulling collection name from req 
(if null)
+   */
+  public void authorizeAdminAction(SolrQueryRequest req,
+      Set<SearchModelAction> actions, String operation, boolean 
checkCollection, String collection)
+      throws SolrException {
+    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, operation, collection, false);
+    }
+  }
+
+  /**
+   * Attempt to authorize a collection action.  The collection
+   * name will be pulled from the request.
+   */
+  public void authorizeCollectionAction(SolrQueryRequest req,
+      Set<SearchModelAction> actions, String operation) throws SolrException {
+    authorizeCollectionAction(req, actions, operation, null, true);
+  }
+
+  /**
+   * Attempt to authorize a collection action.
+   *
+   * @param req request to check
+   * @param actions set of actions to check
+   * @param collectionName the collection to check.  If null, the collection
+   *   name is pulled from the request
+   * @param errorIfNoCollection is true, throw an exception if collection
+   *   cannot be located
+   */
+  public void authorizeCollectionAction(SolrQueryRequest req,
+      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);
+  }
+
+  /**
+   * Get the roles associated with the user
+   * @param userName to get roles for
+   * @return The roles associated with the user
+   */
+  public Set<String> getRoles(String userName) {
+    if (binding == null) {
+      return null;
+    }
+    return binding.getRoles(userName);
+  }
+
+  /**
+   * Get the user name associated with the request
+   *
+   * @param req the request
+   * @return the user name associated with the request
+   */
+  public String getUserName(SolrQueryRequest req) throws SolrException {
+    if (binding == null) {
+      throw new SolrException(SolrException.ErrorCode.UNAUTHORIZED,
+        "Solr binding was not created successfully.  Defaulting to no access");
+    }
+    SolrCore solrCore = req.getCore();
+    HttpServletRequest httpServletRequest = 
(HttpServletRequest)req.getContext().get("httpRequest");
+
+    // LocalSolrQueryRequests won't have the HttpServletRequest because there 
is no
+    // http request associated with it.
+    if (httpServletRequest == null && !(req instanceof LocalSolrQueryRequest)) 
{
+      StringBuilder builder = new StringBuilder("Unable to locate 
HttpServletRequest");
+      if (solrCore != null && solrCore.getSolrConfig().getBool(
+        "requestDispatcher/requestParsers/@addHttpRequestToContext", true) == 
false) {
+        builder.append(", ensure 
requestDispatcher/requestParsers/@addHttpRequestToContext is set to true");
+      }
+      throw new SolrException(SolrException.ErrorCode.UNAUTHORIZED, 
builder.toString());
+    }
+
+    String superUser = (System.getProperty("solr.authorization.superuser", 
"solr"));
+    // If a local request, treat it like a super user request; i.e. it is 
equivalent to an
+    // http request from the same process.
+    return req instanceof LocalSolrQueryRequest?
+      superUser:(String)httpServletRequest.getAttribute(USER_NAME);
+  }
+
+  /**
+   * Attempt to notify the Sentry service when deleting collection happened
+   * @param collection
+   * @throws SolrException
+   */
+  public void deleteCollection(String collection) throws SolrException {
+    try {
+      binding.deleteCollectionPrivilege(collection);
+    } catch (SentrySolrAuthorizationException ex) {
+      throw new SolrException(SolrException.ErrorCode.UNAUTHORIZED, ex);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/aca4d0e9/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 61c2da2..07d95fa 100644
--- a/sentry-solr/solr-sentry-handlers/pom.xml
+++ b/sentry-solr/solr-sentry-handlers/pom.xml
@@ -45,20 +45,12 @@ limitations under the License.
       <scope>test</scope>
     </dependency>
     <dependency>
-      <groupId>log4j</groupId>
-      <artifactId>log4j</artifactId>
-    </dependency>
-    <dependency>
       <groupId>commons-logging</groupId>
       <artifactId>commons-logging</artifactId>
       <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>org.apache.sentry</groupId>
-      <artifactId>sentry-core-common</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.sentry</groupId>
       <artifactId>sentry-core-model-search</artifactId>
     </dependency>
     <dependency>
@@ -79,7 +71,7 @@ limitations under the License.
     </dependency>
     <dependency>
       <groupId>org.apache.sentry</groupId>
-      <artifactId>sentry-binding-solr</artifactId>
+      <artifactId>solr-sentry-core</artifactId>
     </dependency>
     <dependency>
       <groupId>org.apache.solr</groupId>

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/aca4d0e9/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 9ecf139..1c1f6f8 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
@@ -19,6 +19,7 @@ package org.apache.solr.handler;
 
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.response.SolrQueryResponse;
+import org.apache.solr.sentry.SecureRequestHandlerUtil;
 
 /**
  * Secure (sentry-aware) version of DocumentAnalysisRequestHandler

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/aca4d0e9/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 819227b..62f9a19 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
@@ -19,6 +19,7 @@ package org.apache.solr.handler;
 
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.response.SolrQueryResponse;
+import org.apache.solr.sentry.SecureRequestHandlerUtil;
 
 /**
  * Secure (sentry-aware) version of FieldAnalysisRequestHandler

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/aca4d0e9/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 42213ae..bdcd830 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
@@ -18,6 +18,7 @@ package org.apache.solr.handler;
 
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.response.SolrQueryResponse;
+import org.apache.solr.sentry.SecureRequestHandlerUtil;
 
 /**
  * Secure (sentry-aware) version of ReplicationHandler

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/aca4d0e9/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
deleted file mode 100644
index 94341b3..0000000
--- 
a/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/handler/SecureRequestHandlerUtil.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * 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.handler;
-
-import java.util.EnumSet;
-import java.util.Set;
-import org.apache.sentry.core.model.search.SearchModelAction;
-import org.apache.solr.request.SolrQueryRequest;
-import org.apache.solr.response.SolrQueryResponse;
-import org.apache.solr.sentry.SentryIndexAuthorizationSingleton;
-
-/**
- * Utility functions for Secure (sentry-aware) versions of RequestHandlers
- */
-public class SecureRequestHandlerUtil {
-  public static final Set<SearchModelAction> QUERY_ONLY = 
EnumSet.of(SearchModelAction.QUERY);
-  public static final Set<SearchModelAction> UPDATE_ONLY = 
EnumSet.of(SearchModelAction.UPDATE);
-  public static final Set<SearchModelAction> QUERY_AND_UPDATE = 
EnumSet.of(SearchModelAction.QUERY, SearchModelAction.UPDATE);
-
-  // Hack to provide a test-only version of SentryIndexAuthorizationSingleton
-  public static SentryIndexAuthorizationSingleton testOverride = null;
-
-  /**
-   * Attempt to authorize an administrative action.
-   *
-   * @param req request to check
-   * @param andActions set of actions to check
-   * @param checkCollection check the collection the action is on, or only 
"admin"?
-   * @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,
-      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, String operation) {
-    checkSentry(req, andActions, operation, false, false, null);
-   }
-
-  /**
-   * Attempt to sync collection privileges with Sentry when the metadata has 
changed.
-   * ex: When the collection has been deleted, the privileges related to the 
collection
-   * were also needed to drop. When the collection has been renamed, the 
privileges must been
-   * renamed too.
-   */
-  public static void syncDeleteCollection(String collection) {
-    final SentryIndexAuthorizationSingleton sentryInstance =
-        (testOverride == 
null)?SentryIndexAuthorizationSingleton.getInstance():testOverride;
-    sentryInstance.deleteCollection(collection);
-  }
-
-  private static void checkSentry(SolrQueryRequest req, Set<SearchModelAction> 
andActions,
-      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), 
operation, checkCollection, collection);
-      } else {
-        sentryInstance.authorizeCollectionAction(req, EnumSet.of(action), 
operation);
-      }
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/aca4d0e9/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 88016ea..6192dff 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
@@ -25,10 +25,10 @@ import org.apache.solr.core.CoreContainer;
 import org.apache.solr.core.SolrCore;
 import org.apache.sentry.core.model.search.SearchModelAction;
 import org.apache.solr.handler.RequestHandlerBase;
-import org.apache.solr.handler.SecureRequestHandlerUtil;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.request.SolrRequestHandler;
 import org.apache.solr.response.SolrQueryResponse;
+import org.apache.solr.sentry.SecureRequestHandlerUtil;
 import org.apache.solr.util.plugin.SolrCoreAware;
 import org.apache.zookeeper.KeeperException;
 

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/aca4d0e9/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 15a6ba0..dc96698 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
@@ -22,9 +22,9 @@ import org.apache.solr.common.params.SolrParams;
 import org.apache.solr.common.params.CollectionParams.CollectionAction;
 import org.apache.solr.common.params.CoreAdminParams;
 import org.apache.sentry.core.model.search.SearchModelAction;
-import org.apache.solr.handler.SecureRequestHandlerUtil;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.response.SolrQueryResponse;
+import org.apache.solr.sentry.SecureRequestHandlerUtil;
 import org.apache.solr.core.CoreContainer;
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/aca4d0e9/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 57ccc94..ff6e281 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
@@ -23,9 +23,9 @@ import org.apache.solr.common.params.SolrParams;
 import org.apache.solr.core.CoreContainer;
 import org.apache.solr.core.CoreDescriptor;
 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.sentry.SecureRequestHandlerUtil;
 
 /**
  * Secure (sentry-aware) version of CoreAdminHandler

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/aca4d0e9/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
deleted file mode 100644
index 7f3e391..0000000
--- 
a/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/sentry/AuditLogger.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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/aca4d0e9/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
deleted file mode 100644
index ec26ef3..0000000
--- 
a/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/sentry/RollingFileWithoutDeleteAppender.java
+++ /dev/null
@@ -1,176 +0,0 @@
-/**
- * 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/aca4d0e9/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
deleted file mode 100644
index 185884b..0000000
--- 
a/sentry-solr/solr-sentry-handlers/src/main/java/org/apache/solr/sentry/SentryIndexAuthorizationSingleton.java
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * 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.net.URL;
-import java.util.Set;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.apache.sentry.binding.solr.authz.SentrySolrAuthorizationException;
-import org.apache.sentry.binding.solr.authz.SolrAuthzBinding;
-import org.apache.sentry.binding.solr.conf.SolrAuthzConf;
-import org.apache.sentry.core.common.Subject;
-import org.apache.sentry.core.model.search.Collection;
-import org.apache.sentry.core.model.search.SearchModelAction;
-import org.apache.solr.common.SolrException;
-import org.apache.solr.core.SolrCore;
-import org.apache.solr.request.LocalSolrQueryRequest;
-import org.apache.solr.request.SolrQueryRequest;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class SentryIndexAuthorizationSingleton {
-
-  private static Logger log =
-    LoggerFactory.getLogger(SentryIndexAuthorizationSingleton.class);
-
-  public static final String propertyName = "solr.authorization.sentry.site";
-  private static final String USER_NAME = "solr.user.name";
-
-  private static final SentryIndexAuthorizationSingleton INSTANCE =
-    new SentryIndexAuthorizationSingleton(System.getProperty(propertyName));
-
-  private final SolrAuthzBinding binding;
-  private final AuditLogger auditLogger = new AuditLogger();
-
-  private SentryIndexAuthorizationSingleton(String sentrySiteLocation) {
-    SolrAuthzBinding tmpBinding = null;
-    try {
-      if (sentrySiteLocation != null && sentrySiteLocation.length() > 0) {
-        tmpBinding =
-          new SolrAuthzBinding(new SolrAuthzConf(new URL("file://" + 
sentrySiteLocation)));
-        log.info("SolrAuthzBinding created successfully");
-      } else {
-        log.info("SolrAuthzBinding not created because " + propertyName
-          + " not set, sentry not enabled");
-      }
-    } catch (Exception ex) {
-      log.error("Unable to create SolrAuthzBinding", ex);
-    }
-    binding = tmpBinding;
-  }
-
-  public static SentryIndexAuthorizationSingleton getInstance() {
-    return INSTANCE;
-  }
-
-  /**
-   * Returns true iff Sentry index authorization checking is enabled
-   */
-  public boolean isEnabled() {
-    return binding != null;
-  }
-
-  /**
-   * Attempt to authorize an administrative action.
-   *
-   * @param req request to check
-   * @param actions set of actions to check
-   * @param checkCollection check the collection the action is on, or only 
"admin"?
-   * @param collection only relevant if checkCollection==true,
-   *   use collection (if non-null) instead pulling collection name from req 
(if null)
-   */
-  public void authorizeAdminAction(SolrQueryRequest req,
-      Set<SearchModelAction> actions, String operation, boolean 
checkCollection, String collection)
-      throws SolrException {
-    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, operation, collection, false);
-    }
-  }
-
-  /**
-   * Attempt to authorize a collection action.  The collection
-   * name will be pulled from the request.
-   */
-  public void authorizeCollectionAction(SolrQueryRequest req,
-      Set<SearchModelAction> actions, String operation) throws SolrException {
-    authorizeCollectionAction(req, actions, operation, null, true);
-  }
-
-  /**
-   * Attempt to authorize a collection action.
-   *
-   * @param req request to check
-   * @param actions set of actions to check
-   * @param collectionName the collection to check.  If null, the collection
-   *   name is pulled from the request
-   * @param errorIfNoCollection is true, throw an exception if collection
-   *   cannot be located
-   */
-  public void authorizeCollectionAction(SolrQueryRequest req,
-      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);
-  }
-
-  /**
-   * Get the roles associated with the user
-   * @param userName to get roles for
-   * @return The roles associated with the user
-   */
-  public Set<String> getRoles(String userName) {
-    if (binding == null) {
-      return null;
-    }
-    return binding.getRoles(userName);
-  }
-
-  /**
-   * Get the user name associated with the request
-   *
-   * @param req the request
-   * @return the user name associated with the request
-   */
-  public String getUserName(SolrQueryRequest req) throws SolrException {
-    if (binding == null) {
-      throw new SolrException(SolrException.ErrorCode.UNAUTHORIZED,
-        "Solr binding was not created successfully.  Defaulting to no access");
-    }
-    SolrCore solrCore = req.getCore();
-    HttpServletRequest httpServletRequest = 
(HttpServletRequest)req.getContext().get("httpRequest");
-
-    // LocalSolrQueryRequests won't have the HttpServletRequest because there 
is no
-    // http request associated with it.
-    if (httpServletRequest == null && !(req instanceof LocalSolrQueryRequest)) 
{
-      StringBuilder builder = new StringBuilder("Unable to locate 
HttpServletRequest");
-      if (solrCore != null && solrCore.getSolrConfig().getBool(
-        "requestDispatcher/requestParsers/@addHttpRequestToContext", true) == 
false) {
-        builder.append(", ensure 
requestDispatcher/requestParsers/@addHttpRequestToContext is set to true");
-      }
-      throw new SolrException(SolrException.ErrorCode.UNAUTHORIZED, 
builder.toString());
-    }
-
-    String superUser = (System.getProperty("solr.authorization.superuser", 
"solr"));
-    // If a local request, treat it like a super user request; i.e. it is 
equivalent to an
-    // http request from the same process.
-    return req instanceof LocalSolrQueryRequest?
-      superUser:(String)httpServletRequest.getAttribute(USER_NAME);
-  }
-
-  /**
-   * Attempt to notify the Sentry service when deleting collection happened
-   * @param collection
-   * @throws SolrException
-   */
-  public void deleteCollection(String collection) throws SolrException {
-    try {
-      binding.deleteCollectionPrivilege(collection);
-    } catch (SentrySolrAuthorizationException ex) {
-      throw new SolrException(SolrException.ErrorCode.UNAUTHORIZED, ex);
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/aca4d0e9/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/sentry/SentrySingletonTestInstance.java
----------------------------------------------------------------------
diff --git 
a/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/sentry/SentrySingletonTestInstance.java
 
b/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/sentry/SentrySingletonTestInstance.java
index ae02466..664719f 100644
--- 
a/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/sentry/SentrySingletonTestInstance.java
+++ 
b/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/sentry/SentrySingletonTestInstance.java
@@ -21,7 +21,7 @@ import java.lang.reflect.Constructor;
 
 import org.apache.commons.io.FileUtils;
 import org.apache.solr.SolrTestCaseJ4;
-import org.apache.solr.handler.SecureRequestHandlerUtil;
+import org.apache.solr.sentry.SecureRequestHandlerUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 

Reply via email to