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 <[email protected]> Authored: Mon Dec 23 15:44:01 2013 -0800 Committer: Gregory Chanan <[email protected]> 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
