http://git-wip-us.apache.org/repos/asf/sentry/blob/e62fa28d/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestDocLevelOperations.java ---------------------------------------------------------------------- diff --git a/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestDocLevelOperations.java b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestDocLevelOperations.java index 71452e2..a24ceee 100644 --- a/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestDocLevelOperations.java +++ b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestDocLevelOperations.java @@ -16,56 +16,64 @@ */ package org.apache.sentry.tests.e2e.solr; -import org.junit.After; -import org.junit.Before; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.apache.sentry.tests.e2e.solr.TestSentryServer.ADMIN_USER; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.sentry.core.common.exception.SentryUserException; +import org.apache.sentry.core.model.solr.SolrConstants; import org.apache.solr.client.solrj.SolrQuery; -import org.apache.solr.client.solrj.impl.CloudSolrServer; +import org.apache.solr.client.solrj.impl.CloudSolrClient; import org.apache.solr.client.solrj.request.QueryRequest; import org.apache.solr.client.solrj.response.QueryResponse; - import org.apache.solr.common.SolrDocument; import org.apache.solr.common.SolrDocumentList; import org.apache.solr.common.SolrInputDocument; import org.apache.solr.common.params.ModifiableSolrParams; import org.apache.solr.common.params.SolrParams; - -import java.io.File; -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.List; - +import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; /** * Test the document-level security features */ -public class TestDocLevelOperations extends AbstractSolrSentryTestBase { +public class TestDocLevelOperations extends AbstractSolrSentryTestCase { private static final String AUTH_FIELD = "sentry_auth"; private static final int NUM_DOCS = 100; private static final int EXTRA_AUTH_FIELDS = 2; - private String userName = null; - @Before - public void beforeTest() throws Exception { - userName = getAuthenticatedUser(); - } - - @After - public void afterTest() throws Exception { - setAuthenticationUser(userName); + @BeforeClass + public static void setupPermissions() throws SentryUserException { + sentryClient.createRole(ADMIN_USER, "junit_role", COMPONENT_SOLR); + sentryClient.createRole(ADMIN_USER, "doclevel_role", COMPONENT_SOLR); + sentryClient.grantRoleToGroups(ADMIN_USER, "junit_role", COMPONENT_SOLR, + Collections.singleton("junit")); + sentryClient.grantRoleToGroups(ADMIN_USER, "doclevel_role", COMPONENT_SOLR, + Collections.singleton("doclevel")); + + // junit user + grantAdminPrivileges(ADMIN_USER, "junit_role", SolrConstants.ALL, SolrConstants.ALL); + grantCollectionPrivileges(ADMIN_USER, "junit_role", "docLevelCollection", SolrConstants.ALL); + grantCollectionPrivileges(ADMIN_USER, "junit_role", "allRolesCollection", SolrConstants.ALL); + grantCollectionPrivileges(ADMIN_USER, "junit_role", "testUpdateDeleteOperations", SolrConstants.ALL); + + // docLevel user + grantCollectionPrivileges(ADMIN_USER, "doclevel_role", "docLevelCollection", SolrConstants.ALL); + grantCollectionPrivileges(ADMIN_USER, "doclevel_role", "testUpdateDeleteOperations", SolrConstants.ALL); + + // admin user + grantCollectionPrivileges(ADMIN_USER, ADMIN_ROLE, SolrConstants.ALL, SolrConstants.ALL); } - private void setupCollectionWithDocSecurity(String name) throws Exception { - String configDir = RESOURCES_DIR + File.separator + DEFAULT_COLLECTION - + File.separator + "conf"; - uploadConfigDirToZk(configDir); - // replace solrconfig.xml with solrconfig-doc-level.xml - uploadConfigFileToZk(configDir + File.separator + "solrconfig-doclevel.xml", - "solrconfig.xml"); - setupCollection(name); + @Before + public void resetAuthenticatedUser() { + setAuthenticationUser("admin"); } private QueryRequest getRealTimeGetRequest() { @@ -77,6 +85,7 @@ public class TestDocLevelOperations extends AbstractSolrSentryTestBase { return getRealTimeGetRequest(idsBuilder.toString()); } + @SuppressWarnings("serial") private QueryRequest getRealTimeGetRequest(String ids) { final ModifiableSolrParams idsParams = new ModifiableSolrParams(); idsParams.add("ids", ids); @@ -107,34 +116,29 @@ public class TestDocLevelOperations extends AbstractSolrSentryTestBase { // ensure no current documents verifyDeletedocsPass(ADMIN_USER, collectionName, true); - CloudSolrServer server = getCloudSolrServer(collectionName); - try { - DocLevelGenerator generator = new DocLevelGenerator(AUTH_FIELD); - generator.generateDocs(server, NUM_DOCS, "junit_role", "admin_role", EXTRA_AUTH_FIELDS); + DocLevelGenerator generator = new DocLevelGenerator(collectionName, AUTH_FIELD); + generator.generateDocs(cluster.getSolrClient(), NUM_DOCS, "junit_role", "admin_role", EXTRA_AUTH_FIELDS); - querySimple(new QueryRequest(new SolrQuery("*:*")), server, checkNonAdminUsers); - querySimple(getRealTimeGetRequest(), server, checkNonAdminUsers); - } finally { - server.shutdown(); - } + querySimple(collectionName, new QueryRequest(new SolrQuery("*:*")), cluster.getSolrClient(), checkNonAdminUsers); + querySimple(collectionName, getRealTimeGetRequest(), cluster.getSolrClient(), checkNonAdminUsers); } - private void querySimple(QueryRequest request, CloudSolrServer server, + private void querySimple(String collectionName, QueryRequest request, CloudSolrClient client, boolean checkNonAdminUsers) throws Exception { // as admin -- should get the other half setAuthenticationUser("admin"); - QueryResponse rsp = request.process(server); + QueryResponse rsp = request.process(client, collectionName); SolrDocumentList docList = rsp.getResults(); assertEquals(NUM_DOCS / 2, docList.getNumFound()); for (SolrDocument doc : docList) { String id = doc.getFieldValue("id").toString(); assertEquals(1, Long.valueOf(id) % 2); } - + if (checkNonAdminUsers) { // as junit -- should get half the documents setAuthenticationUser("junit"); - rsp = request.process(server); + rsp = request.process(client, collectionName); docList = rsp.getResults(); assertEquals(NUM_DOCS / 2, docList.getNumFound()); for (SolrDocument doc : docList) { @@ -143,8 +147,8 @@ public class TestDocLevelOperations extends AbstractSolrSentryTestBase { } // as docLevel -- should get all - setAuthenticationUser("docLevel"); - rsp = request.process(server); + setAuthenticationUser("doclevel"); + rsp = request.process(client, collectionName); assertEquals(NUM_DOCS, rsp.getResults().getNumFound()); } } @@ -155,38 +159,31 @@ public class TestDocLevelOperations extends AbstractSolrSentryTestBase { @Test public void testDocLevelOperations() throws Exception { String collectionName = "docLevelCollection"; - setupCollectionWithDocSecurity(collectionName); - - try { - createDocsAndQuerySimple(collectionName, true); - CloudSolrServer server = getCloudSolrServer(collectionName); - try { - // test filter queries work as AND -- i.e. user can't avoid doc-level - // checks by prefixing their own filterQuery - setAuthenticationUser("junit"); - String fq = URLEncoder.encode(" {!raw f=" + AUTH_FIELD + " v=docLevel_role}", "UTF-8"); - String path = "/" + collectionName + "/select?q=*:*&fq="+fq; - String retValue = makeHttpRequest(server, "GET", path, null, null); - assertTrue(retValue.contains("numFound=\"" + NUM_DOCS / 2 + "\" ")); - - // test that user can't inject an "OR" into the query - final String syntaxErrorMsg = "org.apache.solr.search.SyntaxError: Cannot parse"; - fq = URLEncoder.encode(" {!raw f=" + AUTH_FIELD + " v=docLevel_role} OR ", "UTF-8"); - path = "/" + collectionName + "/select?q=*:*&fq="+fq; - retValue = makeHttpRequest(server, "GET", path, null, null); - assertTrue(retValue.contains(syntaxErrorMsg)); - - // same test, prefix OR this time - fq = URLEncoder.encode(" OR {!raw f=" + AUTH_FIELD + " v=docLevel_role}", "UTF-8"); - path = "/" + collectionName + "/select?q=*:*&fq="+fq; - retValue = makeHttpRequest(server, "GET", path, null, null); - assertTrue(retValue.contains(syntaxErrorMsg)); - } finally { - server.shutdown(); - } - } finally { - deleteCollection(collectionName); - } + createCollection(ADMIN_USER, collectionName, "cloud-minimal_doc_level_security", NUM_SERVERS, 1); + + CloudSolrClient client = cluster.getSolrClient(); + createDocsAndQuerySimple(collectionName, true); + + // test filter queries work as AND -- i.e. user can't avoid doc-level + // checks by prefixing their own filterQuery + setAuthenticationUser("junit"); + String fq = URLEncoder.encode(" {!raw f=" + AUTH_FIELD + " v=doclevel_role}"); + String path = "/" + collectionName + "/select?q=*:*&fq="+fq; + String retValue = makeHttpRequest(client, "GET", path, null, null, HttpServletResponse.SC_OK); + assertTrue("Result : " + retValue, retValue.contains("\"numFound\":" + NUM_DOCS / 2)); + + // test that user can't inject an "OR" into the query + final String syntaxErrorMsg = "org.apache.solr.search.SyntaxError: Cannot parse"; + fq = URLEncoder.encode(" {!raw f=" + AUTH_FIELD + " v=docLevel_role} OR "); + path = "/" + collectionName + "/select?q=*:*&fq="+fq; + retValue = makeHttpRequest(client, "GET", path, null, null, HttpServletResponse.SC_BAD_REQUEST); + assertTrue(retValue.contains(syntaxErrorMsg)); + + // same test, prefix OR this time + fq = URLEncoder.encode(" OR {!raw f=" + AUTH_FIELD + " v=docLevel_role}"); + path = "/" + collectionName + "/select?q=*:*&fq="+fq; + retValue = makeHttpRequest(client, "GET", path, null, null, HttpServletResponse.SC_BAD_REQUEST); + assertTrue(retValue.contains(syntaxErrorMsg)); } /** @@ -196,67 +193,57 @@ public class TestDocLevelOperations extends AbstractSolrSentryTestBase { @Test public void testAllRolesToken() throws Exception { String collectionName = "allRolesCollection"; - setupCollectionWithDocSecurity(collectionName); - - - try { - String allRolesToken = "OR"; - int junitFactor = 2; - int allRolesFactor = 5; - - int totalJunitAdded = 0; // total docs added with junit token - int totalAllRolesAdded = 0; // total number of docs with the allRolesToken - int totalOnlyAllRolesAdded = 0; // total number of docs with _only_ the allRolesToken - - // create documents - ArrayList<SolrInputDocument> docs = new ArrayList<SolrInputDocument>(); - for (int i = 0; i < NUM_DOCS; ++i) { - boolean addedViaJunit = false; - SolrInputDocument doc = new SolrInputDocument(); - String iStr = Long.toString(i); - doc.addField("id", iStr); - doc.addField("description", "description" + iStr); - - if (i % junitFactor == 0) { - doc.addField(AUTH_FIELD, "junit_role"); - addedViaJunit = true; - ++totalJunitAdded; - } if (i % allRolesFactor == 0) { - doc.addField(AUTH_FIELD, allRolesToken); - ++totalAllRolesAdded; - if (!addedViaJunit) { - ++totalOnlyAllRolesAdded; - } + createCollection(ADMIN_USER, collectionName, "cloud-minimal_doc_level_security", NUM_SERVERS, 1); + + String allRolesToken = "OR"; + int junitFactor = 2; + int allRolesFactor = 5; + + int totalJunitAdded = 0; // total docs added with junit token + int totalAllRolesAdded = 0; // total number of docs with the allRolesToken + int totalOnlyAllRolesAdded = 0; // total number of docs with _only_ the allRolesToken + + // create documents + ArrayList<SolrInputDocument> docs = new ArrayList<SolrInputDocument>(); + for (int i = 0; i < NUM_DOCS; ++i) { + boolean addedViaJunit = false; + SolrInputDocument doc = new SolrInputDocument(); + String iStr = Long.toString(i); + doc.addField("id", iStr); + doc.addField("description", "description" + iStr); + + if (i % junitFactor == 0) { + doc.addField(AUTH_FIELD, "junit_role"); + addedViaJunit = true; + ++totalJunitAdded; + } if (i % allRolesFactor == 0) { + doc.addField(AUTH_FIELD, allRolesToken); + ++totalAllRolesAdded; + if (!addedViaJunit) { + ++totalOnlyAllRolesAdded; } - docs.add(doc); - } - // make sure our factors give us interesting results -- - // that some docs only have all roles and some only have junit - assert(totalOnlyAllRolesAdded > 0); - assert(totalJunitAdded > totalAllRolesAdded); - - CloudSolrServer server = getCloudSolrServer(collectionName); - try { - server.add(docs); - server.commit(true, true); - - checkAllRolesToken(new QueryRequest(new SolrQuery("*:*")), server, - totalAllRolesAdded, totalOnlyAllRolesAdded, allRolesFactor, totalJunitAdded, junitFactor); - checkAllRolesToken(getRealTimeGetRequest(), server, - totalAllRolesAdded, totalOnlyAllRolesAdded, allRolesFactor, totalJunitAdded, junitFactor); - } finally { - server.shutdown(); } - } finally { - deleteCollection(collectionName); + docs.add(doc); } + // make sure our factors give us interesting results -- + // that some docs only have all roles and some only have junit + assert(totalOnlyAllRolesAdded > 0); + assert(totalJunitAdded > totalAllRolesAdded); + + cluster.getSolrClient().add(collectionName, docs); + cluster.getSolrClient().commit(collectionName, true, true); + + checkAllRolesToken(collectionName, new QueryRequest(new SolrQuery("*:*")), cluster.getSolrClient(), + totalAllRolesAdded, totalOnlyAllRolesAdded, allRolesFactor, totalJunitAdded, junitFactor); + checkAllRolesToken(collectionName, getRealTimeGetRequest(), cluster.getSolrClient(), + totalAllRolesAdded, totalOnlyAllRolesAdded, allRolesFactor, totalJunitAdded, junitFactor); } - private void checkAllRolesToken(QueryRequest request, CloudSolrServer server, + private void checkAllRolesToken(String collectionName, QueryRequest request, CloudSolrClient client, int totalAllRolesAdded, int totalOnlyAllRolesAdded, int allRolesFactor, int totalJunitAdded, int junitFactor) throws Exception { // as admin -- should only get all roles token documents setAuthenticationUser("admin"); - QueryResponse rsp = request.process(server); + QueryResponse rsp = request.process(client, collectionName); SolrDocumentList docList = rsp.getResults(); assertEquals(totalAllRolesAdded, docList.getNumFound()); for (SolrDocument doc : docList) { @@ -266,7 +253,7 @@ public class TestDocLevelOperations extends AbstractSolrSentryTestBase { // as junit -- should get junit added + onlyAllRolesAdded setAuthenticationUser("junit"); - rsp = request.process(server); + rsp = request.process(client, collectionName); docList = rsp.getResults(); assertEquals(totalJunitAdded + totalOnlyAllRolesAdded, docList.getNumFound()); for (SolrDocument doc : docList) { @@ -285,122 +272,106 @@ public class TestDocLevelOperations extends AbstractSolrSentryTestBase { private void deleteByQueryTest(String collectionName, String deleteUser, String deleteByQueryStr, String queryUser, int expectedQueryDocs) throws Exception { createDocsAndQuerySimple(collectionName, true); - CloudSolrServer server = getCloudSolrServer(collectionName); - try { - setAuthenticationUser(deleteUser); - server.deleteByQuery(deleteByQueryStr); - server.commit(); - - checkDeleteByQuery(new QueryRequest(new SolrQuery("*:*")), server, - queryUser, expectedQueryDocs); - checkDeleteByQuery(getRealTimeGetRequest(), server, - queryUser, expectedQueryDocs); - } finally { - server.shutdown(); - } + setAuthenticationUser(deleteUser); + cluster.getSolrClient().deleteByQuery(collectionName, deleteByQueryStr); + cluster.getSolrClient().commit(collectionName); + + checkDeleteByQuery(collectionName, new QueryRequest(new SolrQuery("*:*")), cluster.getSolrClient(), + queryUser, expectedQueryDocs); + checkDeleteByQuery(collectionName, getRealTimeGetRequest(), cluster.getSolrClient(), + queryUser, expectedQueryDocs); } - private void checkDeleteByQuery(QueryRequest query, CloudSolrServer server, + private void checkDeleteByQuery(String collectionName, QueryRequest query, CloudSolrClient server, String queryUser, int expectedQueryDocs) throws Exception { - QueryResponse rsp = query.process(server); + QueryResponse rsp = query.process(server, collectionName); long junitResults = rsp.getResults().getNumFound(); assertEquals(0, junitResults); setAuthenticationUser(queryUser); - rsp = query.process(server); + rsp = query.process(server, collectionName); long docLevelResults = rsp.getResults().getNumFound(); assertEquals(expectedQueryDocs, docLevelResults); } private void deleteByIdTest(String collectionName) throws Exception { createDocsAndQuerySimple(collectionName, true); - CloudSolrServer server = getCloudSolrServer(collectionName); - try { - setAuthenticationUser("junit"); - List<String> allIds = new ArrayList<String>(NUM_DOCS); - for (int i = 0; i < NUM_DOCS; ++i) { - allIds.add(Long.toString(i)); - } - server.deleteById(allIds); - server.commit(); - - checkDeleteById(new QueryRequest(new SolrQuery("*:*")), server); - checkDeleteById(getRealTimeGetRequest(), server); - } finally { - server.shutdown(); + setAuthenticationUser("junit"); + List<String> allIds = new ArrayList<String>(NUM_DOCS); + for (int i = 0; i < NUM_DOCS; ++i) { + allIds.add(Long.toString(i)); } + cluster.getSolrClient().deleteById(collectionName, allIds); + cluster.getSolrClient().commit(collectionName); + + checkDeleteById(collectionName, new QueryRequest(new SolrQuery("*:*")), cluster.getSolrClient()); + checkDeleteById(collectionName, getRealTimeGetRequest(), cluster.getSolrClient()); + } - private void checkDeleteById(QueryRequest request, CloudSolrServer server) + private void checkDeleteById(String collectionName, QueryRequest request, CloudSolrClient server) throws Exception { - QueryResponse rsp = request.process(server); + QueryResponse rsp = request.process(server, collectionName); long junitResults = rsp.getResults().getNumFound(); assertEquals(0, junitResults); - setAuthenticationUser("docLevel"); - rsp = request.process(server); + setAuthenticationUser("doclevel"); + rsp = request.process(server, collectionName); long docLevelResults = rsp.getResults().getNumFound(); assertEquals(0, docLevelResults); } private void updateDocsTest(String collectionName) throws Exception { createDocsAndQuerySimple(collectionName, true); - CloudSolrServer server = getCloudSolrServer(collectionName); - try { - setAuthenticationUser("junit"); - String docIdStr = Long.toString(1); - - // verify we can't view one of the odd documents - QueryRequest query = new QueryRequest(new SolrQuery("id:"+docIdStr)); - QueryRequest rtgQuery = getRealTimeGetRequest(docIdStr); - checkUpdateDocsQuery(query, server, 0); - checkUpdateDocsQuery(rtgQuery, server, 0); + setAuthenticationUser("junit"); + String docIdStr = Long.toString(1); + + // verify we can't view one of the odd documents + QueryRequest query = new QueryRequest(new SolrQuery("id:"+docIdStr)); + QueryRequest rtgQuery = getRealTimeGetRequest(docIdStr); + checkUpdateDocsQuery(collectionName, query, cluster.getSolrClient(), 0); + checkUpdateDocsQuery(collectionName, rtgQuery, cluster.getSolrClient(), 0); + + // overwrite the document that we can't see + ArrayList<SolrInputDocument> docs = new ArrayList<SolrInputDocument>(); + SolrInputDocument doc = new SolrInputDocument(); + doc.addField("id", docIdStr); + doc.addField("description", "description" + docIdStr); + doc.addField(AUTH_FIELD, "junit_role"); + docs.add(doc); + cluster.getSolrClient().add(collectionName, docs); + cluster.getSolrClient().commit(collectionName); + + // verify we can now view the document + checkUpdateDocsQuery(collectionName, query, cluster.getSolrClient(), 1); + checkUpdateDocsQuery(collectionName, rtgQuery, cluster.getSolrClient(), 1); - // overwrite the document that we can't see - ArrayList<SolrInputDocument> docs = new ArrayList<SolrInputDocument>(); - SolrInputDocument doc = new SolrInputDocument(); - doc.addField("id", docIdStr); - doc.addField("description", "description" + docIdStr); - doc.addField(AUTH_FIELD, "junit_role"); - docs.add(doc); - server.add(docs); - server.commit(); - - // verify we can now view the document - checkUpdateDocsQuery(query, server, 1); - checkUpdateDocsQuery(rtgQuery, server, 1); - } finally { - server.shutdown(); - } } - private void checkUpdateDocsQuery(QueryRequest request, CloudSolrServer server, int expectedDocs) + private void checkUpdateDocsQuery(String collectionName, QueryRequest request, CloudSolrClient server, int expectedDocs) throws Exception { - QueryResponse rsp = request.process(server); + QueryResponse rsp = request.process(server, collectionName); assertEquals(expectedDocs, rsp.getResults().getNumFound()); } @Test public void testUpdateDeleteOperations() throws Exception { String collectionName = "testUpdateDeleteOperations"; + createCollection(ADMIN_USER, collectionName, "cloud-minimal_doc_level_security", NUM_SERVERS, 1); - setupCollectionWithDocSecurity(collectionName); - try { - createDocsAndQuerySimple(collectionName, true); + createDocsAndQuerySimple(collectionName, true); - // test deleteByQuery "*:*" - deleteByQueryTest(collectionName, "junit", "*:*", "docLevel", 0); + // test deleteByQuery "*:*" + deleteByQueryTest(collectionName, "junit", "*:*", "doclevel", 0); - // test deleteByQuery non-*:* - deleteByQueryTest(collectionName, "junit", "sentry_auth:docLevel_role", "docLevel", 0); + // test deleteByQuery non-*:* + deleteByQueryTest(collectionName, "junit", "sentry_auth:doclevel_role", "doclevel", 0); - // test deleting all documents by Id - deleteByIdTest(collectionName); + // test deleting all documents by Id + deleteByIdTest(collectionName); + + updateDocsTest(collectionName); - updateDocsTest(collectionName); - } finally { - deleteCollection(collectionName); - } } /** @@ -410,19 +381,14 @@ public class TestDocLevelOperations extends AbstractSolrSentryTestBase { @Test public void indexDocAuthTests() throws Exception { String collectionName = "testIndexlevelDoclevelOperations"; + createCollection(ADMIN_USER, collectionName, "cloud-minimal_doc_level_security", NUM_SERVERS, 1); - setupCollectionWithDocSecurity(collectionName); - try { - createDocsAndQuerySimple(collectionName, false); - - // test query for "*:*" fails as junit user (junit user doesn't have index level permissions but has doc level permissions set) - verifyQueryFail("junit", collectionName, ALL_DOCS); + createDocsAndQuerySimple(collectionName, false); - // test query for "*:*" fails as docLevel user (docLevel user has neither index level permissions nor doc level permissions set) - verifyQueryFail("docLevel", collectionName, ALL_DOCS); + // test query for "*:*" fails as junit user (junit user doesn't have index level permissions but has doc level permissions set) + verifyQueryFail("junit", collectionName, ALL_DOCS); - } finally { - deleteCollection(collectionName); - } + // test query for "*:*" fails as docLevel user (docLevel user has neither index level permissions nor doc level permissions set) + verifyQueryFail("doclevel", collectionName, ALL_DOCS); } }
http://git-wip-us.apache.org/repos/asf/sentry/blob/e62fa28d/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestQueryOperations.java ---------------------------------------------------------------------- diff --git a/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestQueryOperations.java b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestQueryOperations.java deleted file mode 100644 index f8ed955..0000000 --- a/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestQueryOperations.java +++ /dev/null @@ -1,78 +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 java.io.PrintWriter; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.apache.solr.common.SolrInputDocument; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.junit.Test; -import static org.junit.Assert.assertEquals; - -public class TestQueryOperations extends AbstractSolrSentryTestBase { - - private static final Logger LOG = LoggerFactory - .getLogger(TestQueryOperations.class); - private static final String COLLECTION_NAME = "sentryCollection"; - private static final List<Boolean> BOOLEAN_VALUES = Arrays.asList(new Boolean[]{true, false}); - private static final String DEFAULT_COLLECTION = "collection1"; - - @Test - public void testQueryOps() throws Exception { - // Upload configs to ZK - uploadConfigDirToZk(RESOURCES_DIR + File.separator + DEFAULT_COLLECTION - + File.separator + "conf"); - setupCollection(COLLECTION_NAME); - ArrayList<String> testFailures = new ArrayList<String>(); - - for (boolean query : BOOLEAN_VALUES) { - for (boolean update : BOOLEAN_VALUES) { - for (boolean all : BOOLEAN_VALUES) { - String test_user = getUsernameForPermissions(COLLECTION_NAME, query, update, all); - LOG.info("TEST_USER: " + test_user); - - try { - cleanSolrCollection(COLLECTION_NAME); - SolrInputDocument solrInputDoc = createSolrTestDoc(); - uploadSolrDoc(COLLECTION_NAME, solrInputDoc); - if (all || query) { - verifyQueryPass(test_user, COLLECTION_NAME, ALL_DOCS); - } else { - verifyQueryFail(test_user, COLLECTION_NAME, ALL_DOCS); - } - } catch (Throwable testException) { - StringWriter stringWriter = new StringWriter(); - PrintWriter printWriter = new PrintWriter(stringWriter); - testException.printStackTrace(printWriter); - testFailures.add("\n\nTestFailure: User -> " + test_user + "\n" - + stringWriter.toString()); - } - } - } - } - - assertEquals("Total test failures: " + testFailures.size() + " \n\n" - + testFailures.toString() + "\n\n\n", 0, testFailures.size()); - } -} http://git-wip-us.apache.org/repos/asf/sentry/blob/e62fa28d/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestRealTimeGet.java ---------------------------------------------------------------------- diff --git a/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestRealTimeGet.java b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestRealTimeGet.java deleted file mode 100644 index f9b6c07..0000000 --- a/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestRealTimeGet.java +++ /dev/null @@ -1,476 +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 org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.impl.CloudSolrServer; -import org.apache.solr.client.solrj.request.QueryRequest; -import org.apache.solr.client.solrj.response.QueryResponse; -import org.apache.solr.common.SolrDocument; -import org.apache.solr.common.SolrDocumentList; -import org.apache.solr.common.SolrInputDocument; -import org.apache.solr.common.params.CollectionParams.CollectionAction; -import org.apache.solr.common.params.ModifiableSolrParams; -import org.apache.solr.common.params.SolrParams; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import java.io.File; -import java.io.IOException; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Random; -import java.util.Set; - -public class TestRealTimeGet extends AbstractSolrSentryTestBase { - private static final String AUTH_FIELD = "sentry_auth"; - private static final Random rand = new Random(); - private String userName = null; - - @Before - public void beforeTest() throws Exception { - userName = getAuthenticatedUser(); - } - - @After - public void afterTest() throws Exception { - setAuthenticationUser(userName); - } - - private void setupCollectionWithDocSecurity(String name) throws Exception { - setupCollectionWithDocSecurity(name, 2); - } - - private void setupCollectionWithDocSecurity(String name, int shards) throws Exception { - String configDir = RESOURCES_DIR + File.separator + DEFAULT_COLLECTION - + File.separator + "conf"; - uploadConfigDirToZk(configDir, name); - // replace solrconfig.xml with solrconfig-doc-level.xml - uploadConfigFileToZk(configDir + File.separator + "solrconfig-doclevel.xml", - "solrconfig.xml", name); - ModifiableSolrParams modParams = new ModifiableSolrParams(); - modParams.set("numShards", shards); - StringBuilder builder = new StringBuilder(); - for (int i = 0; i < shards; ++i) { - if (i != 0) { - builder.append(","); - } - builder.append("shard").append(i+1); - } - modParams.set("shards", builder.toString()); - verifyCollectionAdminOpPass(ADMIN_USER, CollectionAction.CREATE, name, modParams); - } - - private void setupCollectionWithoutDocSecurity(String name) throws Exception { - String configDir = RESOURCES_DIR + File.separator + DEFAULT_COLLECTION - + File.separator + "conf"; - uploadConfigDirToZk(configDir, name); - setupCollection(name); - } - - private QueryRequest getRealTimeGetRequest(final SolrParams params) { - return new QueryRequest() { - @Override - public String getPath() { - return "/get"; - } - - @Override - public SolrParams getParams() { - return params; - } - }; - } - - private void assertExpected(ExpectedResult expectedResult, QueryResponse rsp, - QueryResponse controlRsp) throws Exception { - SolrDocumentList docList = rsp.getResults(); - SolrDocumentList controlDocList = controlRsp.getResults(); - SolrDocument doc = (SolrDocument)rsp.getResponse().get("doc"); - SolrDocument controlDoc = (SolrDocument)controlRsp.getResponse().get("doc"); - - if (expectedResult.expectedDocs == 0) { - // could be null rather than 0 size, check against control that format is identical - assertNull("Should be no doc present: " + doc, doc); - assertNull("Should be no doc present: " + controlDoc, controlDoc); - assertTrue((docList == null && controlDocList == null) || - (controlDocList.getNumFound() == 0)); - } else { - if (docList == null) { - assertNull(controlDocList); - assertNotNull(doc); - assertNotNull(controlDoc); - } else { - assertNotNull(controlDocList); - assertNull(doc); - assertNull(controlDoc); - assertEquals(expectedResult.expectedDocs, docList.getNumFound()); - assertEquals(docList.getNumFound(), controlDocList.getNumFound()); - } - } - } - - private QueryResponse getIdResponse(ExpectedResult expectedResult) throws Exception { - ModifiableSolrParams params = new ModifiableSolrParams(); - for (int i = 0; i < expectedResult.ids.length; ++i) { - params.add("id", expectedResult.ids[ i ]); - } - if (expectedResult.fl != null) { - params.add("fl", expectedResult.fl); - } - QueryRequest request = getRealTimeGetRequest(params); - return request.process(expectedResult.server); - } - - private QueryResponse getIdsResponse(ExpectedResult expectedResult) throws Exception { - StringBuilder builder = new StringBuilder(); - for (int i = 0; i < expectedResult.ids.length; ++i) { - if (i != 0) { - builder.append(","); - } - builder.append(expectedResult.ids[ i ]); - } - ModifiableSolrParams params = new ModifiableSolrParams(); - params.add("ids", builder.toString()); - if (expectedResult.fl != null) { - params.add("fl", expectedResult.fl); - } - QueryRequest request = getRealTimeGetRequest(params); - return request.process(expectedResult.server); - } - - private void assertIdVsIds(ExpectedResult expectedResult, ExpectedResult controlExpectedResult) - throws Exception { - // test specifying with "id" - QueryResponse idRsp = getIdResponse(expectedResult); - QueryResponse idControlRsp = getIdResponse(controlExpectedResult); - assertExpected(expectedResult, idRsp, idControlRsp); - - // test specifying with "ids" - QueryResponse idsRsp = getIdsResponse(expectedResult); - QueryResponse idsControlRsp = getIdsResponse(controlExpectedResult); - assertExpected(expectedResult, idsRsp, idsControlRsp); - } - - @Test - public void testIdvsIds() throws Exception { - final String collection = "testIdvsIds"; - final String collectionControl = collection + "Control"; - setupCollectionWithDocSecurity(collection); - setupCollectionWithoutDocSecurity(collectionControl); - CloudSolrServer server = getCloudSolrServer(collection); - CloudSolrServer serverControl = getCloudSolrServer(collectionControl); - - try { - for (CloudSolrServer s : new CloudSolrServer [] {server, serverControl}) { - DocLevelGenerator generator = new DocLevelGenerator(AUTH_FIELD); - generator.generateDocs(s, 100, "junit_role", "admin_role", 2); - } - - // check that control collection does not filter - assertIdVsIds(new ExpectedResult(serverControl, new String[] {"2"}, 1), - new ExpectedResult(serverControl, new String[] {"2"}, 1)); - - // single id - assertIdVsIds(new ExpectedResult(server, new String[] {"1"}, 1), - new ExpectedResult(serverControl, new String[] {"1"}, 1)); - - // single id (invalid) - assertIdVsIds(new ExpectedResult(server, new String[] {"bogusId"}, 0), - new ExpectedResult(serverControl, new String[] {"bogusId"}, 0)); - - // single id (no permission) - assertIdVsIds(new ExpectedResult(server, new String[] {"2"}, 0), - new ExpectedResult(serverControl, new String[] {"2fake"}, 0)); - - // multiple ids (some invalid, some valid, some no permission) - assertIdVsIds(new ExpectedResult(server, new String[] {"bogus1", "1", "2"}, 1), - new ExpectedResult(serverControl, new String[] {"bogus1", "1", "bogus2"}, 1)); - assertIdVsIds(new ExpectedResult(server, new String[] {"bogus1", "1", "2", "3"}, 2), - new ExpectedResult(serverControl, new String[] {"bogus1", "1", "bogus2", "3"}, 2)); - - // multiple ids (all invalid) - assertIdVsIds(new ExpectedResult(server, new String[] {"bogus1", "bogus2", "bogus3"}, 0), - new ExpectedResult(serverControl, new String[] {"bogus1", "bogus2", "bogus3"}, 0)); - - // multiple ids (all no permission) - assertIdVsIds(new ExpectedResult(server, new String[] {"2", "4", "6"}, 0), - new ExpectedResult(serverControl, new String[] {"bogus2", "bogus4", "bogus6"}, 0)); - - } finally { - server.shutdown(); - serverControl.shutdown(); - } - } - - private void assertFlOnDocList(SolrDocumentList list, Set<String> expectedIds, - List<String> expectedFields) { - assertEquals("Doc list size should be: " + expectedIds.size(), expectedIds.size(), list.getNumFound()); - for (SolrDocument doc : list) { - expectedIds.contains(doc.get("id")); - for (String field : expectedFields) { - assertNotNull("Field: " + field + " should not be null in doc: " + doc, doc.get(field)); - } - assertEquals("doc should have: " + expectedFields.size() + " fields. Doc: " + doc, - expectedFields.size(), doc.getFieldNames().size()); - } - } - - private void assertFl(CloudSolrServer server, String [] ids, Set<String> expectedIds, - String fl, List<String> expectedFields) throws Exception { - { - QueryResponse idRsp = getIdResponse(new ExpectedResult(server, ids, expectedIds.size(), fl)); - SolrDocumentList idList = idRsp.getResults(); - assertFlOnDocList(idList, expectedIds, expectedFields); - } - { - QueryResponse idsRsp = getIdsResponse(new ExpectedResult(server, ids, expectedIds.size(), fl)); - SolrDocumentList idsList = idsRsp.getResults(); - assertFlOnDocList(idsList, expectedIds, expectedFields); - } - } - - @Test - public void testFl() throws Exception { - final String collection = "testFl"; - // FixMe: have to use one shard, because of a Solr bug where "fl" is not applied to - // multi-shard get requests - setupCollectionWithDocSecurity(collection, 1); - CloudSolrServer server = getCloudSolrServer(collection); - - try { - DocLevelGenerator generator = new DocLevelGenerator(AUTH_FIELD); - generator.generateDocs(server, 100, "junit_role", "admin_role", 2); - String [] ids = new String[] {"1", "3", "5"}; - - assertFl(server, ids, new HashSet<String>(Arrays.asList(ids)), "id", Arrays.asList("id")); - assertFl(server, ids, new HashSet<String>(Arrays.asList(ids)), null, Arrays.asList("id", "description", "_version_")); - // test transformer - assertFl(server, ids, new HashSet<String>(Arrays.asList(ids)), "id,mydescription:description", Arrays.asList("id", "mydescription")); - } finally { - server.shutdown(); - } - } - - @Test - public void testNonCommitted() throws Exception { - final String collection = "testNonCommitted"; - setupCollectionWithDocSecurity(collection, 1); - CloudSolrServer server = getCloudSolrServer(collection); - - try { - DocLevelGenerator generator = new DocLevelGenerator(AUTH_FIELD); - generator.generateDocs(server, 100, "junit_role", "admin_role", 2); - - // make some uncommitted modifications and ensure they are reflected - server.deleteById("1"); - - SolrInputDocument doc2 = new SolrInputDocument(); - doc2.addField("id", "2"); - doc2.addField("description", "description2"); - doc2.addField(AUTH_FIELD, "admin_role"); - - SolrInputDocument doc3 = new SolrInputDocument(); - doc3.addField("id", "3"); - doc3.addField("description", "description3"); - doc3.addField(AUTH_FIELD, "junit_role"); - - SolrInputDocument doc200 = new SolrInputDocument(); - doc200.addField("id", "200"); - doc200.addField("description", "description200"); - doc200.addField(AUTH_FIELD, "admin_role"); - server.add(Arrays.asList(new SolrInputDocument [] {doc2, doc3, doc200})); - - assertFl(server, new String[] {"1", "2", "3", "4", "5", "200"}, - new HashSet<String>(Arrays.asList("2", "5", "200")), "id", Arrays.asList("id")); - } finally { - server.shutdown(); - } - } - - private void assertConcurrentOnDocList(SolrDocumentList list, String authField, String expectedAuthFieldValue) { - for (SolrDocument doc : list) { - Collection<Object> authFieldValues = doc.getFieldValues(authField); - assertNotNull(authField + " should not be null. Doc: " + doc, authFieldValues); - - boolean foundAuthFieldValue = false; - for (Object obj : authFieldValues) { - if (obj.toString().equals(expectedAuthFieldValue)) { - foundAuthFieldValue = true; - break; - } - } - assertTrue("Did not find: " + expectedAuthFieldValue + " in doc: " + doc, foundAuthFieldValue); - } - } - - private void assertConcurrent(CloudSolrServer server, String [] ids, String authField, String expectedAuthFieldValue) - throws Exception { - { - QueryResponse idRsp = getIdResponse(new ExpectedResult(server, ids, -1, null)); - SolrDocumentList idList = idRsp.getResults(); - assertConcurrentOnDocList(idList, authField, expectedAuthFieldValue); - } - { - QueryResponse idsRsp = getIdsResponse(new ExpectedResult(server, ids, -1, null)); - SolrDocumentList idsList = idsRsp.getResults(); - assertConcurrentOnDocList(idsList, authField, expectedAuthFieldValue); - } - } - - @Test - public void testConcurrentChanges() throws Exception { - final String collection = "testConcurrentChanges"; - // Ensure the auth field is stored so we can check a consistent doc is returned - final String authField = "sentry_auth_stored"; - System.setProperty("sentry.auth.field", authField); - setupCollectionWithDocSecurity(collection, 1); - CloudSolrServer server = getCloudSolrServer(collection); - int numQueries = 5; - - try { - DocLevelGenerator generator = new DocLevelGenerator(authField); - generator.generateDocs(server, 100, "junit_role", "admin_role", 2); - - List<AuthFieldModifyThread> threads = new LinkedList<AuthFieldModifyThread>(); - int docsToModify = 10; - for (int i = 0; i < docsToModify; ++i) { - SolrInputDocument doc = new SolrInputDocument(); - doc.addField("id", Integer.toString(i)); - doc.addField("description", "description" + Integer.toString(i)); - doc.addField(authField, "junit_role"); - server.add(doc); - - threads.add(new AuthFieldModifyThread(server, doc, - authField, "junit_role", "admin_role")); - } - server.commit(); - - for (AuthFieldModifyThread thread : threads) { - thread.start(); - } - - // query - String [] ids = new String[docsToModify]; - for (int j = 0; j < ids.length; ++j) { - ids[ j ] = Integer.toString(j); - } - for (int k = 0; k < numQueries; ++k) { - assertConcurrent(server, ids, authField, "admin_role"); - } - - for (AuthFieldModifyThread thread : threads) { - thread.setFinished(); - thread.join(); - } - } finally { - System.clearProperty("sentry.auth.field"); - server.shutdown(); - } - } - - @Test - public void testSuperUser() throws Exception { - final String collection = "testSuperUser"; - setupCollectionWithDocSecurity(collection, 1); - CloudSolrServer server = getCloudSolrServer(collection); - int docCount = 100; - - try { - DocLevelGenerator generator = new DocLevelGenerator(AUTH_FIELD); - generator.generateDocs(server, docCount, "junit_role", "admin_role", 2); - - setAuthenticationUser("solr"); - String [] ids = new String[docCount]; - for (int i = 0; i < docCount; ++i) { - ids[ i ] = Integer.toString(i); - } - QueryResponse response = getIdResponse(new ExpectedResult(server, ids, docCount)); - assertEquals("Wrong number of documents", docCount, response.getResults().getNumFound()); - } finally { - server.shutdown(); - } - } - - private class AuthFieldModifyThread extends Thread { - private CloudSolrServer server; - private SolrInputDocument doc; - private String authField; - private String authFieldValue0; - private String authFieldValue1; - private volatile boolean finished = false; - - private AuthFieldModifyThread(CloudSolrServer server, - SolrInputDocument doc, String authField, - String authFieldValue0, String authFieldValue1) { - this.server = server; - this.doc = doc; - this.authField = authField; - this.authFieldValue0 = authFieldValue0; - this.authFieldValue1 = authFieldValue1; - } - - @Override - public void run() { - while (!finished) { - if (rand.nextBoolean()) { - doc.setField(authField, authFieldValue0); - } else { - doc.setField(authField, authFieldValue1); - } - try { - server.add(doc); - } catch (SolrServerException sse) { - throw new RuntimeException(sse); - } catch (IOException ioe) { - throw new RuntimeException(ioe); - } - } - } - - public void setFinished() { - finished = true; - } - } - - private static class ExpectedResult { - public final CloudSolrServer server; - public final String [] ids; - public final int expectedDocs; - public final String fl; - - public ExpectedResult(CloudSolrServer server, String [] ids, int expectedDocs) { - this(server, ids, expectedDocs, null); - } - - public ExpectedResult(CloudSolrServer server, String [] ids, int expectedDocs, String fl) { - this.server = server; - this.ids = ids; - this.expectedDocs = expectedDocs; - this.fl = fl; - } - } -} http://git-wip-us.apache.org/repos/asf/sentry/blob/e62fa28d/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSentryServer.java ---------------------------------------------------------------------- diff --git a/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSentryServer.java b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSentryServer.java new file mode 100644 index 0000000..ff55790 --- /dev/null +++ b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSentryServer.java @@ -0,0 +1,144 @@ +/* + * 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.Closeable; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.Path; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.net.NetUtils; +import org.apache.sentry.provider.db.generic.SentryGenericProviderBackend; +import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClient; +import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClientFactory; +import org.apache.sentry.provider.file.LocalGroupResourceAuthorizationProvider; +import org.apache.sentry.provider.file.PolicyFile; +import org.apache.sentry.service.thrift.SentryService; +import org.apache.sentry.service.thrift.SentryServiceFactory; +import org.apache.sentry.service.thrift.ServiceConstants.ClientConfig; +import org.apache.sentry.service.thrift.ServiceConstants.ServerConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.apache.sentry.binding.solr.conf.SolrAuthzConf.AuthzConfVars; + +public class TestSentryServer implements Closeable { + private static final Logger log = LoggerFactory.getLogger(TestSentryServer.class); + + protected static final String SERVER_HOST = + NetUtils.createSocketAddr("localhost:80").getAddress().getCanonicalHostName(); + protected static final int PORT = 8038; + protected static final String ADMIN_GROUP = "admin_group"; + static final String ADMIN_USER = "admin"; + + private final Path dbDir; + private final Path policyFilePath; + private final Path sentrySitePath; + private final Configuration clientConf; + private final SentryService sentryService; + + public TestSentryServer(Path testDir, Map<String, Set<String>> groupsByUserName) throws Exception { + this.dbDir = testDir.resolve("sentry_policy_db"); + this.policyFilePath = testDir.resolve("local_policy_file.ini"); + this.sentrySitePath = testDir.resolve("sentry-site.xml"); + this.sentryService = new SentryServiceFactory().create(getServerConfig()); + this.clientConf = getClientConfig(); + // Write sentry-site.xml + this.clientConf.writeXml(new FileOutputStream(this.sentrySitePath.toFile())); + // Write sentry policy file (for storing user-group mappings). + PolicyFile policyFile = new PolicyFile(); + for (Map.Entry<String, Set<String>> userGroupMapping : groupsByUserName.entrySet()) { + String userName = userGroupMapping.getKey(); + for (String groupName : userGroupMapping.getValue()) { + log.info("Configuring user-group mapping with userName : {} group: {}", userName, groupName); + policyFile.addGroupsToUser(userName, groupName); + } + } + + policyFile.write(this.policyFilePath.toFile()); + } + + public SentryService getSentryService() { + return sentryService; + } + + public Path getSentrySitePath() { + return sentrySitePath; + } + + public void startSentryService() throws Exception { + sentryService.start(); + final long start = System.nanoTime(); + while(!sentryService.isRunning()) { + Thread.sleep(1000); + if (TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - start) > 60) { + throw new TimeoutException("Server did not start after 60 seconds"); + } + } + } + + public SentryGenericServiceClient connectToSentryService() throws Exception { + return SentryGenericServiceClientFactory.create(this.clientConf); + } + + @Override + public void close() throws IOException { + if (this.sentryService != null) { + try { + this.sentryService.stop(); + } catch (Exception e) { + throw new IOException(e); + } + } + } + + private Configuration getServerConfig () { + Configuration conf = new Configuration(false); + conf.set(ServerConfig.SECURITY_MODE, ServerConfig.SECURITY_MODE_NONE); + conf.set(ServerConfig.SENTRY_VERIFY_SCHEM_VERSION, "false"); + conf.set(ServerConfig.ADMIN_GROUPS, ADMIN_GROUP + ",solr"); + conf.set(ServerConfig.RPC_ADDRESS, SERVER_HOST); + conf.set(ServerConfig.RPC_PORT, String.valueOf(PORT)); + conf.set(ServerConfig.SENTRY_STORE_JDBC_URL, + "jdbc:derby:;databaseName=" + dbDir + ";create=true"); + conf.set(ServerConfig.SENTRY_STORE_JDBC_PASS, "dummy"); + conf.set(ServerConfig.SENTRY_STORE_GROUP_MAPPING, + ServerConfig.SENTRY_STORE_LOCAL_GROUP_MAPPING); + conf.set(ServerConfig.SENTRY_STORE_GROUP_MAPPING_RESOURCE, + policyFilePath.toString()); + return conf; + } + + private Configuration getClientConfig() { + Configuration conf = new Configuration(false); + conf.set(ServerConfig.SECURITY_MODE, ServerConfig.SECURITY_MODE_NONE); + conf.set(ClientConfig.SERVER_RPC_ADDRESS, sentryService.getAddress().getHostName()); + conf.set(ClientConfig.SERVER_RPC_PORT, String.valueOf(sentryService.getAddress().getPort())); + conf.set(AuthzConfVars.AUTHZ_PROVIDER_BACKEND.getVar(), + SentryGenericProviderBackend.class.getName()); + conf.set("sentry.provider", + LocalGroupResourceAuthorizationProvider.class.getName()); + conf.set("sentry.solr.provider.resource", + policyFilePath.toString()); + return conf; + } +} http://git-wip-us.apache.org/repos/asf/sentry/blob/e62fa28d/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSolrAdminOperations.java ---------------------------------------------------------------------- diff --git a/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSolrAdminOperations.java b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSolrAdminOperations.java new file mode 100644 index 0000000..190b9d4 --- /dev/null +++ b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSolrAdminOperations.java @@ -0,0 +1,188 @@ +/* + * 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 static org.apache.sentry.tests.e2e.solr.TestSentryServer.ADMIN_USER; +import static org.apache.sentry.core.model.solr.AdminOperation.COLLECTIONS; + +import java.io.IOException; +import java.util.Map; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.sentry.core.model.solr.AdminOperation; +import org.apache.sentry.core.model.solr.SolrConstants; +import org.apache.solr.client.solrj.SolrServerException; +import org.apache.solr.client.solrj.impl.HttpSolrClient.RemoteSolrException; +import org.apache.solr.client.solrj.request.CollectionAdminRequest; +import org.apache.solr.client.solrj.request.CollectionAdminRequest.ClusterStatus; +import org.apache.solr.SolrTestCaseJ4.SuppressSSL; +import org.junit.Test; +import org.restlet.data.MediaType; +import org.restlet.resource.ClientResource; +import org.restlet.resource.ResourceException; + +@SuppressSSL +public class TestSolrAdminOperations extends AbstractSolrSentryTestCase { + + @Test + public void testQueryAdminOperation() throws Exception { + // Success. + adminQueryActionSuccess(ADMIN_USER); + // Failure + adminQueryActionFailure("user0"); + // Now grant admin privileges to user0 (i.e. role0) and verify the admin operations again. + grantAdminPrivileges(ADMIN_USER, "role0", COLLECTIONS.getName(), SolrConstants.ALL); + adminQueryActionSuccess("user0"); + // Now revoke admin update privileges from user0 (i.e. role0) and verify the admin operations again. + revokeAdminPrivileges(ADMIN_USER, "role0", COLLECTIONS.getName(), SolrConstants.UPDATE); + adminQueryActionSuccess("user0"); + // Now revoke admin query privileges from user0 (i.e. role0) and verify the admin operations again. + revokeAdminPrivileges(ADMIN_USER, "role0", COLLECTIONS.getName(), SolrConstants.QUERY); + adminQueryActionFailure("user0"); + } + + @Test + public void testUpdateAdminOperation() throws Exception { + String collectionName = "testUpdateAdminOperation"; + + // Success. + grantCollectionPrivileges(ADMIN_USER, ADMIN_ROLE, collectionName, SolrConstants.UPDATE); + adminUpdateActionSuccess(ADMIN_USER, collectionName); + + // Failure + adminUpdateActionFailure("user0", collectionName); + + // Now grant admin privileges role0 and verify the admin operations again. + grantAdminPrivileges(ADMIN_USER, "role0", COLLECTIONS.getName(), SolrConstants.ALL); + grantCollectionPrivileges(ADMIN_USER, "role0", collectionName, SolrConstants.UPDATE); + adminUpdateActionSuccess("user0", collectionName); + + // Now revoke admin query privileges from role0 and verify the admin operations again. + revokeAdminPrivileges(ADMIN_USER, "role0", COLLECTIONS.getName(), SolrConstants.QUERY); + adminUpdateActionSuccess(ADMIN_USER, collectionName); + + // Now revoke admin update privileges from role0 and verify the admin operations again. + revokeAdminPrivileges(ADMIN_USER, "role0", COLLECTIONS.getName(), SolrConstants.UPDATE); + adminUpdateActionFailure("user0", collectionName); + } + + @SuppressWarnings("rawtypes") + @Test + public void testMetricsQuerySuccess() throws Exception { + grantAdminPrivileges(ADMIN_USER, "role0", AdminOperation.METRICS.getName(), SolrConstants.QUERY); + + String tmp = getAuthenticatedUser(); + try { + setAuthenticationUser("user0"); + + String url = String.format("%s/admin/metrics?wt=json&group=jvm", + cluster.getJettySolrRunner(0).getBaseUrl().toString()); + ClientResource resource = new ClientResource(url); + Map result = readNestedElement(deserialize(resource.get(MediaType.APPLICATION_JSON)), "metrics"); + assertTrue(result.containsKey("solr.jvm")); + + } finally { + revokeAdminPrivileges(ADMIN_USER, "role0", AdminOperation.METRICS.getName(), SolrConstants.QUERY); + setAuthenticationUser(tmp); + } + } + + @Test + public void testMetricsQueryFailure() throws Exception { + String tmp = getAuthenticatedUser(); + try { + setAuthenticationUser("user1"); + + String url = String.format("%s/admin/metrics?wt=json", + cluster.getJettySolrRunner(0).getBaseUrl().toString()); + ClientResource resource = new ClientResource(url); + resource.get(MediaType.APPLICATION_JSON); + fail("This admin request should have failed with authorization error."); + + } catch (ResourceException ex) { + assertEquals(HttpServletResponse.SC_FORBIDDEN , ex.getStatus().getCode()); + } finally { + setAuthenticationUser(tmp); + } + } + + protected void adminQueryActionSuccess(String userName) throws SolrServerException, IOException { + String tmp = getAuthenticatedUser(); + try { + setAuthenticationUser(userName); + ClusterStatus clusterStatus = new ClusterStatus(); + assertEquals(0, clusterStatus.process(cluster.getSolrClient()).getStatus()); + + } finally { + setAuthenticationUser(tmp); + } + } + + protected void adminQueryActionFailure(String userName) throws SolrServerException, IOException { + String tmp = getAuthenticatedUser(); + try { + setAuthenticationUser(userName); + ClusterStatus clusterStatus = new ClusterStatus(); + clusterStatus.process(cluster.getSolrClient()); + fail("This admin request should have failed with authorization error."); + + } catch (RemoteSolrException ex) { + assertEquals(HttpServletResponse.SC_FORBIDDEN , ex.code()); + } finally { + setAuthenticationUser(tmp); + } + } + + protected void adminUpdateActionSuccess(String userName, String collectionName) + throws SolrServerException, IOException { + // Success. + String tmp = getAuthenticatedUser(); + try { + // Create collection. + setAuthenticationUser(userName); + CollectionAdminRequest.Create createCmd = + CollectionAdminRequest.createCollection(collectionName, "cloud-minimal", 1, NUM_SERVERS); + assertEquals(0, createCmd.process(cluster.getSolrClient()).getStatus()); + + // Delete collection. + CollectionAdminRequest.Delete delCmd = CollectionAdminRequest.deleteCollection(collectionName); + assertEquals(0, delCmd.process(cluster.getSolrClient()).getStatus()); + + } finally { + setAuthenticationUser(tmp); + } + } + + protected void adminUpdateActionFailure(String userName, String collectionName) + throws SolrServerException, IOException { + String tmp = getAuthenticatedUser(); + try { + setAuthenticationUser(userName); // This user doesn't have admin permissions + // Create collection. + CollectionAdminRequest.Create createCmd = + CollectionAdminRequest.createCollection(collectionName, "cloud-minimal", 1, NUM_SERVERS); + createCmd.process(cluster.getSolrClient()); + fail("This admin request should have failed with authorization error."); + + } catch (RemoteSolrException ex) { + assertEquals(HttpServletResponse.SC_FORBIDDEN , ex.code()); + } finally { + setAuthenticationUser(tmp); + } + } +} http://git-wip-us.apache.org/repos/asf/sentry/blob/e62fa28d/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSolrCollectionOperations.java ---------------------------------------------------------------------- diff --git a/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSolrCollectionOperations.java b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSolrCollectionOperations.java new file mode 100644 index 0000000..3d9faa0 --- /dev/null +++ b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSolrCollectionOperations.java @@ -0,0 +1,141 @@ +/* + * 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 static org.apache.sentry.tests.e2e.solr.TestSentryServer.ADMIN_USER; + +import java.io.IOException; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.sentry.core.model.solr.SolrConstants; +import org.apache.solr.client.solrj.SolrQuery; +import org.apache.solr.client.solrj.SolrServerException; +import org.apache.solr.client.solrj.impl.HttpSolrClient.RemoteSolrException; +import org.apache.solr.common.SolrDocument; +import org.apache.solr.common.SolrDocumentList; +import org.apache.solr.common.SolrInputDocument; +import org.apache.solr.common.SolrInputField; +import org.junit.Test; + + +public class TestSolrCollectionOperations extends AbstractSolrSentryTestCase { + + @Test + public void testQueryOperations() throws Exception { + String collectionName = "testCollectionQueryOps"; + + // Create collection as an admin user. + grantCollectionPrivileges(ADMIN_USER, ADMIN_ROLE, collectionName, SolrConstants.UPDATE); + createCollection(ADMIN_USER, collectionName, "cloud-minimal", NUM_SERVERS, 1); + + // Grant all privileges for the test collection to role0 + grantCollectionPrivileges(ADMIN_USER, "role0", collectionName, SolrConstants.ALL); + + cleanSolrCollection("user0", collectionName); + + SolrInputDocument solrInputDoc = createSolrTestDoc(); + uploadSolrDoc("user0", collectionName, solrInputDoc); + SolrDocumentList expectedDocs = expectedDocs(solrInputDoc); + + validateSolrDocCountAndContent(expectedDocs, + getSolrDocs("user0", collectionName, ALL_DOCS)); + + revokeCollectionPrivileges(ADMIN_USER, "role0", collectionName, SolrConstants.UPDATE); + validateSolrDocCountAndContent(expectedDocs, + getSolrDocs("user0", collectionName, ALL_DOCS)); + + revokeCollectionPrivileges(ADMIN_USER, "role0", collectionName, SolrConstants.QUERY); + verifyCollectionQueryFailure("user0", collectionName, ALL_DOCS); + + verifyCollectionQueryFailure("user1", collectionName, ALL_DOCS); + } + + @Test + public void testUpdateOperations() throws Exception { + String collectionName = "testCollectionUpdateOps"; + + // Create collection as an admin user. + grantCollectionPrivileges(ADMIN_USER, ADMIN_ROLE, collectionName, SolrConstants.UPDATE); + createCollection(ADMIN_USER, collectionName, "cloud-minimal", 1, NUM_SERVERS); + + // Grant all privileges for the test collection to role0 + grantCollectionPrivileges(ADMIN_USER, "role0", collectionName, SolrConstants.ALL); + + cleanSolrCollection("user0", collectionName); + + SolrInputDocument solrInputDoc = createSolrTestDoc(); + uploadSolrDoc("user0", collectionName, solrInputDoc); + SolrDocumentList expectedDocs = expectedDocs(solrInputDoc); + + validateSolrDocCountAndContent(expectedDocs, + getSolrDocs("user0", collectionName, ALL_DOCS)); + + verifyDeletedocsPass("user0", collectionName, false); + + revokeCollectionPrivileges(ADMIN_USER, "role0", collectionName, SolrConstants.ALL); + + verifyCollectionUpdateFailure("user0", collectionName, solrInputDoc); + verifyCollectionUpdateFailure("user1", collectionName, solrInputDoc); + } + + + protected void verifyCollectionUpdateFailure(String userName, String collectionName, + SolrInputDocument doc) throws SolrServerException, IOException { + String tmp = getAuthenticatedUser(); + try { + setAuthenticationUser(userName); + cluster.getSolrClient().add(collectionName, doc); + cluster.getSolrClient().commit(collectionName); + fail("This collection query request should have failed with authorization error."); + + } catch (RemoteSolrException ex) { + assertEquals(HttpServletResponse.SC_FORBIDDEN, ex.code()); + } finally { + setAuthenticationUser(tmp); + } + } + + protected void verifyCollectionQueryFailure(String userName, String collectionName, + String queryStr) throws SolrServerException, IOException { + String tmp = getAuthenticatedUser(); + try { + setAuthenticationUser(userName); + cluster.getSolrClient().query(collectionName, new SolrQuery(queryStr)); + fail("This collection query request should have failed with authorization error."); + + } catch (SolrServerException ex) { + assertTrue(ex.getRootCause() instanceof RemoteSolrException); + assertEquals(HttpServletResponse.SC_FORBIDDEN, ((RemoteSolrException)ex.getRootCause()).code()); + } finally { + setAuthenticationUser(tmp); + } + } + + protected SolrDocumentList expectedDocs(SolrInputDocument... docs) { + SolrDocumentList result = new SolrDocumentList(); + + for (SolrInputDocument doc : docs) { + SolrDocument r = new SolrDocument(); + for (SolrInputField field : doc) { + r.setField(field.getName(), field.getValue()); + } + result.add(r); + } + return result; + } +} http://git-wip-us.apache.org/repos/asf/sentry/blob/e62fa28d/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSolrConfigOperations.java ---------------------------------------------------------------------- diff --git a/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSolrConfigOperations.java b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSolrConfigOperations.java new file mode 100644 index 0000000..620825f --- /dev/null +++ b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSolrConfigOperations.java @@ -0,0 +1,232 @@ +/* + * 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 static org.apache.sentry.tests.e2e.solr.TestSentryServer.ADMIN_USER; + +import java.io.IOException; +import java.util.Map; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.sentry.core.model.solr.SolrConstants; +import org.apache.solr.SolrTestCaseJ4.SuppressSSL; +import org.apache.solr.client.solrj.SolrServerException; +import org.apache.solr.client.solrj.impl.HttpSolrClient.RemoteSolrException; +import org.apache.solr.client.solrj.request.ConfigSetAdminRequest; +import org.apache.solr.client.solrj.response.ConfigSetAdminResponse; +import org.junit.Test; +import org.restlet.data.MediaType; +import org.restlet.resource.ClientResource; +import org.restlet.resource.ResourceException; + +@SuppressSSL +public class TestSolrConfigOperations extends AbstractSolrSentryTestCase { + @Test + public void testConfigSetOperations() throws Exception { + grantConfigPrivileges(ADMIN_USER, "role0", "test", SolrConstants.UPDATE); + grantConfigPrivileges(ADMIN_USER, "role1", SolrConstants.ALL, SolrConstants.QUERY); + + configSetCreationSuccess("user0", "test", "cloud-minimal"); + + ConfigSetAdminResponse resp = configSetListSuccess("user1"); + assertEquals(2, resp.getResponse().size()); + + configSetDeleteSuccess("user0", "test"); + + configSetCreationFailure("user1", "test1", "cloud-minimal"); + configSetListFailure("user0"); + } + + @Test + public void testConfigOperations() throws Exception { + String collectionName = "testConfigOperations"; + + grantConfigPrivileges(ADMIN_USER, "role0", collectionName, SolrConstants.ALL); + grantConfigPrivileges(ADMIN_USER, "role1", SolrConstants.ALL, SolrConstants.QUERY); + + grantCollectionPrivileges(ADMIN_USER, ADMIN_ROLE, collectionName, SolrConstants.UPDATE); + createCollection(ADMIN_USER, collectionName, "cloud-minimal", NUM_SERVERS, 1); + + configReadSuccess("user1", collectionName); + configReadSuccess("user0", collectionName); + configUpdateSuccess("user0", collectionName); + + revokeConfigPrivileges(ADMIN_USER, "role0", collectionName, SolrConstants.QUERY); + configReadFailure ("user0", collectionName); + } + + @SuppressWarnings("rawtypes") + protected void configReadSuccess( String userName, String collectionName) + throws ResourceException, IOException { + String tmp = getAuthenticatedUser(); + try { + setAuthenticationUser(userName); + + Map result = queryHandlerConfig(collectionName, "/select"); + assertEquals("/select", (String)readNestedElement(result, + "config", "requestHandler", "/select", "name")); + assertEquals("solr.SearchHandler", (String)readNestedElement(result, + "config", "requestHandler", "/select", "class")); + assertEquals("explicit", (String)readNestedElement(result, + "config", "requestHandler", "/select", "defaults", "echoParams")); + + } finally { + setAuthenticationUser(tmp); + } + } + + protected void configReadFailure( String userName, String collectionName) + throws ResourceException, IOException { + String tmp = getAuthenticatedUser(); + try { + setAuthenticationUser(userName); + + queryHandlerConfig(collectionName, "/select"); + fail("This config query request should have failed with authorization error."); + + } catch (ResourceException ex) { + assertEquals(HttpServletResponse.SC_FORBIDDEN, ex.getStatus().getCode()); + } finally { + setAuthenticationUser(tmp); + } + } + + @SuppressWarnings("rawtypes") + protected void configUpdateSuccess( String userName, String collectionName) + throws ResourceException, IOException { + + String configToBeAdded = "{" + + "\"add-requesthandler\" : { " + + "\"name\": \"/mypath\"," + + "\"class\":\"solr.DumpRequestHandler\", " + + "\"defaults\":{ \"x\":\"y\" ,\"a\":\"b\"," + + " \"wt\":\"json\", \"indent\":true }," + + "\"useParams\":\"x\"}}"; + + String tmp = getAuthenticatedUser(); + try { + setAuthenticationUser(userName); + String url = String.format("%s/%s/config", + cluster.getJettySolrRunner(0).getBaseUrl().toString(), collectionName); + + ClientResource resource = new ClientResource(url); + Map updateResp = deserialize(resource.post(configToBeAdded, MediaType.APPLICATION_JSON)); + assertEquals(0, (long)readNestedElement(updateResp, "responseHeader", "status")); + + Map result = queryHandlerConfig(collectionName, "/mypath"); + assertEquals("/mypath", (String)readNestedElement(result, + "config", "requestHandler", "/mypath", "name")); + assertEquals("solr.DumpRequestHandler", (String)readNestedElement(result, + "config", "requestHandler", "/mypath", "class")); + assertEquals("y", (String)readNestedElement(result, + "config", "requestHandler", "/mypath", "defaults", "x")); + + } finally { + setAuthenticationUser(tmp); + } + } + + protected void configSetCreationSuccess(String userName, String configName, + String baseConfigSetName) throws SolrServerException, IOException { + String tmp = getAuthenticatedUser(); + try { + setAuthenticationUser(userName); + ConfigSetAdminRequest.Create create = new ConfigSetAdminRequest.Create(); + create.setBaseConfigSetName(baseConfigSetName); + create.setConfigSetName(configName); + assertEquals(0, create.process(cluster.getSolrClient()).getStatus()); + + } finally { + setAuthenticationUser(tmp); + } + } + + protected void configSetCreationFailure(String userName, String configName, + String baseConfigSetName) throws SolrServerException, IOException { + String tmp = getAuthenticatedUser(); + try { + setAuthenticationUser(userName); + ConfigSetAdminRequest.Create create = new ConfigSetAdminRequest.Create(); + create.setBaseConfigSetName(baseConfigSetName); + create.setConfigSetName(configName); + create.process(cluster.getSolrClient()); + fail("This config request should have failed with authorization error."); + + } catch (RemoteSolrException ex) { + assertEquals(HttpServletResponse.SC_FORBIDDEN , ex.code()); + } finally { + setAuthenticationUser(tmp); + } + } + + protected void configSetDeleteSuccess(String userName, String configName) + throws SolrServerException, IOException { + String tmp = getAuthenticatedUser(); + try { + setAuthenticationUser(userName); + ConfigSetAdminRequest.Delete delete = new ConfigSetAdminRequest.Delete(); + delete.setConfigSetName(configName); + assertEquals(0, delete.process(cluster.getSolrClient()).getStatus()); + + } finally { + setAuthenticationUser(tmp); + } + } + + protected ConfigSetAdminResponse configSetListSuccess(String userName) + throws SolrServerException, IOException { + String tmp = getAuthenticatedUser(); + try { + setAuthenticationUser(userName); + ConfigSetAdminRequest.List list = new ConfigSetAdminRequest.List(); + ConfigSetAdminResponse resp = list.process(cluster.getSolrClient()); + assertEquals(0, resp.getStatus()); + return resp; + + } finally { + setAuthenticationUser(tmp); + } + } + + protected void configSetListFailure(String userName) + throws SolrServerException, IOException { + String tmp = getAuthenticatedUser(); + try { + setAuthenticationUser(userName); + ConfigSetAdminRequest.List list = new ConfigSetAdminRequest.List(); + list.process(cluster.getSolrClient()); + fail("This config request should have failed with authorization error."); + + } catch (RemoteSolrException ex) { + assertEquals(HttpServletResponse.SC_FORBIDDEN , ex.code()); + } finally { + setAuthenticationUser(tmp); + } + } + + @SuppressWarnings("rawtypes") + protected Map queryHandlerConfig(String collectionName, String handlerPath) throws ResourceException, IOException { + String url = String.format("%s/%s/config/requestHandler?componentName=%s", + cluster.getJettySolrRunner(0).getBaseUrl().toString(), collectionName, handlerPath); + + Map result = deserialize(new ClientResource(url).get()); + assertEquals(0, (long)readNestedElement(result, "responseHeader", "status")); + + return result; + } +} http://git-wip-us.apache.org/repos/asf/sentry/blob/e62fa28d/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSolrSchemaOperations.java ---------------------------------------------------------------------- diff --git a/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSolrSchemaOperations.java b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSolrSchemaOperations.java new file mode 100644 index 0000000..1169b54 --- /dev/null +++ b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSolrSchemaOperations.java @@ -0,0 +1,146 @@ +/* + * 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 static org.apache.sentry.tests.e2e.solr.TestSentryServer.ADMIN_USER; + +import java.io.IOException; +import java.util.Map; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.sentry.core.model.solr.SolrConstants; +import org.apache.solr.SolrTestCaseJ4.SuppressSSL; +import org.junit.Test; +import org.restlet.data.MediaType; +import org.restlet.resource.ClientResource; +import org.restlet.resource.ResourceException; + +@SuppressSSL +public class TestSolrSchemaOperations extends AbstractSolrSentryTestCase { + private static final String fieldToBeAdded = "{ " + + "\"add-field\":{" + + "\"name\":\"test\"," + + "\"type\":\"string\"," + + "\"stored\":true }}"; + + + @Test + public void testSolrSchemaOperations() throws Exception { + String collectionName = "testSolrSchemaOperations"; + + grantSchemaPrivileges(ADMIN_USER, "role0", collectionName, SolrConstants.ALL); + + grantCollectionPrivileges(ADMIN_USER, ADMIN_ROLE, collectionName, SolrConstants.UPDATE); + createCollection(ADMIN_USER, collectionName, "cloud-managed", NUM_SERVERS, 1); + + schemaReadSuccess("user0", collectionName); + schemaUpdateSuccess("user0", collectionName); + + revokeSchemaPrivileges(ADMIN_USER, "role0", collectionName, SolrConstants.QUERY); + schemaReadFailure("user0", collectionName); + + revokeSchemaPrivileges(ADMIN_USER, "role0", collectionName, SolrConstants.UPDATE); + schemaUpdateFailure("user0", collectionName); + } + + + @SuppressWarnings("rawtypes") + protected void schemaReadSuccess( String userName, String collectionName) throws ResourceException, IOException { + String tmp = getAuthenticatedUser(); + try { + setAuthenticationUser(userName); + + Map result = querySchemaConfig(collectionName, "name?wt=json"); + assertEquals("minimal", readNestedElement(result, "name")); + + result = querySchemaConfig(collectionName, "version?wt=json"); + assertEquals(new Double(1.1d), (Double)readNestedElement(result, "version")); + + } finally { + setAuthenticationUser(tmp); + } + } + + protected void schemaReadFailure( String userName, String collectionName) throws ResourceException, IOException { + String tmp = getAuthenticatedUser(); + try { + setAuthenticationUser(userName); + + querySchemaConfig(collectionName, "name?wt=json"); + fail("This schema query request should have failed with authorization error."); + + } catch (ResourceException ex) { + assertEquals(HttpServletResponse.SC_FORBIDDEN, ex.getStatus().getCode()); + } finally { + setAuthenticationUser(tmp); + } + } + + @SuppressWarnings("rawtypes") + protected void schemaUpdateSuccess( String userName, String collectionName) throws ResourceException, IOException { + String tmp = getAuthenticatedUser(); + try { + setAuthenticationUser(userName); + + String url = String.format("%s/%s/schema", + cluster.getJettySolrRunner(0).getBaseUrl().toString(), collectionName); + ClientResource resource = new ClientResource(url); + Map updateResp = deserialize(resource.post(fieldToBeAdded, MediaType.APPLICATION_JSON)); + assertEquals(0, (long)readNestedElement(updateResp, "responseHeader", "status")); + + Map result = querySchemaConfig(collectionName, "fields/test"); + assertEquals("test", readNestedElement(result, "field", "name")); + assertEquals("string", readNestedElement(result, "field", "type")); + assertEquals(true, readNestedElement(result, "field", "stored")); + + } finally { + setAuthenticationUser(tmp); + } + } + + protected void schemaUpdateFailure( String userName, String collectionName) throws ResourceException, IOException { + String tmp = getAuthenticatedUser(); + try { + setAuthenticationUser(userName); + + String url = String.format("%s/%s/schema", + cluster.getJettySolrRunner(0).getBaseUrl().toString(), collectionName); + ClientResource resource = new ClientResource(url); + resource.post(fieldToBeAdded, MediaType.APPLICATION_JSON); + fail("This schema update request should have failed with authorization error."); + + } catch (ResourceException ex) { + assertEquals(HttpServletResponse.SC_FORBIDDEN, ex.getStatus().getCode()); + } finally { + setAuthenticationUser(tmp); + } + } + + @SuppressWarnings("rawtypes") + protected Map querySchemaConfig(String collectionName, String reqPath) throws ResourceException, IOException { + String url = String.format("%s/%s/schema/%s", + cluster.getJettySolrRunner(0).getBaseUrl().toString(), collectionName, reqPath); + System.out.println("^^^:"+url); + + Map result = deserialize(new ClientResource(url).get()); + assertEquals(0, (long)readNestedElement(result, "responseHeader", "status")); + + return result; + } + +}
