http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/bf3eb482/sentry-provider/sentry-provider-db/src/main/resources/sentry_generic_policy_service.thrift ---------------------------------------------------------------------- diff --git a/sentry-provider/sentry-provider-db/src/main/resources/sentry_generic_policy_service.thrift b/sentry-provider/sentry-provider-db/src/main/resources/sentry_generic_policy_service.thrift new file mode 100644 index 0000000..91ff672 --- /dev/null +++ b/sentry-provider/sentry-provider-db/src/main/resources/sentry_generic_policy_service.thrift @@ -0,0 +1,231 @@ +#!/usr/local/bin/thrift -java + +/** + * 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. + */ + +# +# Thrift Service that the MetaStore is built on +# + +include "share/fb303/if/fb303.thrift" +include "sentry_common_service.thrift" +include "sentry_policy_service.thrift" + +namespace java org.apache.sentry.provider.db.generic.service.thrift +namespace php sentry.provider.db.service.db.generic.serivce.thrift +namespace cpp Apache.Sentry.Provider.Db.Generic.Service.Thrift + +typedef sentry_common_service.TSentryResponseStatus TSentryResponseStatus + +# Represents a new generic model privilege for solr or other component in transport +# from the client to the server +enum TSentryGrantOption { + TRUE = 1, + FALSE = 0, + UNSET = -1 +} + +# Represents a authorizable resource in the privilege +# like DATABASE=db1 in the hive, COLLECTION=collection1 in the solr +struct TAuthorizable { +1: required string type, +2: required string name +} + +struct TSentryPrivilege { +1: required string component, +2: required string serviceName, +3: required list<TAuthorizable> authorizables, +4: required string action, +5: optional i64 createTime, # Set on server side +6: optional string grantorPrincipal, # Set on server side +7: optional TSentryGrantOption grantOption = sentry_policy_service.TSentryGrantOption.FALSE +} + +# CREATE ROLE r1 +struct TCreateSentryRoleRequest { +1: required i32 protocol_version = sentry_common_service.TSENTRY_SERVICE_V2, +2: required string requestorUserName, # user on whose behalf the request is issued +3: required string roleName, +4: required string component # The request is issued to which component +} + +struct TCreateSentryRoleResponse { +1: required TSentryResponseStatus status +} + +# DROP ROLE r1 +struct TDropSentryRoleRequest { +1: required i32 protocol_version = sentry_common_service.TSENTRY_SERVICE_V2, +2: required string requestorUserName, # user on whose behalf the request is issued +3: required string roleName, +4: required string component # The request is issued to which component +} + +struct TDropSentryRoleResponse { +1: required TSentryResponseStatus status +} + +# GRANT ROLE r1 TO GROUP g1 +struct TAlterSentryRoleAddGroupsRequest { +1: required i32 protocol_version = sentry_common_service.TSENTRY_SERVICE_V2, +2: required string requestorUserName, # user on whose behalf the request is issued +3: required string roleName, +4: required string component, # The request is issued to which component +5: required set<string> groups +} +struct TAlterSentryRoleAddGroupsResponse { +1: required TSentryResponseStatus status +} + +# REVOLE ROLE r1 FROM GROUP g1 +struct TAlterSentryRoleDeleteGroupsRequest { +1: required i32 protocol_version = sentry_common_service.TSENTRY_SERVICE_V2, +2: required string requestorUserName, # user on whose behalf the request is issued +3: required string roleName, +4: required string component, # The request is issued to which component +5: required set<string> groups +} +struct TAlterSentryRoleDeleteGroupsResponse { +1: required TSentryResponseStatus status +} + +# GRANT ... ON ... TO ROLE ... +struct TAlterSentryRoleGrantPrivilegeRequest { +1: required i32 protocol_version = sentry_common_service.TSENTRY_SERVICE_V2, +2: required string requestorUserName, # user on whose behalf the request is issued +3: required string roleName, +4: required string component, # The request is issued to which component +5: required TSentryPrivilege privilege +} +struct TAlterSentryRoleGrantPrivilegeResponse { +1: required TSentryResponseStatus status +} + +# REVOKE ... ON ... FROM ROLE ... +struct TAlterSentryRoleRevokePrivilegeRequest { +1: required i32 protocol_version = sentry_common_service.TSENTRY_SERVICE_V2, +2: required string requestorUserName, # user on whose behalf the request is issued +3: required string roleName, +4: required string component, # The request is issued to which component +5: required TSentryPrivilege privilege +} +struct TAlterSentryRoleRevokePrivilegeResponse { +1: required TSentryResponseStatus status +} + +# SHOW ROLE GRANT +struct TListSentryRolesRequest { +1: required i32 protocol_version = sentry_common_service.TSENTRY_SERVICE_V2, +2: required string requestorUserName, # user on whose behalf the request is issued +3: optional string groupName, # for this group, or all roles for all groups if null +4: required string component # The request is issued to which component +} +# used only for TListSentryRolesResponse +struct TSentryRole { +1: required string roleName, +2: required set<string> groups +} + +struct TListSentryRolesResponse { +1: required TSentryResponseStatus status +2: optional set<TSentryRole> roles +} +# SHOW GRANT +struct TListSentryPrivilegesRequest { +1: required i32 protocol_version = sentry_common_service.TSENTRY_SERVICE_V2, +2: required string requestorUserName, # user on whose behalf the request is issued +3: required string roleName, # get privileges assigned for this role +4: required string component, # The request is issued to which component +5: required string serviceName, # The privilege belongs to which service +6: optional list<TAuthorizable> authorizables # get privileges assigned for this authorizable hierarchys +} + +struct TListSentryPrivilegesResponse { +1: required TSentryResponseStatus status +2: optional set<TSentryPrivilege> privileges +} + +# Drop privilege +struct TDropPrivilegesRequest { +1: required i32 protocol_version = sentry_common_service.TSENTRY_SERVICE_V2, +2: required string requestorUserName, # user on whose behalf the request is issued +3: required TSentryPrivilege privilege +4: required string component, # The request is issued to which component +} + +struct TDropPrivilegesResponse { +1: required TSentryResponseStatus status +} + +# Rename privilege +struct TRenamePrivilegesRequest { +1: required i32 protocol_version = sentry_common_service.TSENTRY_SERVICE_V2, +2: required string requestorUserName, # user on whose behalf the request is issued +3: required string component, # The request is issued to which component +4: required string serviceName, # The privilege belongs to which service +5: required list<TAuthorizable> oldAuthorizables, # get old privileges assigned for this authorizable hierarchys +6: required list<TAuthorizable> newAuthorizables # change to new authorizable hierarchys +} + +struct TRenamePrivilegesResponse { +1: required TSentryResponseStatus status +} + +# This API was created specifically for ProviderBackend.getPrivileges +# and is not mean for general purpose privilege retrieval. +# This request/response pair are created specifically so we can +# efficiently obtain the specific privilges for a user query +struct TSentryActiveRoleSet { +1: required bool all, +2: required set<string> roles, +} +struct TListSentryPrivilegesForProviderRequest { +1: required i32 protocol_version = sentry_common_service.TSENTRY_SERVICE_V2, +2: required string component, # The request is issued to which component +3: required string serviceName, # The privilege belongs to which service +4: required set<string> groups, +5: required TSentryActiveRoleSet roleSet, +6: optional list<TAuthorizable> authorizables # authorizable hierarchys +} +struct TListSentryPrivilegesForProviderResponse { +1: required TSentryResponseStatus status +2: required set<string> privileges +} + +service SentryGenericPolicyService +{ + TCreateSentryRoleResponse create_sentry_role(1:TCreateSentryRoleRequest request) + TDropSentryRoleResponse drop_sentry_role(1:TDropSentryRoleRequest request) + + TAlterSentryRoleGrantPrivilegeResponse alter_sentry_role_grant_privilege(1:TAlterSentryRoleGrantPrivilegeRequest request) + TAlterSentryRoleRevokePrivilegeResponse alter_sentry_role_revoke_privilege(1:TAlterSentryRoleRevokePrivilegeRequest request) + + TAlterSentryRoleAddGroupsResponse alter_sentry_role_add_groups(1:TAlterSentryRoleAddGroupsRequest request) + TAlterSentryRoleDeleteGroupsResponse alter_sentry_role_delete_groups(1:TAlterSentryRoleDeleteGroupsRequest request) + + TListSentryRolesResponse list_sentry_roles_by_group(1:TListSentryRolesRequest request) + + TListSentryPrivilegesResponse list_sentry_privileges_by_role(1:TListSentryPrivilegesRequest request) + + TListSentryPrivilegesForProviderResponse list_sentry_privileges_for_provider(1:TListSentryPrivilegesForProviderRequest request) + + TDropPrivilegesResponse drop_sentry_privilege(1:TDropPrivilegesRequest request); + + TRenamePrivilegesResponse rename_sentry_privilege(1:TRenamePrivilegesRequest request); +}
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/bf3eb482/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/service/persistent/SentryStoreIntegrationBase.java ---------------------------------------------------------------------- diff --git a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/service/persistent/SentryStoreIntegrationBase.java b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/service/persistent/SentryStoreIntegrationBase.java new file mode 100644 index 0000000..c65a28f --- /dev/null +++ b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/service/persistent/SentryStoreIntegrationBase.java @@ -0,0 +1,95 @@ +/** + * 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.persistent; + +import java.io.File; + +import org.apache.commons.io.FileUtils; +import org.apache.hadoop.conf.Configuration; +import org.apache.sentry.provider.db.generic.service.persistent.SentryStoreLayer; +import org.apache.sentry.provider.file.PolicyFile; +import org.apache.sentry.service.thrift.ServiceConstants.ServerConfig; +import org.junit.After; +import org.junit.Before; + +import com.google.common.io.Files; + +public abstract class SentryStoreIntegrationBase { + protected final String[] adminGroups = {"adminGroup"}; + private File dataDir; + protected SentryStoreLayer sentryStore; + private PolicyFile policyFile; + private File policyFilePath; + + @Before + public void setup() throws Exception { + Configuration conf = new Configuration(false); + setup(conf); + configure(conf); + sentryStore = createSentryStore(conf); + } + + private void setup(Configuration conf) throws Exception { + dataDir = new File(Files.createTempDir(), "sentry_policy_db"); + conf.set(ServerConfig.SENTRY_VERIFY_SCHEM_VERSION, "false"); + conf.set(ServerConfig.SENTRY_STORE_JDBC_URL, + "jdbc:derby:;databaseName=" + dataDir.getPath() + ";create=true"); + conf.setStrings(ServerConfig.ADMIN_GROUPS, adminGroups); + conf.set(ServerConfig.SENTRY_STORE_GROUP_MAPPING, + ServerConfig.SENTRY_STORE_LOCAL_GROUP_MAPPING); + + policyFilePath = new File(Files.createTempDir(), "local_policy_file.ini"); + conf.set(ServerConfig.SENTRY_STORE_GROUP_MAPPING_RESOURCE, + policyFilePath.getPath()); + policyFile = new PolicyFile(); + String adminUser = "admin"; + addGroupsToUser(adminUser, adminGroups); + writePolicyFile(); + } + + @After + public void teardown() { + if (sentryStore != null) { + sentryStore.close(); + } + if (dataDir != null) { + FileUtils.deleteQuietly(dataDir); + } + if (policyFilePath != null) { + FileUtils.deleteQuietly(policyFilePath); + } + } + + public void addGroupsToUser(String user, String... groupNames) { + policyFile.addGroupsToUser(user, groupNames); + } + + public void writePolicyFile() throws Exception { + policyFile.write(policyFilePath); + } + + public String[] getAdminGroups() { + return adminGroups; + } + + public void configure(Configuration conf) throws Exception { + + } + + public abstract SentryStoreLayer createSentryStore(Configuration conf) throws Exception; +} http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/bf3eb482/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/service/persistent/TestDelegateSentryStore.java ---------------------------------------------------------------------- diff --git a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/service/persistent/TestDelegateSentryStore.java b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/service/persistent/TestDelegateSentryStore.java new file mode 100644 index 0000000..c7c6af7 --- /dev/null +++ b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/service/persistent/TestDelegateSentryStore.java @@ -0,0 +1,175 @@ +/** + * 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.persistent; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.fail; + +import java.util.Set; + +import org.apache.hadoop.conf.Configuration; +import org.apache.sentry.provider.db.SentryAlreadyExistsException; +import org.apache.sentry.provider.db.SentryNoSuchObjectException; +import org.junit.Test; + +import com.google.common.collect.Sets; + +public class TestDelegateSentryStore extends SentryStoreIntegrationBase{ + private static final String SEARCH = "solr"; + @Override + public SentryStoreLayer createSentryStore(Configuration conf) throws Exception { + return new DelegateSentryStore(conf); + } + + @Test + public void testCreateDropRole() throws Exception { + String roleName = "test-drop-role"; + String grantor = "grantor"; + long seqId = sentryStore.createRole(SEARCH, roleName, grantor).getSequenceId(); + assertEquals(seqId + 1, sentryStore.dropRole(SEARCH, roleName, grantor).getSequenceId()); + } + + @Test + public void testCaseInsensitiveCreateDropRole() throws Exception { + String roleName1 = "test"; + String roleName2 = "TeSt"; + String grantor = "grantor"; + sentryStore.createRole(SEARCH, roleName1, grantor); + try { + sentryStore.createRole(SEARCH, roleName2, grantor); + fail("SentryAlreadyExistsException should have been thrown"); + } catch (SentryAlreadyExistsException e) { + //ignore the exception + } + + try { + sentryStore.dropRole(SEARCH, roleName2, grantor); + } catch (SentryNoSuchObjectException e) { + fail("SentryNoSuchObjectException shouldn't have been thrown"); + } + } + + @Test(expected=SentryAlreadyExistsException.class) + public void testCreateDuplicateRole() throws Exception { + String roleName = "test-dup-role"; + String grantor = "grantor"; + sentryStore.createRole(SEARCH, roleName, grantor); + sentryStore.createRole(SEARCH, roleName, grantor); + } + + @Test(expected=SentryNoSuchObjectException.class) + public void testDropNotExistRole() throws Exception { + String roleName = "not-exist"; + String grantor = "grantor"; + sentryStore.dropRole(SEARCH, roleName, grantor); + } + + @Test(expected = SentryNoSuchObjectException.class) + public void testAddGroupsNonExistantRole() + throws Exception { + String roleName = "non-existant-role"; + String grantor = "grantor"; + sentryStore.alterRoleAddGroups(SEARCH, roleName, Sets.newHashSet("g1"), grantor); + } + + @Test(expected = SentryNoSuchObjectException.class) + public void testDeleteGroupsNonExistantRole() + throws Exception { + String roleName = "non-existant-role"; + String grantor = "grantor"; + sentryStore.alterRoleDeleteGroups(SEARCH, roleName, Sets.newHashSet("g1"), grantor); + } + + @Test + public void testAddDeleteRoleToGroups() throws Exception { + String role1 = "r1", role2 = "r2"; + Set<String> twoGroups = Sets.newHashSet("g1", "g2"); + Set<String> oneGroup = Sets.newHashSet("g3"); + String grantor = "grantor"; + + sentryStore.createRole(SEARCH, role1, grantor); + sentryStore.createRole(SEARCH, role2, grantor); + + sentryStore.alterRoleAddGroups(SEARCH, role1, twoGroups, grantor); + assertEquals(twoGroups, sentryStore.getGroupsByRoles(SEARCH,Sets.newHashSet(role1))); + + assertEquals(Sets.newHashSet(role1), sentryStore.getRolesByGroups(SEARCH, twoGroups)); + + sentryStore.alterRoleAddGroups(SEARCH, role2, oneGroup, grantor); + assertEquals(oneGroup, sentryStore.getGroupsByRoles(SEARCH, Sets.newHashSet(role2))); + + sentryStore.alterRoleDeleteGroups(SEARCH, role1, Sets.newHashSet("g1"), grantor); + assertEquals(Sets.newHashSet("g2"), sentryStore.getGroupsByRoles(SEARCH, Sets.newHashSet(role1))); + + sentryStore.alterRoleDeleteGroups(SEARCH, role2, oneGroup, grantor); + assertEquals(Sets.newHashSet(), sentryStore.getGroupsByRoles(SEARCH, Sets.newHashSet(role2))); + } + + @Test + public void testGetRolesByGroupNames() throws Exception { + String role1 = "r1", role2 = "r2"; + Set<String> twoGroups = Sets.newHashSet("g1", "g2"); + String grantor = "grantor"; + + sentryStore.createRole(SEARCH, role1, grantor); + sentryStore.createRole(SEARCH, role2, grantor); + + sentryStore.alterRoleAddGroups(SEARCH, role1, twoGroups, grantor); + sentryStore.alterRoleAddGroups(SEARCH, role2, twoGroups, grantor); + + assertEquals(Sets.newHashSet(role1,role2), sentryStore.getRolesByGroups(SEARCH, twoGroups)); + } + + @Test + public void testGetGroupsByRoleNames() throws Exception { + String role1 = "r1", role2 = "r2"; + Set<String> twoGroups = Sets.newHashSet("g1", "g2"); + String grantor = "grantor"; + + sentryStore.createRole(SEARCH, role1, grantor); + sentryStore.createRole(SEARCH, role2, grantor); + + sentryStore.alterRoleAddGroups(SEARCH, role1, twoGroups, grantor); + sentryStore.alterRoleAddGroups(SEARCH, role2, twoGroups, grantor); + + assertEquals(twoGroups, sentryStore.getGroupsByRoles(SEARCH, Sets.newHashSet(role1))); + assertEquals(twoGroups, sentryStore.getGroupsByRoles(SEARCH, Sets.newHashSet(role2))); + assertEquals(twoGroups, sentryStore.getGroupsByRoles(SEARCH, Sets.newHashSet(role1,role2))); + } + + @Test + public void testGetAllRoles() throws Exception { + String role1 = "r1", role2 = "r2"; + Set<String> twoGroups = Sets.newHashSet("g1", "g2"); + String grantor = "grantor"; + + sentryStore.createRole(SEARCH, role1, grantor); + sentryStore.createRole(SEARCH, role2, grantor); + + sentryStore.alterRoleAddGroups(SEARCH, role1, twoGroups, grantor); + sentryStore.alterRoleAddGroups(SEARCH, role2, twoGroups, grantor); + + //test get all roles by groupName=null + String groupName = null; + Set<String> groups = Sets.newHashSet(groupName); + assertEquals(Sets.newHashSet(role1,role2), sentryStore.getRolesByGroups(SEARCH, groups)); + + groups.clear(); + assertEquals(0, sentryStore.getRolesByGroups(SEARCH, groups).size()); + } +} http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/bf3eb482/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/service/persistent/TestPrivilegeOperatePersistence.java ---------------------------------------------------------------------- diff --git a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/service/persistent/TestPrivilegeOperatePersistence.java b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/service/persistent/TestPrivilegeOperatePersistence.java new file mode 100644 index 0000000..5dc5fde --- /dev/null +++ b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/service/persistent/TestPrivilegeOperatePersistence.java @@ -0,0 +1,909 @@ +/** + * 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.persistent; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.fail; + +import java.util.Arrays; +import java.util.List; + +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.db.SentryGrantDeniedException; +import org.apache.sentry.provider.db.generic.service.persistent.DelegateSentryStore; +import org.apache.sentry.provider.db.generic.service.persistent.SentryStoreLayer; +import org.apache.sentry.provider.db.generic.service.persistent.PrivilegeObject.Builder; +import org.junit.Test; + +import com.google.common.collect.Sets; + +/** + * The test cases are used for search component The authorizables are COLLECTION and Field + * The actions of search privilege are ALL,QUERY and UPDATE + */ +public class TestPrivilegeOperatePersistence extends SentryStoreIntegrationBase { + private static final String SEARCH = "solr"; + private static final String ADMIN_USER = "solr"; + private static final String GRANT_OPTION_USER = "user_grant_option"; + private static final String[] GRANT_OPTION_GROUP = { "group_grant_option" }; + private static final String NO_GRANT_OPTION_USER = "user_no_grant_option"; + private static final String[] NO_GRANT_OPTION_GROUP = { "group_no_grant_option" }; + + private static final String SERVICE = "service"; + private static final String COLLECTION_NAME = "collection1"; + private static final String NOT_COLLECTION_NAME = "not_collection1"; + private static final String FIELD_NAME = "field1"; + private static final String NOT_FIELD_NAME = "not_field1"; + + @Override + public void configure(Configuration conf) throws Exception { + /** + * add the solr user to admin groups + */ + addGroupsToUser(ADMIN_USER, getAdminGroups()); + writePolicyFile(); + } + + @Override + public SentryStoreLayer createSentryStore(Configuration conf) + throws Exception { + return new DelegateSentryStore(conf); + } + + /** + * Grant query privilege to role r1 + */ + @Test + public void testGrantPrivilege() throws Exception { + String roleName = "r1"; + /** + * grantor is admin, there is no need to check grant option + */ + String grantor = ADMIN_USER; + PrivilegeObject queryPrivilege = new Builder() + .setComponent(SEARCH) + .setAction(SearchConstants.QUERY) + .setService(SERVICE) + .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME))) + .withGrantOption(null) + .build(); + + sentryStore.createRole(SEARCH, roleName, grantor); + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName, queryPrivilege, grantor); + + assertEquals(Sets.newHashSet(queryPrivilege), + sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName))); + + PrivilegeObject queryPrivilegeWithOption = new Builder() + .setComponent(SEARCH) + .setAction(SearchConstants.QUERY) + .setService(SERVICE) + .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME))) + .withGrantOption(true) + .build(); + + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName, queryPrivilegeWithOption, grantor); + + assertEquals(Sets.newHashSet(queryPrivilege, queryPrivilegeWithOption), + sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName))); + + PrivilegeObject queryPrivilegeWithNoOption = new Builder() + .setComponent(SEARCH) + .setAction(SearchConstants.QUERY) + .setService(SERVICE) + .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME))) + .withGrantOption(false) + .build(); + + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName, queryPrivilegeWithNoOption, grantor); + + assertEquals(Sets.newHashSet(queryPrivilege, queryPrivilegeWithOption, queryPrivilegeWithNoOption), + sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName))); + } + + @Test + public void testGrantPrivilegeTwice() throws Exception { + String roleName = "r1"; + /** + * grantor is admin, there is no need to check grant option + */ + String grantor = ADMIN_USER; + sentryStore.createRole(SEARCH, roleName, grantor); + + PrivilegeObject queryPrivilegeWithOption = new Builder() + .setComponent(SEARCH) + .setAction(SearchConstants.QUERY) + .setService(SERVICE) + .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME))) + .withGrantOption(true) + .build(); + + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName, queryPrivilegeWithOption, grantor); + assertEquals(1,sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName)).size()); + //grant again + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName, queryPrivilegeWithOption, grantor); + assertEquals(1,sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName)).size()); + + PrivilegeObject queryPrivilegeWithNoOption = new Builder() + .setComponent(SEARCH) + .setAction(SearchConstants.QUERY) + .setService(SERVICE) + .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME))) + .withGrantOption(false) + .build(); + + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName, queryPrivilegeWithNoOption, grantor); + assertEquals(2,sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName)).size()); + //grant again + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName, queryPrivilegeWithNoOption, grantor); + assertEquals(2,sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName)).size()); + + PrivilegeObject queryPrivilegeWithNullGrant = new Builder() + .setComponent(SEARCH) + .setAction(SearchConstants.QUERY) + .setService(SERVICE) + .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME))) + .withGrantOption(null) + .build(); + + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName, queryPrivilegeWithNullGrant, grantor); + + assertEquals(3,sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName)).size()); + //grant again + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName, queryPrivilegeWithNullGrant, grantor); + assertEquals(3,sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName)).size()); + + } + + /** + * Grant query privilege to role r1 and there is ALL privilege related this + * collection existed + */ + @Test + public void testGrantPrivilegeWithAllPrivilegeExist() throws Exception { + String roleName = "r1"; + /** + * grantor is admin, there is no need to check grant option + */ + String grantor = ADMIN_USER; + PrivilegeObject allPrivilege = new Builder() + .setComponent(SEARCH) + .setAction(SearchConstants.ALL) + .setService(SERVICE) + .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME))) + .build(); + + sentryStore.createRole(SEARCH, roleName, grantor); + /** + * grant all privilege to role r1 + */ + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName, allPrivilege, grantor); + /** + * check role r1 truly has the privilege been granted + */ + assertEquals(Sets.newHashSet(allPrivilege), + sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName))); + + PrivilegeObject queryPrivilege = new Builder(allPrivilege) + .setAction(SearchConstants.QUERY) + .build(); + + /** + * grant query privilege to role r1 + */ + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName, queryPrivilege, grantor); + /** + * all privilege has been existed, the query privilege will not persistent + */ + assertEquals(Sets.newHashSet(allPrivilege), + sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName))); + } + + /** + * Grant query privilege to role r1 and there are query and update privileges + * related this collection existed + */ + @Test + public void testGrantALLPrivilegeWithOtherPrivilegesExist() throws Exception { + String roleName1 = "r1"; + String roleName2 = "r2"; + /** + * grantor is admin, there is no need to check grant option + */ + String grantor = ADMIN_USER; + + PrivilegeObject queryPrivilege = new Builder() + .setComponent(SEARCH) + .setAction(SearchConstants.QUERY) + .setService(SERVICE) + .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME))) + .build(); + + PrivilegeObject updatePrivilege = new Builder(queryPrivilege) + .setAction(SearchConstants.UPDATE) + .build(); + + sentryStore.createRole(SEARCH, roleName1, grantor); + sentryStore.createRole(SEARCH, roleName2, grantor); + /** + * grant query and update privilege to role r1 and role r2 + */ + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName1, queryPrivilege, grantor); + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName1, updatePrivilege,grantor); + assertEquals(Sets.newHashSet(queryPrivilege, updatePrivilege), + sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName1))); + + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName2, queryPrivilege, grantor); + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName2, updatePrivilege,grantor); + assertEquals(Sets.newHashSet(queryPrivilege, updatePrivilege), + sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName2))); + + PrivilegeObject allPrivilege = new Builder(queryPrivilege) + .setAction(SearchConstants.ALL) + .build(); + + /** + * grant all privilege to role r1 + */ + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName1, allPrivilege, grantor); + + /** + * check the query and update privileges of roleName1 will be removed because of ALl privilege + * granted + */ + assertEquals(Sets.newHashSet(allPrivilege), + sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName1))); + + /** + * check the query and update privileges of roleName2 will not affected and exist + */ + assertEquals(Sets.newHashSet(queryPrivilege, updatePrivilege), + sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName2))); + } + + @Test + public void testGrantRevokeCheckWithGrantOption() throws Exception { + + addGroupsToUser(GRANT_OPTION_USER, GRANT_OPTION_GROUP); + addGroupsToUser(NO_GRANT_OPTION_USER, NO_GRANT_OPTION_GROUP); + writePolicyFile(); + + String roleName1 = "r1"; + String roleName2 = "r2"; + String grantor = "g1"; + sentryStore.createRole(SEARCH, roleName1, grantor); + sentryStore.createRole(SEARCH, roleName2, grantor); + /** + * grant query privilege to role r1 with grant option + */ + PrivilegeObject queryPrivilege1 = new Builder() + .setComponent(SEARCH) + .setAction(SearchConstants.QUERY) + .setService(SERVICE) + .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME))) + .withGrantOption(true) + .build(); + + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName1, queryPrivilege1, + ADMIN_USER); + assertEquals(Sets.newHashSet(queryPrivilege1), + sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName1))); + /** + * grant query privilege to role r2 no grant option + */ + PrivilegeObject queryPrivilege2 = new Builder() + .setComponent(SEARCH) + .setAction(SearchConstants.QUERY) + .setService(SERVICE) + .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME))) + .withGrantOption(false).build(); + + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName2, queryPrivilege2, + ADMIN_USER); + assertEquals(Sets.newHashSet(queryPrivilege2), + sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName2))); + + sentryStore.alterRoleAddGroups(SEARCH, roleName1, + Sets.newHashSet(GRANT_OPTION_GROUP), grantor); + sentryStore.alterRoleAddGroups(SEARCH, roleName2, + Sets.newHashSet(NO_GRANT_OPTION_GROUP), grantor); + + String roleName3 = "r3"; + sentryStore.createRole(SEARCH, roleName3, grantor); + /** + * the user with grant option grant query privilege to rolr r3 + */ + try{ + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName3, queryPrivilege1, + GRANT_OPTION_USER); + } catch (SentryGrantDeniedException e) { + fail("SentryGrantDeniedException shouldn't have been thrown"); + } + + /** + * the user with grant option revoke query privilege to rolr r3 + */ + try{ + sentryStore.alterRoleRevokePrivilege(SEARCH, roleName3, queryPrivilege1, + GRANT_OPTION_USER); + } catch (SentryGrantDeniedException e) { + fail("SentryGrantDeniedException shouldn't have been thrown"); + } + + /** + * the user with no grant option grant query privilege to rolr r3, it will + * throw SentryGrantDeniedException + */ + try { + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName3, queryPrivilege2, + NO_GRANT_OPTION_USER); + fail("SentryGrantDeniedException should have been thrown"); + } catch (SentryGrantDeniedException e) { + //ignore the exception + } + + /** + * the user with no grant option revoke query privilege to rolr r3, it will + * throw SentryGrantDeniedException + */ + try { + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName3, queryPrivilege2, + NO_GRANT_OPTION_USER); + fail("SentryGrantDeniedException should have been thrown"); + } catch (SentryGrantDeniedException e) { + //ignore the exception + } + } + + @Test + public void testGrantWithGrantOption() throws Exception { + + addGroupsToUser(GRANT_OPTION_USER, GRANT_OPTION_GROUP); + addGroupsToUser(NO_GRANT_OPTION_USER, NO_GRANT_OPTION_GROUP); + writePolicyFile(); + + String roleName1 = "r1"; + String grantor = "g1"; + sentryStore.createRole(SEARCH, roleName1, grantor); + /** + * grant query privilege to role r1 with grant option + */ + PrivilegeObject queryPrivilege = new Builder() + .setComponent(SEARCH) + .setAction(SearchConstants.QUERY) + .setService(SERVICE) + .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME))) + .withGrantOption(true) + .build(); + + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName1, queryPrivilege,ADMIN_USER); + sentryStore.alterRoleAddGroups(SEARCH, roleName1, + Sets.newHashSet(GRANT_OPTION_GROUP), grantor); + + /** + * the user with grant option grant query privilege to rolr r2 + */ + String roleName2 = "r2"; + sentryStore.createRole(SEARCH, roleName2, grantor); + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName2, queryPrivilege, GRANT_OPTION_USER); + + assertEquals(Sets.newHashSet(queryPrivilege), + sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName2))); + + } + + + /** + * Grant query and update privileges to role r1 and revoke query privilege + * there is left update privilege related to role r1 + */ + @Test + public void testRevokePrivilege() throws Exception { + String roleName = "r1"; + /** + * grantor is admin, there is no need to check grant option + */ + String grantor = ADMIN_USER; + PrivilegeObject queryPrivilege = new Builder() + .setComponent(SEARCH) + .setAction(SearchConstants.QUERY) + .setService(SERVICE) + .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME), new Field(FIELD_NAME))) + .build(); + + PrivilegeObject updatePrivilege = new Builder(queryPrivilege) + .setAction(SearchConstants.UPDATE) + .build(); + + sentryStore.createRole(SEARCH, roleName, grantor); + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName, queryPrivilege, grantor); + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName, updatePrivilege, grantor); + + assertEquals(Sets.newHashSet(queryPrivilege,updatePrivilege), + sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName))); + /** + * revoke query privilege + */ + sentryStore.alterRoleRevokePrivilege(SEARCH, roleName, queryPrivilege, grantor); + assertEquals(Sets.newHashSet(updatePrivilege), + sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName))); + } + + /** + * Grant query and update privileges to role r1 and revoke all privilege, + * there is no privilege related to role r1 + */ + @Test + public void testRevokeAllPrivilege() throws Exception { + String roleName = "r1"; + /** + * grantor is admin, there is no need to check grant option + */ + String grantor = ADMIN_USER; + PrivilegeObject queryPrivilege = new Builder() + .setComponent(SEARCH) + .setAction(SearchConstants.QUERY) + .setService(SERVICE) + .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME),new Field(FIELD_NAME))) + .build(); + + PrivilegeObject updatePrivilege = new Builder(queryPrivilege) + .setAction(SearchConstants.UPDATE) + .build(); + + sentryStore.createRole(SEARCH, roleName, grantor); + + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName, queryPrivilege, grantor); + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName, updatePrivilege, grantor); + + assertEquals(Sets.newHashSet(queryPrivilege,updatePrivilege), + sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName))); + /** + * revoke all privilege + */ + PrivilegeObject allPrivilege = new Builder(queryPrivilege) + .setAction(SearchConstants.ALL) + .build(); + + sentryStore.alterRoleRevokePrivilege(SEARCH, roleName, allPrivilege, grantor); + + assertEquals(Sets.newHashSet(), + sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName))); + } + + /** + * Grant all privilege to role r1 and revoke query privilege + * there is update privilege related to role r1 + */ + @Test + public void testRevokePrivilegeWithAllPrivilegeExist() throws Exception { + String roleName = "r1"; + /** + * grantor is admin, there is no need to check grant option + */ + String grantor = ADMIN_USER; + PrivilegeObject allPrivilege = new Builder() + .setComponent(SEARCH) + .setAction(SearchConstants.QUERY) + .setService(SERVICE) + .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME), new Field(FIELD_NAME))) + .build(); + + sentryStore.createRole(SEARCH, roleName, grantor); + + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName, allPrivilege, grantor); + + assertEquals(Sets.newHashSet(allPrivilege), + sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName))); + /** + * revoke update privilege + */ + PrivilegeObject updatePrivilege = new Builder(allPrivilege) + .setAction(SearchConstants.UPDATE) + .build(); + + PrivilegeObject queryPrivilege = new Builder(allPrivilege) + .setAction(SearchConstants.QUERY) + .build(); + + sentryStore.alterRoleRevokePrivilege(SEARCH, roleName, updatePrivilege, grantor); + + assertEquals(Sets.newHashSet(queryPrivilege), + sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName))); + } + + @Test + public void testRevokeParentPrivilegeWithChildsExist() throws Exception { + String roleName = "r1"; + /** + * grantor is admin, there is no need to check grant option + */ + String grantor = ADMIN_USER; + PrivilegeObject updatePrivilege1 = new Builder() + .setComponent(SEARCH) + .setAction(SearchConstants.UPDATE) + .setService(SERVICE) + .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME), new Field(FIELD_NAME))) + .build(); + + PrivilegeObject queryPrivilege1 = new Builder() + .setComponent(SEARCH) + .setAction(SearchConstants.QUERY) + .setService(SERVICE) + .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME),new Field(FIELD_NAME))) + .build(); + + PrivilegeObject queryPrivilege2 = new Builder() + .setComponent(SEARCH) + .setAction(SearchConstants.QUERY) + .setService(SERVICE) + .setAuthorizables(Arrays.asList(new Collection(NOT_COLLECTION_NAME))) + .build(); + + sentryStore.createRole(SEARCH, roleName, grantor); + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName, updatePrivilege1, grantor); + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName, queryPrivilege1, grantor); + + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName, queryPrivilege2, grantor); + + /** + * revoke all privilege with collection[COLLECTION_NAME=collection1] and its child privileges + */ + PrivilegeObject allPrivilege = new Builder() + .setComponent(SEARCH) + .setAction(SearchConstants.ALL) + .setService(SERVICE) + .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME))) + .build(); + + sentryStore.alterRoleRevokePrivilege(SEARCH, roleName, allPrivilege, grantor); + assertEquals(Sets.newHashSet(queryPrivilege2), + sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName))); + } + + @Test + public void testRevokeWithGrantOption() throws Exception { + + addGroupsToUser(GRANT_OPTION_USER, GRANT_OPTION_GROUP); + addGroupsToUser(NO_GRANT_OPTION_USER, NO_GRANT_OPTION_GROUP); + writePolicyFile(); + + String roleName1 = "r1"; + String grantor = "g1"; + sentryStore.createRole(SEARCH, roleName1, grantor); + /** + * grant query privilege to role r1 with grant option + */ + PrivilegeObject queryPrivilege = new Builder() + .setComponent(SEARCH) + .setAction(SearchConstants.QUERY) + .setService(SERVICE) + .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME))) + .withGrantOption(true) + .build(); + + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName1, queryPrivilege, + ADMIN_USER); + assertEquals(Sets.newHashSet(queryPrivilege), + sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName1))); + + sentryStore.alterRoleAddGroups(SEARCH, roleName1, + Sets.newHashSet(GRANT_OPTION_GROUP), grantor); + + String roleName2 = "r2"; + sentryStore.createRole(SEARCH, roleName2, grantor); + /** + * the user with grant option grant query privilege to rolr r2 + */ + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName2, queryPrivilege, + GRANT_OPTION_USER); + assertEquals(Sets.newHashSet(queryPrivilege), + sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName2))); + + /** + * the user with grant option revoke query privilege to rolr r3 + */ + sentryStore.alterRoleRevokePrivilege(SEARCH, roleName2, queryPrivilege, GRANT_OPTION_USER); + assertEquals(Sets.newHashSet(), + sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName2))); + } + + @Test + public void testDropPrivilege() throws Exception{ + String roleName1 = "r1"; + String roleName2 = "r2"; + String grantor = ADMIN_USER; + + PrivilegeObject queryPrivilege = new Builder() + .setComponent(SEARCH) + .setAction(SearchConstants.QUERY) + .setService(SERVICE) + .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME), new Field(FIELD_NAME))) + .build(); + + PrivilegeObject updatePrivilege = new Builder(queryPrivilege) + .setAction(SearchConstants.UPDATE) + .build(); + + /** + * grant query and update privilege to role r1 and r2 + */ + sentryStore.createRole(SEARCH, roleName1, grantor); + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName1, queryPrivilege, grantor); + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName1, updatePrivilege, grantor); + + sentryStore.createRole(SEARCH, roleName2, grantor); + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName2, queryPrivilege, grantor); + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName2, updatePrivilege, grantor); + + assertEquals(Sets.newHashSet(queryPrivilege,updatePrivilege), + sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName1))); + + assertEquals(Sets.newHashSet(queryPrivilege,updatePrivilege), + sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName2))); + /** + * drop query privilege + */ + sentryStore.dropPrivilege(SEARCH, queryPrivilege, grantor); + + assertEquals(Sets.newHashSet(updatePrivilege), + sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName1))); + + assertEquals(Sets.newHashSet(updatePrivilege), + sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName2))); + + /** + * drop ALL privilege + */ + PrivilegeObject allPrivilege = new Builder(queryPrivilege) + .setAction(SearchConstants.ALL) + .build(); + + sentryStore.dropPrivilege(SEARCH, allPrivilege, grantor); + + assertEquals(Sets.newHashSet(), + sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName1))); + + assertEquals(Sets.newHashSet(), + sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName2))); + + /** + * grant query and update field scope[collection1,field1] privilege to role r1 + * drop collection scope[collection1] privilege + * there is no privilege + */ + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName1, queryPrivilege, grantor); + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName1, updatePrivilege, grantor); + + PrivilegeObject parentPrivilege = new Builder() + .setComponent(SEARCH) + .setAction(SearchConstants.ALL) + .setService(SERVICE) + .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME))) + .build(); + + sentryStore.dropPrivilege(SEARCH, parentPrivilege, grantor); + assertEquals(Sets.newHashSet(), + sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName1))); + } + + @Test + public void testRenamePrivilege() throws Exception{ + String roleName1 = "r1"; + String roleName2 = "r2"; + String grantor = ADMIN_USER; + + List<? extends Authorizable> oldAuthoriables = Arrays.asList(new Collection(COLLECTION_NAME), new Field(FIELD_NAME)); + List<? extends Authorizable> newAuthoriables = Arrays.asList(new Collection(COLLECTION_NAME), new Field(NOT_FIELD_NAME)); + + PrivilegeObject oldQueryPrivilege = new Builder() + .setComponent(SEARCH) + .setAction(SearchConstants.QUERY) + .setService(SERVICE) + .setAuthorizables(oldAuthoriables) + .build(); + + PrivilegeObject oldUpdatePrivilege = new Builder(oldQueryPrivilege) + .setAction(SearchConstants.UPDATE) + .build(); + + PrivilegeObject oldALLPrivilege = new Builder(oldQueryPrivilege) + .setAction(SearchConstants.ALL) + .build(); + + + PrivilegeObject newQueryPrivilege = new Builder() + .setComponent(SEARCH) + .setAction(SearchConstants.QUERY) + .setService(SERVICE) + .setAuthorizables(newAuthoriables) + .build(); + + PrivilegeObject newUpdatePrivilege = new Builder(newQueryPrivilege) + .setAction(SearchConstants.UPDATE) + .build(); + + PrivilegeObject newALLPrivilege = new Builder(newQueryPrivilege) + .setAction(SearchConstants.ALL) + .build(); + + + /** + * grant query and update privilege to role r1 + * grant all privilege to role r2 + */ + sentryStore.createRole(SEARCH, roleName1, grantor); + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName1, oldQueryPrivilege, grantor); + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName1, oldUpdatePrivilege, grantor); + + sentryStore.createRole(SEARCH, roleName2, grantor); + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName2, oldALLPrivilege, grantor); + + assertEquals(Sets.newHashSet(oldQueryPrivilege,oldUpdatePrivilege), + sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName1))); + + assertEquals(Sets.newHashSet(oldALLPrivilege), + sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName2))); + /** + * rename old query privilege to new query privilege + */ + sentryStore.renamePrivilege(SEARCH, SERVICE, + oldAuthoriables, + newAuthoriables, + grantor); + + assertEquals(Sets.newHashSet(newQueryPrivilege,newUpdatePrivilege), + sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName1))); + + assertEquals(Sets.newHashSet(newALLPrivilege), + sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName2))); + /** + * rename collection scope[collection=collection1] privilege to [collection=not_collection1] + * These privileges belong to collection scope[collection=collection1] will change to + * [collection=not_collection1] + */ + + List<? extends Authorizable> newAuthoriables1 = Arrays.asList(new Collection(NOT_COLLECTION_NAME),new Field(NOT_FIELD_NAME)); + + PrivilegeObject newQueryPrivilege1 = new Builder(newQueryPrivilege) + .setAuthorizables(newAuthoriables1) + .build(); + + PrivilegeObject newUpdatePrivilege1 = new Builder(newUpdatePrivilege) + .setAuthorizables(newAuthoriables1) + .build(); + + PrivilegeObject newALLPrivilege1 = new Builder(newALLPrivilege) + .setAuthorizables(newAuthoriables1) + .build(); + + sentryStore.renamePrivilege(SEARCH, SERVICE, + Arrays.asList(new Collection(COLLECTION_NAME)), + Arrays.asList(new Collection(NOT_COLLECTION_NAME)), + grantor); + + assertEquals(Sets.newHashSet(newQueryPrivilege1,newUpdatePrivilege1), + sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName1))); + + assertEquals(Sets.newHashSet(newALLPrivilege1), + sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName2))); + } + + @Test + public void testGetPrivilegesByRoleName() throws Exception { + String roleName1 = "r1"; + String roleName2 = "r2"; + String grantor = "g1"; + + PrivilegeObject queryPrivilege = new Builder() + .setComponent(SEARCH) + .setAction(SearchConstants.QUERY) + .setService(SERVICE) + .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME))) + .build(); + + sentryStore.createRole(SEARCH, roleName1, grantor); + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName1, queryPrivilege, + ADMIN_USER); + + PrivilegeObject updatePrivilege = new Builder() + .setComponent(SEARCH) + .setAction(SearchConstants.QUERY) + .setService(SERVICE) + .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME))) + .build(); + + sentryStore.createRole(SEARCH, roleName2, grantor); + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName2, updatePrivilege, + ADMIN_USER); + + assertEquals(Sets.newHashSet(queryPrivilege,updatePrivilege), + sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName1,roleName2))); + + } + + @Test + public void testGetPrivilegesByProvider() throws Exception { + String roleName1 = "r1"; + String roleName2 = "r2"; + String roleName3 = "r3"; + String group = "g3"; + String grantor = ADMIN_USER; + + String service1 = "service1"; + + PrivilegeObject queryPrivilege1 = new Builder() + .setComponent(SEARCH) + .setAction(SearchConstants.QUERY) + .setService(service1) + .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME))) + .build(); + + PrivilegeObject updatePrivilege1 = new Builder() + .setComponent(SEARCH) + .setAction(SearchConstants.UPDATE) + .setService(service1) + .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME), new Field(FIELD_NAME))) + .build(); + + PrivilegeObject queryPrivilege2 = new Builder() + .setComponent(SEARCH) + .setAction(SearchConstants.QUERY) + .setService(service1) + .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME))) + .build(); + + PrivilegeObject updatePrivilege2 = new Builder() + .setComponent(SEARCH) + .setAction(SearchConstants.UPDATE) + .setService(service1) + .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME), new Field(FIELD_NAME))) + .build(); + + sentryStore.createRole(SEARCH, roleName1, grantor); + sentryStore.createRole(SEARCH, roleName2, grantor); + sentryStore.createRole(SEARCH, roleName3, grantor); + + sentryStore.alterRoleAddGroups(SEARCH, roleName3, Sets.newHashSet(group), grantor); + + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName1, queryPrivilege1, grantor); + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName1, updatePrivilege1, grantor); + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName2, queryPrivilege2, grantor); + sentryStore.alterRoleGrantPrivilege(SEARCH, roleName3, updatePrivilege2, grantor); + + assertEquals(Sets.newHashSet(updatePrivilege1, queryPrivilege1), + sentryStore.getPrivilegesByProvider(SEARCH, service1, Sets.newHashSet(roleName1), null, null)); + + assertEquals(Sets.newHashSet(updatePrivilege1, queryPrivilege1, queryPrivilege2), + sentryStore.getPrivilegesByProvider(SEARCH, service1, Sets.newHashSet(roleName1,roleName2), + null, null)); + + assertEquals(Sets.newHashSet(updatePrivilege1, queryPrivilege1, queryPrivilege2, updatePrivilege2), + sentryStore.getPrivilegesByProvider(SEARCH, service1, Sets.newHashSet(roleName1,roleName2), + Sets.newHashSet(group), null)); + + List<? extends Authorizable> authorizables = Arrays.asList(new Collection(COLLECTION_NAME), new Field(FIELD_NAME)); + assertEquals(Sets.newHashSet(updatePrivilege1, updatePrivilege2), + sentryStore.getPrivilegesByProvider(SEARCH, service1, Sets.newHashSet(roleName1,roleName2), + Sets.newHashSet(group), authorizables)); + } +} http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/bf3eb482/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/service/persistent/TestSentryGMPrivilege.java ---------------------------------------------------------------------- diff --git a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/service/persistent/TestSentryGMPrivilege.java b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/service/persistent/TestSentryGMPrivilege.java new file mode 100644 index 0000000..1411692 --- /dev/null +++ b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/service/persistent/TestSentryGMPrivilege.java @@ -0,0 +1,207 @@ +/** + * 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.persistent; + +import static junit.framework.Assert.assertTrue; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.fail; + +import java.util.Arrays; + +import org.apache.sentry.core.model.db.AccessConstants; +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.db.service.model.MSentryGMPrivilege; +import org.junit.Test; + +public class TestSentryGMPrivilege { + + @Test + public void testValidateAuthorizables() throws Exception { + try { + MSentryGMPrivilege fieldPrivilege = new MSentryGMPrivilege("solr", + "service1", Arrays.asList(new Collection("c1"), new Field("f1")),SearchConstants.QUERY, false); + } catch (IllegalStateException e) { + fail("unexpect happend: it is a validated privilege"); + } + + try { + MSentryGMPrivilege collectionPrivilege = new MSentryGMPrivilege("solr", + "service1", Arrays.asList(new Collection(""), new Field("f1")),SearchConstants.QUERY, false); + fail("unexpect happend: it is not a validated privilege, The empty name of authorizable can't be empty"); + } catch (IllegalStateException e) { + } + + try { + MSentryGMPrivilege fieldPrivilege = new MSentryGMPrivilege("solr", + "service1", Arrays.asList(null, new Field("f1")),SearchConstants.QUERY, false); + fail("unexpect happend: it is not a validated privilege, The authorizable can't be null"); + } catch (IllegalStateException e) { + } + } + + @Test + public void testImpliesWithServerScope() throws Exception { + //The persistent privilege is server scope + MSentryGMPrivilege serverPrivilege = new MSentryGMPrivilege("solr", + "service1", null,SearchConstants.QUERY, false); + + MSentryGMPrivilege collectionPrivilege = new MSentryGMPrivilege("solr", + "service1", Arrays.asList(new Collection("c1")), + SearchConstants.QUERY, false); + assertTrue(serverPrivilege.implies(collectionPrivilege)); + + MSentryGMPrivilege fieldPrivilege = new MSentryGMPrivilege("solr", + "service1", Arrays.asList(new Collection("c1"), new Field("f1")), + SearchConstants.QUERY, false); + assertTrue(serverPrivilege.implies(fieldPrivilege)); + assertTrue(collectionPrivilege.implies(fieldPrivilege)); + + serverPrivilege.setAction(SearchConstants.UPDATE); + assertFalse(serverPrivilege.implies(collectionPrivilege)); + assertFalse(serverPrivilege.implies(fieldPrivilege)); + + serverPrivilege.setAction(SearchConstants.ALL); + assertTrue(serverPrivilege.implies(collectionPrivilege)); + assertTrue(serverPrivilege.implies(fieldPrivilege)); + } + /** + * The requested privilege has the different authorizable size with the persistent privilege + * @throws Exception + */ + @Test + public void testImpliesDifferentAuthorizable() throws Exception { + /** + * Test the scope of persistent privilege is the larger than the requested privilege + */ + MSentryGMPrivilege serverPrivilege = new MSentryGMPrivilege("solr", + "service1", null, SearchConstants.QUERY, false); + + MSentryGMPrivilege collectionPrivilege = new MSentryGMPrivilege("solr", + "service1", Arrays.asList(new Collection("c1")), + SearchConstants.QUERY, false); + + MSentryGMPrivilege fieldPrivilege = new MSentryGMPrivilege("solr", + "service1", Arrays.asList(new Collection("c1"), new Field("f1")), + SearchConstants.QUERY, false); + assertTrue(serverPrivilege.implies(collectionPrivilege)); + assertTrue(serverPrivilege.implies(fieldPrivilege)); + assertTrue(collectionPrivilege.implies(fieldPrivilege)); + /** + * Test the scope of persistent privilege is less than the request privilege + */ + assertFalse(fieldPrivilege.implies(collectionPrivilege)); + assertFalse(fieldPrivilege.implies(serverPrivilege)); + assertFalse(collectionPrivilege.implies(serverPrivilege)); + + /** + * Test the scope of persistent privilege is less than the request privilege, + * but the name of left authorizable is ALL + */ + MSentryGMPrivilege fieldAllPrivilege = new MSentryGMPrivilege("solr", + "service1", Arrays.asList(new Collection("c1"), new Field(AccessConstants.ALL)), + SearchConstants.QUERY, false); + + assertTrue(fieldAllPrivilege.implies(collectionPrivilege)); + + /** + * Test the scope of persistent privilege has the same scope as request privilege + */ + MSentryGMPrivilege fieldPrivilege1 = new MSentryGMPrivilege("solr", + "service1", Arrays.asList(new Collection("c1"), new Field("f1")), + SearchConstants.QUERY, false); + + MSentryGMPrivilege fieldPrivilege2 = new MSentryGMPrivilege("solr", + "service1", Arrays.asList(new Collection("c2"), new Field("f2")), + SearchConstants.QUERY, false); + assertFalse(fieldPrivilege1.implies(fieldPrivilege2)); + } + + /** + * The requested privilege has the same authorizable size as with the persistent privilege + * @throws Exception + */ + @Test + public void testSearchImpliesEqualAuthorizable() throws Exception { + + MSentryGMPrivilege serverPrivilege1 = new MSentryGMPrivilege("solr", + "service1", null,SearchConstants.QUERY, false); + + MSentryGMPrivilege serverPrivilege2 = new MSentryGMPrivilege("solr", + "service2", null,SearchConstants.QUERY, false); + + assertFalse(serverPrivilege1.implies(serverPrivilege2)); + + MSentryGMPrivilege collectionPrivilege1 = new MSentryGMPrivilege("solr", + "service1", Arrays.asList(new Collection("c1")), + SearchConstants.QUERY, false); + + MSentryGMPrivilege collectionPrivilege2 = new MSentryGMPrivilege("solr", + "service1", Arrays.asList(new Collection("c2")), + SearchConstants.QUERY, false); + + assertFalse(collectionPrivilege1.implies(collectionPrivilege2)); + + MSentryGMPrivilege fieldPrivilege1 = new MSentryGMPrivilege("solr", + "service1", Arrays.asList(new Collection("c1"), new Field("f1")), + SearchConstants.QUERY, false); + + MSentryGMPrivilege fieldPrivilege2 = new MSentryGMPrivilege("solr", + "service1", Arrays.asList(new Collection("c1"), new Field("f2")), + SearchConstants.QUERY, false); + + assertFalse(fieldPrivilege1.implies(fieldPrivilege2)); + + /** + * The authorizables aren't equal,but the persistent privilege has the ALL name + */ + collectionPrivilege2.setAuthorizables(Arrays.asList(new Collection(AccessConstants.ALL))); + collectionPrivilege2.implies(collectionPrivilege1); + + fieldPrivilege2.setAuthorizables(Arrays.asList(new Collection("c1"), new Field(AccessConstants.ALL))); + fieldPrivilege2.implies(fieldPrivilege1); + } + + @Test + public void testSearchImpliesAction() throws Exception { + /** + * action is equal + */ + MSentryGMPrivilege fieldPrivilege1 = new MSentryGMPrivilege("solr", + "service1", Arrays.asList(new Collection("c1"), new Field("f2")), + SearchConstants.QUERY, false); + + MSentryGMPrivilege fieldPrivilege2 = new MSentryGMPrivilege("solr", + "service1", Arrays.asList(new Collection("c1"), new Field("f2")), + SearchConstants.QUERY, false); + + assertTrue(fieldPrivilege1.implies(fieldPrivilege2)); + + /** + * action isn't equal + */ + fieldPrivilege2.setAction(SearchConstants.UPDATE); + assertFalse(fieldPrivilege1.implies(fieldPrivilege2)); + /** + * action isn't equal,but the persistent privilege has the ALL action + */ + fieldPrivilege1.setAction(SearchConstants.ALL); + assertTrue(fieldPrivilege1.implies(fieldPrivilege2)); + } +} http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/bf3eb482/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/service/persistent/TestSentryRole.java ---------------------------------------------------------------------- diff --git a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/service/persistent/TestSentryRole.java b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/service/persistent/TestSentryRole.java new file mode 100644 index 0000000..f8eecd9 --- /dev/null +++ b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/service/persistent/TestSentryRole.java @@ -0,0 +1,373 @@ +/** + * 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.persistent; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertTrue; +import static junit.framework.Assert.fail; + +import java.io.File; +import java.util.Arrays; +import java.util.Properties; + +import javax.jdo.JDOHelper; +import javax.jdo.PersistenceManager; +import javax.jdo.PersistenceManagerFactory; +import javax.jdo.Query; +import javax.jdo.Transaction; + +import org.apache.commons.io.FileUtils; +import org.apache.sentry.core.model.search.Collection; +import org.apache.sentry.provider.db.service.model.MSentryGMPrivilege; +import org.apache.sentry.provider.db.service.model.MSentryPrivilege; +import org.apache.sentry.provider.db.service.model.MSentryRole; +import org.apache.sentry.provider.db.service.persistent.SentryStore; +import org.apache.sentry.service.thrift.ServiceConstants.ServerConfig; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.google.common.base.Preconditions; +import com.google.common.io.Files; +/** + * The class tests that the new feature SENTRY-398 generic model adds the new field in the MSentryRole + * will not affect the functionality of the origin hive/impala authorization model + */ +public class TestSentryRole { + private static PersistenceManagerFactory pmf; + private static File dataDir; + + @Before + public void setup() throws Exception { + dataDir = new File(Files.createTempDir(), "sentry_policy_db"); + Properties prop = new Properties(); + prop.setProperty(ServerConfig.JAVAX_JDO_URL, "jdbc:derby:;databaseName=" + dataDir.getPath() + ";create=true"); + prop.setProperty(ServerConfig.JAVAX_JDO_USER, "Sentry"); + prop.setProperty(ServerConfig.JAVAX_JDO_PASS, "Sentry"); + prop.setProperty(ServerConfig.JAVAX_JDO_DRIVER_NAME, "org.apache.derby.jdbc.EmbeddedDriver"); + prop.setProperty("datanucleus.autoCreateSchema", "true"); + prop.setProperty("datanucleus.fixedDatastore", "false"); + prop.setProperty("datanucleus.NontransactionalRead", "false"); + prop.setProperty("datanucleus.NontransactionalWrite", "false"); + pmf = JDOHelper.getPersistenceManagerFactory(prop); + } + + @After + public void tearDown() throws Exception { + pmf.close(); + FileUtils.deleteQuietly(dataDir); + } + + @Test + public void grantMixedPrivilegeTest() throws Exception { + String roleName = "r1"; + //hive/impala privilege + MSentryPrivilege hivePrivilege = new MSentryPrivilege(); + hivePrivilege.setServerName("hive.server1"); + hivePrivilege.setDbName("db1"); + hivePrivilege.setTableName("tb1"); + hivePrivilege.setPrivilegeScope("table"); + hivePrivilege.setAction("select"); + hivePrivilege.setGrantOption(true); + //solr privilege + MSentryGMPrivilege solrPrivilege = new MSentryGMPrivilege(); + solrPrivilege.setComponentName("solr"); + solrPrivilege.setServiceName("solr.server1"); + solrPrivilege.setAuthorizables(Arrays.asList(new Collection("c1"))); + solrPrivilege.setAction("query"); + solrPrivilege.setGrantOption(true); + + PersistenceManager pm = null; + //create role + pm = openTransaction(); + pm.makePersistent(new MSentryRole(roleName, System.currentTimeMillis())); + commitTransaction(pm); + //add hivePrivilege to role + pm = openTransaction(); + MSentryRole role = getMSentryRole(pm, roleName); + hivePrivilege.appendRole(role); + pm.makePersistent(hivePrivilege); + commitTransaction(pm); + //check hivePrivlege and solrPrivilege + pm = openTransaction(); + role = getMSentryRole(pm, roleName); + pm.retrieve(role); + assertEquals(1, role.getPrivileges().size()); + assertEquals(0, role.getGmPrivileges().size()); + commitTransaction(pm); + //add solrPrivilege to role + pm = openTransaction(); + role = getMSentryRole(pm, roleName); + pm.retrieve(role); + solrPrivilege.appendRole(role); + pm.makePersistent(solrPrivilege); + commitTransaction(pm); + //check hivePrivlege and solrPrivilege + pm = openTransaction(); + role = getMSentryRole(pm, roleName); + pm.retrieve(role); + assertEquals(1, role.getPrivileges().size()); + assertEquals(1, role.getGmPrivileges().size()); + commitTransaction(pm); + } + + @Test + public void testWantGrantPrivilegeTwice() throws Exception { + String roleName = "r1"; + //hive/impala privilege + MSentryPrivilege hivePrivilege = new MSentryPrivilege(); + hivePrivilege.setServerName("hive.server1"); + hivePrivilege.setDbName("db1"); + hivePrivilege.setTableName("tb1"); + hivePrivilege.setPrivilegeScope("table"); + hivePrivilege.setAction("select"); + hivePrivilege.setURI(SentryStore.NULL_COL); + hivePrivilege.setColumnName(SentryStore.NULL_COL); + hivePrivilege.setGrantOption(true); + //The same hivePrivilege + MSentryPrivilege hivePrivilege2 = new MSentryPrivilege(hivePrivilege); + //solr privilege + MSentryGMPrivilege solrPrivilege = new MSentryGMPrivilege(); + solrPrivilege.setComponentName("solr"); + solrPrivilege.setServiceName("solr.server1"); + solrPrivilege.setAuthorizables(Arrays.asList(new Collection("c1"))); + solrPrivilege.setAction("query"); + solrPrivilege.setGrantOption(true); + //The same solrPrivilege + MSentryGMPrivilege solrPrivilege2 = new MSentryGMPrivilege(solrPrivilege); + + PersistenceManager pm = null; + //create role + pm = openTransaction(); + pm.makePersistent(new MSentryRole(roleName, System.currentTimeMillis())); + commitTransaction(pm); + + //grant hivePrivilege and solrPrivilege to role + pm = openTransaction(); + MSentryRole role = getMSentryRole(pm, roleName); + solrPrivilege.appendRole(role); + hivePrivilege.appendRole(role); + pm.makePersistent(solrPrivilege); + pm.makePersistent(hivePrivilege); + commitTransaction(pm); + //check + pm = openTransaction(); + role = getMSentryRole(pm, roleName); + pm.retrieve(role); + assertEquals(1, role.getPrivileges().size()); + assertEquals(1, role.getGmPrivileges().size()); + commitTransaction(pm); + + //want to grant the same hivePrivilege and solrPrivilege to role again + //hivePrivilege2 is equal to hivePrivilege + //solrPrivilege2 is equal to solrPrivilege + pm = openTransaction(); + role = getMSentryRole(pm, roleName); + pm.retrieve(role); + if (!role.getGmPrivileges().contains(solrPrivilege2)) { + fail("unexpect happend: the MSentryGMPrivilege:" + solrPrivilege2 + " already be granted"); + } + if (!role.getPrivileges().contains(hivePrivilege2)) { + fail("unexpect happend: the MSentryPrivilege:" + hivePrivilege2 + " already be granted"); + } + commitTransaction(pm); + } + + @Test + public void testMixedRevokePrivilege() throws Exception { + String roleName = "r1"; + //hive/impala privilege + MSentryPrivilege hivePrivilege = new MSentryPrivilege(); + hivePrivilege.setServerName("hive.server1"); + hivePrivilege.setDbName("db1"); + hivePrivilege.setTableName("tb1"); + hivePrivilege.setPrivilegeScope("table"); + hivePrivilege.setAction("select"); + hivePrivilege.setURI(SentryStore.NULL_COL); + hivePrivilege.setColumnName(SentryStore.NULL_COL); + hivePrivilege.setGrantOption(true); + + //solr privilege + MSentryGMPrivilege solrPrivilege = new MSentryGMPrivilege(); + solrPrivilege.setComponentName("solr"); + solrPrivilege.setServiceName("solr.server1"); + solrPrivilege.setAuthorizables(Arrays.asList(new Collection("c1"))); + solrPrivilege.setAction("query"); + solrPrivilege.setGrantOption(true); + + PersistenceManager pm = null; + //create role + pm = openTransaction(); + pm.makePersistent(new MSentryRole(roleName, System.currentTimeMillis())); + commitTransaction(pm); + + //grant hivePrivilege and solrPrivilege to role + pm = openTransaction(); + MSentryRole role = getMSentryRole(pm, roleName); + hivePrivilege.appendRole(role); + solrPrivilege.appendRole(role); + pm.makePersistent(hivePrivilege); + pm.makePersistent(solrPrivilege); + commitTransaction(pm); + + //check + pm = openTransaction(); + role = getMSentryRole(pm, roleName); + pm.retrieve(role); + assertEquals(1, role.getPrivileges().size()); + assertEquals(1, role.getGmPrivileges().size()); + commitTransaction(pm); + + //revoke solrPrivilege from role + pm = openTransaction(); + role = getMSentryRole(pm, roleName); + solrPrivilege = (MSentryGMPrivilege)role.getGmPrivileges().toArray()[0]; + solrPrivilege.removeRole(role); + pm.makePersistent(solrPrivilege); + commitTransaction(pm); + + //check + pm = openTransaction(); + role = getMSentryRole(pm, roleName); + pm.retrieve(role); + assertEquals(1, role.getPrivileges().size()); + assertEquals(0, role.getGmPrivileges().size()); + commitTransaction(pm); + + //revoke hivePrivilege from role + pm = openTransaction(); + role = getMSentryRole(pm, roleName); + pm.retrieve(role); + hivePrivilege = (MSentryPrivilege)role.getPrivileges().toArray()[0]; + hivePrivilege.removeRole(role); + pm.makePersistent(hivePrivilege); + commitTransaction(pm); + + //check + pm = openTransaction(); + role = getMSentryRole(pm, roleName); + pm.retrieve(role); + assertEquals(0, role.getPrivileges().size()); + assertEquals(0, role.getGmPrivileges().size()); + commitTransaction(pm); + } + + @Test + public void testDeletePrivilegeAndRole() throws Exception { + String roleName = "r1"; + //hive/impala privilege + MSentryPrivilege hivePrivilege = new MSentryPrivilege(); + hivePrivilege.setServerName("hive.server1"); + hivePrivilege.setDbName("db1"); + hivePrivilege.setTableName("tb1"); + hivePrivilege.setPrivilegeScope("table"); + hivePrivilege.setAction("select"); + hivePrivilege.setURI(SentryStore.NULL_COL); + hivePrivilege.setColumnName(SentryStore.NULL_COL); + hivePrivilege.setGrantOption(true); + + //solr privilege + MSentryGMPrivilege solrPrivilege = new MSentryGMPrivilege(); + solrPrivilege.setComponentName("solr"); + solrPrivilege.setServiceName("solr.server1"); + solrPrivilege.setAuthorizables(Arrays.asList(new Collection("c1"))); + solrPrivilege.setAction("query"); + solrPrivilege.setGrantOption(true); + + PersistenceManager pm = null; + //create role + pm = openTransaction(); + pm.makePersistent(new MSentryRole(roleName, System.currentTimeMillis())); + commitTransaction(pm); + + //grant hivePrivilege and solrPrivilege to role + pm = openTransaction(); + MSentryRole role = getMSentryRole(pm, roleName); + hivePrivilege.appendRole(role); + solrPrivilege.appendRole(role); + pm.makePersistent(hivePrivilege); + pm.makePersistent(solrPrivilege); + commitTransaction(pm); + + //check + pm = openTransaction(); + role = getMSentryRole(pm, roleName); + pm.retrieve(role); + assertEquals(1, role.getPrivileges().size()); + assertEquals(1, role.getGmPrivileges().size()); + commitTransaction(pm); + + //remove all privileges + pm = openTransaction(); + role = getMSentryRole(pm, roleName); + role.removeGMPrivileges(); + role.removePrivileges(); + pm.makePersistent(role); + commitTransaction(pm); + + //check + pm = openTransaction(); + role = getMSentryRole(pm, roleName); + pm.retrieve(role); + assertEquals(0, role.getPrivileges().size()); + assertEquals(0, role.getGmPrivileges().size()); + commitTransaction(pm); + + //delete role + pm = openTransaction(); + role = getMSentryRole(pm, roleName); + pm.deletePersistent(role); + commitTransaction(pm); + + //check + pm = openTransaction(); + role = getMSentryRole(pm, roleName); + assertTrue(role == null); + commitTransaction(pm); + } + + private PersistenceManager openTransaction() { + PersistenceManager pm = pmf.getPersistenceManager(); + Transaction currentTransaction = pm.currentTransaction(); + currentTransaction.begin(); + return pm; + } + + private void commitTransaction(PersistenceManager pm) { + Transaction currentTransaction = pm.currentTransaction(); + try { + Preconditions.checkState(currentTransaction.isActive(), "Transaction is not active"); + currentTransaction.commit(); + } finally { + pm.close(); + } + } + + private MSentryRole getMSentryRole(PersistenceManager pm, String roleName) { + Query query = pm.newQuery(MSentryRole.class); + query.setFilter("this.roleName == t"); + query.declareParameters("java.lang.String t"); + query.setUnique(true); + MSentryRole sentryRole = (MSentryRole) query.execute(roleName); + return sentryRole; + } + + +}
