You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sentry.apache.org by gc...@apache.org on 2013/12/26 20:20:06 UTC
git commit: SENTRY-71: Solr Update authorization tests for Sentry
(Vamsee Yarlagadda via Gregory Chanan)
Updated Branches:
refs/heads/master b9aa0b7a0 -> 5601cdd18
SENTRY-71: Solr Update authorization tests for Sentry (Vamsee Yarlagadda via Gregory Chanan)
Project: http://git-wip-us.apache.org/repos/asf/incubator-sentry/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-sentry/commit/5601cdd1
Tree: http://git-wip-us.apache.org/repos/asf/incubator-sentry/tree/5601cdd1
Diff: http://git-wip-us.apache.org/repos/asf/incubator-sentry/diff/5601cdd1
Branch: refs/heads/master
Commit: 5601cdd18c4a89b468c1c0cdde3b68fbabf28ceb
Parents: b9aa0b7
Author: Gregory Chanan <gc...@cloudera.com>
Authored: Mon Dec 23 15:44:01 2013 -0800
Committer: Gregory Chanan <gc...@cloudera.com>
Committed: Mon Dec 23 15:44:01 2013 -0800
----------------------------------------------------------------------
sentry-tests/sentry-tests-solr/pom.xml | 15 +-
.../e2e/solr/AbstractSolrSentryTestBase.java | 335 ++++++++++++++++++-
.../e2e/solr/JunitAuthenticationFilter.java | 55 ---
.../ModifiableUserAuthenticationFilter.java | 68 ++++
.../e2e/solr/TestSimpleUpdatePositiveTest.java | 44 ---
.../tests/e2e/solr/TestUpdateOperations.java | 79 +++++
.../solr/sentry/test-authz-provider.ini | 35 +-
7 files changed, 521 insertions(+), 110 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/5601cdd1/sentry-tests/sentry-tests-solr/pom.xml
----------------------------------------------------------------------
diff --git a/sentry-tests/sentry-tests-solr/pom.xml b/sentry-tests/sentry-tests-solr/pom.xml
index 23a2ec5..3f0fa2d 100644
--- a/sentry-tests/sentry-tests-solr/pom.xml
+++ b/sentry-tests/sentry-tests-solr/pom.xml
@@ -18,14 +18,22 @@ 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-tests</artifactId>
<version>1.3.0-incubating-SNAPSHOT</version>
</parent>
+
<artifactId>sentry-tests-solr</artifactId>
<name>Sentry Solr Tests</name>
<description>end to end tests for sentry-solr integration</description>
+
+ <properties>
+ <lucene-junit.version>4.10</lucene-junit.version>
+ <carrot-search.version>2.0.10</carrot-search.version>
+ </properties>
+
<dependencies>
<dependency>
<groupId>org.apache.solr</groupId>
@@ -46,7 +54,12 @@ limitations under the License.
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
- <version>4.10</version> <!-- required for LuceneTestCase -->
+ <version>${lucene-junit.version}</version> <!-- required for LuceneTestCase -->
+ </dependency>
+ <dependency>
+ <groupId>com.carrotsearch.randomizedtesting</groupId>
+ <artifactId>randomizedtesting-runner</artifactId>
+ <version>${carrot-search.version}</version>
</dependency>
</dependencies>
</project>
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/5601cdd1/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/AbstractSolrSentryTestBase.java
----------------------------------------------------------------------
diff --git a/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/AbstractSolrSentryTestBase.java b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/AbstractSolrSentryTestBase.java
index 52fcecf..c0abd28 100644
--- a/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/AbstractSolrSentryTestBase.java
+++ b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/AbstractSolrSentryTestBase.java
@@ -18,7 +18,11 @@ package org.apache.sentry.tests.e2e.solr;
import java.io.File;
import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.Arrays;
import java.util.Comparator;
+import java.util.List;
+import java.util.Random;
import java.util.SortedMap;
import java.util.TreeMap;
@@ -27,11 +31,17 @@ import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hdfs.MiniDFSCluster;
import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.impl.CloudSolrServer;
+import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.cloud.AbstractFullDistribZkTestBase;
import org.apache.solr.cloud.ZkController;
+import org.apache.solr.common.SolrDocument;
+import org.apache.solr.common.SolrDocumentList;
+import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.servlet.SolrDispatchFilter;
+import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
@@ -41,8 +51,11 @@ import org.slf4j.LoggerFactory;
public abstract class AbstractSolrSentryTestBase extends AbstractFullDistribZkTestBase {
private static final Logger LOG = LoggerFactory.getLogger(AbstractSolrSentryTestBase.class);
+ protected static final String SENTRY_ERROR_MSG = "401, message:Unauthorized";
private static MiniDFSCluster dfsCluster;
private static SortedMap<Class, String> extraRequestFilters;
+ protected static final String ADMIN_USER = "admin";
+ protected static final Random RANDOM = new Random();
private static void addPropertyToSentry(StringBuilder builder, String name, String value) {
builder.append("<property>\n");
@@ -92,7 +105,7 @@ public abstract class AbstractSolrSentryTestBase extends AbstractFullDistribZkTe
return true;
}
});
- extraRequestFilters.put(JunitAuthenticationFilter.class, "*");
+ extraRequestFilters.put(ModifiableUserAuthenticationFilter.class, "*");
}
@AfterClass
@@ -104,17 +117,23 @@ public abstract class AbstractSolrSentryTestBase extends AbstractFullDistribZkTe
extraRequestFilters = null;
}
- @Override
- protected String getDataDir(String dataDir) throws IOException {
- return HdfsTestUtil.getDataDir(dfsCluster, dataDir);
- }
-
@Before
- @Override
- public void setUp() throws Exception {
- super.setUp();
+ public void setupBeforeTest() throws Exception {
System.setProperty("numShards", Integer.toString(sliceCount));
System.setProperty("solr.xml.persist", "true");
+ super.setUp();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ super.tearDown();
+ System.clearProperty("numShards");
+ System.clearProperty("solr.xml.persist");
+ }
+
+ @Override
+ protected String getDataDir(String dataDir) throws IOException {
+ return HdfsTestUtil.getDataDir(dfsCluster, dataDir);
}
@Override
@@ -133,6 +152,304 @@ public abstract class AbstractSolrSentryTestBase extends AbstractFullDistribZkTe
}
/**
+ * Set the proper user in the Solr authentication filter
+ * @param solrUser
+ */
+ protected void setAuthenticationUser(String solrUser) throws Exception {
+ ModifiableUserAuthenticationFilter.setUser(solrUser);
+ }
+
+ /**
+ * Function to return the user name based on the permissions provided.
+ * @param collectionName - Name of the solr collection.
+ * @param isQuery - Boolean that specifies query permission.
+ * @param isUpdate - Boolean that specifies update permission.
+ * @param isAll - Boolean that specifies all permission.
+ * @return - String which represents the Solr username.
+ */
+ protected String getUsernameForPermissions(String collectionName,
+ boolean isQuery,
+ boolean isUpdate,
+ boolean isAll) {
+ StringBuilder finalStr = new StringBuilder();
+ finalStr.append(collectionName);
+ finalStr.append("_");
+ StringBuilder permissions = new StringBuilder();
+ if (isQuery) {
+ permissions.append("q");
+ }
+
+ if (isUpdate) {
+ permissions.append("u");
+ }
+
+ if (isAll) {
+ permissions.append("a");
+ }
+
+ finalStr.append(permissions.toString());
+ return finalStr.toString();
+ }
+
+ /**
+ * Method to validate Solr update passes
+ * @param solrUserName - User authenticated into Solr
+ * @param collectionName - Name of the collection to which the data has to be updated
+ * @param solrInputDoc - Instance of SolrInputDocument
+ * @throws Exception
+ */
+ protected void verifyUpdatePass(String solrUserName,
+ String collectionName,
+ SolrInputDocument solrInputDoc)
+ throws Exception {
+ int originalSolrDocCount = getSolrDocs(collectionName).size();
+ setAuthenticationUser(solrUserName);
+ CloudSolrServer cloudSolrServer = getCloudSolrServer(collectionName);
+ try {
+ cloudSolrServer.add(solrInputDoc);
+ cloudSolrServer.commit();
+ } finally {
+ cloudSolrServer.shutdown();
+ }
+
+ // Validate Solr content to check whether the update command went through.
+ // Authenticate as user "admin"
+ validateSolrDocCountAndContent(collectionName, originalSolrDocCount+1, solrInputDoc);
+ }
+
+ /**
+ * Method to validate Solr update fails
+ * @param solrUserName - User authenticated into Solr
+ * @param collectionName - Name of the collection to which the data has to be updated
+ * @param solrInputDoc - Instance of SolrInputDocument
+ * @throws Exception
+ */
+ protected void verifyUpdateFail(String solrUserName,
+ String collectionName,
+ SolrInputDocument solrInputDoc)
+ throws Exception {
+ int originalSolrDocCount = getSolrDocs(collectionName).size();
+ setAuthenticationUser(solrUserName);
+ CloudSolrServer cloudSolrServer = getCloudSolrServer(collectionName);
+ try {
+ cloudSolrServer.add(solrInputDoc);
+ cloudSolrServer.commit();
+ fail("The specified user: " + solrUserName + " shouldn't get update access!");
+ } catch (Exception exception) {
+ assertTrue("Expected " + SENTRY_ERROR_MSG + " in " + exception.toString(),
+ exception.toString().contains(SENTRY_ERROR_MSG));
+ } finally {
+ cloudSolrServer.shutdown();
+ }
+
+ // Validate Solr content to check whether the update command didn't go through.
+ // Authenticate as user "admin"
+ validateSolrDocCountAndContent(collectionName, originalSolrDocCount, null);
+ }
+
+ /**
+ * Method to validate Solr deletedocs passes
+ * (This function doesn't check if there is at least one Solr document present in Solr)
+ * @param solrUserName - User authenticated into Solr
+ * @param collectionName - Name of the collection to which the data has to be updated
+ * @param allowZeroDocs - Boolean for running this method only if there is atleast one Solr doc present.
+ * @throws MalformedURLException, SolrServerException, IOException
+ */
+ protected void verifyDeletedocsPass(String solrUserName,
+ String collectionName, boolean allowZeroDocs)
+ throws Exception {
+ int originalSolrDocCount = getSolrDocs(collectionName).size();
+ if (allowZeroDocs == false) {
+ assertTrue("Solr should contain atleast one solr doc to run this test.", originalSolrDocCount > 0);
+ }
+
+ setAuthenticationUser(solrUserName);
+ CloudSolrServer cloudSolrServer = getCloudSolrServer(collectionName);
+ try {
+ cloudSolrServer.deleteByQuery("*:*");
+ cloudSolrServer.commit();
+ } finally {
+ cloudSolrServer.shutdown();
+ }
+
+ // Validate Solr content to check whether the update command didn't go through.
+ // Authenticate as user "admin"
+ validateSolrDocCountAndContent(collectionName, 0, null);
+ }
+
+ /**
+ * Method to validate Solr deletedocs fails
+ * (This function doesn't check if there is at least one Solr document present in Solr)
+ * @param solrUserName - User authenticated into Solr
+ * @param collectionName - Name of the collection to which the data has to be updated
+ * @param allowZeroDocs - Boolean for running this method only if there is atleast one Solr doc present.
+ * @throws Exception
+ */
+ protected void verifyDeletedocsFail(String solrUserName,
+ String collectionName, boolean allowZeroDocs)
+ throws Exception {
+ int originalSolrDocCount = getSolrDocs(collectionName).size();
+ if (allowZeroDocs == false) {
+ assertTrue("Solr should contain atleast one solr doc to run this test.", originalSolrDocCount > 0);
+ }
+
+ setAuthenticationUser(solrUserName);
+ CloudSolrServer cloudSolrServer = getCloudSolrServer(collectionName);
+ try {
+ cloudSolrServer.deleteByQuery("*:*");
+ cloudSolrServer.commit();
+ fail("The specified user: " + solrUserName + " shouldn't get deletedocs access!");
+ } catch (Exception exception) {
+ assertTrue("Expected " + SENTRY_ERROR_MSG + " in " + exception.toString(),
+ exception.toString().contains(SENTRY_ERROR_MSG));
+ } finally {
+ cloudSolrServer.shutdown();
+ }
+
+ // Validate Solr content to check whether the deletedocs command didn't go through.
+ // Authenticate as user "admin"
+ validateSolrDocCountAndContent(collectionName, originalSolrDocCount, null);
+ }
+
+ /**
+ * Function to verify whether Solr doc count matches the expected number and
+ * also to verify if the Input document is present in present in the response.
+ * @param collectionName - Name of the Solr collection
+ * @param expectedDocCount - Count of expected Solr docs
+ * @param solrInputDoc - Solr doc inserted into Solr
+ * @throws Exception
+ */
+ public void validateSolrDocCountAndContent(String collectionName, int expectedDocCount, SolrInputDocument solrInputDoc)
+ throws Exception {
+ // Authenticate as user "admin"
+ setAuthenticationUser(ADMIN_USER);
+ SolrDocumentList solrRespDocs = getSolrDocs(collectionName);
+ assertEquals("Expected: " + expectedDocCount + " Solr docs; But, found "
+ + solrRespDocs.size() + " Solr docs.", solrRespDocs.size(), expectedDocCount);
+ if (solrInputDoc != null) {
+ validateSolrDocContent(solrInputDoc, solrRespDocs);
+ }
+ }
+
+ /**
+ * Function to query the collection and fetch the Solr docs
+ * @param collectionName - Name of the collection
+ * @return - Instance of SolrDocumentList
+ * @throws Exception
+ */
+ protected SolrDocumentList getSolrDocs(String collectionName) throws Exception {
+ // Authenticate as user "admin"
+ setAuthenticationUser(ADMIN_USER);
+ CloudSolrServer cloudSolrServer = getCloudSolrServer(collectionName);
+ SolrDocumentList solrDocs = null;
+ try {
+ SolrQuery query = new SolrQuery("*:*");
+ QueryResponse response = cloudSolrServer.query(query);
+ solrDocs = response.getResults();
+ } finally {
+ cloudSolrServer.shutdown();
+ }
+
+ return solrDocs;
+ }
+
+ /**
+ * Function to validate the content of Solr response with that of input document.
+ * @param solrInputDoc - Solr doc inserted into Solr
+ * @param solrRespDocs - List of Solr doc obtained as response
+ * (NOTE: This function ignores "_version_" field in validating Solr doc content)
+ */
+ public void validateSolrDocContent(SolrInputDocument solrInputDoc, SolrDocumentList solrRespDocs) {
+ solrInputDoc.removeField("_version_");
+ for (SolrDocument solrRespDoc : solrRespDocs) {
+ solrRespDoc.removeFields("_version_");
+ String expFieldValue = (String) solrInputDoc.getFieldValue("id");
+ String resFieldValue = (String) solrRespDoc.getFieldValue("id");
+ if (expFieldValue.equals(resFieldValue)) {
+ assertEquals("Expected " + solrInputDoc.size() + " fields. But, found "
+ + solrRespDoc.size() + " fields", solrInputDoc.size() , solrRespDoc.size());
+ for (String field : solrInputDoc.getFieldNames()) {
+ expFieldValue = (String) solrInputDoc.getFieldValue(field);
+ resFieldValue = (String) solrRespDoc.getFieldValue(field);
+ assertEquals("Expected value for field: " + field + " is " + expFieldValue
+ + "; But, found " + resFieldValue, expFieldValue, resFieldValue);
+ }
+
+ return;
+ }
+ }
+
+ fail("Solr doc not found in Solr collection");
+ }
+
+ /**
+ * Function to return the instance of CloudSolrServer for the collectionName specified
+ * @param collectionName - Name of the collection
+ * @return instance of CloudSolrServer
+ * @throws MalformedURLException
+ */
+ protected CloudSolrServer getCloudSolrServer(String collectionName) throws MalformedURLException {
+ CloudSolrServer cloudSolrServer = new CloudSolrServer(zkServer.getZkAddress(),
+ random().nextBoolean());
+ cloudSolrServer.setDefaultCollection(collectionName);
+ cloudSolrServer.connect();
+ return cloudSolrServer;
+ }
+
+ /**
+ * Function to create a solr collection with the name passed as parameter
+ * (Runs commands as ADMIN user)
+ * @param collectionName - Name of the collection
+ * @throws Exception
+ */
+ protected void setupCollection(String collectionName) throws Exception {
+ // Authenticate as user "admin"
+ setAuthenticationUser(ADMIN_USER);
+ uploadConfigDirToZk(getSolrHome() + File.separator + DEFAULT_COLLECTION
+ + File.separator + "conf");
+ createCollection(collectionName, 1, 1, 1);
+ waitForRecoveriesToFinish(collectionName, false);
+ }
+
+ /**
+ * Function to clean Solr collections
+ * @param collectionName - Name of the collection
+ * @throws Exception
+ */
+ protected void cleanSolrCollection(String collectionName)
+ throws Exception {
+ verifyDeletedocsPass(ADMIN_USER, collectionName, true);
+ }
+
+ /**
+ * Function to create a test Solrdoc with a random number as the ID
+ * @throws Exception
+ */
+ protected SolrInputDocument createSolrTestDoc() throws Exception {
+ SolrInputDocument solrInputDoc = new SolrInputDocument();
+ String solrDocId = String.valueOf(RANDOM.nextInt());
+ solrInputDoc.addField("id", solrDocId);
+ solrInputDoc.addField("name", "testdoc" + solrDocId);
+ return solrInputDoc;
+ }
+
+ /**
+ * Load Solr collection with the SolrDocument passed.
+ * @param collectionName - Name of the Solr collection
+ * @param solrInputDoc - Solr document to be uploaded
+ * (If solrInputDoc is null, then a test Solr doc will be uploaded)
+ * @throws Exception
+ */
+ protected void uploadSolrDoc(String collectionName,
+ SolrInputDocument solrInputDoc) throws Exception {
+ if (solrInputDoc == null) {
+ solrInputDoc = createSolrTestDoc();
+ }
+
+ verifyUpdatePass(ADMIN_USER, collectionName, solrInputDoc);
+ }
+
+ /**
* Subclasses can override this to change a test's solr home
* (default is in test-files)
*/
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/5601cdd1/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/JunitAuthenticationFilter.java
----------------------------------------------------------------------
diff --git a/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/JunitAuthenticationFilter.java b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/JunitAuthenticationFilter.java
deleted file mode 100644
index 7e2690f..0000000
--- a/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/JunitAuthenticationFilter.java
+++ /dev/null
@@ -1,55 +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.sentry.tests.e2e.solr;
-
-import java.io.IOException;
-
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import org.apache.solr.servlet.SolrHadoopAuthenticationFilter;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Authentication Filter that authenticates any request as user "junit"
- */
-public class JunitAuthenticationFilter implements Filter {
- private static final Logger LOG = LoggerFactory
- .getLogger(JunitAuthenticationFilter.class);
- private static final String userName = "junit";
-
- @Override
- public void init(FilterConfig filterConfig) throws ServletException {
- }
-
- @Override
- public void destroy() {
- }
-
- @Override
- public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
- HttpServletRequest httpRequest = (HttpServletRequest) request;
- httpRequest.setAttribute(SolrHadoopAuthenticationFilter.USER_NAME, userName);
- chain.doFilter(request, response);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/5601cdd1/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/ModifiableUserAuthenticationFilter.java
----------------------------------------------------------------------
diff --git a/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/ModifiableUserAuthenticationFilter.java b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/ModifiableUserAuthenticationFilter.java
new file mode 100644
index 0000000..9f550c4
--- /dev/null
+++ b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/ModifiableUserAuthenticationFilter.java
@@ -0,0 +1,68 @@
+/*
+ * 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.sentry.tests.e2e.solr;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import org.apache.solr.servlet.SolrHadoopAuthenticationFilter;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Authentication Filter that authenticates any request as user "junit"
+ */
+public class ModifiableUserAuthenticationFilter implements Filter {
+ private static final Logger LOG = LoggerFactory
+ .getLogger(ModifiableUserAuthenticationFilter.class);
+
+ /**
+ * String that saves the user to be authenticated into Solr
+ */
+ private static String userName = "admin";
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+ }
+
+ @Override
+ public void destroy() {
+ }
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response,
+ FilterChain chain) throws IOException, ServletException {
+ HttpServletRequest httpRequest = (HttpServletRequest) request;
+ httpRequest.setAttribute(SolrHadoopAuthenticationFilter.USER_NAME, userName);
+ chain.doFilter(request, response);
+ }
+
+ /**
+ * Function to set the userName with the corresponding user passed as parameter
+ * @param solrUser
+ */
+ public static void setUser(String solrUser) {
+ userName = solrUser;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/5601cdd1/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSimpleUpdatePositiveTest.java
----------------------------------------------------------------------
diff --git a/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSimpleUpdatePositiveTest.java b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSimpleUpdatePositiveTest.java
deleted file mode 100644
index c5174b6..0000000
--- a/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSimpleUpdatePositiveTest.java
+++ /dev/null
@@ -1,44 +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.sentry.tests.e2e.solr;
-
-import java.io.File;
-import org.apache.solr.client.solrj.impl.CloudSolrServer;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope;
-import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope.Scope;
-
-@ThreadLeakScope(Scope.NONE) // hdfs client currently leaks thread(s)
-public class TestSimpleUpdatePositiveTest extends AbstractSolrSentryTestBase {
- private static final Logger LOG = LoggerFactory.getLogger(TestSimpleUpdatePositiveTest.class);
-
- /**
- * Solr-sentry positive test on updates
- */
- @Override
- public void doTest() throws Exception {
- uploadConfigDirToZk(getSolrHome() + File.separator + DEFAULT_COLLECTION
- + File.separator + "conf");
- createCollection(DEFAULT_COLLECTION, 1, 1, 1);
- waitForRecoveriesToFinish(DEFAULT_COLLECTION, false);
- CloudSolrServer cloudServer = getCommonCloudSolrServer();
- cloudServer.deleteByQuery("*:*");
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/5601cdd1/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestUpdateOperations.java
----------------------------------------------------------------------
diff --git a/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestUpdateOperations.java b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestUpdateOperations.java
new file mode 100644
index 0000000..131fa2c
--- /dev/null
+++ b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestUpdateOperations.java
@@ -0,0 +1,79 @@
+/*
+ * 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.sentry.tests.e2e.solr;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope;
+import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope.Scope;
+import java.util.ArrayList;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.solr.common.SolrInputDocument;
+
+@ThreadLeakScope(Scope.NONE) // hdfs client currently leaks thread(s)
+public class TestUpdateOperations extends AbstractSolrSentryTestBase {
+ private static final Logger LOG = LoggerFactory
+ .getLogger(TestUpdateOperations.class);
+ private static final String COLLECTION_NAME = "sentryCollection";
+ private static final List<Boolean> BOOLEAN_VALUES = Arrays.asList(new Boolean[]{true, false});
+
+ @Override
+ public void doTest() throws Exception {
+ setupCollection(COLLECTION_NAME);
+ ArrayList<String> testFailures = new ArrayList<String>();
+
+ for (boolean query : BOOLEAN_VALUES) {
+ for (boolean update : BOOLEAN_VALUES) {
+ for (boolean all : BOOLEAN_VALUES) {
+ // Create user name to be used for Solr requests based on the permissions generated by the for-loop.
+ String test_user = getUsernameForPermissions(COLLECTION_NAME, query, update, all);
+ LOG.info("TEST_USER: " + test_user);
+
+ try {
+ if (all || update) {
+ cleanSolrCollection(COLLECTION_NAME);
+ SolrInputDocument solrInputDoc = createSolrTestDoc();
+ verifyUpdatePass(test_user, COLLECTION_NAME, solrInputDoc);
+
+ cleanSolrCollection(COLLECTION_NAME);
+ uploadSolrDoc(COLLECTION_NAME, null);
+ verifyDeletedocsPass(test_user, COLLECTION_NAME, false);
+ } else {
+ cleanSolrCollection(COLLECTION_NAME);
+ SolrInputDocument solrInputDoc = createSolrTestDoc();
+ verifyUpdateFail(test_user, COLLECTION_NAME, solrInputDoc);
+
+ cleanSolrCollection(COLLECTION_NAME);
+ uploadSolrDoc(COLLECTION_NAME, null);
+ verifyDeletedocsFail(test_user, COLLECTION_NAME, false);
+ }
+ } catch (Throwable testException) {
+ testFailures.add("\n\nTestFailure: User -> " + test_user + "\n"
+ + testException.toString());
+ }
+ }
+ }
+ }
+
+ assertEquals("Total test failures: " + testFailures.size() + " \n\n"
+ + testFailures.toString(), 0, testFailures.size());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/5601cdd1/sentry-tests/sentry-tests-solr/src/test/resources/solr/sentry/test-authz-provider.ini
----------------------------------------------------------------------
diff --git a/sentry-tests/sentry-tests-solr/src/test/resources/solr/sentry/test-authz-provider.ini b/sentry-tests/sentry-tests-solr/src/test/resources/solr/sentry/test-authz-provider.ini
index 34926ae..f988eae 100644
--- a/sentry-tests/sentry-tests-solr/src/test/resources/solr/sentry/test-authz-provider.ini
+++ b/sentry-tests/sentry-tests-solr/src/test/resources/solr/sentry/test-authz-provider.ini
@@ -17,9 +17,42 @@
[groups]
junit = junit_role
+admin = admin_role
+sentry_collection_query_group = sentry_collection_query_role
+sentry_collection_update_group = sentry_collection_update_role
+sentry_collection_query_update_group = sentry_collection_query_update_role
+sentry_collection_all_group = sentry_collection_all_role
+admin_query_group = admin_query_role
+admin_update_group = admin_update_role
+admin_query_update_group = admin_query_update_role
+admin_all_group = admin_all_role
[roles]
junit_role = collection=admin, collection=collection1
+admin_role = collection=admin, collection=collection1, collection=sentryCollection
+sentry_collection_query_role = collection=sentryCollection->action=query
+sentry_collection_update_role = collection=sentryCollection->action=update
+sentry_collection_query_update_role = collection=sentryCollection->action=query, collection=sentryCollection->action=update
+sentry_collection_all_role = collection=sentryCollection->action=*
+admin_query_role = collection=admin->action=query
+admin_update_role = collection=admin->action=update
+admin_query_update_role = collection=admin->action=query, collection=admin->action=update
+admin_all_role = collection=admin->action=*
[users]
-junit=junit
+junit = junit
+admin = admin
+sentryCollection_q = sentry_collection_query_group
+sentryCollection_u = sentry_collection_update_group
+sentryCollection_a = sentry_collection_all_group
+sentryCollection_qu = sentry_collection_query_update_group
+sentryCollection_ua = sentry_collection_update_group, sentry_collection_all_group
+sentryCollection_qa = sentry_collection_query_group, sentry_collection_all_group
+sentryCollection_qua = sentry_collection_query_group, sentry_collection_update_group, sentry_collection_all_group
+admin_q = admin_query_group
+admin_u = admin_update_group
+admin_a = admin_all_group
+admin_qu = admin_query_update_group
+admin_ua = admin_update_group, admin_all_group
+admin_qa = admin_query_group, admin_all_group
+admin_qua = admin_query_group, admin_update_group, admin_all_group
\ No newline at end of file