Repository: sentry Updated Branches: refs/heads/master 372ffc9b4 -> 755e94250
SENTRY-2042: Support file based Sentry provider for Solr plugin. (Hrishikesh Gadre, reviewed by Kalyan Kumar Kalvagadda) Project: http://git-wip-us.apache.org/repos/asf/sentry/repo Commit: http://git-wip-us.apache.org/repos/asf/sentry/commit/755e9425 Tree: http://git-wip-us.apache.org/repos/asf/sentry/tree/755e9425 Diff: http://git-wip-us.apache.org/repos/asf/sentry/diff/755e9425 Branch: refs/heads/master Commit: 755e94250e430e290a0642bcb5a575d29f190b4c Parents: 372ffc9 Author: Kalyan Kumar Kalvagadda <[email protected]> Authored: Mon Nov 20 16:10:23 2017 -0600 Committer: Kalyan Kumar Kalvagadda <[email protected]> Committed: Mon Nov 20 16:10:23 2017 -0600 ---------------------------------------------------------------------- sentry-binding/sentry-binding-solr/pom.xml | 1 - .../solr/authz/SentrySolrPluginImpl.java | 54 +++- sentry-tests/sentry-tests-solr/pom.xml | 4 +- .../e2e/solr/AbstractSolrSentryTestCase.java | 265 +++++-------------- .../e2e/solr/SolrSentryServiceTestBase.java | 211 +++++++++++++++ .../tests/e2e/solr/TestDocLevelOperations.java | 2 +- .../tests/e2e/solr/TestSolrAdminOperations.java | 19 +- .../e2e/solr/TestSolrCollectionOperations.java | 57 +--- .../e2e/solr/TestSolrConfigOperations.java | 2 +- .../e2e/solr/TestSolrSchemaOperations.java | 2 +- .../TestSolrWithSimpleFileProviderBackend.java | 127 +++++++++ .../solr/sentry/test-authz-provider.ini | 104 +------- 12 files changed, 466 insertions(+), 382 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/sentry/blob/755e9425/sentry-binding/sentry-binding-solr/pom.xml ---------------------------------------------------------------------- diff --git a/sentry-binding/sentry-binding-solr/pom.xml b/sentry-binding/sentry-binding-solr/pom.xml index 2452e2f..c64769b 100644 --- a/sentry-binding/sentry-binding-solr/pom.xml +++ b/sentry-binding/sentry-binding-solr/pom.xml @@ -76,7 +76,6 @@ limitations under the License. <dependency> <groupId>org.apache.sentry</groupId> <artifactId>sentry-provider-file</artifactId> - <scope>test</scope> </dependency> <dependency> <groupId>org.apache.hadoop</groupId> http://git-wip-us.apache.org/repos/asf/sentry/blob/755e9425/sentry-binding/sentry-binding-solr/src/main/java/org/apache/sentry/binding/solr/authz/SentrySolrPluginImpl.java ---------------------------------------------------------------------- diff --git a/sentry-binding/sentry-binding-solr/src/main/java/org/apache/sentry/binding/solr/authz/SentrySolrPluginImpl.java b/sentry-binding/sentry-binding-solr/src/main/java/org/apache/sentry/binding/solr/authz/SentrySolrPluginImpl.java index c0ead28..91d08f0 100644 --- a/sentry-binding/sentry-binding-solr/src/main/java/org/apache/sentry/binding/solr/authz/SentrySolrPluginImpl.java +++ b/sentry-binding/sentry-binding-solr/src/main/java/org/apache/sentry/binding/solr/authz/SentrySolrPluginImpl.java @@ -16,6 +16,7 @@ */ package org.apache.sentry.binding.solr.authz; +import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHENTICATION; import static org.apache.sentry.binding.solr.authz.SolrAuthzBinding.QUERY; import static org.apache.sentry.binding.solr.authz.SolrAuthzBinding.UPDATE; @@ -43,6 +44,7 @@ import org.apache.sentry.core.model.solr.Collection; import org.apache.sentry.core.model.solr.SolrConstants; import org.apache.sentry.core.model.solr.SolrModelAction; import org.apache.sentry.core.model.solr.SolrModelAuthorizable; +import org.apache.sentry.provider.file.SimpleFileProviderBackend; import org.apache.solr.common.SolrException; import org.apache.solr.common.SolrException.ErrorCode; import org.apache.solr.common.params.CoreAdminParams; @@ -110,6 +112,20 @@ public class SentrySolrPluginImpl implements AuthorizationPlugin { */ public static final String SENTRY_HADOOP_CONF_DIR_PROPERTY = "authorization.sentry.hadoop.conf"; + /** + * A configuration property to specify the kerberos principal to be used for communicating with + * HDFS. This is required only in case of {@linkplain SimpleFileProviderBackend} when the policy + * file is stored on HDFS. + */ + public static final String SENTRY_HDFS_KERBEROS_PRINCIPAL = "authorization.hdfs.kerberos.principal"; + + /** + * A configuration property to specify the kerberos keytab file to be used for communicating with + * HDFS. This is required only in case of {@linkplain SimpleFileProviderBackend} when the policy + * file is stored on HDFS. + */ + public static final String SENTRY_HDFS_KERBEROS_KEYTAB = "authorization.hdfs.kerberos.keytabfile"; + private String solrSuperUser; private SolrAuthzBinding binding; private Optional<AuditLogger> auditLog = Optional.empty(); @@ -267,7 +283,16 @@ public class SentrySolrPluginImpl implements AuthorizationPlugin { List<URL> configFiles = getHadoopConfigFiles(sentryHadoopConfLoc); configFiles.add((new File(sentrySiteLoc)).toURI().toURL()); - binding = new SolrAuthzBinding(new SolrAuthzConf(configFiles)); + SolrAuthzConf conf = new SolrAuthzConf(configFiles); + if (shouldInitializeKereberos(conf)) { + String princ = Preconditions.checkNotNull(config.get(SENTRY_HDFS_KERBEROS_PRINCIPAL), + "The authorization plugin is missing the " + SENTRY_HDFS_KERBEROS_PRINCIPAL + " property."); + String keytab = Preconditions.checkNotNull(config.get(SENTRY_HDFS_KERBEROS_KEYTAB), + "The authorization plugin is missing the " + SENTRY_HDFS_KERBEROS_KEYTAB + " property."); + initKerberos(conf, keytab, princ); + } + + binding = new SolrAuthzBinding(conf); LOG.info("SolrAuthzBinding created successfully"); } catch (Exception e) { throw new SolrException(ErrorCode.SERVER_ERROR, "Unable to create SolrAuthzBinding", e); @@ -405,4 +430,31 @@ public class SentrySolrPluginImpl implements AuthorizationPlugin { return result; } + + /** + * Initialize kerberos via UserGroupInformation. Will only attempt to login + * during the first request, subsequent calls will have no effect. + */ + private void initKerberos(SolrAuthzConf authzConf, String keytabFile, String principal) { + synchronized (SentrySolrPluginImpl.class) { + UserGroupInformation.setConfiguration(authzConf); + LOG.info( + "Attempting to acquire kerberos ticket with keytab: {}, principal: {} ", + keytabFile, principal); + try { + UserGroupInformation.loginUserFromKeytab(principal, keytabFile); + } catch (IOException ioe) { + throw new SolrException(ErrorCode.SERVER_ERROR, ioe); + } + LOG.info("Got Kerberos ticket"); + } + } + + private boolean shouldInitializeKereberos(SolrAuthzConf conf) { + String providerBackend = conf.get(SolrAuthzConf.AuthzConfVars.AUTHZ_PROVIDER_BACKEND.getVar()); + String authVal = conf.get(HADOOP_SECURITY_AUTHENTICATION); + return SimpleFileProviderBackend.class.getName().equals(providerBackend) + && "kerberos".equalsIgnoreCase(authVal); + } + } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/sentry/blob/755e9425/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 9d400b2..c171b6f 100644 --- a/sentry-tests/sentry-tests-solr/pom.xml +++ b/sentry-tests/sentry-tests-solr/pom.xml @@ -274,7 +274,9 @@ limitations under the License. <systemPropertyVariables> <test.solr.allowed.securerandom>NativePRNG</test.solr.allowed.securerandom> <!-- Solr test framework randomizes the locale configuration which sometimes - result in test failures due to derby initialization errors --> + result in test failures due to derby initialization errors (Ref: LUCENE-8009). + To reduce the flakiness of the unit tests, setting the locale explicitly. + --> <tests.locale>en-US</tests.locale> </systemPropertyVariables> </configuration> http://git-wip-us.apache.org/repos/asf/sentry/blob/755e9425/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/AbstractSolrSentryTestCase.java ---------------------------------------------------------------------- diff --git a/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/AbstractSolrSentryTestCase.java b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/AbstractSolrSentryTestCase.java index e6e7a70..3d4d555 100644 --- a/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/AbstractSolrSentryTestCase.java +++ b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/AbstractSolrSentryTestCase.java @@ -19,18 +19,11 @@ package org.apache.sentry.tests.e2e.solr; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; -import java.lang.Thread.UncaughtExceptionHandler; import java.net.MalformedURLException; import java.net.URI; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; -import java.util.Locale; import javax.servlet.http.HttpServletResponse; @@ -43,19 +36,11 @@ import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.entity.ByteArrayEntity; import org.apache.http.util.EntityUtils; import org.apache.commons.io.IOUtils; -import org.apache.hadoop.security.UserGroupInformation; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.sentry.binding.solr.authz.SentrySolrPluginImpl; -import org.apache.sentry.core.common.exception.SentryUserException; -import org.apache.sentry.core.model.solr.SolrConstants; -import org.apache.sentry.core.model.solr.SolrModelAuthorizable; -import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClient; -import org.apache.sentry.provider.db.generic.service.thrift.TAuthorizable; -import org.apache.sentry.provider.db.generic.service.thrift.TSentryGrantOption; -import org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege; import org.apache.solr.client.solrj.SolrQuery; import org.apache.solr.client.solrj.SolrServerException; import org.apache.solr.client.solrj.impl.CloudSolrClient; @@ -66,208 +51,23 @@ import org.apache.solr.cloud.SolrCloudTestCase; 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.apache.solr.common.util.Utils; import org.apache.solr.SolrTestCaseJ4; -import org.junit.AfterClass; -import org.junit.BeforeClass; import org.restlet.representation.Representation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope; @ThreadLeakScope(ThreadLeakScope.Scope.NONE) @SolrTestCaseJ4.SuppressSSL public abstract class AbstractSolrSentryTestCase extends SolrCloudTestCase { - private static final Logger log = LoggerFactory.getLogger(AbstractSolrSentryTestCase.class); protected static final int NUM_SERVERS = 3; protected static final String COMPONENT_SOLR = "solr"; protected static final String SERVICE_NAME = "service1"; protected static final String ADMIN_ROLE = "admin_role"; - private static final String SENTRY_SITE_LOC_SYSPROP = "solr."+SentrySolrPluginImpl.SNTRY_SITE_LOCATION_PROPERTY; + protected static final String SENTRY_SITE_LOC_SYSPROP = "solr."+SentrySolrPluginImpl.SNTRY_SITE_LOCATION_PROPERTY; protected static final String ALL_DOCS = "*:*"; - protected static TestSentryServer sentrySvc; - protected static SentryGenericServiceClient sentryClient; - protected static UncaughtExceptionHandler orgExceptionHandler; - - @BeforeClass - public static void setupClass() throws Exception { - skipBrokenLocales(); - - Path testDataPath = createTempDir("solr-integration-db-"); - - try { - sentrySvc = new TestSentryServer(testDataPath, getUserGroupMappings()); - sentrySvc.startSentryService(); - sentryClient = sentrySvc.connectToSentryService(); - log.info("Successfully started Sentry service"); - } catch (Exception ex) { - log.error ("Unexpected exception while starting Sentry service", ex); - throw ex; - } - - for (int i = 0; i < 4; i++) { - sentryClient.createRole(TestSentryServer.ADMIN_USER, "role"+i, COMPONENT_SOLR); - sentryClient.grantRoleToGroups(TestSentryServer.ADMIN_USER, "role"+i, COMPONENT_SOLR, Collections.singleton("group"+i)); - } - - log.info("Successfully created roles in Sentry service"); - - sentryClient.createRole(TestSentryServer.ADMIN_USER, ADMIN_ROLE, COMPONENT_SOLR); - sentryClient.grantRoleToGroups(TestSentryServer.ADMIN_USER, ADMIN_ROLE, COMPONENT_SOLR, - Collections.singleton(TestSentryServer.ADMIN_GROUP)); - grantAdminPrivileges(TestSentryServer.ADMIN_USER, ADMIN_ROLE, SolrConstants.ALL, SolrConstants.ALL); - - log.info("Successfully granted admin privileges to " + ADMIN_ROLE); - - - System.setProperty(SENTRY_SITE_LOC_SYSPROP, sentrySvc.getSentrySitePath().toString()); - - // set the solr for the loginUser and belongs to solr group - // Note - Solr/Sentry unit tests don't use Hadoop authentication framework. Hence the - // UserGroupInformation is not available when the request is being processed by the Solr server. - // The document level security search component requires this UserGroupInformation while querying - // the roles associated with the user. Please refer to implementation of - // SentryGenericProviderBackend#getRoles(...) method. Hence this is a workaround to satisfy this requirement. - UserGroupInformation.setLoginUser(UserGroupInformation.createUserForTesting("solr", new String[]{"solr"})); - - try { - configureCluster(NUM_SERVERS) - .withSecurityJson(TEST_PATH().resolve("security").resolve("security.json")) - .addConfig("cloud-minimal", TEST_PATH().resolve("configsets").resolve("cloud-minimal").resolve("conf")) - .addConfig("cloud-managed", TEST_PATH().resolve("configsets").resolve("cloud-managed").resolve("conf")) - .addConfig("cloud-minimal_doc_level_security", TEST_PATH().resolve("configsets") - .resolve("cloud-minimal_doc_level_security").resolve("conf")) - .configure(); - log.info("Successfully started Solr service"); - - } catch (Exception ex) { - log.error ("Unexpected exception while starting SolrCloud", ex); - throw ex; - } - - log.info("Successfully setup Solr with Sentry service"); - } - - /** - * A sample failed run was with following parameters - * -Dtests.seed=C92C593AE70E7466 -Dtests.locale=und -Dtests.timezone=Europe/Sarajevo -Dtests.asserts=true -Dtests.file.encoding=UTF-8 - */ - private static void skipBrokenLocales() { - assumeFalse("This test fails on UNIX whenever Locale has a language, country, or variant that does not satisfy" + - " the IETF BCP 47 language tag syntax requirements", - "und".equals(Locale.getDefault().toLanguageTag())); - assumeFalse("This test fails on UNIX with error - Supplied locale description 'sr__#Latn' is invalid, expecting ln[_CO[_variant]]" + - "ln=lower-case two-letter ISO-639 language code, CO=upper-case two-letter ISO-3166 country code", - "sr-Latn".equals(Locale.getDefault().toLanguageTag())); - } - - @AfterClass - public static void cleanUpResources() throws Exception { - if (sentryClient != null) { - sentryClient.close(); - sentryClient = null; - } - if (sentrySvc != null) { - sentrySvc.close(); - sentrySvc = null; - } - System.clearProperty(SENTRY_SITE_LOC_SYSPROP); - } - - public static void grantAdminPrivileges(String requestor, String roleName, String entityName, String action) - throws SentryUserException { - List<TAuthorizable> auths = new ArrayList<>(1); - auths.add(new TAuthorizable(SolrModelAuthorizable.AuthorizableType.Admin.name(), entityName)); - - TSentryPrivilege privilege = new TSentryPrivilege(COMPONENT_SOLR, SERVICE_NAME, auths, action); - privilege.setGrantOption(TSentryGrantOption.TRUE); - sentryClient.grantPrivilege(requestor, roleName, COMPONENT_SOLR, privilege); - } - - public static void revokeAdminPrivileges(String requestor, String roleName, String entityName, String action) - throws SentryUserException { - List<TAuthorizable> auths = new ArrayList<>(1); - auths.add(new TAuthorizable(SolrModelAuthorizable.AuthorizableType.Admin.name(), entityName)); - - TSentryPrivilege privilege = new TSentryPrivilege(COMPONENT_SOLR, SERVICE_NAME, auths, action); - privilege.setGrantOption(TSentryGrantOption.TRUE); - sentryClient.revokePrivilege(requestor, roleName, COMPONENT_SOLR, privilege); - } - - public static void grantCollectionPrivileges(String requestor, String roleName, - String collectionName, String action) throws SentryUserException { - List<TAuthorizable> auths = new ArrayList<>(1); - auths.add(new TAuthorizable(SolrModelAuthorizable.AuthorizableType.Collection.name(), collectionName)); - - TSentryPrivilege privilege = new TSentryPrivilege(COMPONENT_SOLR, SERVICE_NAME, auths, action); - privilege.setGrantOption(TSentryGrantOption.TRUE); - sentryClient.grantPrivilege(requestor, roleName, COMPONENT_SOLR, privilege); - } - - public static void revokeCollectionPrivileges(String requestor, String roleName, - String collectionName, String action) throws SentryUserException { - List<TAuthorizable> auths = new ArrayList<>(1); - auths.add(new TAuthorizable(SolrModelAuthorizable.AuthorizableType.Collection.name(), collectionName)); - - TSentryPrivilege privilege = new TSentryPrivilege(COMPONENT_SOLR, SERVICE_NAME, auths, action); - privilege.setGrantOption(TSentryGrantOption.TRUE); - sentryClient.revokePrivilege(requestor, roleName, COMPONENT_SOLR, privilege); - } - - public static void grantConfigPrivileges(String requestor, String roleName, String configName, - String action) throws SentryUserException { - List<TAuthorizable> auths = new ArrayList<>(1); - auths.add(new TAuthorizable(SolrModelAuthorizable.AuthorizableType.Config.name(), configName)); - - TSentryPrivilege privilege = new TSentryPrivilege(COMPONENT_SOLR, SERVICE_NAME, auths, action); - privilege.setGrantOption(TSentryGrantOption.TRUE); - sentryClient.grantPrivilege(requestor, roleName, COMPONENT_SOLR, privilege); - } - - public static void revokeConfigPrivileges(String requestor, String roleName, String configName, - String action) throws SentryUserException { - List<TAuthorizable> auths = new ArrayList<>(1); - auths.add(new TAuthorizable(SolrModelAuthorizable.AuthorizableType.Config.name(), configName)); - - TSentryPrivilege privilege = new TSentryPrivilege(COMPONENT_SOLR, SERVICE_NAME, auths, action); - privilege.setGrantOption(TSentryGrantOption.TRUE); - sentryClient.revokePrivilege(requestor, roleName, COMPONENT_SOLR, privilege); - } - - public static void grantSchemaPrivileges(String requestor, String roleName, String schemaName, - String action) throws SentryUserException { - List<TAuthorizable> auths = new ArrayList<>(1); - auths.add(new TAuthorizable(SolrModelAuthorizable.AuthorizableType.Schema.name(), schemaName)); - - TSentryPrivilege privilege = new TSentryPrivilege(COMPONENT_SOLR, SERVICE_NAME, auths, action); - privilege.setGrantOption(TSentryGrantOption.TRUE); - sentryClient.grantPrivilege(requestor, roleName, COMPONENT_SOLR, privilege); - } - - public static void revokeSchemaPrivileges(String requestor, String roleName, String schemaName, - String action) throws SentryUserException { - List<TAuthorizable> auths = new ArrayList<>(1); - auths.add(new TAuthorizable(SolrModelAuthorizable.AuthorizableType.Schema.name(), schemaName)); - - TSentryPrivilege privilege = new TSentryPrivilege(COMPONENT_SOLR, SERVICE_NAME, auths, action); - privilege.setGrantOption(TSentryGrantOption.TRUE); - sentryClient.revokePrivilege(requestor, roleName, COMPONENT_SOLR, privilege); - } - - protected static Map<String, Set<String>> getUserGroupMappings() { - Map<String, Set<String>> result = new HashMap<>(); - result.put("user0", Collections.singleton("group0")); - result.put("user1", Collections.singleton("group1")); - result.put("user2", Collections.singleton("group2")); - result.put("user3", Collections.singleton("group3")); - result.put(TestSentryServer.ADMIN_USER, Collections.singleton(TestSentryServer.ADMIN_GROUP)); - result.put("solr", Collections.singleton("solr")); - result.put("junit", Collections.singleton("junit")); - result.put("doclevel", Collections.singleton("doclevel")); - return Collections.unmodifiableMap(result); - } /** * Get the user defined in the Solr authentication plugin @@ -596,5 +396,66 @@ public abstract class AbstractSolrSentryTestCase extends SolrCloudTestCase { return makeHttpRequest(client, firstServer, httpMethod, path, content, contentType, expectedStatusCode); } + 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; + } + + 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); + } + } + + 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); + } + } } http://git-wip-us.apache.org/repos/asf/sentry/blob/755e9425/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/SolrSentryServiceTestBase.java ---------------------------------------------------------------------- diff --git a/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/SolrSentryServiceTestBase.java b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/SolrSentryServiceTestBase.java new file mode 100644 index 0000000..c4a46fa --- /dev/null +++ b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/SolrSentryServiceTestBase.java @@ -0,0 +1,211 @@ +/* + * 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.lang.Thread.UncaughtExceptionHandler; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.hadoop.security.UserGroupInformation; +import org.apache.sentry.core.common.exception.SentryUserException; +import org.apache.sentry.core.model.solr.SolrConstants; +import org.apache.sentry.core.model.solr.SolrModelAuthorizable; +import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClient; +import org.apache.sentry.provider.db.generic.service.thrift.TAuthorizable; +import org.apache.sentry.provider.db.generic.service.thrift.TSentryGrantOption; +import org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SolrSentryServiceTestBase extends AbstractSolrSentryTestCase { + private static final Logger log = LoggerFactory.getLogger(SolrSentryServiceTestBase.class); + protected static TestSentryServer sentrySvc; + protected static SentryGenericServiceClient sentryClient; + protected static UncaughtExceptionHandler orgExceptionHandler; + + @BeforeClass + public static void setupClass() throws Exception { + Path testDataPath = createTempDir("solr-integration-db-"); + + try { + sentrySvc = new TestSentryServer(testDataPath, getUserGroupMappings()); + sentrySvc.startSentryService(); + sentryClient = sentrySvc.connectToSentryService(); + log.info("Successfully started Sentry service"); + } catch (Exception ex) { + log.error ("Unexpected exception while starting Sentry service", ex); + throw ex; + } + + for (int i = 0; i < 4; i++) { + sentryClient.createRole(TestSentryServer.ADMIN_USER, "role"+i, COMPONENT_SOLR); + sentryClient.grantRoleToGroups(TestSentryServer.ADMIN_USER, "role"+i, COMPONENT_SOLR, Collections.singleton("group"+i)); + } + + log.info("Successfully created roles in Sentry service"); + + sentryClient.createRole(TestSentryServer.ADMIN_USER, ADMIN_ROLE, COMPONENT_SOLR); + sentryClient.grantRoleToGroups(TestSentryServer.ADMIN_USER, ADMIN_ROLE, COMPONENT_SOLR, + Collections.singleton(TestSentryServer.ADMIN_GROUP)); + grantAdminPrivileges(TestSentryServer.ADMIN_USER, ADMIN_ROLE, SolrConstants.ALL, SolrConstants.ALL); + + log.info("Successfully granted admin privileges to " + ADMIN_ROLE); + + + System.setProperty(SENTRY_SITE_LOC_SYSPROP, sentrySvc.getSentrySitePath().toString()); + + // set the solr for the loginUser and belongs to solr group + // Note - Solr/Sentry unit tests don't use Hadoop authentication framework. Hence the + // UserGroupInformation is not available when the request is being processed by the Solr server. + // The document level security search component requires this UserGroupInformation while querying + // the roles associated with the user. Please refer to implementation of + // SentryGenericProviderBackend#getRoles(...) method. Hence this is a workaround to satisfy this requirement. + UserGroupInformation.setLoginUser(UserGroupInformation.createUserForTesting("solr", new String[]{"solr"})); + + try { + configureCluster(NUM_SERVERS) + .withSecurityJson(TEST_PATH().resolve("security").resolve("security.json")) + .addConfig("cloud-minimal", TEST_PATH().resolve("configsets").resolve("cloud-minimal").resolve("conf")) + .addConfig("cloud-managed", TEST_PATH().resolve("configsets").resolve("cloud-managed").resolve("conf")) + .addConfig("cloud-minimal_doc_level_security", TEST_PATH().resolve("configsets") + .resolve("cloud-minimal_doc_level_security").resolve("conf")) + .configure(); + log.info("Successfully started Solr service"); + + } catch (Exception ex) { + log.error ("Unexpected exception while starting SolrCloud", ex); + throw ex; + } + + log.info("Successfully setup Solr with Sentry service"); + } + + @AfterClass + public static void cleanUpResources() throws Exception { + if (sentryClient != null) { + sentryClient.close(); + sentryClient = null; + } + if (sentrySvc != null) { + sentrySvc.close(); + sentrySvc = null; + } + System.clearProperty(SENTRY_SITE_LOC_SYSPROP); + } + + public static void grantAdminPrivileges(String requestor, String roleName, String entityName, String action) + throws SentryUserException { + List<TAuthorizable> auths = new ArrayList<>(1); + auths.add(new TAuthorizable(SolrModelAuthorizable.AuthorizableType.Admin.name(), entityName)); + + TSentryPrivilege privilege = new TSentryPrivilege(COMPONENT_SOLR, SERVICE_NAME, auths, action); + privilege.setGrantOption(TSentryGrantOption.TRUE); + sentryClient.grantPrivilege(requestor, roleName, COMPONENT_SOLR, privilege); + } + + public static void revokeAdminPrivileges(String requestor, String roleName, String entityName, String action) + throws SentryUserException { + List<TAuthorizable> auths = new ArrayList<>(1); + auths.add(new TAuthorizable(SolrModelAuthorizable.AuthorizableType.Admin.name(), entityName)); + + TSentryPrivilege privilege = new TSentryPrivilege(COMPONENT_SOLR, SERVICE_NAME, auths, action); + privilege.setGrantOption(TSentryGrantOption.TRUE); + sentryClient.revokePrivilege(requestor, roleName, COMPONENT_SOLR, privilege); + } + + public static void grantCollectionPrivileges(String requestor, String roleName, + String collectionName, String action) throws SentryUserException { + List<TAuthorizable> auths = new ArrayList<>(1); + auths.add(new TAuthorizable(SolrModelAuthorizable.AuthorizableType.Collection.name(), collectionName)); + + TSentryPrivilege privilege = new TSentryPrivilege(COMPONENT_SOLR, SERVICE_NAME, auths, action); + privilege.setGrantOption(TSentryGrantOption.TRUE); + sentryClient.grantPrivilege(requestor, roleName, COMPONENT_SOLR, privilege); + } + + public static void revokeCollectionPrivileges(String requestor, String roleName, + String collectionName, String action) throws SentryUserException { + List<TAuthorizable> auths = new ArrayList<>(1); + auths.add(new TAuthorizable(SolrModelAuthorizable.AuthorizableType.Collection.name(), collectionName)); + + TSentryPrivilege privilege = new TSentryPrivilege(COMPONENT_SOLR, SERVICE_NAME, auths, action); + privilege.setGrantOption(TSentryGrantOption.TRUE); + sentryClient.revokePrivilege(requestor, roleName, COMPONENT_SOLR, privilege); + } + + public static void grantConfigPrivileges(String requestor, String roleName, String configName, + String action) throws SentryUserException { + List<TAuthorizable> auths = new ArrayList<>(1); + auths.add(new TAuthorizable(SolrModelAuthorizable.AuthorizableType.Config.name(), configName)); + + TSentryPrivilege privilege = new TSentryPrivilege(COMPONENT_SOLR, SERVICE_NAME, auths, action); + privilege.setGrantOption(TSentryGrantOption.TRUE); + sentryClient.grantPrivilege(requestor, roleName, COMPONENT_SOLR, privilege); + } + + public static void revokeConfigPrivileges(String requestor, String roleName, String configName, + String action) throws SentryUserException { + List<TAuthorizable> auths = new ArrayList<>(1); + auths.add(new TAuthorizable(SolrModelAuthorizable.AuthorizableType.Config.name(), configName)); + + TSentryPrivilege privilege = new TSentryPrivilege(COMPONENT_SOLR, SERVICE_NAME, auths, action); + privilege.setGrantOption(TSentryGrantOption.TRUE); + sentryClient.revokePrivilege(requestor, roleName, COMPONENT_SOLR, privilege); + } + + public static void grantSchemaPrivileges(String requestor, String roleName, String schemaName, + String action) throws SentryUserException { + List<TAuthorizable> auths = new ArrayList<>(1); + auths.add(new TAuthorizable(SolrModelAuthorizable.AuthorizableType.Schema.name(), schemaName)); + + TSentryPrivilege privilege = new TSentryPrivilege(COMPONENT_SOLR, SERVICE_NAME, auths, action); + privilege.setGrantOption(TSentryGrantOption.TRUE); + sentryClient.grantPrivilege(requestor, roleName, COMPONENT_SOLR, privilege); + } + + public static void revokeSchemaPrivileges(String requestor, String roleName, String schemaName, + String action) throws SentryUserException { + List<TAuthorizable> auths = new ArrayList<>(1); + auths.add(new TAuthorizable(SolrModelAuthorizable.AuthorizableType.Schema.name(), schemaName)); + + TSentryPrivilege privilege = new TSentryPrivilege(COMPONENT_SOLR, SERVICE_NAME, auths, action); + privilege.setGrantOption(TSentryGrantOption.TRUE); + sentryClient.revokePrivilege(requestor, roleName, COMPONENT_SOLR, privilege); + } + + protected static Map<String, Set<String>> getUserGroupMappings() { + Map<String, Set<String>> result = new HashMap<>(); + result.put("user0", Collections.singleton("group0")); + result.put("user1", Collections.singleton("group1")); + result.put("user2", Collections.singleton("group2")); + result.put("user3", Collections.singleton("group3")); + result.put(TestSentryServer.ADMIN_USER, Collections.singleton(TestSentryServer.ADMIN_GROUP)); + result.put("solr", Collections.singleton("solr")); + result.put("junit", Collections.singleton("junit")); + result.put("doclevel", Collections.singleton("doclevel")); + return Collections.unmodifiableMap(result); + } + + +} http://git-wip-us.apache.org/repos/asf/sentry/blob/755e9425/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 a24ceee..7834f33 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 @@ -43,7 +43,7 @@ import org.junit.Test; /** * Test the document-level security features */ -public class TestDocLevelOperations extends AbstractSolrSentryTestCase { +public class TestDocLevelOperations extends SolrSentryServiceTestBase { private static final String AUTH_FIELD = "sentry_auth"; private static final int NUM_DOCS = 100; private static final int EXTRA_AUTH_FIELDS = 2; http://git-wip-us.apache.org/repos/asf/sentry/blob/755e9425/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 index 190b9d4..b004ba0 100644 --- 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 @@ -37,7 +37,7 @@ import org.restlet.resource.ClientResource; import org.restlet.resource.ResourceException; @SuppressSSL -public class TestSolrAdminOperations extends AbstractSolrSentryTestCase { +public class TestSolrAdminOperations extends SolrSentryServiceTestBase { @Test public void testQueryAdminOperation() throws Exception { @@ -168,21 +168,4 @@ public class TestSolrAdminOperations extends AbstractSolrSentryTestCase { } } - 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/755e9425/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 index 3d9faa0..2ca6010 100644 --- 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 @@ -18,22 +18,13 @@ 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 { +public class TestSolrCollectionOperations extends SolrSentryServiceTestBase { @Test public void testQueryOperations() throws Exception { @@ -92,50 +83,4 @@ public class TestSolrCollectionOperations extends AbstractSolrSentryTestCase { 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/755e9425/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 index 620825f..454fd02 100644 --- 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 @@ -35,7 +35,7 @@ import org.restlet.resource.ClientResource; import org.restlet.resource.ResourceException; @SuppressSSL -public class TestSolrConfigOperations extends AbstractSolrSentryTestCase { +public class TestSolrConfigOperations extends SolrSentryServiceTestBase { @Test public void testConfigSetOperations() throws Exception { grantConfigPrivileges(ADMIN_USER, "role0", "test", SolrConstants.UPDATE); http://git-wip-us.apache.org/repos/asf/sentry/blob/755e9425/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 index 1169b54..2443780 100644 --- 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 @@ -31,7 +31,7 @@ import org.restlet.resource.ClientResource; import org.restlet.resource.ResourceException; @SuppressSSL -public class TestSolrSchemaOperations extends AbstractSolrSentryTestCase { +public class TestSolrSchemaOperations extends SolrSentryServiceTestBase { private static final String fieldToBeAdded = "{ " + "\"add-field\":{" + "\"name\":\"test\"," + http://git-wip-us.apache.org/repos/asf/sentry/blob/755e9425/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSolrWithSimpleFileProviderBackend.java ---------------------------------------------------------------------- diff --git a/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSolrWithSimpleFileProviderBackend.java b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSolrWithSimpleFileProviderBackend.java new file mode 100644 index 0000000..f6e7442 --- /dev/null +++ b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSolrWithSimpleFileProviderBackend.java @@ -0,0 +1,127 @@ +/* + * 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.nio.charset.StandardCharsets; + +import org.apache.commons.io.FileUtils; +import org.apache.solr.common.SolrDocumentList; +import org.apache.solr.common.SolrInputDocument; +import org.junit.BeforeClass; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TestSolrWithSimpleFileProviderBackend extends AbstractSolrSentryTestCase { + private static final Logger log = LoggerFactory.getLogger(TestSolrWithSimpleFileProviderBackend.class); + protected static final String RESOURCES_DIR = "target" + File.separator + "test-classes" + File.separator + "solr"; + + @BeforeClass + public static void setupClass() throws Exception { + // Configure file-based Sentry provider + File sentrySiteXml = setupSentry(); + System.setProperty(SENTRY_SITE_LOC_SYSPROP, sentrySiteXml.getAbsolutePath()); + + try { + configureCluster(NUM_SERVERS) + .withSecurityJson(TEST_PATH().resolve("security").resolve("security.json")) + .addConfig("cloud-minimal", TEST_PATH().resolve("configsets").resolve("cloud-minimal").resolve("conf")) + .addConfig("cloud-managed", TEST_PATH().resolve("configsets").resolve("cloud-managed").resolve("conf")) + .addConfig("cloud-minimal_doc_level_security", TEST_PATH().resolve("configsets") + .resolve("cloud-minimal_doc_level_security").resolve("conf")) + .configure(); + log.info("Successfully started Solr service"); + + } catch (Exception ex) { + log.error ("Unexpected exception while starting SolrCloud", ex); + throw ex; + } + + log.info("Successfully setup Solr with Sentry service"); + } + + private static void addPropertyToSentry(StringBuilder builder, String name, String value) { + builder.append("<property>\n"); + builder.append("<name>").append(name).append("</name>\n"); + builder.append("<value>").append(value).append("</value>\n"); + builder.append("</property>\n"); + } + + private static File setupSentry() throws Exception { + File sentrySite = File.createTempFile("sentry-site", "xml"); + sentrySite.deleteOnExit(); + File authProviderDir = new File(RESOURCES_DIR, "sentry"); + File authProviderName = new File (authProviderDir, "test-authz-provider.ini"); + + // need to write sentry-site at execution time because we don't know + // the location of sentry.solr.provider.resource beforehand + StringBuilder sentrySiteData = new StringBuilder(); + sentrySiteData.append("<configuration>\n"); + addPropertyToSentry(sentrySiteData, "sentry.provider", + "org.apache.sentry.provider.file.LocalGroupResourceAuthorizationProvider"); + addPropertyToSentry(sentrySiteData, "sentry.solr.provider.resource", + authProviderName.getAbsolutePath()); + sentrySiteData.append("</configuration>\n"); + FileUtils.writeStringToFile(sentrySite,sentrySiteData.toString(), StandardCharsets.UTF_8); + return sentrySite; + } + + @Test + public void testCollectionOperationsSuccess() throws Exception { + String collectionName = "testCollectionOperations_s"; + createCollection("admin", collectionName, "cloud-minimal", NUM_SERVERS, 1); + + cleanSolrCollection("junit", collectionName); + + SolrInputDocument solrInputDoc = createSolrTestDoc(); + uploadSolrDoc("junit", collectionName, solrInputDoc); + + SolrDocumentList expectedDocs = expectedDocs(solrInputDoc); + + validateSolrDocCountAndContent(expectedDocs, + getSolrDocs("junit", collectionName, ALL_DOCS)); + } + + @Test + public void testCollectionOperationFailures() throws Exception { + String collectionName = "testCollectionOperations_f"; + + // junit user can not create a collection. + adminUpdateActionFailure ("junit", collectionName); + + // admin user can create collection + createCollection("admin", collectionName, "cloud-minimal", NUM_SERVERS, 1); + + SolrInputDocument solrInputDoc = createSolrTestDoc(); + + // foo user can not update collection + verifyCollectionUpdateFailure("foo", collectionName, solrInputDoc); + + // junit user can update collection + uploadSolrDoc("junit", collectionName, solrInputDoc); + + SolrDocumentList expectedDocs = expectedDocs(solrInputDoc); + + // junit user can query collection + validateSolrDocCountAndContent(expectedDocs, + getSolrDocs("junit", collectionName, ALL_DOCS)); + + // foo user can not query collection + verifyCollectionQueryFailure("foo", collectionName, ALL_DOCS); + } +} http://git-wip-us.apache.org/repos/asf/sentry/blob/755e9425/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 a376cb8..0751dbe 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 @@ -18,109 +18,13 @@ [groups] junit = junit_role admin = admin_role -docLevel = docLevel_role -sentryCollection_query_group = sentryCollection_query_role -sentryCollection_update_group = sentryCollection_update_role -sentryCollection_query_update_group = sentryCollection_query_update_role -sentryCollection_all_group = sentryCollection_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 +foo = foo_role [roles] -junit_role = collection=admin, collection=collection1, collection=docLevelCollection, collection=allRolesCollection, collection=testUpdateDeleteOperations -docLevel_role = collection=docLevelCollection, collection=testUpdateDeleteOperations -admin_role = collection=admin, collection=collection1, collection=sentryCollection, collection=sentryCollection_underlying1, collection=sentryCollection_underlying2, collection=docLevelCollection, collection=allRolesCollection, collection=testInvariantCollection, collection=testUpdateDeleteOperations, collection=testIndexlevelDoclevelOperations, collection=testUpdateDistribPhase, collection=testIdvsIds, collection=testIdvsIdsControl, collection=testFl, collection=testNonCommitted, collection=testConcurrentChanges, collection=testSuperUser -sentryCollection_query_role = collection=sentryCollection->action=query -sentryCollection_update_role = collection=sentryCollection->action=update -sentryCollection_query_update_role = collection=sentryCollection->action=query, collection=sentryCollection->action=update -sentryCollection_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=* +junit_role = collection=testCollectionOperations_s, collection=testCollectionOperations_f +admin_role = admin=collections, admin=cores, collection=testCollectionOperations_s, collection=testCollectionOperations_f [users] junit = junit -docLevel = docLevel admin = admin -admin_qua = admin_query_group, admin_update_group, admin_all_group, -admin_qu = admin_query_group, admin_update_group, -admin_qa = admin_query_group, admin_all_group, -admin_q = admin_query_group, -admin_ua = admin_update_group, admin_all_group, -admin_u = admin_update_group, -admin_a = admin_all_group, -admin_qua__sentryCollection_qua = sentryCollection_query_group, sentryCollection_update_group, sentryCollection_all_group, admin_query_group, admin_update_group, admin_all_group, -admin_qu__sentryCollection_qua = sentryCollection_query_group, sentryCollection_update_group, sentryCollection_all_group, admin_query_group, admin_update_group, -admin_qa__sentryCollection_qua = sentryCollection_query_group, sentryCollection_update_group, sentryCollection_all_group, admin_query_group, admin_all_group, -admin_q__sentryCollection_qua = sentryCollection_query_group, sentryCollection_update_group, sentryCollection_all_group, admin_query_group, -admin_ua__sentryCollection_qua = sentryCollection_query_group, sentryCollection_update_group, sentryCollection_all_group, admin_update_group, admin_all_group, -admin_u__sentryCollection_qua = sentryCollection_query_group, sentryCollection_update_group, sentryCollection_all_group, admin_update_group, -admin_a__sentryCollection_qua = sentryCollection_query_group, sentryCollection_update_group, sentryCollection_all_group, admin_all_group, -admin___sentryCollection_qua = sentryCollection_query_group, sentryCollection_update_group, sentryCollection_all_group, -admin_qua__sentryCollection_qu = sentryCollection_query_group, sentryCollection_update_group, admin_query_group, admin_update_group, admin_all_group, -admin_qu__sentryCollection_qu = sentryCollection_query_group, sentryCollection_update_group, admin_query_group, admin_update_group, -admin_qa__sentryCollection_qu = sentryCollection_query_group, sentryCollection_update_group, admin_query_group, admin_all_group, -admin_q__sentryCollection_qu = sentryCollection_query_group, sentryCollection_update_group, admin_query_group, -admin_ua__sentryCollection_qu = sentryCollection_query_group, sentryCollection_update_group, admin_update_group, admin_all_group, -admin_u__sentryCollection_qu = sentryCollection_query_group, sentryCollection_update_group, admin_update_group, -admin_a__sentryCollection_qu = sentryCollection_query_group, sentryCollection_update_group, admin_all_group, -admin___sentryCollection_qu = sentryCollection_query_group, sentryCollection_update_group, -admin_qua__sentryCollection_qa = sentryCollection_query_group, sentryCollection_all_group, admin_query_group, admin_update_group, admin_all_group, -admin_qu__sentryCollection_qa = sentryCollection_query_group, sentryCollection_all_group, admin_query_group, admin_update_group, -admin_qa__sentryCollection_qa = sentryCollection_query_group, sentryCollection_all_group, admin_query_group, admin_all_group, -admin_q__sentryCollection_qa = sentryCollection_query_group, sentryCollection_all_group, admin_query_group, -admin_ua__sentryCollection_qa = sentryCollection_query_group, sentryCollection_all_group, admin_update_group, admin_all_group, -admin_u__sentryCollection_qa = sentryCollection_query_group, sentryCollection_all_group, admin_update_group, -admin_a__sentryCollection_qa = sentryCollection_query_group, sentryCollection_all_group, admin_all_group, -admin___sentryCollection_qa = sentryCollection_query_group, sentryCollection_all_group, -admin_qua__sentryCollection_q = sentryCollection_query_group, admin_query_group, admin_update_group, admin_all_group, -admin_qu__sentryCollection_q = sentryCollection_query_group, admin_query_group, admin_update_group, -admin_qa__sentryCollection_q = sentryCollection_query_group, admin_query_group, admin_all_group, -admin_q__sentryCollection_q = sentryCollection_query_group, admin_query_group, -admin_ua__sentryCollection_q = sentryCollection_query_group, admin_update_group, admin_all_group, -admin_u__sentryCollection_q = sentryCollection_query_group, admin_update_group, -admin_a__sentryCollection_q = sentryCollection_query_group, admin_all_group, -admin___sentryCollection_q = sentryCollection_query_group, -admin_qua__sentryCollection_ua = sentryCollection_update_group, sentryCollection_all_group, admin_query_group, admin_update_group, admin_all_group, -admin_qu__sentryCollection_ua = sentryCollection_update_group, sentryCollection_all_group, admin_query_group, admin_update_group, -admin_qa__sentryCollection_ua = sentryCollection_update_group, sentryCollection_all_group, admin_query_group, admin_all_group, -admin_q__sentryCollection_ua = sentryCollection_update_group, sentryCollection_all_group, admin_query_group, -admin_ua__sentryCollection_ua = sentryCollection_update_group, sentryCollection_all_group, admin_update_group, admin_all_group, -admin_u__sentryCollection_ua = sentryCollection_update_group, sentryCollection_all_group, admin_update_group, -admin_a__sentryCollection_ua = sentryCollection_update_group, sentryCollection_all_group, admin_all_group, -admin___sentryCollection_ua = sentryCollection_update_group, sentryCollection_all_group, -admin_qua__sentryCollection_u = sentryCollection_update_group, admin_query_group, admin_update_group, admin_all_group, -admin_qu__sentryCollection_u = sentryCollection_update_group, admin_query_group, admin_update_group, -admin_qa__sentryCollection_u = sentryCollection_update_group, admin_query_group, admin_all_group, -admin_q__sentryCollection_u = sentryCollection_update_group, admin_query_group, -admin_ua__sentryCollection_u = sentryCollection_update_group, admin_update_group, admin_all_group, -admin_u__sentryCollection_u = sentryCollection_update_group, admin_update_group, -admin_a__sentryCollection_u = sentryCollection_update_group, admin_all_group, -admin___sentryCollection_u = sentryCollection_update_group, -admin_qua__sentryCollection_a = sentryCollection_all_group, admin_query_group, admin_update_group, admin_all_group, -admin_qu__sentryCollection_a = sentryCollection_all_group, admin_query_group, admin_update_group, -admin_qa__sentryCollection_a = sentryCollection_all_group, admin_query_group, admin_all_group, -admin_q__sentryCollection_a = sentryCollection_all_group, admin_query_group, -admin_ua__sentryCollection_a = sentryCollection_all_group, admin_update_group, admin_all_group, -admin_u__sentryCollection_a = sentryCollection_all_group, admin_update_group, -admin_a__sentryCollection_a = sentryCollection_all_group, admin_all_group, -admin___sentryCollection_a = sentryCollection_all_group, -admin_qua__sentryCollection_ = admin_query_group, admin_update_group, admin_all_group, -admin_qu__sentryCollection_ = admin_query_group, admin_update_group, -admin_qa__sentryCollection_ = admin_query_group, admin_all_group, -admin_q__sentryCollection_ = admin_query_group, -admin_ua__sentryCollection_ = admin_update_group, admin_all_group, -admin_u__sentryCollection_ = admin_update_group, -admin_a__sentryCollection_ = admin_all_group, -admin___sentryCollection_ = sentryCollection_temp_group, -sentryCollection_qua = sentryCollection_query_group, sentryCollection_update_group, sentryCollection_all_group, -sentryCollection_qu = sentryCollection_query_group, sentryCollection_update_group, -sentryCollection_qa = sentryCollection_query_group, sentryCollection_all_group, -sentryCollection_q = sentryCollection_query_group, -sentryCollection_ua = sentryCollection_update_group, sentryCollection_all_group, -sentryCollection_u = sentryCollection_update_group, -sentryCollection_a = sentryCollection_all_group, -sentryCollection_ = sentryCollection_temp_group \ No newline at end of file +foo = foo
