| /** |
| * 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 junit.framework.Assert.assertEquals; |
| import static org.mockito.Matchers.any; |
| import static org.mockito.Matchers.anyListOf; |
| import static org.mockito.Matchers.anySetOf; |
| import static org.mockito.Matchers.anyString; |
| import static org.mockito.Mockito.mock; |
| import static org.mockito.Mockito.when; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Set; |
| import java.util.UUID; |
| |
| import org.apache.hadoop.conf.Configuration; |
| 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.apache.sentry.provider.common.GroupMappingService; |
| import org.apache.sentry.provider.db.SentryAlreadyExistsException; |
| import org.apache.sentry.provider.db.SentryGrantDeniedException; |
| import org.apache.sentry.provider.db.SentryInvalidInputException; |
| import org.apache.sentry.provider.db.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.generic.service.thrift.SentryGenericPolicyProcessor; |
| import org.apache.sentry.provider.db.service.persistent.CommitContext; |
| import org.apache.sentry.provider.db.service.thrift.PolicyStoreConstants; |
| import org.apache.sentry.provider.db.service.thrift.SentryConfigurationException; |
| 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 com.google.common.collect.Sets; |
| |
| public class TestSentryGenericPolicyProcessor { |
| 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 = 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 { |
| when(mockStore.createRole(anyString(), anyString(), anyString())) |
| .thenReturn(new CommitContext(SERVER_UUID, SEQ_ID)); |
| |
| when(mockStore.dropRole(anyString(), anyString(), anyString())) |
| .thenReturn(new CommitContext(SERVER_UUID, SEQ_ID + 1)); |
| |
| when(mockStore.alterRoleAddGroups(anyString(), anyString(), anySetOf(String.class),anyString())) |
| .thenReturn(new CommitContext(SERVER_UUID, SEQ_ID + 2)); |
| |
| when(mockStore.alterRoleDeleteGroups(anyString(), anyString(),anySetOf(String.class), anyString())) |
| .thenReturn(new CommitContext(SERVER_UUID, SEQ_ID + 3)); |
| |
| when(mockStore.dropPrivilege(anyString(), any(PrivilegeObject.class), anyString())) |
| .thenReturn(new CommitContext(SERVER_UUID, SEQ_ID + 4)); |
| |
| when(mockStore.renamePrivilege(anyString(), anyString(), anyListOf(Authorizable.class), |
| anyListOf(Authorizable.class), anyString())) |
| .thenReturn(new CommitContext(SERVER_UUID, SEQ_ID + 5)); |
| testOperation(ADMIN_USER, Status.OK); |
| } |
| |
| @Test |
| public void testGrantAndRevokePrivilege() throws Exception { |
| when(mockStore.alterRoleGrantPrivilege(anyString(), anyString(), any(PrivilegeObject.class), anyString())) |
| .thenReturn(new CommitContext(SERVER_UUID, SEQ_ID + 6)); |
| |
| when(mockStore.alterRoleRevokePrivilege(anyString(), anyString(),any(PrivilegeObject.class), 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 { |
| when(mockStore.createRole(anyString(), anyString(), anyString())) |
| .thenThrow(new SentryAlreadyExistsException("role already exists")); |
| |
| when(mockStore.dropRole(anyString(), anyString(), anyString())) |
| .thenThrow(new SentryNoSuchObjectException("role isn't exist")); |
| |
| when(mockStore.alterRoleAddGroups(anyString(), anyString(), anySetOf(String.class),anyString())) |
| .thenThrow(new SentryNoSuchObjectException("role isn't exist")); |
| |
| when(mockStore.alterRoleDeleteGroups(anyString(), anyString(),anySetOf(String.class), anyString())) |
| .thenThrow(new SentryNoSuchObjectException("role isn't exist")); |
| |
| when(mockStore.alterRoleGrantPrivilege(anyString(), anyString(), any(PrivilegeObject.class), anyString())) |
| .thenThrow(new SentryGrantDeniedException("has no grant")); |
| |
| when(mockStore.alterRoleRevokePrivilege(anyString(), anyString(),any(PrivilegeObject.class), anyString())) |
| .thenThrow(new SentryGrantDeniedException("has no grant")); |
| |
| when(mockStore.dropPrivilege(anyString(), any(PrivilegeObject.class), anyString())) |
| .thenThrow(new SentryInvalidInputException("nvalid input privilege object")); |
| |
| when(mockStore.renamePrivilege(anyString(), anyString(), anyListOf(Authorizable.class), |
| anyListOf(Authorizable.class), 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(); |
| |
| when(mockStore.getRolesByGroups(anyString(), anySetOf(String.class))) |
| .thenReturn(Sets.newHashSet(roleName)); |
| |
| when(mockStore.getPrivilegesByProvider(anyString(), anyString(), anySetOf(String.class), |
| anySetOf(String.class), anyListOf(Authorizable.class))) |
| .thenReturn(Sets.newHashSet(queryPrivilege, updatePrivilege)); |
| |
| when(mockStore.getGroupsByRoles(anyString(), anySetOf(String.class))) |
| .thenReturn(Sets.newHashSet(groupName)); |
| |
| 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()); |
| } |
| |
| @Test(expected=SentryConfigurationException.class) |
| public void testConfigCannotCreateNotificationHandler() throws Exception { |
| Configuration conf = new Configuration(); |
| conf.set(PolicyStoreConstants.SENTRY_GENERIC_POLICY_NOTIFICATION,"junk"); |
| SentryGenericPolicyProcessor.createHandlers(conf); |
| } |
| |
| @Test(expected=SentryConfigurationException.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) { |
| } |
| @Override |
| public Set<String> getGroups(String user) { |
| if (user.equalsIgnoreCase(ADMIN_USER)) { |
| return Sets.newHashSet(ADMIN_GROUP); |
| } else { |
| return Sets.newHashSet("not" + ADMIN_GROUP); |
| } |
| } |
| } |
| |
| } |