http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/service/thrift/TestAuditLogForSentryGenericService.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/service/thrift/TestAuditLogForSentryGenericService.java b/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/service/thrift/TestAuditLogForSentryGenericService.java new file mode 100644 index 0000000..187676d --- /dev/null +++ b/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/service/thrift/TestAuditLogForSentryGenericService.java @@ -0,0 +1,296 @@ +/** + * 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.provider.db.generic.service.thrift; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.security.PrivilegedExceptionAction; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import org.apache.log4j.Level; +import org.apache.log4j.Logger; +import org.apache.sentry.provider.db.log.appender.AuditLoggerTestAppender; +import org.apache.sentry.provider.db.log.util.CommandUtil; +import org.apache.sentry.provider.db.log.util.Constants; +import org.apache.sentry.service.thrift.SentryServiceIntegrationBase; +import org.codehaus.jettison.json.JSONObject; +import org.junit.After; +import org.junit.BeforeClass; +import org.junit.Test; +import org.slf4j.LoggerFactory; + +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; + +public class TestAuditLogForSentryGenericService extends SentryServiceIntegrationBase { + + private SentryGenericServiceClient client; + private static final String COMPONENT = "SQOOP"; + private static final org.slf4j.Logger LOGGER = LoggerFactory + .getLogger(TestAuditLogForSentryGenericService.class); + + @BeforeClass + public static void setup() throws Exception { + SentryServiceIntegrationBase.setup(); + Logger logger = Logger.getLogger("sentry.generic.authorization.ddl.logger"); + AuditLoggerTestAppender testAppender = new AuditLoggerTestAppender(); + logger.addAppender(testAppender); + logger.setLevel(Level.INFO); + } + + @Override + @After + public void after() { + try { + runTestAsSubject(new TestOperation() { + @Override + public void runTestAsSubject() throws Exception { + Set<TSentryRole> tRoles = client.listAllRoles(SentryServiceIntegrationBase.ADMIN_USER, COMPONENT); + for (TSentryRole tRole : tRoles) { + client.dropRole(SentryServiceIntegrationBase.ADMIN_USER, tRole.getRoleName(), COMPONENT); + } + if (client != null) { + client.close(); + } + } + }); + } catch (Exception e) { + // log the exception + LOGGER.warn("Exception happened after test case.", e); + } finally { + policyFilePath.delete(); + } + } + + /** + * use the generic client to connect sentry service + */ + @Override + public void connectToSentryService() throws Exception { + if (SentryServiceIntegrationBase.kerberos) { + this.client = SentryServiceIntegrationBase.clientUgi.doAs(new PrivilegedExceptionAction<SentryGenericServiceClient>() { + @Override + public SentryGenericServiceClient run() throws Exception { + return SentryGenericServiceClientFactory.create(SentryServiceIntegrationBase.conf); + } + }); + } else { + this.client = SentryGenericServiceClientFactory.create(SentryServiceIntegrationBase.conf); + } + } + + @Test + public void testAuditLogForGenericModel() throws Exception { + runTestAsSubject(new TestOperation() { + @Override + public void runTestAsSubject() throws Exception { + String requestorUserName = SentryServiceIntegrationBase.ADMIN_USER; + Set<String> requestorUserGroupNames = Sets.newHashSet(SentryServiceIntegrationBase.ADMIN_GROUP); + String roleName = "admin_r"; + String testGroupName = "g1"; + String action = "all"; + String service = "sentryService"; + setLocalGroupMapping(requestorUserName, requestorUserGroupNames); + writePolicyFile(); + + // test the audit log for create role, success + client.createRole(requestorUserName, roleName, COMPONENT); + Map<String, String> fieldValueMap = new HashMap<String, String>(); + fieldValueMap.put(Constants.LOG_FIELD_OPERATION, Constants.OPERATION_CREATE_ROLE); + fieldValueMap.put(Constants.LOG_FIELD_COMPONENT, COMPONENT); + fieldValueMap.put(Constants.LOG_FIELD_OPERATION_TEXT, "CREATE ROLE " + roleName); + fieldValueMap.put(Constants.LOG_FIELD_ALLOWED, Constants.TRUE); + fieldValueMap.put(Constants.LOG_FIELD_IP_ADDRESS, null); + assertAuditLog(fieldValueMap); + + // test the audit log for create role, failed + try { + client.createRole(requestorUserName, roleName, COMPONENT); + fail("Exception should have been thrown"); + } catch (Exception e) { + fieldValueMap.clear(); + fieldValueMap.put(Constants.LOG_FIELD_OPERATION, Constants.OPERATION_CREATE_ROLE); + fieldValueMap.put(Constants.LOG_FIELD_COMPONENT, COMPONENT); + fieldValueMap.put(Constants.LOG_FIELD_OPERATION_TEXT, "CREATE ROLE " + roleName); + fieldValueMap.put(Constants.LOG_FIELD_ALLOWED, Constants.FALSE); + fieldValueMap.put(Constants.LOG_FIELD_IP_ADDRESS, null); + assertAuditLog(fieldValueMap); + } + + // test the audit log for add role to group, success + client.addRoleToGroups(requestorUserName, roleName, COMPONENT, + Sets.newHashSet(testGroupName)); + fieldValueMap.clear(); + fieldValueMap.put(Constants.LOG_FIELD_OPERATION, Constants.OPERATION_ADD_ROLE); + fieldValueMap.put(Constants.LOG_FIELD_COMPONENT, COMPONENT); + fieldValueMap.put(Constants.LOG_FIELD_OPERATION_TEXT, "GRANT ROLE " + roleName + + " TO GROUP " + testGroupName); + fieldValueMap.put(Constants.LOG_FIELD_ALLOWED, Constants.TRUE); + fieldValueMap.put(Constants.LOG_FIELD_IP_ADDRESS, null); + assertAuditLog(fieldValueMap); + + // test the audit log for add role to group, failed + try { + client.addRoleToGroups(requestorUserName, "invalidRole", COMPONENT, + Sets.newHashSet(testGroupName)); + fail("Exception should have been thrown"); + } catch (Exception e) { + fieldValueMap.clear(); + fieldValueMap.put(Constants.LOG_FIELD_OPERATION, Constants.OPERATION_ADD_ROLE); + fieldValueMap.put(Constants.LOG_FIELD_COMPONENT, COMPONENT); + fieldValueMap.put(Constants.LOG_FIELD_OPERATION_TEXT, "GRANT ROLE invalidRole TO GROUP " + + testGroupName); + fieldValueMap.put(Constants.LOG_FIELD_ALLOWED, Constants.FALSE); + fieldValueMap.put(Constants.LOG_FIELD_IP_ADDRESS, null); + assertAuditLog(fieldValueMap); + } + + // test the audit log for grant privilege, success + TSentryPrivilege privilege = new TSentryPrivilege(COMPONENT, service, Lists.newArrayList( + new TAuthorizable("resourceType1", "resourceName1"), new TAuthorizable("resourceType2", + "resourceName2")), action); + client.grantPrivilege(requestorUserName, roleName, COMPONENT, privilege); + fieldValueMap.clear(); + fieldValueMap.put(Constants.LOG_FIELD_OPERATION, Constants.OPERATION_GRANT_PRIVILEGE); + fieldValueMap.put(Constants.LOG_FIELD_COMPONENT, COMPONENT); + fieldValueMap.put(Constants.LOG_FIELD_OPERATION_TEXT, + "GRANT ALL ON resourceType1 resourceName1 resourceType2 resourceName2 TO ROLE " + + roleName); + fieldValueMap.put(Constants.LOG_FIELD_ALLOWED, Constants.TRUE); + fieldValueMap.put(Constants.LOG_FIELD_IP_ADDRESS, null); + assertAuditLog(fieldValueMap); + + // for error audit log + TSentryPrivilege invalidPrivilege = new TSentryPrivilege(COMPONENT, service, + Lists.newArrayList(new TAuthorizable("resourceType1", "resourceName1")), + "invalidAction"); + // test the audit log for grant privilege, failed + try { + client.grantPrivilege(requestorUserName, roleName, COMPONENT, invalidPrivilege); + fail("Exception should have been thrown"); + } catch (Exception e) { + fieldValueMap.clear(); + fieldValueMap.put(Constants.LOG_FIELD_OPERATION, Constants.OPERATION_GRANT_PRIVILEGE); + fieldValueMap.put(Constants.LOG_FIELD_COMPONENT, COMPONENT); + fieldValueMap.put(Constants.LOG_FIELD_OPERATION_TEXT, + "GRANT INVALIDACTION ON resourceType1 resourceName1 TO ROLE " + roleName); + fieldValueMap.put(Constants.LOG_FIELD_ALLOWED, Constants.FALSE); + fieldValueMap.put(Constants.LOG_FIELD_IP_ADDRESS, null); + assertAuditLog(fieldValueMap); + } + + // test the audit log for revoke privilege, success + client.revokePrivilege(requestorUserName, roleName, COMPONENT, privilege); + fieldValueMap.clear(); + fieldValueMap.put(Constants.LOG_FIELD_OPERATION, Constants.OPERATION_REVOKE_PRIVILEGE); + fieldValueMap.put(Constants.LOG_FIELD_COMPONENT, COMPONENT); + fieldValueMap.put(Constants.LOG_FIELD_OPERATION_TEXT, + "REVOKE ALL ON resourceType1 resourceName1 resourceType2 resourceName2 FROM ROLE " + + roleName); + fieldValueMap.put(Constants.LOG_FIELD_ALLOWED, Constants.TRUE); + fieldValueMap.put(Constants.LOG_FIELD_IP_ADDRESS, null); + assertAuditLog(fieldValueMap); + + // test the audit log for revoke privilege, failed + try { + client.revokePrivilege(requestorUserName, "invalidRole", COMPONENT, invalidPrivilege); + fail("Exception should have been thrown"); + } catch (Exception e) { + fieldValueMap.clear(); + fieldValueMap.put(Constants.LOG_FIELD_OPERATION, Constants.OPERATION_REVOKE_PRIVILEGE); + fieldValueMap.put(Constants.LOG_FIELD_COMPONENT, COMPONENT); + fieldValueMap.put(Constants.LOG_FIELD_OPERATION_TEXT, + "REVOKE INVALIDACTION ON resourceType1 resourceName1 FROM ROLE invalidRole"); + fieldValueMap.put(Constants.LOG_FIELD_ALLOWED, Constants.FALSE); + fieldValueMap.put(Constants.LOG_FIELD_IP_ADDRESS, null); + assertAuditLog(fieldValueMap); + } + + // test the audit log for delete role from group, success + client.deleteRoleToGroups(requestorUserName, roleName, COMPONENT, + Sets.newHashSet(testGroupName)); + fieldValueMap.clear(); + fieldValueMap.put(Constants.LOG_FIELD_OPERATION, Constants.OPERATION_DELETE_ROLE); + fieldValueMap.put(Constants.LOG_FIELD_COMPONENT, COMPONENT); + fieldValueMap.put(Constants.LOG_FIELD_OPERATION_TEXT, "REVOKE ROLE " + roleName + + " FROM GROUP " + testGroupName); + fieldValueMap.put(Constants.LOG_FIELD_ALLOWED, Constants.TRUE); + fieldValueMap.put(Constants.LOG_FIELD_IP_ADDRESS, null); + assertAuditLog(fieldValueMap); + // test the audit log for delete role from group, failed + try { + client.deleteRoleToGroups(requestorUserName, "invalidRole", COMPONENT, + Sets.newHashSet(testGroupName)); + fail("Exception should have been thrown"); + } catch (Exception e) { + fieldValueMap.clear(); + fieldValueMap.put(Constants.LOG_FIELD_OPERATION, Constants.OPERATION_DELETE_ROLE); + fieldValueMap.put(Constants.LOG_FIELD_COMPONENT, COMPONENT); + fieldValueMap.put(Constants.LOG_FIELD_OPERATION_TEXT, + "REVOKE ROLE invalidRole FROM GROUP " + testGroupName); + fieldValueMap.put(Constants.LOG_FIELD_ALLOWED, Constants.FALSE); + fieldValueMap.put(Constants.LOG_FIELD_IP_ADDRESS, null); + assertAuditLog(fieldValueMap); + } + // test the audit log for drop role, success + client.dropRole(requestorUserName, roleName, COMPONENT); + fieldValueMap.clear(); + fieldValueMap.put(Constants.LOG_FIELD_OPERATION, Constants.OPERATION_DROP_ROLE); + fieldValueMap.put(Constants.LOG_FIELD_COMPONENT, COMPONENT); + fieldValueMap.put(Constants.LOG_FIELD_OPERATION_TEXT, "DROP ROLE " + roleName); + fieldValueMap.put(Constants.LOG_FIELD_ALLOWED, Constants.TRUE); + fieldValueMap.put(Constants.LOG_FIELD_IP_ADDRESS, null); + assertAuditLog(fieldValueMap); + // test the audit log for drop role, failed + try { + client.dropRole(requestorUserName, roleName, COMPONENT); + fail("Exception should have been thrown"); + } catch (Exception e) { + fieldValueMap.clear(); + fieldValueMap.put(Constants.LOG_FIELD_OPERATION, Constants.OPERATION_DROP_ROLE); + fieldValueMap.put(Constants.LOG_FIELD_COMPONENT, COMPONENT); + fieldValueMap.put(Constants.LOG_FIELD_OPERATION_TEXT, "DROP ROLE " + roleName); + fieldValueMap.put(Constants.LOG_FIELD_ALLOWED, Constants.FALSE); + fieldValueMap.put(Constants.LOG_FIELD_IP_ADDRESS, null); + assertAuditLog(fieldValueMap); + } + } + }); + } + + private void assertAuditLog(Map<String, String> fieldValueMap) throws Exception { + assertThat(AuditLoggerTestAppender.getLastLogLevel(), is(Level.INFO)); + JSONObject jsonObject = new JSONObject(AuditLoggerTestAppender.getLastLogEvent()); + if (fieldValueMap != null) { + for (Map.Entry<String, String> entry : fieldValueMap.entrySet()) { + String entryKey = entry.getKey(); + if (Constants.LOG_FIELD_IP_ADDRESS.equals(entryKey)) { + assertTrue(CommandUtil.assertIPInAuditLog(jsonObject.get(entryKey).toString())); + } else { + assertTrue(entry.getValue().equalsIgnoreCase(jsonObject.get(entryKey).toString())); + } + } + } + } +}
http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/service/thrift/TestSentryGenericPolicyProcessor.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/service/thrift/TestSentryGenericPolicyProcessor.java b/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/service/thrift/TestSentryGenericPolicyProcessor.java new file mode 100644 index 0000000..8b3599f --- /dev/null +++ b/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/service/thrift/TestSentryGenericPolicyProcessor.java @@ -0,0 +1,349 @@ +/** + * 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.provider.db.generic.service.thrift; + +import java.util.*; + +import org.apache.hadoop.conf.Configuration; +import org.apache.sentry.core.common.Authorizable; +import org.apache.sentry.core.common.exception.SentrySiteConfigurationException; +import org.apache.sentry.core.model.search.Collection; +import org.apache.sentry.core.model.search.Field; +import org.apache.sentry.core.model.search.SearchConstants; +import org.apache.sentry.core.common.service.GroupMappingService; +import org.apache.sentry.core.common.exception.SentryAlreadyExistsException; +import org.apache.sentry.core.common.exception.SentryGrantDeniedException; +import org.apache.sentry.core.common.exception.SentryInvalidInputException; +import org.apache.sentry.core.common.exception.SentryNoSuchObjectException; +import org.apache.sentry.provider.db.generic.service.persistent.PrivilegeObject; +import org.apache.sentry.provider.db.generic.service.persistent.SentryStoreLayer; +import org.apache.sentry.provider.db.generic.service.persistent.PrivilegeObject.Builder; +import org.apache.sentry.provider.db.service.model.MSentryGMPrivilege; +import org.apache.sentry.provider.db.service.model.MSentryRole; +import org.apache.sentry.provider.db.service.persistent.CommitContext; +import org.apache.sentry.provider.db.service.thrift.PolicyStoreConstants; +import org.apache.sentry.service.thrift.ServiceConstants.ServerConfig; +import org.apache.sentry.service.thrift.Status; +import org.apache.sentry.service.thrift.TSentryResponseStatus; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; +import org.mockito.Matchers; + +import com.google.common.collect.Sets; + +public class TestSentryGenericPolicyProcessor extends org.junit.Assert { + private static final String ADMIN_GROUP = "admin_group"; + private static final String ADMIN_USER = "admin_user"; + private static final UUID SERVER_UUID = UUID.randomUUID(); + private static final long SEQ_ID = 10000; + + private SentryStoreLayer mockStore = Mockito.mock(SentryStoreLayer.class); + private SentryGenericPolicyProcessor processor; + + @Before + public void setup() throws Exception { + Configuration conf = new Configuration(); + conf.set(ServerConfig.ADMIN_GROUPS, ADMIN_GROUP); + conf.set(ServerConfig.SENTRY_STORE_GROUP_MAPPING, MockGroupMapping.class.getName()); + processor = new SentryGenericPolicyProcessor(conf, mockStore); + } + + @Test + public void testNotAdminOperation() throws Exception { + String requestUser = "not_" + ADMIN_USER; + Status validateStatus = Status.ACCESS_DENIED; + testOperation(requestUser, validateStatus); + } + + private void testOperation(String requestUser, Status validateStatus) throws Exception { + TCreateSentryRoleRequest createrequest = new TCreateSentryRoleRequest(); + createrequest.setRequestorUserName(requestUser); + createrequest.setRoleName("r1"); + assertEquals(validateStatus, fromTSentryStatus(processor.create_sentry_role(createrequest).getStatus())); + + TDropSentryRoleRequest dropRequest = new TDropSentryRoleRequest(); + dropRequest.setRequestorUserName(requestUser); + dropRequest.setRoleName("r1"); + assertEquals(validateStatus, fromTSentryStatus(processor.drop_sentry_role(dropRequest).getStatus())); + + TAlterSentryRoleAddGroupsRequest addRequest = new TAlterSentryRoleAddGroupsRequest(); + addRequest.setRequestorUserName(requestUser); + addRequest.setRoleName("r1"); + addRequest.setGroups(Sets.newHashSet("g1")); + assertEquals(validateStatus, fromTSentryStatus(processor.alter_sentry_role_add_groups(addRequest).getStatus())); + + TAlterSentryRoleDeleteGroupsRequest delRequest = new TAlterSentryRoleDeleteGroupsRequest(); + delRequest.setRequestorUserName(requestUser); + delRequest.setRoleName("r1"); + delRequest.setGroups(Sets.newHashSet("g1")); + assertEquals(validateStatus, fromTSentryStatus(processor.alter_sentry_role_delete_groups(delRequest).getStatus())); + + TDropPrivilegesRequest dropPrivRequest = new TDropPrivilegesRequest(); + dropPrivRequest.setRequestorUserName(requestUser); + dropPrivRequest.setPrivilege(new TSentryPrivilege("test", "test", new ArrayList<TAuthorizable>(), "test")); + assertEquals(validateStatus, fromTSentryStatus(processor.drop_sentry_privilege(dropPrivRequest).getStatus())); + + TRenamePrivilegesRequest renameRequest = new TRenamePrivilegesRequest(); + renameRequest.setRequestorUserName(requestUser); + assertEquals(validateStatus, fromTSentryStatus(processor.rename_sentry_privilege(renameRequest).getStatus())); + } + + private Status fromTSentryStatus(TSentryResponseStatus status) { + return Status.fromCode(status.getValue()); + } + + @Test + public void testAdminOperation() throws Exception { + Mockito.when(mockStore.createRole(Matchers.anyString(), Matchers.anyString(), Matchers.anyString())) + .thenReturn(new CommitContext(SERVER_UUID, SEQ_ID)); + + Mockito.when(mockStore.dropRole(Matchers.anyString(), Matchers.anyString(), Matchers.anyString())) + .thenReturn(new CommitContext(SERVER_UUID, SEQ_ID + 1)); + + Mockito.when(mockStore.alterRoleAddGroups(Matchers.anyString(), Matchers.anyString(), Matchers.anySetOf(String.class), Matchers.anyString())) + .thenReturn(new CommitContext(SERVER_UUID, SEQ_ID + 2)); + + Mockito.when(mockStore.alterRoleDeleteGroups(Matchers.anyString(), Matchers.anyString(), Matchers.anySetOf(String.class), Matchers.anyString())) + .thenReturn(new CommitContext(SERVER_UUID, SEQ_ID + 3)); + + Mockito.when(mockStore.dropPrivilege(Matchers.anyString(), Matchers.any(PrivilegeObject.class), Matchers.anyString())) + .thenReturn(new CommitContext(SERVER_UUID, SEQ_ID + 4)); + + Mockito.when(mockStore.renamePrivilege(Matchers.anyString(), Matchers.anyString(), Matchers.anyListOf(Authorizable.class), + Matchers.anyListOf(Authorizable.class), Matchers.anyString())) + .thenReturn(new CommitContext(SERVER_UUID, SEQ_ID + 5)); + testOperation(ADMIN_USER, Status.OK); + } + + @Test + public void testGrantAndRevokePrivilege() throws Exception { + Mockito.when(mockStore.alterRoleGrantPrivilege(Matchers.anyString(), Matchers.anyString(), Matchers.any(PrivilegeObject.class), Matchers.anyString())) + .thenReturn(new CommitContext(SERVER_UUID, SEQ_ID + 6)); + + Mockito.when(mockStore.alterRoleRevokePrivilege(Matchers.anyString(), Matchers.anyString(), Matchers.any(PrivilegeObject.class), Matchers.anyString())) + .thenReturn(new CommitContext(SERVER_UUID, SEQ_ID + 7)); + setup(); + + TSentryPrivilege tprivilege = new TSentryPrivilege("test", "test", new ArrayList<TAuthorizable>(), "test"); + tprivilege.setGrantOption(TSentryGrantOption.UNSET); + + TAlterSentryRoleGrantPrivilegeRequest grantRequest = new TAlterSentryRoleGrantPrivilegeRequest(); + grantRequest.setRequestorUserName(ADMIN_USER); + grantRequest.setRoleName("r1"); + grantRequest.setPrivilege(tprivilege); + assertEquals(Status.OK, fromTSentryStatus(processor.alter_sentry_role_grant_privilege(grantRequest).getStatus())); + + TAlterSentryRoleRevokePrivilegeRequest revokeRequest = new TAlterSentryRoleRevokePrivilegeRequest(); + revokeRequest.setRequestorUserName(ADMIN_USER); + revokeRequest.setRoleName("r1"); + revokeRequest.setPrivilege(tprivilege); + assertEquals(Status.OK, fromTSentryStatus(processor.alter_sentry_role_revoke_privilege(revokeRequest).getStatus())); + } + + @Test + public void testOperationWithException() throws Exception { + String roleName = Matchers.anyString(); + Mockito.when(mockStore.createRole(Matchers.anyString(), roleName, Matchers.anyString())) + .thenThrow(new SentryAlreadyExistsException("Role: " + roleName + " already exists")); + + roleName = Matchers.anyString(); + Mockito.when(mockStore.dropRole(Matchers.anyString(), roleName, Matchers.anyString())) + .thenThrow(new SentryNoSuchObjectException("Role: " + roleName + " doesn't exist")); + + roleName = Matchers.anyString(); + Mockito.when(mockStore.alterRoleAddGroups(Matchers.anyString(), roleName, Matchers.anySetOf(String.class), Matchers.anyString())) + .thenThrow(new SentryNoSuchObjectException("Role: " + roleName + " doesn't exist")); + + roleName = Matchers.anyString(); + Mockito.when(mockStore.alterRoleDeleteGroups(Matchers.anyString(), roleName, Matchers.anySetOf(String.class), Matchers.anyString())) + .thenThrow(new SentryNoSuchObjectException("Role: " + roleName + " doesn't exist")); + + roleName = Matchers.anyString(); + Mockito.when(mockStore.alterRoleGrantPrivilege(Matchers.anyString(), roleName, Matchers.any(PrivilegeObject.class), Matchers.anyString())) + .thenThrow(new SentryGrantDeniedException("Role: " + roleName + " is not allowed to do grant")); + + roleName = Matchers.anyString(); + Mockito.when(mockStore.alterRoleRevokePrivilege(Matchers.anyString(), roleName, Matchers.any(PrivilegeObject.class), Matchers.anyString())) + .thenThrow(new SentryGrantDeniedException("Role: " + roleName + " is not allowed to do grant")); + + Mockito.when(mockStore.dropPrivilege(Matchers.anyString(), Matchers.any(PrivilegeObject.class), Matchers.anyString())) + .thenThrow(new SentryInvalidInputException("Invalid input privilege object")); + + Mockito.when(mockStore.renamePrivilege(Matchers.anyString(), Matchers.anyString(), Matchers.anyListOf(Authorizable.class), + Matchers.anyListOf(Authorizable.class), Matchers.anyString())) + .thenThrow(new RuntimeException("Unknown error")); + + setup(); + + TCreateSentryRoleRequest createrequest = new TCreateSentryRoleRequest(); + createrequest.setRequestorUserName(ADMIN_USER); + createrequest.setRoleName("r1"); + assertEquals(Status.ALREADY_EXISTS, fromTSentryStatus(processor.create_sentry_role(createrequest).getStatus())); + + TDropSentryRoleRequest dropRequest = new TDropSentryRoleRequest(); + dropRequest.setRequestorUserName(ADMIN_USER); + dropRequest.setRoleName("r1"); + assertEquals(Status.NO_SUCH_OBJECT, fromTSentryStatus(processor.drop_sentry_role(dropRequest).getStatus())); + + TAlterSentryRoleAddGroupsRequest addRequest = new TAlterSentryRoleAddGroupsRequest(); + addRequest.setRequestorUserName(ADMIN_USER); + addRequest.setRoleName("r1"); + addRequest.setGroups(Sets.newHashSet("g1")); + assertEquals(Status.NO_SUCH_OBJECT, fromTSentryStatus(processor.alter_sentry_role_add_groups(addRequest).getStatus())); + + TAlterSentryRoleDeleteGroupsRequest delRequest = new TAlterSentryRoleDeleteGroupsRequest(); + delRequest.setRequestorUserName(ADMIN_USER); + delRequest.setRoleName("r1"); + delRequest.setGroups(Sets.newHashSet("g1")); + assertEquals(Status.NO_SUCH_OBJECT, fromTSentryStatus(processor.alter_sentry_role_delete_groups(delRequest).getStatus())); + + TDropPrivilegesRequest dropPrivRequest = new TDropPrivilegesRequest(); + dropPrivRequest.setRequestorUserName(ADMIN_USER); + dropPrivRequest.setPrivilege(new TSentryPrivilege("test", "test", new ArrayList<TAuthorizable>(), "test")); + assertEquals(Status.INVALID_INPUT, fromTSentryStatus(processor.drop_sentry_privilege(dropPrivRequest).getStatus())); + + TRenamePrivilegesRequest renameRequest = new TRenamePrivilegesRequest(); + renameRequest.setRequestorUserName(ADMIN_USER); + assertEquals(Status.RUNTIME_ERROR, fromTSentryStatus(processor.rename_sentry_privilege(renameRequest).getStatus())); + + TSentryPrivilege tprivilege = new TSentryPrivilege("test", "test", new ArrayList<TAuthorizable>(), "test"); + tprivilege.setGrantOption(TSentryGrantOption.UNSET); + + TAlterSentryRoleGrantPrivilegeRequest grantRequest = new TAlterSentryRoleGrantPrivilegeRequest(); + grantRequest.setRequestorUserName(ADMIN_USER); + grantRequest.setRoleName("r1"); + grantRequest.setPrivilege(tprivilege); + assertEquals(Status.ACCESS_DENIED, fromTSentryStatus(processor.alter_sentry_role_grant_privilege(grantRequest).getStatus())); + + TAlterSentryRoleRevokePrivilegeRequest revokeRequest = new TAlterSentryRoleRevokePrivilegeRequest(); + revokeRequest.setRequestorUserName(ADMIN_USER); + revokeRequest.setRoleName("r1"); + revokeRequest.setPrivilege(tprivilege); + assertEquals(Status.ACCESS_DENIED, fromTSentryStatus(processor.alter_sentry_role_revoke_privilege(revokeRequest).getStatus())); + } + + @Test + public void testGetRolesAndPrivileges() throws Exception { + String roleName = "r1"; + String groupName = "g1"; + PrivilegeObject queryPrivilege = new Builder() + .setComponent("SOLR") + .setAction(SearchConstants.QUERY) + .setService("service1") + .setAuthorizables(Arrays.asList(new Collection("c1"), new Field("f1"))) + .build(); + PrivilegeObject updatePrivilege = new Builder(queryPrivilege) + .setAction(SearchConstants.UPDATE) + .build(); + + MSentryGMPrivilege mSentryGMPrivilege = new MSentryGMPrivilege("SOLR", "service1", + Arrays.asList(new Collection("c1"), new Field("f1")), + SearchConstants.QUERY, true); + + MSentryRole role = new MSentryRole("r1", 290); + mSentryGMPrivilege.setRoles(Sets.newHashSet(role)); + + Mockito.when(mockStore.getRolesByGroups(Matchers.anyString(), Matchers.anySetOf(String.class))) + .thenReturn(Sets.newHashSet(roleName)); + + Mockito.when(mockStore.getPrivilegesByProvider(Matchers.anyString(), Matchers.anyString(), Matchers.anySetOf(String.class), + Matchers.anySetOf(String.class), Matchers.anyListOf(Authorizable.class))) + .thenReturn(Sets.newHashSet(queryPrivilege, updatePrivilege)); + + Mockito.when(mockStore.getGroupsByRoles(Matchers.anyString(), Matchers.anySetOf(String.class))) + .thenReturn(Sets.newHashSet(groupName)); + + Mockito.when(mockStore.getPrivilegesByAuthorizable(Matchers.anyString(), Matchers.anyString(), Matchers.anySetOf(String.class), Matchers.anyListOf(Authorizable.class))) + .thenReturn(Sets.newHashSet(mSentryGMPrivilege)); + + Mockito.when(mockStore.getAllRoleNames()) + .thenReturn(Sets.newHashSet(roleName)); + + TListSentryPrivilegesRequest request1 = new TListSentryPrivilegesRequest(); + request1.setRoleName(roleName); + request1.setRequestorUserName(ADMIN_USER); + TListSentryPrivilegesResponse response1 = processor.list_sentry_privileges_by_role(request1); + assertEquals(Status.OK, fromTSentryStatus(response1.getStatus())); + assertEquals(2, response1.getPrivileges().size()); + + TListSentryRolesRequest request2 = new TListSentryRolesRequest(); + request2.setRequestorUserName(ADMIN_USER); + request2.setGroupName(groupName); + TListSentryRolesResponse response2 = processor.list_sentry_roles_by_group(request2); + assertEquals(Status.OK, fromTSentryStatus(response2.getStatus())); + assertEquals(1, response2.getRoles().size()); + + TListSentryPrivilegesForProviderRequest request3 = new TListSentryPrivilegesForProviderRequest(); + request3.setGroups(Sets.newHashSet(groupName)); + request3.setRoleSet(new TSentryActiveRoleSet(true, null)); + TListSentryPrivilegesForProviderResponse response3 = processor.list_sentry_privileges_for_provider(request3); + assertEquals(Status.OK, fromTSentryStatus(response3.getStatus())); + assertEquals(2, response3.getPrivileges().size()); + + // Optional parameters activeRoleSet and requested group name are both provided. + TListSentryPrivilegesByAuthRequest request4 = new TListSentryPrivilegesByAuthRequest(); + request4.setGroups(Sets.newHashSet(groupName)); + request4.setRoleSet(new TSentryActiveRoleSet(true, null)); + request4.setRequestorUserName(ADMIN_USER); + Set<String> authorizablesSet = Sets.newHashSet("Collection=c1->Field=f1"); + request4.setAuthorizablesSet(authorizablesSet); + + TListSentryPrivilegesByAuthResponse response4 = processor.list_sentry_privileges_by_authorizable(request4); + assertEquals(Status.OK, fromTSentryStatus(response4.getStatus())); + assertEquals(1, response4.getPrivilegesMapByAuth().size()); + + // Optional parameters activeRoleSet and requested group name are both not provided. + TListSentryPrivilegesByAuthRequest request5 = new TListSentryPrivilegesByAuthRequest(); + request5.setRequestorUserName("not_" + ADMIN_USER); + authorizablesSet = Sets.newHashSet("Collection=c1->Field=f2"); + request5.setAuthorizablesSet(authorizablesSet); + + TListSentryPrivilegesByAuthResponse response5 = processor.list_sentry_privileges_by_authorizable(request5); + assertEquals(Status.OK, fromTSentryStatus(response5.getStatus())); + assertEquals(1, response5.getPrivilegesMapByAuth().size()); + } + + @Test(expected=SentrySiteConfigurationException.class) + public void testConfigCannotCreateNotificationHandler() throws Exception { + Configuration conf = new Configuration(); + conf.set(PolicyStoreConstants.SENTRY_GENERIC_POLICY_NOTIFICATION,"junk"); + SentryGenericPolicyProcessor.createHandlers(conf); + } + + @Test(expected=SentrySiteConfigurationException.class) + public void testConfigCannotCreateSentryStore() throws Exception { + Configuration conf = new Configuration(); + conf.set(PolicyStoreConstants.SENTRY_GENERIC_POLICY_STORE,"junk"); + SentryGenericPolicyProcessor.createStore(conf); + } + + public static class MockGroupMapping implements GroupMappingService { + public MockGroupMapping(Configuration conf, String resource) { //NOPMD + } + @Override + public Set<String> getGroups(String user) { + if (user.equalsIgnoreCase(ADMIN_USER)) { + return Sets.newHashSet(ADMIN_GROUP); + } else { + return Sets.newHashSet("not" + ADMIN_GROUP); + } + } + } + +} http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/service/thrift/TestSentryGenericServiceIntegration.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/service/thrift/TestSentryGenericServiceIntegration.java b/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/service/thrift/TestSentryGenericServiceIntegration.java new file mode 100644 index 0000000..b59d172 --- /dev/null +++ b/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/service/thrift/TestSentryGenericServiceIntegration.java @@ -0,0 +1,503 @@ +/** + * 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.provider.db.generic.service.thrift; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.sentry.core.common.exception.SentryUserException; +import org.apache.sentry.core.common.ActiveRoleSet; +import org.apache.sentry.core.common.Authorizable; +import org.apache.sentry.core.model.search.Collection; +import org.apache.sentry.core.model.search.Field; +import org.apache.sentry.core.model.search.SearchConstants; +import org.junit.Test; + +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; + +public class TestSentryGenericServiceIntegration extends SentryGenericServiceIntegrationBase { + + @Test + public void testCreateDropShowRole() throws Exception { + runTestAsSubject(new TestOperation(){ + @Override + public void runTestAsSubject() throws Exception { + String requestorUserName = ADMIN_USER; + Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP); + String roleName = "admin_r"; + setLocalGroupMapping(requestorUserName, requestorUserGroupNames); + writePolicyFile(); + + client.dropRoleIfExists(requestorUserName, roleName, SOLR); + + client.createRole(requestorUserName, roleName, SOLR); + + client.addRoleToGroups(requestorUserName, roleName, SOLR, Sets.newHashSet(requestorUserGroupNames)); + + Set<TSentryRole> roles = client.listUserRoles(requestorUserName,SOLR); + assertEquals("Incorrect number of roles", 1, roles.size()); + for (TSentryRole role:roles) { + assertTrue(role.getRoleName(), role.getRoleName().equalsIgnoreCase(roleName)); + } + client.dropRole(requestorUserName, roleName, SOLR); + }}); + } + + @Test + public void testAddDeleteRoleToGroup() throws Exception { + runTestAsSubject(new TestOperation(){ + @Override + public void runTestAsSubject() throws Exception { + String requestorUserName = ADMIN_USER; + Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP); + String testGroupName = "g1"; + String roleName = "admin_r"; + setLocalGroupMapping(requestorUserName, requestorUserGroupNames); + setLocalGroupMapping(requestorUserName, Sets.newHashSet(testGroupName)); + writePolicyFile(); + + client.dropRoleIfExists(requestorUserName, roleName, SOLR); + + client.createRole(requestorUserName, roleName, SOLR); + + client.addRoleToGroups(requestorUserName, roleName, SOLR, Sets.newHashSet(testGroupName)); + + Set<TSentryRole> roles = client.listUserRoles(requestorUserName,SOLR); + assertEquals("Incorrect number of roles", 1, roles.size()); + for (TSentryRole role:roles) { + assertTrue(role.getRoleName(), role.getRoleName().equalsIgnoreCase(roleName)); + assertTrue(role.getGroups().size() == 1); + for (String group :role.getGroups()) { + assertEquals(testGroupName, group); + } + } + + client.deleteRoleToGroups(requestorUserName, roleName, SOLR, Sets.newHashSet(testGroupName)); + roles = client.listUserRoles(requestorUserName,SOLR); + assertEquals("Incorrect number of roles", 0, roles.size()); + + client.dropRole(requestorUserName, roleName, SOLR); + }}); + } + + @Test + public void testGranRevokePrivilege() throws Exception { + runTestAsSubject(new TestOperation(){ + @Override + public void runTestAsSubject() throws Exception { + String requestorUserName = ADMIN_USER; + Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP); + setLocalGroupMapping(requestorUserName, requestorUserGroupNames); + writePolicyFile(); + String roleName1 = "admin_r1"; + String roleName2 = "admin_r2"; + + client.dropRoleIfExists(requestorUserName, roleName1, SOLR); + client.createRole(requestorUserName, roleName1, SOLR); + + client.dropRoleIfExists(requestorUserName, roleName2, SOLR); + client.createRole(requestorUserName, roleName2, SOLR); + + TSentryPrivilege queryPrivilege = new TSentryPrivilege(SOLR, "service1", + fromAuthorizable(Arrays.asList(new Collection("c1"), new Field("f1"))), + SearchConstants.QUERY); + + TSentryPrivilege updatePrivilege = new TSentryPrivilege(SOLR, "service1", + fromAuthorizable(Arrays.asList(new Collection("c1"), new Field("f1"))), + SearchConstants.UPDATE); + + client.grantPrivilege(requestorUserName, roleName1, SOLR, queryPrivilege); + client.grantPrivilege(requestorUserName, roleName2, SOLR, updatePrivilege); + + client.revokePrivilege(requestorUserName, roleName1, SOLR, queryPrivilege); + client.revokePrivilege(requestorUserName, roleName2, SOLR, updatePrivilege); + }}); + } + + @Test + public void testMultipleRolesSamePrivilege() throws Exception { + runTestAsSubject(new TestOperation(){ + @Override + public void runTestAsSubject() throws Exception { + String requestorUserName = ADMIN_USER; + Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP); + setLocalGroupMapping(requestorUserName, requestorUserGroupNames); + writePolicyFile(); + String roleName1 = "admin_r1"; + String roleName2 = "admin_r2"; + + client.dropRoleIfExists(requestorUserName, roleName1, SOLR); + client.createRole(requestorUserName, roleName1, SOLR); + + client.dropRoleIfExists(requestorUserName, roleName2, SOLR); + client.createRole(requestorUserName, roleName2, SOLR); + + TSentryPrivilege queryPrivilege = new TSentryPrivilege(SOLR, "service1", + fromAuthorizable(Arrays.asList(new Collection("c1"), new Field("f1"))), + SearchConstants.QUERY); + + client.grantPrivilege(requestorUserName, roleName1, SOLR, queryPrivilege); + Set<TSentryPrivilege> listPrivilegesByRoleName = client.listPrivilegesByRoleName(requestorUserName, roleName1, SOLR, "service1"); + assertTrue("Privilege not assigned to role1 !!", listPrivilegesByRoleName.size() == 1); + + client.grantPrivilege(requestorUserName, roleName2, SOLR, queryPrivilege); + listPrivilegesByRoleName = client.listPrivilegesByRoleName(requestorUserName, roleName2, SOLR, "service1"); + assertTrue("Privilege not assigned to role2 !!", listPrivilegesByRoleName.size() == 1); + }}); + } + + @Test + public void testShowRoleGrant() throws Exception { + runTestAsSubject(new TestOperation(){ + @Override + public void runTestAsSubject() throws Exception { + String requestorUserName = ADMIN_USER; + Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP); + String roleName = "admin_r1"; + String groupName = "group1"; + setLocalGroupMapping(requestorUserName, requestorUserGroupNames); + setLocalGroupMapping(requestorUserName, Sets.newHashSet(groupName)); + writePolicyFile(); + + client.dropRoleIfExists(requestorUserName, roleName, SOLR); + client.createRole(requestorUserName, roleName, SOLR); + client.addRoleToGroups(requestorUserName, roleName, SOLR, Sets.newHashSet(groupName)); + + Set<TSentryRole> groupRoles = client.listRolesByGroupName(requestorUserName, groupName,SOLR); + assertTrue(groupRoles.size() == 1); + for (TSentryRole role:groupRoles) { + assertTrue(role.getRoleName(), role.getRoleName().equalsIgnoreCase(roleName)); + assertTrue(role.getGroups().size() == 1); + for (String group :role.getGroups()) { + assertEquals(groupName, group); + } + } + + client.dropRole(requestorUserName, roleName, SOLR); + }}); + } + + @Test + public void testShowGrant() throws Exception { + runTestAsSubject(new TestOperation(){ + @Override + public void runTestAsSubject() throws Exception { + String requestorUserName = ADMIN_USER; + Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP); + String roleName = "admin_r1"; + setLocalGroupMapping(requestorUserName, requestorUserGroupNames); + writePolicyFile(); + + client.dropRoleIfExists(requestorUserName, roleName, SOLR); + client.createRole(requestorUserName, roleName, SOLR); + + TSentryPrivilege queryPrivilege = new TSentryPrivilege(SOLR, "service1", + fromAuthorizable(Arrays.asList(new Collection("c1"), new Field("f1"))), + SearchConstants.QUERY); + + TSentryPrivilege updatePrivilege = new TSentryPrivilege(SOLR, "service1", + fromAuthorizable(Arrays.asList(new Collection("c1"), new Field("f1"))), + SearchConstants.UPDATE); + + client.grantPrivilege(requestorUserName, roleName, SOLR, updatePrivilege); + client.grantPrivilege(requestorUserName, roleName, SOLR, queryPrivilege); + Set<TSentryPrivilege> privileges = client.listPrivilegesByRoleName(requestorUserName, roleName, SOLR, "service1"); + assertTrue(privileges.size() == 2); + + client.revokePrivilege(requestorUserName, roleName, SOLR, updatePrivilege); + privileges = client.listPrivilegesByRoleName(requestorUserName, roleName, SOLR, "service1"); + assertTrue(privileges.size() == 1); + }}); + } + + @Test + public void testSameGrantTwice() throws Exception { + runTestAsSubject(new TestOperation(){ + @Override + public void runTestAsSubject() throws Exception { + String requestorUserName = ADMIN_USER; + Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP); + setLocalGroupMapping(requestorUserName, requestorUserGroupNames); + writePolicyFile(); + String roleName = "admin_r1"; + + client.createRole(requestorUserName, roleName, SOLR); + + TSentryPrivilege queryPrivilege = new TSentryPrivilege(SOLR, "service1", + fromAuthorizable(Arrays.asList(new Collection("c1"), new Field("f1"))), + SearchConstants.QUERY); + + client.grantPrivilege(requestorUserName, roleName, SOLR, queryPrivilege); + assertEquals(1, client.listPrivilegesByRoleName(requestorUserName, roleName, SOLR, "service1").size()); + }}); + } + + @Test + public void testGrantRevokeWithGrantOption() throws Exception { + runTestAsSubject(new TestOperation(){ + @Override + public void runTestAsSubject() throws Exception { + String adminUser = ADMIN_USER; + Set<String> adminGroup = Sets.newHashSet(ADMIN_GROUP); + String grantOptionUser = "user1"; + Set<String> grantOptionGroup = Sets.newHashSet("group1"); + String noGrantOptionUser = "user2"; + Set<String> noGrantOptionGroup = Sets.newHashSet("group2"); + + setLocalGroupMapping(adminUser, adminGroup); + setLocalGroupMapping(grantOptionUser, grantOptionGroup); + setLocalGroupMapping(noGrantOptionUser, noGrantOptionGroup); + writePolicyFile(); + + String grantRole = "grant_r"; + String noGrantRole = "no_grant_r"; + String testRole = "test_role"; + + client.createRole(adminUser, grantRole, SOLR); + client.createRole(adminUser, noGrantRole, SOLR); + client.createRole(adminUser, testRole, SOLR); + + TSentryPrivilege grantPrivilege = new TSentryPrivilege(SOLR, "service1", + fromAuthorizable(Arrays.asList(new Collection("c1"))), + SearchConstants.QUERY); + grantPrivilege.setGrantOption(TSentryGrantOption.TRUE); + + TSentryPrivilege noGrantPrivilege = new TSentryPrivilege(SOLR, "service1", + fromAuthorizable(Arrays.asList(new Collection("c1"))), + SearchConstants.QUERY); + noGrantPrivilege.setGrantOption(TSentryGrantOption.FALSE); + + TSentryPrivilege testPrivilege = new TSentryPrivilege(SOLR, "service1", + fromAuthorizable(Arrays.asList(new Collection("c1"), new Field("f1"))), + SearchConstants.QUERY); + testPrivilege.setGrantOption(TSentryGrantOption.FALSE); + + client.grantPrivilege(adminUser, grantRole, SOLR, grantPrivilege); + client.grantPrivilege(adminUser, noGrantRole, SOLR, noGrantPrivilege); + + client.addRoleToGroups(adminUser, grantRole, SOLR, grantOptionGroup); + client.addRoleToGroups(adminUser, noGrantRole, SOLR, noGrantOptionGroup); + + try { + client.grantPrivilege(grantOptionUser,testRole,SOLR, testPrivilege); + } catch (SentryUserException e) { + fail("grantOptionUser failed grant privilege to user"); + } + + try { + client.grantPrivilege(noGrantOptionUser, testRole, SOLR, testPrivilege); + fail("noGrantOptionUser can't grant privilege to user"); + } catch (SentryUserException e) { + } + + try { + client.revokePrivilege(grantOptionUser, testRole, SOLR, testPrivilege); + } catch(SentryUserException e) { + fail("grantOptionUser failed revoke privilege to user"); + } + + try { + client.revokePrivilege(noGrantOptionUser, testRole, SOLR, testPrivilege); + fail("noGrantOptionUser can't revoke privilege to user"); + } catch (SentryUserException e) { + } + }}); + } + + @Test + public void testGetPrivilegeByHierarchy() throws Exception { + runTestAsSubject(new TestOperation(){ + @Override + public void runTestAsSubject() throws Exception { + String adminUser = ADMIN_USER; + Set<String> adminGroup = Sets.newHashSet(ADMIN_GROUP); + String testRole = "role1"; + Set<String> testGroup = Sets.newHashSet("group1"); + String testUser = "user1"; + setLocalGroupMapping(adminUser, adminGroup); + setLocalGroupMapping(testUser, testGroup); + writePolicyFile(); + + + client.createRole(adminUser, testRole, SOLR); + client.addRoleToGroups(adminUser, testRole, SOLR, testGroup); + + TSentryPrivilege queryPrivilege = new TSentryPrivilege(SOLR, "service1", + fromAuthorizable(Arrays.asList(new Collection("c1"), new Field("f1"))), + SearchConstants.QUERY); + + TSentryPrivilege updatePrivilege = new TSentryPrivilege(SOLR, "service1", + fromAuthorizable(Arrays.asList(new Collection("c2"), new Field("f2"))), + SearchConstants.UPDATE); + + client.grantPrivilege(adminUser, testRole, SOLR, queryPrivilege); + client.grantPrivilege(adminUser, testRole, SOLR, updatePrivilege); + + assertEquals(2, client.listPrivilegesByRoleName(testUser, testRole, SOLR, "service1").size()); + + assertEquals(1, client.listPrivilegesByRoleName(testUser, testRole, + SOLR, "service1", Arrays.asList(new Collection("c1"))).size()); + + assertEquals(1, client.listPrivilegesByRoleName(testUser, testRole, + SOLR, "service1", Arrays.asList(new Collection("c2"))).size()); + + assertEquals(1, client.listPrivilegesByRoleName(testUser, testRole, + SOLR, "service1", Arrays.asList(new Collection("c1"), new Field("f1"))).size()); + + assertEquals(1, client.listPrivilegesByRoleName(testUser, testRole, + SOLR, "service1", Arrays.asList(new Collection("c2"), new Field("f2"))).size()); + + //test listPrivilegesForProvider by group(testGroup) + ActiveRoleSet roleSet = ActiveRoleSet.ALL; + + assertEquals(1, client.listPrivilegesForProvider(SOLR, "service1", roleSet, + testGroup, Arrays.asList(new Collection("c1"))).size()); + + assertEquals(1, client.listPrivilegesForProvider(SOLR, "service1", roleSet, + testGroup, Arrays.asList(new Collection("c2"))).size()); + + assertEquals(1, client.listPrivilegesForProvider(SOLR, "service1", roleSet, + testGroup, Arrays.asList(new Collection("c1"), new Field("f1"))).size()); + + assertEquals(1, client.listPrivilegesForProvider(SOLR, "service1", roleSet, + testGroup, Arrays.asList(new Collection("c2"), new Field("f2"))).size()); + }}); + } + + @Test + public void testGetPrivilegeByAuthorizable() throws Exception { + runTestAsSubject(new TestOperation(){ + @Override + public void runTestAsSubject() throws Exception { + String adminUser = ADMIN_USER; + Set<String> adminGroup = Sets.newHashSet(ADMIN_GROUP); + String testRole = "role1"; + Set<String> testGroup = Sets.newHashSet("group1"); + String testUser = "user1"; + setLocalGroupMapping(adminUser, adminGroup); + setLocalGroupMapping(testUser, testGroup); + writePolicyFile(); + + client.createRole(adminUser, testRole, SOLR); + client.addRoleToGroups(adminUser, testRole, SOLR, adminGroup); + + TSentryPrivilege queryPrivilege = new TSentryPrivilege(SOLR, "service1", + fromAuthorizable(Arrays.asList(new Collection("c1"), new Field("f1"))), + SearchConstants.QUERY); + + TSentryPrivilege updatePrivilege = new TSentryPrivilege(SOLR, "service1", + fromAuthorizable(Arrays.asList(new Collection("c1"), new Field("f2"))), + SearchConstants.UPDATE); + + client.grantPrivilege(adminUser, testRole, SOLR, queryPrivilege); + client.grantPrivilege(adminUser, testRole, SOLR, updatePrivilege); + + //test listPrivilegsbyAuthorizable without requested group and active role set. + assertEquals(1, client.listPrivilegsbyAuthorizable(SOLR, "service1", adminUser, + Sets.newHashSet(new String("Collection=c1->Field=f1")), null, null).size()); + + //test listPrivilegsbyAuthorizable with requested group (testGroup) + Map<String, TSentryPrivilegeMap> privilegeMap = client.listPrivilegsbyAuthorizable(SOLR, + "service1", adminUser, Sets.newHashSet(new String("Collection=c1->Field=f1")), testGroup, null); + TSentryPrivilegeMap actualMap = privilegeMap.get(new String("Collection=c1->Field=f1")); + assertEquals(0, actualMap.getPrivilegeMap().size()); + + //test listPrivilegsbyAuthorizable with active role set. + ActiveRoleSet roleSet = ActiveRoleSet.ALL; + assertEquals(1, client.listPrivilegsbyAuthorizable(SOLR, "service1", adminUser, + Sets.newHashSet(new String("Collection=c1->Field=f1")), null, roleSet).size()); + privilegeMap = client.listPrivilegsbyAuthorizable(SOLR, + "service1", adminUser, Sets.newHashSet(new String("Collection=c1->Field=f1")), null, roleSet); + actualMap = privilegeMap.get(new String("Collection=c1->Field=f1")); + assertEquals(1, actualMap.getPrivilegeMap().size()); + + privilegeMap = client.listPrivilegsbyAuthorizable(SOLR, + "service1", testUser, Sets.newHashSet(new String("Collection=c1->Field=f1")), null, roleSet); + actualMap = privilegeMap.get(new String("Collection=c1->Field=f1")); + assertEquals(0, actualMap.getPrivilegeMap().size()); + + // grant tesRole to testGroup. + client.addRoleToGroups(adminUser, testRole, SOLR, testGroup); + + privilegeMap = client.listPrivilegsbyAuthorizable(SOLR, + "service1", testUser, Sets.newHashSet(new String("Collection=c1")), null, roleSet); + actualMap = privilegeMap.get(new String("Collection=c1")); + assertEquals(1, actualMap.getPrivilegeMap().size()); + assertEquals(2, actualMap.getPrivilegeMap().get(testRole).size()); + }}); + } + + @Test + public void testDropAndRenamePrivilege() throws Exception { + runTestAsSubject(new TestOperation(){ + @Override + public void runTestAsSubject() throws Exception { + String requestorUserName = ADMIN_USER; + Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP); + setLocalGroupMapping(requestorUserName, requestorUserGroupNames); + writePolicyFile(); + String roleName = "admin_r1"; + + client.createRole(requestorUserName, roleName, SOLR); + + TSentryPrivilege queryPrivilege = new TSentryPrivilege(SOLR, "service1", + fromAuthorizable(Arrays.asList(new Collection("c1"), new Field("f1"))), + SearchConstants.QUERY); + client.grantPrivilege(requestorUserName, roleName, SOLR, queryPrivilege); + + assertEquals(1, client.listPrivilegesByRoleName(requestorUserName, roleName, + SOLR, "service1", Arrays.asList(new Collection("c1"), new Field("f1"))).size()); + + assertEquals(0, client.listPrivilegesByRoleName(requestorUserName, roleName, + SOLR, "service1", Arrays.asList(new Collection("c2"), new Field("f2"))).size()); + + client.renamePrivilege(requestorUserName, SOLR, "service1", Arrays.asList(new Collection("c1"), new Field("f1")), + Arrays.asList(new Collection("c2"), new Field("f2"))); + + assertEquals(0, client.listPrivilegesByRoleName(requestorUserName, roleName, + SOLR, "service1", Arrays.asList(new Collection("c1"), new Field("f1"))).size()); + + assertEquals(1, client.listPrivilegesByRoleName(requestorUserName, roleName, + SOLR, "service1", Arrays.asList(new Collection("c2"), new Field("f2"))).size()); + + TSentryPrivilege dropPrivilege = new TSentryPrivilege(SOLR, "service1", + fromAuthorizable(Arrays.asList(new Collection("c2"), new Field("f2"))), + SearchConstants.QUERY); + + client.dropPrivilege(requestorUserName, SOLR, dropPrivilege); + + assertEquals(0, client.listPrivilegesByRoleName(requestorUserName, roleName, + SOLR, "service1", Arrays.asList(new Collection("c2"), new Field("f2"))).size()); + }}); + } + + private List<TAuthorizable> fromAuthorizable(List<? extends Authorizable> authorizables) { + List<TAuthorizable> tAuthorizables = Lists.newArrayList(); + for (Authorizable authorizable : authorizables) { + tAuthorizables.add(new TAuthorizable(authorizable.getTypeName(), authorizable.getName())); + } + return tAuthorizables; + } +} http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryConfigToolSolr.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryConfigToolSolr.java b/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryConfigToolSolr.java new file mode 100644 index 0000000..d199d20 --- /dev/null +++ b/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryConfigToolSolr.java @@ -0,0 +1,261 @@ + /** + * 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.provider.db.generic.tools; + +import com.google.common.io.Files; +import com.google.common.collect.Sets; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.File; +import java.io.FileOutputStream; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.io.FileUtils; +import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceIntegrationBase; +import org.apache.sentry.provider.db.generic.service.thrift.TSentryRole; +import org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege; +import org.apache.sentry.core.common.exception.SentryConfigurationException; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class TestSentryConfigToolSolr extends SentryGenericServiceIntegrationBase { + private static String RESOURCES_DIR = "target" + File.separator + "test-classes" + File.separator; + private static String VALID_POLICY_INI = RESOURCES_DIR + "solr_config_import_tool.ini"; + private static String INVALID_POLICY_INI = RESOURCES_DIR + "solr_invalid.ini"; + private static String CASE_POLICY_INI = RESOURCES_DIR + "solr_case.ini"; + private File confDir; + private File confPath; + private String requestorName = ""; + private String service = "service1"; + + @Before + public void prepareForTest() throws Exception { + confDir = Files.createTempDir(); + confPath = new File(confDir, "sentry-site.xml"); + if (confPath.createNewFile()) { + FileOutputStream to = new FileOutputStream(confPath); + conf.writeXml(to); + to.close(); + } + requestorName = clientUgi.getShortUserName();//System.getProperty("user.name", ""); + Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP); + setLocalGroupMapping(requestorName, requestorUserGroupNames); + // add ADMIN_USER for the after() in SentryServiceIntegrationBase + setLocalGroupMapping(ADMIN_USER, requestorUserGroupNames); + writePolicyFile(); + } + + @After + public void clearTestData() throws Exception { + FileUtils.deleteQuietly(confDir); + + // clear roles and privileges + Set<TSentryRole> tRoles = client.listAllRoles(requestorName, SOLR); + for (TSentryRole tRole : tRoles) { + String role = tRole.getRoleName(); + Set<TSentryPrivilege> privileges = client.listPrivilegesByRoleName( + requestorName, role, SOLR, service); + for (TSentryPrivilege privilege : privileges) { + client.revokePrivilege(requestorName, role, SOLR, privilege); + } + client.dropRole(requestorName, role, SOLR); + } + } + + @Test + public void testConvertIni() throws Exception { + runTestAsSubject(new TestOperation() { + @Override + public void runTestAsSubject() throws Exception { + String[] args = { "-p", VALID_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-v", "-i"}; + SentryConfigToolSolr sentryTool = new SentryConfigToolSolr(); + sentryTool.executeConfigTool(args); + + Map<String, Set<String>> groupMapping = new HashMap<String, Set<String>>(); + groupMapping.put("corporal_role", Sets.newHashSet("corporal", "sergeant", "general", "commander_in_chief")); + groupMapping.put("sergeant_role", Sets.newHashSet("sergeant", "general", "commander_in_chief")); + groupMapping.put("general_role", Sets.newHashSet("general", "commander_in_chief")); + groupMapping.put("commander_in_chief_role", Sets.newHashSet("commander_in_chief")); + + Map<String, Set<String>> privilegeMapping = new HashMap<String, Set<String>>(); + privilegeMapping.put("corporal_role", + Sets.newHashSet("Collection=info->action=query", "Collection=info->action=update")); + privilegeMapping.put("sergeant_role", + Sets.newHashSet("Collection=info->action=update")); + privilegeMapping.put("general_role", + Sets.newHashSet("Collection=info->action=*")); + privilegeMapping.put("commander_in_chief_role", + Sets.newHashSet("Collection=*->action=*")); + + // check roles + Set<TSentryRole> tRoles = client.listAllRoles(requestorName, SOLR); + assertEquals("Unexpected number of roles", groupMapping.keySet().size(), tRoles.size()); + Set<String> roles = new HashSet<String>(); + for (TSentryRole tRole : tRoles) { + roles.add(tRole.getRoleName()); + } + + for (String expectedRole : groupMapping.keySet()) { + assertTrue("Didn't find expected role: " + expectedRole, roles.contains(expectedRole)); + } + + // check groups + for (TSentryRole tRole : tRoles) { + Set<String> expectedGroups = groupMapping.get(tRole.getRoleName()); + assertEquals("Group size doesn't match for role: " + tRole.getRoleName(), + expectedGroups.size(), tRole.getGroups().size()); + assertTrue("Group does not contain all expected members for role: " + tRole.getRoleName(), + tRole.getGroups().containsAll(expectedGroups)); + } + + // check privileges + SolrTSentryPrivilegeConverter convert = new SolrTSentryPrivilegeConverter(SOLR, service); + for (String role : roles) { + Set<TSentryPrivilege> privileges = client.listPrivilegesByRoleName( + requestorName, role, SOLR, service); + Set<String> expectedPrivileges = privilegeMapping.get(role); + assertEquals("Privilege set size doesn't match for role: " + role, + expectedPrivileges.size(), privileges.size()); + + Set<String> privilegeStrs = new HashSet<String>(); + for (TSentryPrivilege privilege : privileges) { + privilegeStrs.add(convert.toString(privilege)); + } + + for (String expectedPrivilege : expectedPrivileges) { + assertTrue("Did not find expected privilege: " + expectedPrivilege, + privilegeStrs.contains(expectedPrivilege)); + } + } + } + }); + } + + @Test + public void testNoPolicyFile() throws Exception { + runTestAsSubject(new TestOperation() { + @Override + public void runTestAsSubject() throws Exception { + String[] args = { "-p", INVALID_POLICY_INI + "Foobar", "-conf", confPath.getAbsolutePath(), "-v", "-i"}; + SentryConfigToolSolr sentryTool = new SentryConfigToolSolr(); + try { + sentryTool.executeConfigTool(args); + fail("Exception should be thrown for nonexistant ini"); + } catch (SentryConfigurationException e) { + // expected exception + } + } + }); + } + + @Test + public void testNoValidateNorImport() throws Exception { + runTestAsSubject(new TestOperation() { + @Override + public void runTestAsSubject() throws Exception { + String[] args = { "-p", INVALID_POLICY_INI, "-conf", confPath.getAbsolutePath()}; + SentryConfigToolSolr sentryTool = new SentryConfigToolSolr(); + try { + sentryTool.executeConfigTool(args); + fail("Exception should be thrown for validating invalid ini"); + } catch (IllegalArgumentException e) { + // expected exception + } + } + }); + } + + @Test + public void testConvertInvalidIni() throws Exception { + runTestAsSubject(new TestOperation() { + @Override + public void runTestAsSubject() throws Exception { + // test: validate an invalid ini + String[] args = { "-p", INVALID_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-v", "-i"}; + SentryConfigToolSolr sentryTool = new SentryConfigToolSolr(); + try { + sentryTool.executeConfigTool(args); + fail("Exception should be thrown for validating invalid ini"); + } catch (SentryConfigurationException e) { + // expected exception + } + + // test without validating, should not error + args = new String[] { "-p", INVALID_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-i"}; + sentryTool = new SentryConfigToolSolr(); + sentryTool.executeConfigTool(args); + } + }); + } + + @Test + public void testCompatCheck() throws Exception { + runTestAsSubject(new TestOperation() { + @Override + public void runTestAsSubject() throws Exception { + // test: validate an invalid ini + String[] args = { "-p", CASE_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-v", "-i", "-c"}; + SentryConfigToolSolr sentryTool = new SentryConfigToolSolr(); + try { + sentryTool.executeConfigTool(args); + fail("Exception should be thrown for validating invalid ini"); + } catch (SentryConfigurationException e) { + assertEquals("Expected error", 1, e.getConfigErrors().size()); + String error = e.getConfigErrors().get(0); + assertCasedRoleNamesInMessage(error, "RoLe1", "rOlE1"); + String warning = e.getConfigWarnings().get(0); + assertCasedRoleNamesInMessage(warning, "ROLE2", "RoLe1", "rOlE1"); + assertEquals("Expected warning", 1, e.getConfigWarnings().size()); + } + + // test without compat checking + args = new String[] { "-p", CASE_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-i", "-v"}; + sentryTool = new SentryConfigToolSolr(); + sentryTool.executeConfigTool(args); + } + }); + } + + // Test that a valid compat check doesn't throw an exception + @Test + public void testCompatCheckValid() throws Exception { + runTestAsSubject(new TestOperation() { + @Override + public void runTestAsSubject() throws Exception { + String[] args = { "-p", VALID_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-v", "-i", "-c"}; + SentryConfigToolSolr sentryTool = new SentryConfigToolSolr(); + sentryTool.executeConfigTool(args); + } + }); + } + + private void assertCasedRoleNamesInMessage(String message, String ... casedRoleNames) { + for (String casedRoleName : casedRoleNames) { + assertTrue("Expected cased role name: " + casedRoleName, message.contains(casedRoleName)); + } + } +}
