Repository: incubator-sentry Updated Branches: refs/heads/master 4796ec9b4 -> 60bb10037
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/60bb1003/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/sentry/SentryIndexAuthorizationSingletonTest.java ---------------------------------------------------------------------- diff --git a/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/sentry/SentryIndexAuthorizationSingletonTest.java b/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/sentry/SentryIndexAuthorizationSingletonTest.java new file mode 100644 index 0000000..4bea251 --- /dev/null +++ b/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/sentry/SentryIndexAuthorizationSingletonTest.java @@ -0,0 +1,235 @@ +package org.apache.solr.sentry; +/* + * 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. + */ + +import java.lang.reflect.Constructor; +import java.util.Collection; +import java.util.EnumSet; +import java.util.Set; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.sentry.core.model.search.SearchModelAction; +import org.apache.solr.common.SolrException; +import org.apache.solr.common.params.ModifiableSolrParams; +import org.apache.solr.cloud.CloudDescriptor; +import org.apache.solr.core.SolrCore; +// import org.apache.solr.servlet.SolrHadoopAuthenticationFilter; +import org.apache.solr.request.LocalSolrQueryRequest; +import org.apache.solr.request.SolrQueryRequest; +import org.apache.solr.request.SolrQueryRequestBase; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.google.common.collect.ImmutableSet; + +/** + * Test for SentryIndexAuthorizationSingleton + */ +public class SentryIndexAuthorizationSingletonTest extends SentryTestBase { + + private static SolrCore core; + private static CloudDescriptor cloudDescriptor; + private static SentryIndexAuthorizationSingleton sentryInstance; + + @BeforeClass + public static void beforeClass() throws Exception { + core = createCore("solrconfig.xml", "schema-minimal.xml"); + // store the CloudDescriptor, because we will overwrite it with a mock + // and restore it later + cloudDescriptor = core.getCoreDescriptor().getCloudDescriptor(); + sentryInstance = SentrySingletonTestInstance.getInstance().getSentryInstance(); + } + + @AfterClass + public static void afterClass() throws Exception { + closeCore(core, cloudDescriptor); + core = null; + cloudDescriptor = null; + } + + @Override + public void setUp() throws Exception { + super.setUp(core); + } + + /** + * Expect an unauthorized SolrException with a message that contains + * msgContains. + */ + private void doExpectUnauthorized(SolrQueryRequest request, + Set<SearchModelAction> actions, String msgContains) throws Exception { + doExpectUnauthorized(sentryInstance, request, actions, msgContains); + } + + private void doExpectUnauthorized(SentryIndexAuthorizationSingleton singleton, SolrQueryRequest request, + Set<SearchModelAction> actions, String msgContains) throws Exception { + try { + singleton.authorizeCollectionAction(request, actions); + Assert.fail("Expected SolrException"); + } catch (SolrException ex) { + assertEquals(ex.code(), SolrException.ErrorCode.UNAUTHORIZED.code); + assertTrue(ex.getMessage().contains(msgContains)); + } + } + + @Test + public void testNoBinding() throws Exception { + // Use reflection to construct a non-singleton version of SentryIndexAuthorizationSingleton + // in order to get an instance without a binding + Constructor ctor = + SentryIndexAuthorizationSingleton.class.getDeclaredConstructor(String.class); + ctor.setAccessible(true); + SentryIndexAuthorizationSingleton nonSingleton = + (SentryIndexAuthorizationSingleton)ctor.newInstance(""); + doExpectUnauthorized(nonSingleton, null, null, "binding"); + + // test getUserName + try { + nonSingleton.getUserName(null); + Assert.fail("Expected Solr exception"); + } catch (SolrException ex) { + assertEquals(ex.code(), SolrException.ErrorCode.UNAUTHORIZED.code); + } + + Collection<String> groups = nonSingleton.getRoles("junit"); + assertEquals(null, groups); + } + + @Test + public void testNoHttpRequest() throws Exception { + SolrQueryRequest request = getRequest(); + doExpectUnauthorized(request, null, "HttpServletRequest"); + } + + @Test + public void testNullUserName() throws Exception { + SolrQueryRequest request = getRequest(); + prepareCollAndUser(core, request, "collection1", null); + doExpectUnauthorized(request, EnumSet.of(SearchModelAction.ALL), + "User null does not have privileges for collection1"); + } + + @Test + public void testEmptySuperUser() throws Exception { + System.setProperty("solr.authorization.superuser", ""); + SolrQueryRequest request = getRequest(); + prepareCollAndUser(core, request, "collection1", "solr"); + doExpectUnauthorized(request, EnumSet.of(SearchModelAction.ALL), + "User solr does not have privileges for collection1"); + } + + /** + * User name matches super user, should have access otherwise + */ + @Test + public void testSuperUserAccess() throws Exception { + System.setProperty("solr.authorization.superuser", "junit"); + SolrQueryRequest request = getRequest(); + prepareCollAndUser(core, request, "collection1", "junit"); + + sentryInstance.authorizeCollectionAction( + request, EnumSet.of(SearchModelAction.ALL)); + } + + /** + * User name matches super user, should not have access otherwise + */ + @Test + public void testSuperUserNoAccess() throws Exception { + System.setProperty("solr.authorization.superuser", "junit"); + SolrQueryRequest request = getRequest(); + prepareCollAndUser(core, request, "bogusCollection", "junit"); + + sentryInstance.authorizeCollectionAction( + request, EnumSet.of(SearchModelAction.ALL)); + } + + /** + * Test getting the user name. + */ + @Test + public void testUserName() throws Exception { + SolrQueryRequest request = null; + try { + // no http request + request = new SolrQueryRequestBase( core, new ModifiableSolrParams() ) {}; + try { + sentryInstance.getUserName(request); + Assert.fail("Expected SolrException"); + } catch (SolrException ex) { + assertEquals(ex.code(), SolrException.ErrorCode.UNAUTHORIZED.code); + } + + // no http request, but LocalSolrQueryRequest + LocalSolrQueryRequest localRequest = null; + try { + localRequest = new LocalSolrQueryRequest(null, new ModifiableSolrParams()); + String superUser = (System.getProperty("solr.authorization.superuser", "solr")); + String localName = sentryInstance.getUserName(localRequest); + assertEquals(superUser, localName); + } finally { + if (localRequest != null) localRequest.close(); + } + + // null userName + SolrQueryRequest sqr = getRequest(); + prepareCollAndUser(core, sqr, "collection", null, true); + String nullName = sentryInstance.getUserName(sqr); + assertEquals(null, nullName); + + // standard userName + String userName = "foobar"; + prepareCollAndUser(core, sqr, "collection", userName, true); + String returnedName = sentryInstance.getUserName(sqr); + assertEquals(userName, returnedName); + } finally { + if (request != null) request.close(); + } + } + + /** + * Test getting the roles from user name + */ + @Test + public void testGetRoles() throws Exception { + Collection<String> emptyCollection = ImmutableSet.<String>of(); + + // null user + Collection<String> roles = sentryInstance.getRoles(null); + assertTrue(CollectionUtils.isEqualCollection(emptyCollection, roles)); + + // no group + roles = sentryInstance.getRoles("bogusUser"); + assertTrue(CollectionUtils.isEqualCollection(emptyCollection, roles)); + + // no role + roles = sentryInstance.getRoles("undefinedRoleUser"); + assertTrue(CollectionUtils.isEqualCollection(emptyCollection, roles)); + + // single member + Collection<String> singleRole = ImmutableSet.<String>of("junit_role"); + roles = sentryInstance.getRoles("junit"); + assertTrue(CollectionUtils.isEqualCollection(singleRole, roles)); + + // multiple members + Collection<String> multipleRoles = ImmutableSet.<String>of("junit_role", "queryOnlyAdmin_role", "updateOnlyAdmin_role"); + roles = sentryInstance.getRoles("multiGroupUser"); + assertTrue(CollectionUtils.isEqualCollection(multipleRoles, roles)); + } +} http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/60bb1003/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/sentry/SentrySingletonTestInstance.java ---------------------------------------------------------------------- diff --git a/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/sentry/SentrySingletonTestInstance.java b/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/sentry/SentrySingletonTestInstance.java new file mode 100644 index 0000000..ae02466 --- /dev/null +++ b/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/sentry/SentrySingletonTestInstance.java @@ -0,0 +1,94 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.solr.sentry; + +import java.io.File; +import java.lang.reflect.Constructor; + +import org.apache.commons.io.FileUtils; +import org.apache.solr.SolrTestCaseJ4; +import org.apache.solr.handler.SecureRequestHandlerUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.apache.commons.codec.Charsets; + +/** + * Provides SentryIndexAuthorizationSingleton instance for use with + * sentry-related unit tests. In the unit tests, the primary + * SentryIndexAuthorizationSingleton will be initialized without a sentry-site, + * thus Sentry checking will not occur. The SentryIndexAuthorizationSingleton + * provided by getInstance in this class will be properly initialized for Sentry checking. + * + * NOTE: this is a hack, as there are multiple "singletons". It may be cleaner + * to just force the Sentry related tests to run in their own JVMs, so they + * will always have the properly-initialized SentryIndexAuthorizationSingleton. + */ +public class SentrySingletonTestInstance { + private static final Logger LOGGER = LoggerFactory.getLogger(SentrySingletonTestInstance.class); + + private static SentrySingletonTestInstance INSTANCE = new SentrySingletonTestInstance(); + private SentryIndexAuthorizationSingleton sentryInstance; + private File sentrySite; + + private 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"); + } + + public void setupSentry() throws Exception { + sentrySite = File.createTempFile("sentry-site", "xml"); + File authProviderDir = SolrTestCaseJ4.getFile("sentry-handlers/sentry"); + sentrySite.deleteOnExit(); + + // 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", + new File(authProviderDir.toString(), "test-authz-provider.ini").toURI().toURL().toString()); + sentrySiteData.append("</configuration>\n"); + FileUtils.writeStringToFile(sentrySite,sentrySiteData.toString(), Charsets.UTF_8.toString()); + } + + private SentrySingletonTestInstance() { + try { + setupSentry(); + Constructor ctor = + SentryIndexAuthorizationSingleton.class.getDeclaredConstructor(String.class); + ctor.setAccessible(true); + sentryInstance = + (SentryIndexAuthorizationSingleton)ctor.newInstance(sentrySite.toURI().toURL().toString().substring("file:".length())); + // ensure all SecureAdminHandlers use this instance + SecureRequestHandlerUtil.testOverride = sentryInstance; + } catch (Exception ex) { + LOGGER.error("Unable to create SentrySingletonTestInstance", ex); + } + } + + public static SentrySingletonTestInstance getInstance() { + return INSTANCE; + } + + public SentryIndexAuthorizationSingleton getSentryInstance() { + return sentryInstance; + } +} http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/60bb1003/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/sentry/SentryTestBase.java ---------------------------------------------------------------------- diff --git a/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/sentry/SentryTestBase.java b/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/sentry/SentryTestBase.java new file mode 100644 index 0000000..b5548e6 --- /dev/null +++ b/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/sentry/SentryTestBase.java @@ -0,0 +1,179 @@ +package org.apache.solr.sentry; +/* + * 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. + */ + +import javax.servlet.http.HttpServletRequest; + +import org.apache.solr.SolrTestCaseJ4; +import org.apache.solr.cloud.CloudDescriptor; +import org.apache.solr.common.SolrException; +import org.apache.solr.common.params.ModifiableSolrParams; +import org.apache.solr.core.CoreDescriptor; +import org.apache.solr.core.SolrCore; +import org.apache.solr.handler.RequestHandlerBase; +import org.apache.solr.request.SolrQueryRequest; +import org.apache.solr.request.SolrQueryRequestBase; +import org.apache.solr.request.SolrRequestHandler; +import org.apache.solr.response.SolrQueryResponse; +import org.easymock.EasyMock; +import org.easymock.IExpectationSetters; + +import java.lang.reflect.Field; + +import org.junit.Assert; + +/** + * Base class for Sentry tests + */ +public abstract class SentryTestBase extends SolrTestCaseJ4 { + + private static final String USER_NAME = "solr.user.name"; + + private SolrQueryRequest request; + + public void setUp(SolrCore core) throws Exception { + super.setUp(); + request = new SolrQueryRequestBase( core, new ModifiableSolrParams() ) { }; + } + + @Override + public void tearDown() throws Exception { + super.tearDown(); + request.close(); + } + + public static SolrCore createCore(String solrconfig, String schema) throws Exception { + initCore(solrconfig, schema, "sentry-handlers/solr"); + return h.getCoreContainer().getCore("collection1"); + } + + public static void closeCore(SolrCore coreToClose, CloudDescriptor cloudDescriptor) + throws Exception { + if (cloudDescriptor != null) { + CoreDescriptor coreDescriptor = coreToClose.getCoreDescriptor(); + Field cloudDescField = CoreDescriptor.class.getDeclaredField("cloudDesc"); + cloudDescField.setAccessible(true); + cloudDescField.set(coreDescriptor, cloudDescriptor); + } + coreToClose.close(); + } + + protected SolrQueryRequest getRequest() { + return request; + } + + protected SolrQueryRequest prepareCollAndUser(SolrCore core, SolrQueryRequest request, + String collection, String user) throws Exception { + return prepareCollAndUser(core, request, collection, user, true); + } + + protected SolrQueryRequest prepareCollAndUser(SolrCore core, SolrQueryRequest request, + String collection, String user, boolean onlyOnce) throws Exception { + CloudDescriptor mCloudDescriptor = EasyMock.createMock(CloudDescriptor.class); + IExpectationSetters getCollNameExpect = EasyMock.expect(mCloudDescriptor.getCollectionName()).andReturn(collection); + getCollNameExpect.anyTimes(); + IExpectationSetters getShardIdExpect = EasyMock.expect(mCloudDescriptor.getShardId()).andReturn("shard1"); + getShardIdExpect.anyTimes(); + EasyMock.replay(mCloudDescriptor); + CoreDescriptor coreDescriptor = core.getCoreDescriptor(); + Field cloudDescField = CoreDescriptor.class.getDeclaredField("cloudDesc"); + cloudDescField.setAccessible(true); + cloudDescField.set(coreDescriptor, mCloudDescriptor); + + HttpServletRequest httpServletRequest = EasyMock.createMock(HttpServletRequest.class); + IExpectationSetters getAttributeExpect = + EasyMock.expect(httpServletRequest.getAttribute(USER_NAME)).andReturn(user); + if(!onlyOnce) getAttributeExpect.anyTimes(); + EasyMock.replay(httpServletRequest); + request.getContext().put("httpRequest", httpServletRequest); + return request; + } + + private void verifyAuthorized(SolrRequestHandler handler, + RequestHandlerBase handlerBase, SolrQueryRequest req) throws Exception { + assert((handler == null && handlerBase != null) + || (handler != null && handlerBase == null)); + SolrQueryResponse rsp = new SolrQueryResponse(); + // just ensure we don't get an unauthorized exception + try { + if (handler != null) { + handler.handleRequest(req, rsp); + } else { + handlerBase.handleRequestBody(req, rsp); + } + } catch (SolrException ex) { + assertFalse(ex.code() == SolrException.ErrorCode.UNAUTHORIZED.code); + } catch (Exception ex) { + // okay, we only want to verify we didn't get an Unauthorized exception, + // going to treat each handler as a black box. + } + } + + protected void verifyAuthorized(RequestHandlerBase handlerBase, + SolrQueryRequest req) throws Exception { + verifyAuthorized(null, handlerBase, req); + } + + + protected void verifyAuthorized(SolrRequestHandler handler, + SolrQueryRequest req) throws Exception { + verifyAuthorized(handler, null, req); + } + + protected void verifyUnauthorized(SolrRequestHandler handler, + RequestHandlerBase handlerBase, SolrQueryRequest req, String collection, String user, boolean shouldFailAdmin) + throws Exception { + assert((handler == null && handlerBase != null) + || (handler != null && handlerBase == null)); + String exMsgContains = "User " + user + " does not have privileges for " + (shouldFailAdmin?"admin":collection); + SolrQueryResponse rsp = new SolrQueryResponse(); + try { + if (handler!= null) { + handler.handleRequest(req, rsp); + if (rsp.getException() != null) { + throw rsp.getException(); + } + } else { + handlerBase.handleRequestBody(req, rsp); + if (rsp.getException() != null) { + throw rsp.getException(); + } + } + Assert.fail("Expected SolrException"); + } catch (SolrException ex) { + assertEquals(SolrException.ErrorCode.UNAUTHORIZED.code, ex.code()); + assertTrue(ex.getMessage().contains(exMsgContains)); + } catch (Exception ex) { + Assert.fail("Expected SolrException"); + } + } + + protected void verifyUnauthorized(RequestHandlerBase handlerBase, + SolrQueryRequest req, String collection, String user, boolean shouldFailAdmin) throws Exception { + verifyUnauthorized(null, handlerBase, req, collection, user, shouldFailAdmin); + } + + protected void verifyUnauthorized(RequestHandlerBase handlerBase, + SolrQueryRequest req, String collection, String user) throws Exception { + verifyUnauthorized(null, handlerBase, req, collection, user, false); + } + + protected void verifyUnauthorized(SolrRequestHandler handler, + SolrQueryRequest req, String collection, String user) throws Exception { + verifyUnauthorized(handler, null, req, collection, user, false); + } +} http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/60bb1003/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/update/processor/UpdateIndexAuthorizationProcessorTest.java ---------------------------------------------------------------------- diff --git a/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/update/processor/UpdateIndexAuthorizationProcessorTest.java b/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/update/processor/UpdateIndexAuthorizationProcessorTest.java new file mode 100644 index 0000000..e297232 --- /dev/null +++ b/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/update/processor/UpdateIndexAuthorizationProcessorTest.java @@ -0,0 +1,181 @@ +package org.apache.solr.update.processor; +/* + * 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. + */ + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Arrays; +import java.util.List; +import java.util.TreeSet; + +import org.apache.commons.lang.mutable.MutableInt; +import org.apache.solr.cloud.CloudDescriptor; +import org.apache.solr.common.SolrException; +import org.apache.solr.core.SolrCore; +import org.apache.solr.request.SolrQueryRequest; +import org.apache.solr.sentry.SentryTestBase; +import org.apache.solr.sentry.SentrySingletonTestInstance; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +/** + * Test for UpdateIndexAuthorizationProcessor + */ +public class UpdateIndexAuthorizationProcessorTest extends SentryTestBase { + + private List<String> methodNames = Arrays.asList("processAdd", "processDelete", + "processMergeIndexes","processCommit", "processRollback", "finish"); + + private static SolrCore core; + private static CloudDescriptor cloudDescriptor; + + @BeforeClass + public static void beforeClass() throws Exception { + core = createCore("solrconfig.xml", "schema-minimal.xml"); + // store the CloudDescriptor, because we will overwrite it with a mock + // and restore it later + cloudDescriptor = core.getCoreDescriptor().getCloudDescriptor(); + } + + @AfterClass + public static void afterClass() throws Exception { + closeCore(core, cloudDescriptor); + core = null; + cloudDescriptor = null; + } + + @Override + public void setUp() throws Exception { + super.setUp(core); + } + + private void verifyAuthorized(String collection, String user) throws Exception { + getProcessor(collection, user).processAdd(null); + getProcessor(collection, user).processDelete(null); + getProcessor(collection, user).processMergeIndexes(null); + getProcessor(collection, user).processCommit(null); + getProcessor(collection, user).processRollback(null); + getProcessor(collection, user).finish(); + } + + private void verifyUnauthorizedException(SolrException ex, String exMsgContains, MutableInt numExceptions) { + assertEquals(ex.code(), SolrException.ErrorCode.UNAUTHORIZED.code); + assertTrue(ex.getMessage().contains(exMsgContains)); + numExceptions.add(1); + } + + private void verifyUnauthorized(String collection, String user) throws Exception { + MutableInt numExceptions = new MutableInt(0); + String contains = "User " + user + " does not have privileges for " + collection; + + try { + getProcessor(collection, user).processAdd(null); + } catch(SolrException ex) { + verifyUnauthorizedException(ex, contains, numExceptions); + } + try { + getProcessor(collection, user).processDelete(null); + } catch(SolrException ex) { + verifyUnauthorizedException(ex, contains, numExceptions); + } + try { + getProcessor(collection, user).processMergeIndexes(null); + } catch(SolrException ex) { + verifyUnauthorizedException(ex, contains, numExceptions); + } + try { + getProcessor(collection, user).processCommit(null); + } catch(SolrException ex) { + verifyUnauthorizedException(ex, contains, numExceptions); + } + try { + getProcessor(collection, user).processRollback(null); + } catch(SolrException ex) { + verifyUnauthorizedException(ex, contains, numExceptions); + } + try { + getProcessor(collection, user).finish(); + } catch(SolrException ex) { + verifyUnauthorizedException(ex, contains, numExceptions); + } + + assertEquals(methodNames.size(), numExceptions.intValue()); + } + + private UpdateIndexAuthorizationProcessor getProcessor(String collection, String user) + throws Exception { + SolrQueryRequest request = getRequest(); + prepareCollAndUser(core, request, collection, user); + return new UpdateIndexAuthorizationProcessor( + SentrySingletonTestInstance.getInstance().getSentryInstance(), request, null, null); + } + + /** + * Test the UpdateIndexAuthorizationComponent on a collection that + * the user has ALL access + */ + @Test + public void testUpdateComponentAccessAll() throws Exception { + verifyAuthorized("collection1", "junit"); + } + + /** + * Test the UpdateIndexAuthorizationComponent on a collection that + * the user has UPDATE only access + */ + @Test + public void testUpdateComponentAccessUpdate() throws Exception { + verifyAuthorized("updateCollection", "junit"); + } + + /** + * Test the UpdateIndexAuthorizationComponent on a collection that + * the user has QUERY only access + */ + @Test + public void testUpdateComponentAccessQuery() throws Exception { + verifyUnauthorized("queryCollection", "junit"); + } + + /** + * Test the UpdateIndexAuthorizationComponent on a collection that + * the user has no access + */ + @Test + public void testUpdateComponentAccessNone() throws Exception { + verifyUnauthorized("noAccessCollection", "junit"); + } + + /** + * Ensure no new methods have been added to base class that are not invoking + * Sentry + */ + @Test + public void testAllMethodsChecked() throws Exception { + Method [] methods = UpdateRequestProcessor.class.getDeclaredMethods(); + TreeSet<String> foundNames = new TreeSet<String>(); + for (Method method : methods) { + if (Modifier.isPublic(method.getModifiers())) { + foundNames.add(method.getName()); + } + } + assertEquals(methodNames.size(), foundNames.size()); + assertTrue(foundNames.containsAll(methodNames)); + } +} http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/60bb1003/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 d40dbd2..dfc3792 100644 --- a/sentry-tests/sentry-tests-solr/pom.xml +++ b/sentry-tests/sentry-tests-solr/pom.xml @@ -40,7 +40,7 @@ limitations under the License. <artifactId>solr-test-framework</artifactId> </dependency> <dependency> - <groupId>org.apache.solr</groupId> + <groupId>org.apache.sentry</groupId> <artifactId>solr-sentry-handlers</artifactId> </dependency> <dependency>
