From commits-return-12696-archive-asf-public=cust-asf.ponee.io@sentry.apache.org Thu May 31 05:32:04 2018 Return-Path: X-Original-To: archive-asf-public@cust-asf.ponee.io Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx-eu-01.ponee.io (Postfix) with SMTP id A42A01807A1 for ; Thu, 31 May 2018 05:32:01 +0200 (CEST) Received: (qmail 37925 invoked by uid 500); 31 May 2018 03:32:00 -0000 Mailing-List: contact commits-help@sentry.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@sentry.apache.org Delivered-To: mailing list commits@sentry.apache.org Received: (qmail 34603 invoked by uid 99); 31 May 2018 03:31:43 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 31 May 2018 03:31:43 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 7521BE1136; Thu, 31 May 2018 03:31:40 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: spena@apache.org To: commits@sentry.apache.org Date: Thu, 31 May 2018 03:32:24 -0000 Message-Id: <2d1ec55af8ca4ef3811865550a4ac057@git.apache.org> In-Reply-To: <5efebc2704cd43a891f304274777fee8@git.apache.org> References: <5efebc2704cd43a891f304274777fee8@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [46/86] sentry git commit: SENTRY-2208: Refactor out Sentry service into own module from sentry-provider-db (Anthony Young-Garner, reviewed by Sergio Pena, Steve Moist, Na Li) http://git-wip-us.apache.org/repos/asf/sentry/blob/7db84b2f/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/service/persistent/TestSentryStore.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/service/persistent/TestSentryStore.java b/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/service/persistent/TestSentryStore.java new file mode 100644 index 0000000..e2d24e5 --- /dev/null +++ b/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/service/persistent/TestSentryStore.java @@ -0,0 +1,4036 @@ +/** + * 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.service.persistent; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; +import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; + +import com.google.common.collect.Lists; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.io.FileUtils; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.security.alias.CredentialProvider; +import org.apache.hadoop.security.alias.CredentialProviderFactory; +import org.apache.hadoop.security.alias.UserProvider; +import org.apache.sentry.core.common.exception.SentryAccessDeniedException; +import org.apache.sentry.core.common.exception.SentryInvalidInputException; +import org.apache.sentry.core.model.db.AccessConstants; +import org.apache.sentry.core.common.exception.SentryAlreadyExistsException; +import org.apache.sentry.core.common.exception.SentryGrantDeniedException; +import org.apache.sentry.core.common.exception.SentryNoSuchObjectException; +import org.apache.sentry.hdfs.PathsUpdate; +import org.apache.sentry.hdfs.PermissionsUpdate; +import org.apache.sentry.hdfs.UniquePathsUpdate; +import org.apache.sentry.hdfs.Updateable; +import org.apache.sentry.hdfs.service.thrift.TPathEntry; +import org.apache.sentry.hdfs.service.thrift.TPathsDump; +import org.apache.sentry.hdfs.service.thrift.TPathsUpdate; +import org.apache.sentry.hdfs.service.thrift.TPrivilegeChanges; +import org.apache.sentry.hdfs.service.thrift.TPrivilegeEntity; +import org.apache.sentry.hdfs.service.thrift.TPrivilegeEntityType; +import org.apache.sentry.hdfs.service.thrift.TRoleChanges; +import org.apache.sentry.provider.db.service.model.MSentryPermChange; +import org.apache.sentry.provider.db.service.model.MSentryPathChange; +import org.apache.sentry.provider.db.service.model.MSentryPrivilege; +import org.apache.sentry.provider.db.service.model.MSentryRole; +import org.apache.sentry.api.service.thrift.TSentryActiveRoleSet; +import org.apache.sentry.api.service.thrift.TSentryAuthorizable; +import org.apache.sentry.api.service.thrift.TSentryGrantOption; +import org.apache.sentry.api.service.thrift.TSentryGroup; +import org.apache.sentry.api.service.thrift.TSentryPrivilege; +import org.apache.sentry.api.service.thrift.TSentryRole; +import org.apache.sentry.provider.db.service.model.MSentryUser; +import org.apache.sentry.provider.file.PolicyFile; +import org.apache.sentry.api.common.SentryServiceUtil; +import org.apache.sentry.service.common.ServiceConstants; +import org.apache.sentry.service.common.ServiceConstants.SentryEntityType; +import org.apache.sentry.service.common.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.collect.Iterables; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import com.google.common.io.Files; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static org.apache.sentry.provider.db.service.persistent.QueryParamBuilder.newQueryParamBuilder; + +import javax.jdo.JDODataStoreException; + +public class TestSentryStore extends org.junit.Assert { + + private static final Logger LOGGER = LoggerFactory.getLogger(TestSentryStore.class); + + private static File dataDir; + private static SentryStore sentryStore; + private static String[] adminGroups = { "adminGroup1" }; + private static PolicyFile policyFile; + private static File policyFilePath; + final long NUM_PRIVS = 5; // > SentryStore.PrivCleaner.NOTIFY_THRESHOLD + private static Configuration conf = null; + private static char[] passwd = new char[] { '1', '2', '3'}; + + @BeforeClass + public static void setup() throws Exception { + conf = new Configuration(false); + final String ourUrl = UserProvider.SCHEME_NAME + ":///"; + conf.set(CredentialProviderFactory.CREDENTIAL_PROVIDER_PATH, ourUrl); + + // enable HDFS sync, so perm and path changes will be saved into DB + conf.set(ServiceConstants.ServerConfig.PROCESSOR_FACTORIES, "org.apache.sentry.hdfs.SentryHDFSServiceProcessorFactory"); + conf.set(ServiceConstants.ServerConfig.SENTRY_POLICY_STORE_PLUGINS, "org.apache.sentry.hdfs.SentryPlugin"); + + // THis should be a UserGroupInformation provider + CredentialProvider provider = CredentialProviderFactory.getProviders(conf).get(0); + + + // The user credentials are stored as a static variable by UserGrouoInformation provider. + // We need to only set the password the first time, an attempt to set it for the second + // time fails with an exception. + if(provider.getCredentialEntry(ServerConfig.SENTRY_STORE_JDBC_PASS) == null) { + provider.createCredentialEntry(ServerConfig.SENTRY_STORE_JDBC_PASS, passwd); + provider.flush(); + } + + 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.set(ServerConfig.SENTRY_STORE_JDBC_PASS, "dummy"); + conf.setStrings(ServerConfig.ADMIN_GROUPS, adminGroups); + conf.set(ServerConfig.SENTRY_STORE_GROUP_MAPPING, + ServerConfig.SENTRY_STORE_LOCAL_GROUP_MAPPING); + policyFilePath = new File(dataDir, "local_policy_file.ini"); + conf.set(ServerConfig.SENTRY_STORE_GROUP_MAPPING_RESOURCE, + policyFilePath.getPath()); + + // These tests do not need to retry transactions, so setting to 1 to reduce testing time + conf.setInt(ServerConfig.SENTRY_STORE_TRANSACTION_RETRY, 1); + + // SentryStore should be initialized only once. The tables created by the test cases will + // be cleaned up during the @After method. + sentryStore = new SentryStore(conf); + + boolean hdfsSyncEnabled = SentryServiceUtil.isHDFSSyncEnabled(conf); + sentryStore.setPersistUpdateDeltas(hdfsSyncEnabled); + } + + @Before + public void before() throws Exception { + policyFile = new PolicyFile(); + String adminUser = "g1"; + addGroupsToUser(adminUser, adminGroups); + writePolicyFile(); + } + + @After + public void after() { + sentryStore.clearAllTables(); + } + + @AfterClass + public static void teardown() { + if (dataDir != null) { + FileUtils.deleteQuietly(dataDir); + } + + sentryStore.stop(); + } + + /** + * Fail test if role already exists + * @param roleName Role name to checl + * @throws Exception + */ + private void checkRoleDoesNotExist(String roleName) throws Exception { + try { + sentryStore.getMSentryRoleByName(roleName); + fail("Role " + roleName + "already exists"); + } catch (SentryNoSuchObjectException e) { + // Ok + } + } + + /** + * Fail test if role doesn't exist + * @param roleName Role name to checl + * @throws Exception + */ + private void checkRoleExists(String roleName) throws Exception { + assertEquals(roleName.toLowerCase(), + sentryStore.getMSentryRoleByName(roleName).getRoleName()); + } + + /** + * Create a role with the given name and verify that it is created + * @param roleName + * @throws Exception + */ + private void createRole(String roleName) throws Exception { + checkRoleDoesNotExist(roleName); + sentryStore.createSentryRole(roleName); + checkRoleExists(roleName); + } + + @Test + public void testCredentialProvider() throws Exception { + assertArrayEquals(passwd, conf.getPassword(ServerConfig. + SENTRY_STORE_JDBC_PASS)); + } + + @Test + public void testCaseInsensitiveRole() throws Exception { + String roleName = "newRole"; + String grantor = "g1"; + Set groups = Sets.newHashSet(); + TSentryGroup group = new TSentryGroup(); + group.setGroupName("test-groups-g1"); + groups.add(group); + + TSentryPrivilege privilege = new TSentryPrivilege(); + privilege.setPrivilegeScope("TABLE"); + privilege.setServerName("server1"); + privilege.setDbName("default"); + privilege.setTableName("table1"); + privilege.setAction(AccessConstants.ALL); + privilege.setCreateTime(System.currentTimeMillis()); + + Set users = Sets.newHashSet("user1"); + + createRole(roleName); + + sentryStore.alterSentryRoleAddGroups(grantor, roleName, groups); + sentryStore.alterSentryRoleDeleteGroups(roleName, groups); + sentryStore.alterSentryRoleAddUsers(roleName, users); + sentryStore.alterSentryRoleDeleteUsers(roleName, users); + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName, privilege); + sentryStore.alterSentryRoleRevokePrivilege(grantor, roleName, privilege); + } + + @Test + public void testURI() throws Exception { + String roleName = "test-dup-role"; + String grantor = "g1"; + String uri = "file:///var/folders/dt/9zm44z9s6bjfxbrm4v36lzdc0000gp/T/1401860678102-0/data/kv1.dat"; + createRole(roleName); + TSentryPrivilege tSentryPrivilege = new TSentryPrivilege("URI", "server1", "ALL"); + tSentryPrivilege.setURI(uri); + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName, tSentryPrivilege); + + TSentryAuthorizable tSentryAuthorizable = new TSentryAuthorizable(); + tSentryAuthorizable.setUri(uri); + tSentryAuthorizable.setServer("server1"); + + Set privileges = + sentryStore.getTSentryPrivileges(SentryEntityType.ROLE, new HashSet(Arrays.asList(roleName)), tSentryAuthorizable); + + assertTrue(privileges.size() == 1); + + Set tSentryGroups = new HashSet(); + tSentryGroups.add(new TSentryGroup("group1")); + sentryStore.alterSentryRoleAddGroups(grantor, roleName, tSentryGroups); + sentryStore.alterSentryRoleAddUsers(roleName, Sets.newHashSet("user1")); + + TSentryActiveRoleSet thriftRoleSet = new TSentryActiveRoleSet(true, new HashSet(Arrays.asList(roleName))); + + // list privilege for group only + Set privs = sentryStore.listSentryPrivilegesForProvider( + new HashSet(Arrays.asList("group1")), Sets.newHashSet(""), thriftRoleSet, + tSentryAuthorizable); + + assertTrue(privs.size()==1); + assertTrue(privs.contains("server=server1->uri=" + uri + "->action=all")); + + // list privilege for user only + privs = sentryStore.listSentryPrivilegesForProvider(new HashSet(Arrays.asList("")), + Sets.newHashSet("user1"), thriftRoleSet, tSentryAuthorizable); + assertTrue(privs.size() == 1); + assertTrue(privs.contains("server=server1->uri=" + uri + "->action=all")); + + // list privilege for both user and group + privs = sentryStore.listSentryPrivilegesForProvider( + new HashSet(Arrays.asList("group1")), Sets.newHashSet("user1"), thriftRoleSet, + tSentryAuthorizable); + assertTrue(privs.size() == 1); + assertTrue(privs.contains("server=server1->uri=" + uri + "->action=all")); + } + + @Test + public void testURIGrantRevokeOnEmptyPath() throws Exception { + String roleName = "test-empty-uri-role"; + String grantor = "g1"; + String uri = ""; + createRole(roleName); + TSentryPrivilege tSentryPrivilege = new TSentryPrivilege("URI", "server1", "ALL"); + tSentryPrivilege.setURI(uri); + //Test grant on empty URI + try { + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName, tSentryPrivilege); + fail("Expected SentryInvalidInputException"); + } catch(SentryInvalidInputException e) { + // expected + } + //Test revoke on empty URI + try { + sentryStore.alterSentryRoleRevokePrivilege(grantor, roleName, tSentryPrivilege); + fail("Expected SentryInvalidInputException"); + } catch(SentryInvalidInputException e) { + // expected + } + } + + @Test + public void testCreateDuplicateRole() throws Exception { + String roleName = "test-dup-role"; + createRole(roleName); + try { + sentryStore.createSentryRole(roleName); + fail("Expected SentryAlreadyExistsException"); + } catch(SentryAlreadyExistsException e) { + // expected + } + } + + @Test + public void testCaseSensitiveScope() throws Exception { + String roleName = "role1"; + String grantor = "g1"; + createRole(roleName); + TSentryPrivilege sentryPrivilege = new TSentryPrivilege("Database", "server1", "all"); + sentryPrivilege.setDbName("db1"); + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName, sentryPrivilege); + } + + /** + * Create a new role and then destroy it + * @throws Exception + */ + @Test + public void testCreateDropRole() throws Exception { + String roleName = "test-drop-role"; + createRole(roleName); + sentryStore.dropSentryRole(roleName); + checkRoleDoesNotExist(roleName); + } + + @Test + public void testAddDeleteGroupsNonExistantRole() + throws Exception { + String roleName = "non-existant-role"; + String grantor = "g1"; + Set groups = Sets.newHashSet(); + Set users = Sets.newHashSet(grantor); + try { + sentryStore.alterSentryRoleAddGroups(grantor, roleName, groups); + fail("Expected SentryNoSuchObjectException exception"); + } catch (SentryNoSuchObjectException e) { + // excepted exception + } + try { + sentryStore.alterSentryRoleAddUsers(roleName, users); + fail("Expected SentryNoSuchObjectException exception"); + } catch (SentryNoSuchObjectException e) { + // excepted exception + } + } + + @Test + public void testAddDeleteGroups() throws Exception { + String roleName = "test-groups"; + String grantor = "g1"; + createRole(roleName); + Set groups = Sets.newHashSet(); + TSentryGroup group = new TSentryGroup(); + group.setGroupName("test-groups-g1"); + groups.add(group); + group = new TSentryGroup(); + group.setGroupName("test-groups-g2"); + groups.add(group); + sentryStore.alterSentryRoleAddGroups(grantor, roleName, groups); + sentryStore.alterSentryRoleDeleteGroups(roleName, groups); + MSentryRole role = sentryStore.getMSentryRoleByName(roleName); + assertEquals(Collections.emptySet(), role.getGroups()); + } + + @Test + public void testAddDeleteUsers() throws Exception { + String roleName = "test-users"; + createRole(roleName); + Set users = Sets.newHashSet("test-user-u1", "test-user-u2"); + sentryStore.alterSentryRoleAddUsers(roleName, users); + MSentryRole role = sentryStore.getMSentryRoleByName(roleName); + role.getUsers().size(); + sentryStore.alterSentryRoleDeleteUsers(roleName, users); + role = sentryStore.getMSentryRoleByName(roleName); + assertEquals(0, role.getUsers().size()); + } + + @Test + public void testGetTSentryRolesForUser() throws Exception { + // Test the method GetTSentryRolesForUser according to the following test data: + // user1->group1 + // user2->group1 + // user3->group1, group2 + // user4->group2, group3 + // group1->r1 + // group2->r2 + // group3->r2 + // user2->r3 + // user4->r3 + String roleName1 = "r1"; + String roleName2 = "r2"; + String roleName3 = "r3"; + String user1 = "u1"; + String user2 = "u2"; + String user3 = "u3"; + String user4 = "u4"; + String group1 = "group1"; + String group2 = "group2"; + String group3 = "group3"; + Map> userToGroups = Maps.newHashMap(); + userToGroups.put(user1, Sets.newHashSet(group1)); + userToGroups.put(user2, Sets.newHashSet(group1)); + userToGroups.put(user3, Sets.newHashSet(group1, group2)); + userToGroups.put(user4, Sets.newHashSet(group2, group3)); + + sentryStore.createSentryRole(roleName1); + sentryStore.createSentryRole(roleName2); + sentryStore.createSentryRole(roleName3); + sentryStore.alterSentryRoleAddUsers(roleName1, Sets.newHashSet(user1)); + sentryStore.alterSentryRoleAddUsers(roleName2, Sets.newHashSet(user2)); + sentryStore.alterSentryRoleAddUsers(roleName2, Sets.newHashSet(user3)); + sentryStore.alterSentryRoleAddUsers(roleName3, Sets.newHashSet(user2, user4)); + + Set roles = sentryStore.getTSentryRolesByUserNames(Sets.newHashSet(user1)); + assertEquals(1, roles.size()); + for (TSentryRole role : roles) { + assertTrue(roleName1.equals(role.getRoleName())); + } + + roles = sentryStore.getTSentryRolesByUserNames(Sets.newHashSet(user2)); + assertEquals(2, roles.size()); + for (TSentryRole role : roles) { + assertTrue(roleName2.equals(role.getRoleName()) || roleName3.equals(role.getRoleName())); + } + + roles = sentryStore.getTSentryRolesByUserNames(Sets.newHashSet(user3)); + assertEquals(1, roles.size()); + for (TSentryRole role : roles) { + assertTrue(roleName2.equals(role.getRoleName())); + } + + roles = sentryStore.getTSentryRolesByUserNames(Sets.newHashSet(user4)); + assertEquals(1, roles.size()); + for (TSentryRole role : roles) { + assertTrue(roleName3.equals(role.getRoleName())); + } + } + + @Test + public void testGetTSentryRolesForUsers() throws Exception { + // Test the method getTSentryRolesByUserNames according to the following test data: + // user1->r1 + // user2->r3 + // user3->r2 + // user4->r3, r2 + String roleName1 = "r1"; + String roleName2 = "r2"; + String roleName3 = "r3"; + String user1 = "u1"; + String user2 = "u2"; + String user3 = "u3"; + String user4 = "u4"; + + createRole(roleName1); + createRole(roleName2); + createRole(roleName3); + sentryStore.alterSentryRoleAddUsers(roleName1, Sets.newHashSet(user1)); + sentryStore.alterSentryRoleAddUsers(roleName2, Sets.newHashSet(user3)); + sentryStore.alterSentryRoleAddUsers(roleName2, Sets.newHashSet(user4)); + sentryStore.alterSentryRoleAddUsers(roleName3, Sets.newHashSet(user2, user4)); + + Set userSet1 = Sets.newHashSet(user1, user2, user3); + Set roleSet1 = Sets.newHashSet(roleName1, roleName2, roleName3); + + Set userSet2 = Sets.newHashSet(user4); + Set roleSet2 = Sets.newHashSet(roleName2, roleName3); + + Set userSet3 = Sets.newHashSet("foo"); + Set roleSet3 = Sets.newHashSet(); + + // Query for multiple users + Set roles = convertToRoleNameSet(sentryStore.getTSentryRolesByUserNames(userSet1)); + assertEquals("Returned roles should match the expected roles", 0, Sets.symmetricDifference(roles, roleSet1).size()); + + // Query for single users + roles = convertToRoleNameSet(sentryStore.getTSentryRolesByUserNames(userSet2)); + assertEquals("Returned roles should match the expected roles", 0, Sets.symmetricDifference(roles, roleSet2).size()); + + // Query for non-existing user + roles = convertToRoleNameSet(sentryStore.getTSentryRolesByUserNames(userSet3)); + assertEquals("Returned roles should match the expected roles", 0, Sets.symmetricDifference(roles, roleSet3).size()); + } + + private Set convertToRoleNameSet(Set tSentryRoles) { + Set roleNameSet = Sets.newHashSet(); + for (TSentryRole role : tSentryRoles) { + roleNameSet.add(role.getRoleName()); + } + return roleNameSet; + } + + @Test + public void testGetTSentryRolesForGroups() throws Exception { + // Test the method getRoleNamesForGroups according to the following test data: + // group1->r1 + // group2->r2 + // group3->r2 + String grantor = "g1"; + String roleName1 = "r1"; + String roleName2 = "r2"; + String roleName3 = "r3"; + String group1 = "group1"; + String group2 = "group2"; + String group3 = "group3"; + + createRole(roleName1); + createRole(roleName2); + createRole(roleName3); + sentryStore.alterSentryRoleAddGroups(grantor, roleName1, Sets.newHashSet(new TSentryGroup(group1))); + sentryStore.alterSentryRoleAddGroups(grantor, roleName2, Sets.newHashSet(new TSentryGroup(group2), + new TSentryGroup(group3))); + + Set groupSet1 = Sets.newHashSet(group1, group2, group3); + Set roleSet1 = Sets.newHashSet(roleName1, roleName2); + + Set groupSet2 = Sets.newHashSet(group1); + Set roleSet2 = Sets.newHashSet(roleName1); + + Set groupSet3 = Sets.newHashSet("foo"); + Set roleSet3 = Sets.newHashSet(); + + // Query for multiple groups + Set roles = sentryStore.getRoleNamesForGroups(groupSet1); + assertEquals("Returned roles should match the expected roles", 0, Sets.symmetricDifference(roles, roleSet1).size()); + + // Query for single group + roles = sentryStore.getRoleNamesForGroups(groupSet2); + assertEquals("Returned roles should match the expected roles", 0, Sets.symmetricDifference(roles, roleSet2).size()); + + // Query for non-existing group + roles = sentryStore.getRoleNamesForGroups(groupSet3); + assertEquals("Returned roles should match the expected roles", 0, Sets.symmetricDifference(roles, roleSet3).size()); + } + + @Test + public void testGrantRevokePrivilege() throws Exception { + String roleName = "test-privilege"; + String grantor = "g1"; + String server = "server1"; + String db = "db1"; + String table = "tbl1"; + createRole(roleName); + TSentryPrivilege privilege = new TSentryPrivilege(); + privilege.setPrivilegeScope("TABLE"); + privilege.setServerName(server); + privilege.setDbName(db); + privilege.setTableName(table); + privilege.setAction(AccessConstants.ALL); + privilege.setCreateTime(System.currentTimeMillis()); + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName, privilege); + MSentryRole role = sentryStore.getMSentryRoleByName(roleName); + Set privileges = role.getPrivileges(); + assertEquals(privileges.toString(), 1, privileges.size()); + privilege.setAction(AccessConstants.SELECT); + sentryStore.alterSentryRoleRevokePrivilege(grantor, roleName, privilege); + // after having ALL and revoking SELECT, we should have INSERT + role = sentryStore.getMSentryRoleByName(roleName); + privileges = role.getPrivileges(); + assertEquals(privileges.toString(), 1, privileges.size()); + for (MSentryPrivilege mPrivilege : privileges) { + assertEquals(server, mPrivilege.getServerName()); + assertEquals(db, mPrivilege.getDbName()); + assertEquals(table, mPrivilege.getTableName()); + assertNotSame(AccessConstants.SELECT, mPrivilege.getAction()); + assertFalse(mPrivilege.getGrantOption()); + } + long numDBPrivs = sentryStore.countMSentryPrivileges(); + assertEquals("Privilege count", numDBPrivs,1); + } + + private void verifyOrphanCleanup() throws Exception { + assertFalse("Failed to cleanup orphaned privileges", sentryStore.findOrphanedPrivileges()); + } + + /** + * Create several privileges in the database, then delete the role that + * created them. This makes them all orphans. Wait a bit to ensure the + * cleanup thread runs, and expect them all to be gone from the database. + * @throws Exception + */ + // @Ignore("Disabled with SENTRY-545 following SENTRY-140 problems") + @Test + public void testPrivilegeCleanup() throws Exception { + final String roleName = "test-priv-cleanup"; + final String grantor = "g1"; + final String server = "server"; + final String dBase = "db"; + final String table = "table-"; + + createRole(roleName); + + // Create NUM_PRIVS unique privilege objects in the database + for (int i = 0; i < NUM_PRIVS; i++) { + TSentryPrivilege priv = new TSentryPrivilege(); + priv.setPrivilegeScope("TABLE"); + priv.setServerName(server); + priv.setAction(AccessConstants.ALL); + priv.setCreateTime(System.currentTimeMillis()); + priv.setTableName(table + i); + priv.setDbName(dBase); + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName, priv); + } + + // Make sure we really have the expected number of privs in the database + assertEquals(sentryStore.countMSentryPrivileges(), NUM_PRIVS); + + // Now to make a bunch of orphans, we just remove the role that + // created them. + sentryStore.dropSentryRole(roleName); + + // Now wait and see if the orphans get cleaned up + verifyOrphanCleanup(); + + List list = sentryStore.getAllMSentryPrivileges(); + assertEquals(list.size(), 0); + } + + /** + * Much like testPrivilegeCleanup, make a lot of privileges and make sure + * they get cleaned up. The difference here is that the privileges are + * created by granting ALL and then removing SELECT - thus leaving INSERT. + * This test exists because the revocation plays havoc with the orphan + * cleanup thread. + * @throws Exception + */ + // @Ignore("Disabled with SENTRY-545 following SENTRY-140 problems") + @Test + public void testPrivilegeCleanup2() throws Exception { + final String roleName = "test-priv-cleanup"; + final String grantor = "g1"; + final String server = "server"; + final String dBase = "db"; + final String table = "table-"; + + createRole(roleName); + + // Create NUM_PRIVS unique privilege objects in the database once more, + // this time granting ALL and revoking SELECT to make INSERT. + for (int i=0 ; i < NUM_PRIVS; i++) { + TSentryPrivilege priv = new TSentryPrivilege(); + priv.setPrivilegeScope("DATABASE"); + priv.setServerName(server); + priv.setAction(AccessConstants.ALL); + priv.setCreateTime(System.currentTimeMillis()); + priv.setTableName(table + i); + priv.setDbName(dBase); + priv.setGrantOption(TSentryGrantOption.TRUE); + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName, priv); + + priv.setAction(AccessConstants.SELECT); + priv.setGrantOption(TSentryGrantOption.UNSET); + sentryStore.alterSentryRoleRevokePrivilege(grantor, roleName, priv); + // after having ALL and revoking SELECT, we should have INSERT + MSentryRole role = sentryStore.getMSentryRoleByName(roleName); + Set privileges = role.getPrivileges(); + assertEquals(privileges.toString(), 1 * (i+1), privileges.size()); + for ( MSentryPrivilege mSentryPrivilege : privileges) { + assertNotSame(AccessConstants.INSERT, mSentryPrivilege.getAction()); + assertNotSame(AccessConstants.ALL, mSentryPrivilege.getAction()); + } + } + + // Drop the role and clean up as before + sentryStore.dropSentryRole(roleName); + verifyOrphanCleanup(); + //There should not be any Privileges left + List list = sentryStore.getAllMSentryPrivileges(); + assertEquals(list.size(), 0); + } + + /** + * This method tries to add ALL privileges on + * databases to a role and immediately revokes + * SELECT and INSERT privileges. At the end of + * each iteration we should not find any privileges + * for that role. Finally we should not find any + * privileges, as we are cleaning up orphan privileges + * immediately. + * @throws Exception + */ + @Test + public void testPrivilegeCleanup3() throws Exception { + final String roleName = "test-priv-cleanup"; + final String grantor = "g1"; + final String server = "server"; + final String dBase = "db"; + final String table = "table-"; + + createRole(roleName); + + // Create NUM_PRIVS unique privilege objects in the database once more, + // this time granting ALL and revoking SELECT to make INSERT. + for (int i=0 ; i < NUM_PRIVS; i++) { + TSentryPrivilege priv = new TSentryPrivilege(); + priv.setPrivilegeScope("DATABASE"); + priv.setServerName(server); + priv.setAction(AccessConstants.ALL); + priv.setCreateTime(System.currentTimeMillis()); + priv.setTableName(table + i); + priv.setDbName(dBase); + priv.setGrantOption(TSentryGrantOption.TRUE); + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName, priv); + + priv.setAction(AccessConstants.SELECT); + priv.setGrantOption(TSentryGrantOption.UNSET); + sentryStore.alterSentryRoleRevokePrivilege(grantor, roleName, priv); + + assertFalse(sentryStore.findOrphanedPrivileges()); + + //After having ALL and revoking SELECT, we should have INSERT + //Remove the INSERT privilege as well. + //There should not be any more privileges in the sentry store + priv.setAction(AccessConstants.INSERT); + sentryStore.alterSentryRoleRevokePrivilege(grantor, roleName, priv); + + MSentryRole role = sentryStore.getMSentryRoleByName(roleName); + assertEquals("Privilege Count", 0, role.getPrivileges().size()); + + priv.setAction(AccessConstants.CREATE); + sentryStore.alterSentryRoleRevokePrivilege(grantor, roleName, priv); + + role = sentryStore.getMSentryRoleByName(roleName); + assertEquals("Privilege Count", 0, role.getPrivileges().size()); + + priv.setAction(AccessConstants.DROP); + sentryStore.alterSentryRoleRevokePrivilege(grantor, roleName, priv); + + role = sentryStore.getMSentryRoleByName(roleName); + assertEquals("Privilege Count", 0, role.getPrivileges().size()); + + priv.setAction(AccessConstants.ALTER); + sentryStore.alterSentryRoleRevokePrivilege(grantor, roleName, priv); + + role = sentryStore.getMSentryRoleByName(roleName); + assertEquals("Privilege Count", 0, role.getPrivileges().size()); + } + + // Drop the role and clean up as before + verifyOrphanCleanup(); + + //There should not be any Privileges left + List list = sentryStore.getAllMSentryPrivileges(); + assertEquals(list.size(), 0); + + } + + /** + * This method "n" privileges with action "ALL" on + * tables to a role. Later we are revoking insert + * and select privileges to of the tables making the + * the privilege orphan. Finally we should find only + * n -1 privileges, as we are cleaning up orphan + * privileges immediately. + * @throws Exception + */ + @Test + public void testPrivilegeCleanup4 () throws Exception { + final String roleName = "test-priv-cleanup"; + final String grantor = "g1"; + final String server = "server"; + final String dBase = "db"; + final String table = "table-"; + + createRole(roleName); + + // Create NUM_PRIVS unique privilege objects in the database + for (int i = 0; i < NUM_PRIVS; i++) { + TSentryPrivilege priv = new TSentryPrivilege(); + priv.setPrivilegeScope("TABLE"); + priv.setServerName(server); + priv.setAction(AccessConstants.ALL); + priv.setCreateTime(System.currentTimeMillis()); + priv.setTableName(table + i); + priv.setDbName(dBase); + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName, priv); + } + + // Make sure we really have the expected number of privs in the database + assertEquals(sentryStore.countMSentryPrivileges(), NUM_PRIVS); + + //Revoking INSERT privilege. This is change the privilege to SELECT, CREATE, DROP, ALTER + TSentryPrivilege priv = new TSentryPrivilege(); + priv.setPrivilegeScope("TABLE"); + priv.setServerName(server); + priv.setAction(AccessConstants.INSERT); + priv.setCreateTime(System.currentTimeMillis()); + priv.setTableName(table + '0'); + priv.setDbName(dBase); + sentryStore.alterSentryRoleRevokePrivilege(grantor, roleName, priv); + + //There should be SELECT privilege in the sentry store + priv = new TSentryPrivilege(); + priv.setPrivilegeScope("TABLE"); + priv.setServerName(server); + priv.setAction(AccessConstants.SELECT); + priv.setCreateTime(System.currentTimeMillis()); + priv.setTableName(table + '0'); + priv.setDbName(dBase); + MSentryPrivilege mPriv = sentryStore.findMSentryPrivilegeFromTSentryPrivilege(priv); + assertNotNull(mPriv); + + MSentryRole role = sentryStore.getMSentryRoleByName(roleName); + + // should have NUM_PRIVS - 1 ALL privileges, and 4 privileges (SELECT, CREATE, DROP, ALTER) + assertEquals("Privilege Count", NUM_PRIVS, role.getPrivileges().size()); + + sentryStore.alterSentryRoleRevokePrivilege(grantor, roleName, priv); + role = sentryStore.getMSentryRoleByName(roleName); + assertEquals("Privilege Count", NUM_PRIVS - 1, role.getPrivileges().size()); + + } + + /** + * This method tries to add alter privileges on + * databases to a role and immediately revokes + * them. At the end of each iteration we should + * not find any privileges for that role + * Finally we should not find any privileges, as + * we are cleaning up orphan privileges immediately. + * @throws Exception + */ + @Test + public void testPrivilegeCleanup5() throws Exception { + final String roleName = "test-priv-cleanup"; + final String grantor = "g1"; + final String server = "server"; + final String dBase = "db"; + final String table = "table-"; + + createRole(roleName); + + // Create NUM_PRIVS unique privilege objects in the database once more, + // this time granting ALL and revoking SELECT to make INSERT. + for (int i=0 ; i < NUM_PRIVS; i++) { + TSentryPrivilege priv = new TSentryPrivilege(); + priv.setPrivilegeScope("DATABASE"); + priv.setServerName(server); + priv.setAction(AccessConstants.ALTER); + priv.setCreateTime(System.currentTimeMillis()); + priv.setTableName(table + i); + priv.setDbName(dBase); + priv.setGrantOption(TSentryGrantOption.TRUE); + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName, priv); + + priv.setAction(AccessConstants.ALTER); + sentryStore.alterSentryRoleRevokePrivilege(grantor, roleName, priv); + + MSentryRole role = sentryStore.getMSentryRoleByName(roleName); + assertEquals("Privilege Count", 0, role.getPrivileges().size()); + } + //There should not be any Privileges left + List list = sentryStore.getAllMSentryPrivileges(); + assertEquals(list.size(), 0); + + } + + //TODO Use new transaction Manager logic, Instead of + + @Test + public void testGrantRevokeMultiPrivileges() throws Exception { + String roleName = "test-privilege"; + String grantor = "g1"; + String server = "server1"; + String db = "db1"; + String table = "tbl1"; + String[] columns = {"c1","c2","c3","c4"}; + createRole(roleName); + Set tPrivileges = Sets.newHashSet(); + for (String column : columns) { + TSentryPrivilege privilege = new TSentryPrivilege(); + privilege.setPrivilegeScope("Column"); + privilege.setServerName(server); + privilege.setDbName(db); + privilege.setTableName(table); + privilege.setColumnName(column); + privilege.setAction(AccessConstants.SELECT); + privilege.setCreateTime(System.currentTimeMillis()); + tPrivileges.add(privilege); + } + sentryStore.alterSentryRoleGrantPrivileges(grantor, roleName, tPrivileges); + MSentryRole role = sentryStore.getMSentryRoleByName(roleName); + Set privileges = role.getPrivileges(); + assertEquals(privileges.toString(), 4, privileges.size()); + + tPrivileges = Sets.newHashSet(); + for (int i = 0; i < 2; i++) { + TSentryPrivilege privilege = new TSentryPrivilege(); + privilege.setPrivilegeScope("Column"); + privilege.setServerName(server); + privilege.setDbName(db); + privilege.setTableName(table); + privilege.setColumnName(columns[i]); + privilege.setAction(AccessConstants.SELECT); + privilege.setCreateTime(System.currentTimeMillis()); + tPrivileges.add(privilege); + } + sentryStore.alterSentryRoleRevokePrivileges(grantor, roleName, tPrivileges); + role = sentryStore.getMSentryRoleByName(roleName); + privileges = role.getPrivileges(); + assertEquals(privileges.toString(), 2, privileges.size()); + + TSentryPrivilege privilege = new TSentryPrivilege(); + privilege.setPrivilegeScope("Table"); + privilege.setServerName(server); + privilege.setDbName(db); + privilege.setTableName(table); + privilege.setAction(AccessConstants.SELECT); + privilege.setCreateTime(System.currentTimeMillis()); + sentryStore.alterSentryRoleRevokePrivilege(grantor, roleName, privilege); + // After revoking table scope, we will have 0 privileges + role = sentryStore.getMSentryRoleByName(roleName); + privileges = role.getPrivileges(); + assertEquals(privileges.toString(), 0, privileges.size()); + } + + /** + * Regression test for SENTRY-74 and SENTRY-552 + */ + @Test + public void testGrantRevokePrivilegeWithColumn() throws Exception { + String roleName = "test-col-privilege"; + String grantor = "g1"; + String server = "server1"; + String db = "db1"; + String table = "tbl1"; + String column1 = "c1"; + String column2 = "c2"; + createRole(roleName); + TSentryPrivilege privilege = new TSentryPrivilege(); + privilege.setPrivilegeScope("COLUMN"); + privilege.setServerName(server); + privilege.setDbName(db); + privilege.setTableName(table); + privilege.setColumnName(column1); + privilege.setAction(AccessConstants.ALL); + privilege.setCreateTime(System.currentTimeMillis()); + + // Grant ALL on c1 and c2 + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName, privilege); + privilege.setColumnName(column2); + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName, privilege); + MSentryRole role = sentryStore.getMSentryRoleByName(roleName); + Set privileges = role.getPrivileges(); + assertEquals(privileges.toString(), 2, privileges.size()); + + // Revoke SELECT on c2 + privilege.setAction(AccessConstants.SELECT); + sentryStore.alterSentryRoleRevokePrivilege(grantor, roleName, privilege); + + // At this point c1 has ALL privileges and c2 should have (INSERT, CREATE, DROP, ALTER) + // after revoking SELECT + role = sentryStore.getMSentryRoleByName(roleName); + privileges = role.getPrivileges(); + assertEquals(privileges.toString(), 2, privileges.size()); + for (MSentryPrivilege mPrivilege: privileges) { + assertEquals(server, mPrivilege.getServerName()); + assertEquals(db, mPrivilege.getDbName()); + assertEquals(table, mPrivilege.getTableName()); + assertFalse(mPrivilege.getGrantOption()); + if (mPrivilege.getColumnName().equals(column1)) { + assertEquals(AccessConstants.ALL, mPrivilege.getAction()); + } else if (mPrivilege.getColumnName().equals(column2)) { + assertNotSame(AccessConstants.SELECT, mPrivilege.getAction()); + assertNotSame(AccessConstants.ALL, mPrivilege.getAction()); + } else { + fail("Unexpected column name: " + mPrivilege.getColumnName()); + } + } + + // after revoking INSERT table level privilege will remove INSERT privileges from column2 + // and downgrade column1 to (SELECT) privileges. + privilege = new TSentryPrivilege(); + privilege.setPrivilegeScope("TABLE"); + privilege.setServerName(server); + privilege.setDbName(db); + privilege.setTableName(table); + privilege.setAction(AccessConstants.INSERT); + privilege.setCreateTime(System.currentTimeMillis()); + sentryStore.alterSentryRoleRevokePrivilege(grantor, roleName, privilege); + role = sentryStore.getMSentryRoleByName(roleName); + privileges = role.getPrivileges(); + assertEquals(privileges.toString(), 1, privileges.size()); + + // Revoke ALL from the table should now remove all the column privileges. + privilege.setAction(AccessConstants.ALL); + privilege.setCreateTime(System.currentTimeMillis()); + sentryStore.alterSentryRoleRevokePrivilege(grantor, roleName, privilege); + role = sentryStore.getMSentryRoleByName(roleName); + privileges = role.getPrivileges(); + assertEquals(privileges.toString(), 0, privileges.size()); + } + + /** + * Regression test for SENTRY-552 + */ + @Test + public void testGrantRevokeTablePrivilegeDowngradeByDb() throws Exception { + String roleName = "test-table-db-downgrade-privilege"; + String grantor = "g1"; + String server = "server1"; + String db = "db1"; + String table1 = "tbl1"; + String table2 = "tbl2"; + createRole(roleName); + TSentryPrivilege privilegeTable1 = new TSentryPrivilege(); + privilegeTable1.setPrivilegeScope("TABLE"); + privilegeTable1.setServerName(server); + privilegeTable1.setDbName(db); + privilegeTable1.setTableName(table1); + privilegeTable1.setAction(AccessConstants.ALL); + privilegeTable1.setCreateTime(System.currentTimeMillis()); + TSentryPrivilege privilegeTable2 = privilegeTable1.deepCopy(); + privilegeTable2.setTableName(table2); + + // Grant ALL on table1 and table2 + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName, privilegeTable1); + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName, privilegeTable2); + MSentryRole role = sentryStore.getMSentryRoleByName(roleName); + Set privileges = role.getPrivileges(); + assertEquals(privileges.toString(), 2, privileges.size()); + + // Revoke SELECT on table2 + privilegeTable2.setAction(AccessConstants.SELECT); + sentryStore.alterSentryRoleRevokePrivilege(grantor, roleName, privilegeTable2); + // after having ALL and revoking SELECT, we should have (INSERT) at table2 + role = sentryStore.getMSentryRoleByName(roleName); + privileges = role.getPrivileges(); + assertEquals(privileges.toString(), 2, privileges.size()); + + for (MSentryPrivilege mPrivilege: privileges) { + assertEquals(server, mPrivilege.getServerName()); + assertEquals(db, mPrivilege.getDbName()); + assertFalse(mPrivilege.getGrantOption()); + if (mPrivilege.getTableName().equals(table1)) { + assertEquals(AccessConstants.ALL, mPrivilege.getAction()); + } else if (mPrivilege.getTableName().equals(table2)) { + assertNotSame(AccessConstants.SELECT, mPrivilege.getAction()); + assertNotSame(AccessConstants.ALL, mPrivilege.getAction()); + } else { + fail("Unexpected table name: " + mPrivilege.getTableName()); + } + } + + // Revoke INSERT on Database + privilegeTable2.setAction(AccessConstants.INSERT); + privilegeTable2.setPrivilegeScope("DATABASE"); + privilegeTable2.unsetTableName(); + sentryStore.alterSentryRoleRevokePrivilege(grantor, roleName, privilegeTable2); + role = sentryStore.getMSentryRoleByName(roleName); + privileges = role.getPrivileges(); + + // after revoking INSERT database level privilege + // table1 should have (SELECT) + // table2 should have () + assertEquals(privileges.toString(), 1, privileges.size()); + for (MSentryPrivilege mPrivilege : privileges) { + assertEquals(server, mPrivilege.getServerName()); + assertEquals(db, mPrivilege.getDbName()); + if (table1.equals(mPrivilege.getTableName())) { + assertNotSame(AccessConstants.INSERT, mPrivilege.getAction()); + assertNotSame(AccessConstants.ALL, mPrivilege.getAction()); + } else if (table2.equals(mPrivilege.getTableName())) { + assertNotSame(AccessConstants.INSERT, mPrivilege.getAction()); + assertNotSame(AccessConstants.SELECT, mPrivilege.getAction()); + assertNotSame(AccessConstants.ALL, mPrivilege.getAction()); + } + assertFalse(mPrivilege.getGrantOption()); + } + } + + /** + * Regression test for SENTRY-552 + */ + @Test + public void testGrantRevokeColumnPrivilegeDowngradeByDb() throws Exception { + String roleName = "test-column-db-downgrade-privilege"; + String grantor = "g1"; + String server = "server1"; + String db = "db1"; + String table = "tbl1"; + String column1 = "c1"; + String column2 = "c2"; + createRole(roleName); + TSentryPrivilege privilegeCol1 = new TSentryPrivilege(); + privilegeCol1.setPrivilegeScope("COLUMN"); + privilegeCol1.setServerName(server); + privilegeCol1.setDbName(db); + privilegeCol1.setTableName(table); + privilegeCol1.setColumnName(column1); + privilegeCol1.setAction(AccessConstants.ALL); + privilegeCol1.setCreateTime(System.currentTimeMillis()); + TSentryPrivilege privilegeCol2 = privilegeCol1.deepCopy(); + privilegeCol2.setColumnName(column2); + + // Grant ALL on column1 and column2 + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName, privilegeCol1); + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName, privilegeCol2); + MSentryRole role = sentryStore.getMSentryRoleByName(roleName); + Set privileges = role.getPrivileges(); + assertEquals(privileges.toString(), 2, privileges.size()); + + // Revoke SELECT on column2 + privilegeCol2.setAction(AccessConstants.SELECT); + sentryStore.alterSentryRoleRevokePrivilege(grantor, roleName, privilegeCol2); + // after having ALL and revoking SELECT, we should have (INSERT) + role = sentryStore.getMSentryRoleByName(roleName); + privileges = role.getPrivileges(); + assertEquals(privileges.toString(), 2, privileges.size()); + + for (MSentryPrivilege mPrivilege: privileges) { + assertEquals(server, mPrivilege.getServerName()); + assertEquals(db, mPrivilege.getDbName()); + assertEquals(table, mPrivilege.getTableName()); + assertFalse(mPrivilege.getGrantOption()); + if (mPrivilege.getColumnName().equals(column1)) { + assertEquals(AccessConstants.ALL, mPrivilege.getAction()); + } else if (mPrivilege.getColumnName().equals(column2)) { + assertNotSame(AccessConstants.SELECT, mPrivilege.getAction()); + } else { + fail("Unexpected column name: " + mPrivilege.getColumnName()); + } + } + + // Revoke INSERT on Database + privilegeCol2.setAction(AccessConstants.INSERT); + privilegeCol2.setPrivilegeScope("DATABASE"); + privilegeCol2.unsetTableName(); + privilegeCol2.unsetColumnName(); + sentryStore.alterSentryRoleRevokePrivilege(grantor, roleName, privilegeCol2); + role = sentryStore.getMSentryRoleByName(roleName); + privileges = role.getPrivileges(); + + // after revoking INSERT database level privilege + // column2 has () + // and downgrade column1 to (SELECT) privileges. + assertEquals(privileges.toString(), 1, privileges.size()); + for (MSentryPrivilege mPrivilege : privileges) { + assertEquals(server, mPrivilege.getServerName()); + assertEquals(db, mPrivilege.getDbName()); + assertEquals(table, mPrivilege.getTableName()); + if (column1.equals(mPrivilege.getColumnName())) { + assertNotSame(AccessConstants.INSERT, mPrivilege.getAction()); + } else if (column1.equals(mPrivilege.getColumnName())) { + assertNotSame(AccessConstants.SELECT, mPrivilege.getAction()); + assertNotSame(AccessConstants.INSERT, mPrivilege.getAction()); + } + assertFalse(mPrivilege.getGrantOption()); + } + } + + @Test + public void testGrantRevokePrivilegeWithGrantOption() throws Exception { + String roleName = "test-grantOption-table"; + String grantor = "g1"; + String server = "server1"; + String db = "db1"; + String table = "tbl1"; + TSentryGrantOption grantOption = TSentryGrantOption.TRUE; + createRole(roleName); + + TSentryPrivilege privilege = new TSentryPrivilege(); + privilege.setPrivilegeScope("TABLE"); + privilege.setServerName(server); + privilege.setDbName(db); + privilege.setTableName(table); + privilege.setAction(AccessConstants.ALL); + privilege.setCreateTime(System.currentTimeMillis()); + privilege.setGrantOption(grantOption); + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName, privilege); + MSentryRole role = sentryStore.getMSentryRoleByName(roleName); + Set privileges = role.getPrivileges(); + assertEquals(privileges.toString(), 1, privileges.size()); + assertEquals(Boolean.valueOf(privilege.getGrantOption().toString()), Iterables.get(privileges, 0).getGrantOption()); + sentryStore.alterSentryRoleRevokePrivilege(grantor, roleName, privilege); + role = sentryStore.getMSentryRoleByName(roleName); + privileges = role.getPrivileges(); + assertEquals(0, privileges.size()); + + roleName = "test-grantOption-db"; + + createRole(roleName); + privilege = new TSentryPrivilege(); + privilege.setPrivilegeScope("DATABASE"); + privilege.setServerName(server); + privilege.setDbName(db); + privilege.setAction(AccessConstants.ALL); + privilege.setGrantOption(TSentryGrantOption.TRUE); + privilege.setCreateTime(System.currentTimeMillis()); + privilege.setGrantOption(grantOption); + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName, privilege); + role = sentryStore.getMSentryRoleByName(roleName); + privileges = role.getPrivileges(); + assertEquals(privileges.toString(), 1, privileges.size()); + + privilege.setAction(AccessConstants.SELECT); + privilege.setGrantOption(TSentryGrantOption.UNSET); + sentryStore.alterSentryRoleRevokePrivilege(grantor, roleName, privilege); + // after having ALL and revoking SELECT, we should have (INSERT) + role = sentryStore.getMSentryRoleByName(roleName); + privileges = role.getPrivileges(); + assertEquals(privileges.toString(), 1, privileges.size()); + for (MSentryPrivilege mPrivilege : privileges) { + assertEquals(server, mPrivilege.getServerName()); + assertEquals(db, mPrivilege.getDbName()); + assertNotSame(AccessConstants.SELECT, mPrivilege.getAction()); + } + } + + @Test + public void testGrantCheckWithGroupAndUser() throws Exception { + // 1. set local group mapping and group-role, user-role mapping + // user0_0->group0 + // user0_1->group0 + // user1_0->group1 + // user1_1->group1 + // group0->roleG0 + // group1->roleG1 + // user0_0->roleU00 + // user0_1->roleU01 + // user1_0->roleU10 + // user1_1->roleU11 + String grantor = "g1"; + String[][] users = { { "user0_0", "user0_1" }, { "user1_0", "user1_1" } }; + String[] groups = { "group0", "group1" }; + String[] rolesForGroup = { "roleG0", "roleG1" }; + String[] rolesForUser = { "roleU0", "roleU1", "roleU2", "roleU3" }; + for (int i = 0; i < groups.length; i++) { + for (int j = 0; j < users[i].length; j++) { + addGroupsToUser(users[i][j], groups[i]); + sentryStore.createSentryRole(rolesForUser[i * 2 + j]); + sentryStore.alterSentryRoleAddUsers(rolesForUser[i * 2 + j], Sets.newHashSet(users[i][j])); + } + sentryStore.createSentryRole(rolesForGroup[i]); + Set tGroups = Sets.newHashSet(); + TSentryGroup tGroup = new TSentryGroup(groups[i]); + tGroups.add(tGroup); + sentryStore.alterSentryRoleAddGroups(grantor, rolesForGroup[i], tGroups); + } + writePolicyFile(); + + // 2. g1 grant all on database db1 to roleG0, roleU0 without grant option + String server = "server1"; + String db = "db1"; + grantor = "g1"; + TSentryPrivilege privilege1 = new TSentryPrivilege(); + privilege1.setPrivilegeScope("DATABASE"); + privilege1.setServerName(server); + privilege1.setDbName(db); + privilege1.setAction(AccessConstants.ALL); + privilege1.setCreateTime(System.currentTimeMillis()); + privilege1.setGrantOption(TSentryGrantOption.FALSE); + // user0_0 has the privilege without grant option + sentryStore.alterSentryRoleGrantPrivilege(grantor, "roleG0", privilege1); + sentryStore.alterSentryRoleGrantPrivilege(grantor, "roleU0", privilege1); + try { + sentryStore.alterSentryRoleGrantPrivilege("user0_0", "roleG1", privilege1); + fail("Expected SentryGrantDeniedException exception"); + } catch (SentryGrantDeniedException e) { + // excepted exception + } + try { + sentryStore.alterSentryRoleRevokePrivilege("user0_0", "roleG1", privilege1); + fail("Expected SentryGrantDeniedException exception"); + } catch (SentryGrantDeniedException e) { + // excepted exception + } + + // 3. g1 grant all on database db1 to roleG0 with grant option + TSentryPrivilege privilege2 = new TSentryPrivilege(); + privilege2.setPrivilegeScope("DATABASE"); + privilege2.setServerName(server); + privilege2.setDbName(db); + privilege2.setAction(AccessConstants.ALL); + privilege2.setCreateTime(System.currentTimeMillis()); + privilege2.setGrantOption(TSentryGrantOption.TRUE); + // user0_0, user0_1 can grant the same privilege to other roles + sentryStore.alterSentryRoleGrantPrivilege(grantor, "roleG0", privilege2); + sentryStore.alterSentryRoleGrantPrivilege("user0_0", "roleG1", privilege2); + validatePrivilegeByRoleName("roleG1", privilege2); + sentryStore.alterSentryRoleRevokePrivilege("user0_0", "roleG1", privilege2); + validateEmptyPrivilegeByRoleName("roleG1"); + sentryStore.alterSentryRoleGrantPrivilege("user0_1", "roleG1", privilege2); + validatePrivilegeByRoleName("roleG1", privilege2); + sentryStore.alterSentryRoleRevokePrivilege("user0_1", "roleG1", privilege2); + validateEmptyPrivilegeByRoleName("roleG1"); + // clear privilege for roleG0 + sentryStore.alterSentryRoleRevokePrivilege(grantor, "roleG0", privilege2); + + // 4. g1 grant all on database db1 to roleU0 with grant option + sentryStore.alterSentryRoleGrantPrivilege(grantor, "roleU0", privilege2); + sentryStore.alterSentryRoleGrantPrivilege("user0_0", "roleG1", privilege2); + validatePrivilegeByRoleName("roleG1", privilege2); + sentryStore.alterSentryRoleRevokePrivilege("user0_0", "roleG1", privilege2); + validateEmptyPrivilegeByRoleName("roleG1"); + try { + sentryStore.alterSentryRoleGrantPrivilege("user0_1", "roleG1", privilege2); + fail("Expected SentryGrantDeniedException exception"); + } catch (SentryGrantDeniedException e) { + // excepted exception + } + try { + sentryStore.alterSentryRoleRevokePrivilege("user0_1", "roleG1", privilege2); + fail("Expected SentryGrantDeniedException exception"); + } catch (SentryGrantDeniedException e) { + // excepted exception + } + // clear privilege for roleG0 + sentryStore.alterSentryRoleRevokePrivilege(grantor, "roleU0", privilege2); + + // 5. g1 grant all on database db1 to roleU2, roleG0 with grant option + sentryStore.alterSentryRoleGrantPrivilege(grantor, "roleU2", privilege2); + sentryStore.alterSentryRoleGrantPrivilege(grantor, "roleG0", privilege2); + sentryStore.alterSentryRoleGrantPrivilege("user0_0", "roleG1", privilege2); + validatePrivilegeByRoleName("roleG1", privilege2); + sentryStore.alterSentryRoleRevokePrivilege("user0_0", "roleG1", privilege2); + validateEmptyPrivilegeByRoleName("roleG1"); + sentryStore.alterSentryRoleGrantPrivilege("user0_1", "roleG1", privilege2); + validatePrivilegeByRoleName("roleG1", privilege2); + sentryStore.alterSentryRoleRevokePrivilege("user0_1", "roleG1", privilege2); + validateEmptyPrivilegeByRoleName("roleG1"); + + sentryStore.alterSentryRoleGrantPrivilege("user1_0", "roleG1", privilege2); + validatePrivilegeByRoleName("roleG1", privilege2); + sentryStore.alterSentryRoleRevokePrivilege("user1_0", "roleG1", privilege2); + validateEmptyPrivilegeByRoleName("roleG1"); + try { + sentryStore.alterSentryRoleGrantPrivilege("user1_1", "roleG1", privilege2); + fail("Expected SentryGrantDeniedException exception"); + } catch (SentryGrantDeniedException e) { + // excepted exception + } + try { + sentryStore.alterSentryRoleRevokePrivilege("user1_1", "roleG1", privilege2); + fail("Expected SentryGrantDeniedException exception"); + } catch (SentryGrantDeniedException e) { + // excepted exception + } + // clear privilege for roleG0 + sentryStore.alterSentryRoleRevokePrivilege(grantor, "roleG0", privilege2); + sentryStore.alterSentryRoleRevokePrivilege(grantor, "roleU2", privilege2); + } + + private void validatePrivilegeByRoleName(String roleName, TSentryPrivilege exceptedTPrivelege) + throws Exception { + MSentryRole role = sentryStore.getMSentryRoleByName(roleName); + Set privileges = role.getPrivileges(); + assertEquals(privileges.toString(), 1, privileges.size()); + MSentryPrivilege mPrivilege = Iterables.get(privileges, 0); + assertEquals(exceptedTPrivelege.getServerName(), mPrivilege.getServerName()); + assertEquals(exceptedTPrivelege.getDbName(), mPrivilege.getDbName()); + assertEquals(AccessConstants.ALL, mPrivilege.getAction()); + } + + private void validateEmptyPrivilegeByRoleName(String roleName) throws Exception { + MSentryRole role = sentryStore.getMSentryRoleByName(roleName); + Set privileges = role.getPrivileges(); + assertEquals(privileges.toString(), 0, privileges.size()); + } + + @Test + public void testGrantCheckWithGrantOption() throws Exception { + // 1. set local group mapping + // user0->group0->role0 + // user1->group1->role1 + // user2->group2->role2 + // user3->group3->role3 + // user4->group4->role4 + String grantor = "g1"; + String[] users = {"user0","user1","user2","user3","user4"}; + String[] groups = { "group0", "group1", "group2", "group3", "group4" }; + String[] roles = {"role0","role1","role2","role3","role4"}; + for (int i = 0; i < users.length; i++) { + addGroupsToUser(users[i], groups[i]); + sentryStore.createSentryRole(roles[i]); + Set tGroups = Sets.newHashSet(); + TSentryGroup tGroup = new TSentryGroup(groups[i]); + tGroups.add(tGroup); + sentryStore.alterSentryRoleAddGroups(grantor, roles[i], tGroups); + } + writePolicyFile(); + + // 2. g1 grant all on database db1 to role0 with grant option + String server = "server1"; + String db = "db1"; + String table = "tbl1"; + String roleName = roles[0]; + grantor = "g1"; + TSentryPrivilege privilege1 = new TSentryPrivilege(); + privilege1.setPrivilegeScope("DATABASE"); + privilege1.setServerName(server); + privilege1.setDbName(db); + privilege1.setAction(AccessConstants.ALL); + privilege1.setCreateTime(System.currentTimeMillis()); + privilege1.setGrantOption(TSentryGrantOption.TRUE); + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName, privilege1); + MSentryRole role = sentryStore.getMSentryRoleByName(roleName); + Set privileges = role.getPrivileges(); + assertEquals(privileges.toString(), 1, privileges.size()); + + // 3. user0 grant select on database db1 to role1, with grant option + roleName = roles[1]; + grantor = users[0]; + TSentryPrivilege privilege2 = new TSentryPrivilege(); + privilege2.setPrivilegeScope("DATABASE"); + privilege2.setServerName(server); + privilege2.setDbName(db); + privilege2.setAction(AccessConstants.SELECT); + privilege2.setCreateTime(System.currentTimeMillis()); + privilege2.setGrantOption(TSentryGrantOption.TRUE); + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName, privilege2); + + // 4. user0 grant all on table tb1 to role2, no grant option + roleName = roles[2]; + grantor = users[0]; + TSentryPrivilege privilege3 = new TSentryPrivilege(); + privilege3.setPrivilegeScope("TABLE"); + privilege3.setServerName(server); + privilege3.setDbName(db); + privilege3.setTableName(table); + privilege3.setAction(AccessConstants.ALL); + privilege3.setCreateTime(System.currentTimeMillis()); + privilege3.setGrantOption(TSentryGrantOption.FALSE); + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName, privilege3); + + // 5. user1 has role1, no insert privilege, + // grant insert to role3, will throw no grant exception + roleName = roles[3]; + grantor = users[1]; + TSentryPrivilege privilege4 = new TSentryPrivilege(); + privilege4.setPrivilegeScope("DATABASE"); + privilege4.setServerName(server); + privilege4.setDbName(db); + privilege4.setAction(AccessConstants.INSERT); + privilege4.setCreateTime(System.currentTimeMillis()); + privilege4.setGrantOption(TSentryGrantOption.FALSE); + try { + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName, privilege4); + fail("Expected SentryGrantDeniedException exception"); + } catch (SentryGrantDeniedException e) { + // excepted exception + } + + // 6. user2 has role2, no grant option, + // grant insert to role4, will throw no grant exception + roleName = roles[4]; + grantor = users[2]; + TSentryPrivilege privilege5 = new TSentryPrivilege(); + privilege5.setPrivilegeScope("TABLE"); + privilege5.setServerName(server); + privilege5.setDbName(db); + privilege5.setTableName(table); + privilege5.setAction(AccessConstants.INSERT); + privilege5.setCreateTime(System.currentTimeMillis()); + privilege5.setGrantOption(TSentryGrantOption.FALSE); + try { + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName, privilege5); + fail("Expected SentryGrantDeniedException exception"); + } catch (SentryGrantDeniedException e) { + // excepted exception + } + } + + @Test + public void testRevokeCheckWithGrantOption() throws Exception { + // 1. set local group mapping + // user0->group0->role0 + // user1->group1->role1 + // user2->group2->role2 + String grantor = "g1"; + String[] users = {"user0","user1","user2"}; + String[] roles = {"role0","role1","role2"}; + String[] groups = {"group0","group1","group2"}; + for (int i = 0; i < users.length; i++) { + addGroupsToUser(users[i], groups[i]); + sentryStore.createSentryRole(roles[i]); + Set tGroups = Sets.newHashSet(); + TSentryGroup tGroup = new TSentryGroup(groups[i]); + tGroups.add(tGroup); + sentryStore.alterSentryRoleAddGroups(grantor, roles[i], tGroups); + sentryStore.alterSentryRoleAddUsers(roles[i], Sets.newHashSet(users[i])); + } + writePolicyFile(); + + // 2. g1 grant select on database db1 to role0, with grant option + String server = "server1"; + String db = "db1"; + String table = "tbl1"; + String roleName = roles[0]; + grantor = "g1"; + TSentryPrivilege privilege1 = new TSentryPrivilege(); + privilege1.setPrivilegeScope("DATABASE"); + privilege1.setServerName(server); + privilege1.setDbName(db); + privilege1.setAction(AccessConstants.SELECT); + privilege1.setCreateTime(System.currentTimeMillis()); + privilege1.setGrantOption(TSentryGrantOption.TRUE); + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName, privilege1); + MSentryRole role = sentryStore.getMSentryRoleByName(roleName); + Set privileges = role.getPrivileges(); + assertEquals(privileges.toString(), 1, privileges.size()); + + // 3. g1 grant all on table tb1 to role1, no grant option + roleName = roles[1]; + grantor = "g1"; + TSentryPrivilege privilege2 = new TSentryPrivilege(); + privilege2.setPrivilegeScope("TABLE"); + privilege2.setServerName(server); + privilege2.setDbName(db); + privilege2.setTableName(table); + privilege2.setAction(AccessConstants.ALL); + privilege2.setCreateTime(System.currentTimeMillis()); + privilege2.setGrantOption(TSentryGrantOption.FALSE); + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName, privilege2); + + // 4. g1 grant select on table tb1 to role2, no grant option + roleName = roles[2]; + grantor = "g1"; + TSentryPrivilege privilege3 = new TSentryPrivilege(); + privilege3.setPrivilegeScope("TABLE"); + privilege3.setServerName(server); + privilege3.setDbName(db); + privilege3.setTableName(table); + privilege3.setAction(AccessConstants.SELECT); + privilege3.setCreateTime(System.currentTimeMillis()); + privilege3.setGrantOption(TSentryGrantOption.FALSE); + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName, privilege3); + + // 5. user1 has role1, no grant option, + // revoke from role2 will throw no grant exception + roleName = roles[2]; + grantor = users[1]; + try { + sentryStore.alterSentryRoleRevokePrivilege(grantor, roleName, privilege3); + fail("Expected SentryGrantDeniedException exception"); + } catch (SentryGrantDeniedException e) { + // excepted exception + } + + // 6. user0 has role0, only have select, + // revoke all from role1 will throw no grant exception + roleName = roles[1]; + grantor = users[0]; + try { + sentryStore.alterSentryRoleRevokePrivilege(grantor, roleName, privilege2); + fail("Expected SentryGrantDeniedException exception"); + } catch (SentryGrantDeniedException e) { + // excepted exception + } + + // 7. user0 has role0, has select and grant option, + // revoke select from role2 + roleName = roles[2]; + grantor = users[0]; + sentryStore.alterSentryRoleRevokePrivilege(grantor, roleName, privilege3); + role = sentryStore.getMSentryRoleByName(roleName); + privileges = role.getPrivileges(); + assertEquals(0, privileges.size()); + } + + @Test + public void testRevokeAllGrantOption() throws Exception { + // 1. set local group mapping + // user0->group0->role0 + String grantor = "g1"; + String[] users = {"user0"}; + String[] roles = {"role0"}; + String[] groups = {"group0"}; + for (int i = 0; i < users.length; i++) { + addGroupsToUser(users[i], groups[i]); + sentryStore.createSentryRole(roles[i]); + Set tGroups = Sets.newHashSet(); + TSentryGroup tGroup = new TSentryGroup(groups[i]); + tGroups.add(tGroup); + sentryStore.alterSentryRoleAddGroups(grantor, roles[i], tGroups); + } + writePolicyFile(); + + // 2. g1 grant select on table tb1 to role0, with grant option + String server = "server1"; + String db = "db1"; + String table = "tbl1"; + String roleName = roles[0]; + grantor = "g1"; + TSentryPrivilege privilege = new TSentryPrivilege(); + privilege.setPrivilegeScope("TABLE"); + privilege.setServerName(server); + privilege.setDbName(db); + privilege.setTableName(table); + privilege.setAction(AccessConstants.SELECT); + privilege.setCreateTime(System.currentTimeMillis()); + privilege.setGrantOption(TSentryGrantOption.TRUE); + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName, privilege); + + // 3. g1 grant select on table tb1 to role0, no grant option + roleName = roles[0]; + grantor = "g1"; + privilege.setGrantOption(TSentryGrantOption.FALSE); + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName, privilege); + + // 4. g1 revoke all privilege from role0 + roleName = roles[0]; + grantor = "g1"; + privilege.setGrantOption(TSentryGrantOption.UNSET); + sentryStore.alterSentryRoleRevokePrivilege(grantor, roleName, privilege); + MSentryRole role = sentryStore.getMSentryRoleByName(roleName); + Set privileges = role.getPrivileges(); + assertEquals(privileges.toString(), 0, privileges.size()); + } + + @Test + public void testGrantCheckWithColumn() throws Exception { + // 1. set local group mapping + // user0->group0->role0 + // user1->group1->role1 + String grantor = "g1"; + String[] users = {"user0","user1"}; + String[] roles = {"role0","role1"}; + String[] groups = {"group0","group1"}; + for (int i = 0; i < users.length; i++) { + addGroupsToUser(users[i], groups[i]); + sentryStore.createSentryRole(roles[i]); + Set tGroups = Sets.newHashSet(); + TSentryGroup tGroup = new TSentryGroup(groups[i]); + tGroups.add(tGroup); + sentryStore.alterSentryRoleAddGroups(grantor, roles[i], tGroups); + } + writePolicyFile(); + + // 2. g1 grant select on table tb1 to role0, with grant option + String server = "server1"; + String db = "db1"; + String table = "tbl1"; + String roleName = roles[0]; + grantor = "g1"; + TSentryPrivilege privilege1 = new TSentryPrivilege(); + privilege1.setPrivilegeScope("TABLE"); + privilege1.setServerName(server); + privilege1.setDbName(db); + privilege1.setTableName(table); + privilege1.setAction(AccessConstants.SELECT); + privilege1.setCreateTime(System.currentTimeMillis()); + privilege1.setGrantOption(TSentryGrantOption.TRUE); + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName, privilege1); + MSentryRole role = sentryStore.getMSentryRoleByName(roleName); + Set privileges = role.getPrivileges(); + assertEquals(privileges.toString(), 1, privileges.size()); + + // 3. user0 grant select on column tb1.c1 to role1, with grant option + roleName = roles[1]; + grantor = users[0]; + String column = "c1"; + TSentryPrivilege privilege2 = new TSentryPrivilege(); + privilege2.setPrivilegeScope("COLUMN"); + privilege2.setServerName(server); + privilege2.setDbName(db); + privilege2.setTableName(table); + privilege2.setColumnName(column); + privilege2.setAction(AccessConstants.SELECT); + privilege2.setCreateTime(System.currentTimeMillis()); + privilege2.setGrantOption(TSentryGrantOption.TRUE); + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName, privilege2); + + // 4. user1 revoke table level privilege from user0, will throw grant denied exception + roleName = roles[0]; + grantor = users[1]; + try { + sentryStore.alterSentryRoleRevokePrivilege(grantor, roleName, privilege1); + fail("Expected SentryGrantDeniedException exception"); + } catch (SentryGrantDeniedException e) { + // excepted exception + } + + // 5. user0 revoke column level privilege from user1 + roleName = roles[1]; + grantor = users[0]; + sentryStore.alterSentryRoleRevokePrivilege(grantor, roleName, privilege2); + role = sentryStore.getMSentryRoleByName(roleName); + privileges = role.getPrivileges(); + assertEquals(0, privileges.size()); + } + + @Test + public void testGrantDuplicatePrivilege() throws Exception { + String roleName = "test-privilege"; + String grantor = "g1"; + String server = "server1"; + String db = "db1"; + String table = "tbl1"; + createRole(roleName); + TSentryPrivilege privilege = new TSentryPrivilege(); + privilege.setPrivilegeScope("TABLE"); + privilege.setServerName(server); + privilege.setDbName(db); + privilege.setTableName(table); + privilege.setAction(AccessConstants.ALL); + privilege.setCreateTime(System.currentTimeMillis()); + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName, privilege); + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName, privilege); + privilege.setServerName("Server1"); + privilege.setDbName("DB1"); + privilege.setTableName("TBL1"); + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName, privilege); + MSentryRole role = sentryStore.getMSentryRoleByName(roleName); + Set privileges = role.getPrivileges(); + assertEquals(privileges.toString(), 1, privileges.size()); + } + + @Test + public void testListSentryPrivilegesForProvider() throws Exception { + String roleName1 = "list-privs-r1", roleName2 = "list-privs-r2"; + String groupName1 = "list-privs-g1", groupName2 = "list-privs-g2"; + String userName1 = "list-privs-u1", userName2 = "list-privs-u2"; + String userWithoutRole = "user-no-privs"; + Set noRoleUsers = Sets.newHashSet(userWithoutRole); + String grantor = "g1"; + sentryStore.createSentryRole(roleName1); + sentryStore.createSentryRole(roleName2); + TSentryPrivilege privilege1 = new TSentryPrivilege(); + privilege1.setPrivilegeScope("TABLE"); + privilege1.setServerName("server1"); + privilege1.setDbName("db1"); + privilege1.setTableName("tbl1"); + privilege1.setAction("SELECT"); + privilege1.setCreateTime(System.currentTimeMillis()); + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName1, privilege1); + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName2, privilege1); + TSentryPrivilege privilege2 = new TSentryPrivilege(); + privilege2.setPrivilegeScope("SERVER"); + privilege2.setServerName("server1"); + privilege2.setCreateTime(System.currentTimeMillis()); + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName2, privilege2); + Set groups = Sets.newHashSet(); + Set users = Sets.newHashSet(); + TSentryGroup group = new TSentryGroup(); + group.setGroupName(groupName1); + groups.add(group); + users.add(userName1); + sentryStore.alterSentryRoleAddGroups(grantor, roleName1, groups); + sentryStore.alterSentryRoleAddUsers(roleName1, users); + groups.clear(); + users.clear(); + group = new TSentryGroup(); + group.setGroupName(groupName2); + groups.add(group); + users.add(userName2); + // group 2 and user2 has both roles 1 and 2 + sentryStore.alterSentryRoleAddGroups(grantor, roleName1, groups); + sentryStore.alterSentryRoleAddGroups(grantor, roleName2, groups); + sentryStore.alterSentryRoleAddUsers(roleName1, users); + sentryStore.alterSentryRoleAddUsers(roleName2, users); + // group1 all roles + assertEquals(Sets.newHashSet("server=server1->db=db1->table=tbl1->action=select"), + SentryStore.toTrimedLower(sentryStore.listAllSentryPrivilegesForProvider(Sets + .newHashSet(groupName1), noRoleUsers, new TSentryActiveRoleSet(true, + new HashSet())))); + // user1 all roles + assertEquals(Sets.newHashSet("server=server1->db=db1->table=tbl1->action=select"), + SentryStore.toTrimedLower(sentryStore.listAllSentryPrivilegesForProvider(Sets + .newHashSet(""), Sets.newHashSet(userName1), new TSentryActiveRoleSet(true, + new HashSet())))); + // group1 and user1 all roles + assertEquals(Sets.newHashSet("server=server1->db=db1->table=tbl1->action=select"), + SentryStore.toTrimedLower(sentryStore.listAllSentryPrivilegesForProvider(Sets + .newHashSet(groupName1), Sets.newHashSet(userName1), new TSentryActiveRoleSet(true, + new HashSet())))); + // one active role + assertEquals( + Sets.newHashSet("server=server1->db=db1->table=tbl1->action=select"), + SentryStore.toTrimedLower(sentryStore.listAllSentryPrivilegesForProvider( + Sets.newHashSet(groupName1), noRoleUsers, + new TSentryActiveRoleSet(false, Sets.newHashSet(roleName1))))); + // unknown active role + assertEquals( + Sets.newHashSet(), + SentryStore.toTrimedLower(sentryStore.listAllSentryPrivilegesForProvider( + Sets.newHashSet(groupName1), noRoleUsers, + new TSentryActiveRoleSet(false, Sets.newHashSet("not a role"))))); + // no active roles + assertEquals(Sets.newHashSet(), SentryStore.toTrimedLower(sentryStore + .listAllSentryPrivilegesForProvider(Sets.newHashSet(groupName1), noRoleUsers, + new TSentryActiveRoleSet(false, new HashSet())))); + + // group2 all roles + assertEquals(Sets.newHashSet("server=server1->db=db1->table=tbl1->action=select", + "server=server1"), SentryStore.toTrimedLower(sentryStore + .listAllSentryPrivilegesForProvider(Sets.newHashSet(groupName2), Sets.newHashSet(""), + new TSentryActiveRoleSet(true, new HashSet())))); + // user2 all roles + assertEquals(Sets.newHashSet("server=server1->db=db1->table=tbl1->action=select", + "server=server1"), SentryStore.toTrimedLower(sentryStore + .listAllSentryPrivilegesForProvider(Sets.newHashSet(""), Sets.newHashSet(userName2), + new TSentryActiveRoleSet(true, new HashSet())))); + // user2 and group2 all roles + assertEquals(Sets.newHashSet("server=server1->db=db1->table=tbl1->action=select", + "server=server1"), SentryStore.toTrimedLower(sentryStore + .listAllSentryPrivilegesForProvider(Sets.newHashSet(groupName2), + Sets.newHashSet(userName2), new TSentryActiveRoleSet(true, new HashSet())))); + + // one active role + assertEquals( + Sets.newHashSet("server=server1->db=db1->table=tbl1->action=select"), + SentryStore.toTrimedLower(sentryStore.listAllSentryPrivilegesForProvider( + Sets.newHashSet(groupName2), noRoleUsers, + new TSentryActiveRoleSet(false, Sets.newHashSet(roleName1))))); + assertEquals( + Sets.newHashSet("server=server1->db=db1->table=tbl1->action=select", "server=server1"), + SentryStore.toTrimedLower(sentryStore.listAllSentryPrivilegesForProvider( + Sets.newHashSet(groupName2), noRoleUsers, + new TSentryActiveRoleSet(false, Sets.newHashSet(roleName2))))); + // unknown active role + assertEquals( + Sets.newHashSet(), + SentryStore.toTrimedLower(sentryStore.listAllSentryPrivilegesForProvider( + Sets.newHashSet(groupName2), noRoleUsers, + new TSentryActiveRoleSet(false, Sets.newHashSet("not a role"))))); + // no active roles + assertEquals(Sets.newHashSet(), SentryStore.toTrimedLower(sentryStore + .listAllSentryPrivilegesForProvider(Sets.newHashSet(groupName2), noRoleUsers, + new TSentryActiveRoleSet(false, new HashSet())))); + + // both groups, all active roles + assertEquals(Sets.newHashSet("server=server1->db=db1->table=tbl1->action=select", + "server=server1"), SentryStore.toTrimedLower(sentryStore + .listAllSentryPrivilegesForProvider(Sets.newHashSet(groupName1, groupName2), noRoleUsers, + new TSentryActiveRoleSet(true, new HashSet())))); + // both users and groups, all active roles + assertEquals(Sets.newHashSet("server=server1->db=db1->table=tbl1->action=select", + "server=server1"), SentryStore.toTrimedLower(sentryStore + .listAllSentryPrivilegesForProvider(Sets.newHashSet(groupName1, groupName2), Sets + .newHashSet(userName1, userName2), + new TSentryActiveRoleSet(true, new HashSet())))); + // one active role + assertEquals(Sets.newHashSet("server=server1->db=db1->table=tbl1->action=select"), + SentryStore.toTrimedLower(sentryStore.listAllSentryPrivilegesForProvider(Sets.newHashSet( + groupName1, groupName2), noRoleUsers, + new TSentryActiveRoleSet(false, Sets.newHashSet(roleName1))))); + assertEquals(Sets.newHashSet("server=server1->db=db1->table=tbl1->action=select", + "server=server1"), SentryStore.toTrimedLower(sentryStore + .listAllSentryPrivilegesForProvider(Sets.newHashSet(groupName1, groupName2), noRoleUsers, + new TSentryActiveRoleSet(false, Sets.newHashSet(roleName2))))); + // unknown active role + assertEquals(Sets.newHashSet(), SentryStore.toTrimedLower(sentryStore + .listAllSentryPrivilegesForProvider(Sets.newHashSet(groupName1, groupName2), noRoleUsers, + new TSentryActiveRoleSet(false, Sets.newHashSet("not a role"))))); + // no active roles + assertEquals(Sets.newHashSet(), SentryStore.toTrimedLower(sentryStore + .listAllSentryPrivilegesForProvider(Sets.newHashSet(groupName1, groupName2), noRoleUsers, + new TSentryActiveRoleSet(false, new HashSet())))); + } + + @Test + public void testListRole() throws Exception { + String roleName1 = "role1", roleName2 = "role2", roleName3 = "role3"; + String group1 = "group1", group2 = "group2"; + String grantor = "g1"; + + sentryStore.createSentryRole(roleName1); + sentryStore.createSentryRole(roleName2); + sentryStore.createSentryRole(roleName3); + + sentryStore.alterSentryRoleAddGroups(grantor, roleName1, Sets.newHashSet(new TSentryGroup(group1))); + sentryStore.alterSentryRoleAddGroups(grantor, roleName2, Sets.newHashSet(new TSentryGroup(group2))); + sentryStore.alterSentryRoleAddGroups(grantor, roleName3, + Sets.newHashSet(new TSentryGroup(group1), new TSentryGroup(group2))); + + assertEquals(2, sentryStore.getTSentryRolesByGroupName(Sets.newHashSet(group1), false).size()); + assertEquals(2, sentryStore.getTSentryRolesByGroupName(Sets.newHashSet(group2), false).size()); + assertEquals(3, sentryStore.getTSentryRolesByGroupName(Sets.newHashSet(group1,group2), false).size()); + assertEquals(0, + sentryStore.getTSentryRolesByGroupName(Sets.newHashSet("foo"), true) + .size()); + } + + /** + * Assign multiple table and SERVER privileges to roles + * drop privilege for the object verify that it's removed correctl + * @throws Exception + */ + @Test + public void testDropDbObject() throws Exception { + String roleName1 = "list-privs-r1", roleName2 = "list-privs-r2", roleName3 = "list-privs-r3"; + String grantor = "g1"; + sentryStore.createSentryRole(roleName1); + sentryStore.createSentryRole(roleName2); + sentryStore.createSentryRole(roleName3); + + TSentryPrivilege privilege_tbl1 = new TSentryPrivilege(); + privilege_tbl1.setPrivilegeScope("TABLE"); + privilege_tbl1.setServerName("server1"); + privilege_tbl1.setDbName("db1"); + privilege_tbl1.setTableName("tbl1"); + privilege_tbl1.setCreateTime(System.currentTimeMillis()); + + TSentryPrivilege privilege1 = new TSentryPrivilege(privilege_tbl1); + privilege1.setAction("SELECT"); + + TSentryPrivilege privilege2_1 = new TSentryPrivilege(privilege_tbl1); + privilege2_1.setAction("INSERT"); + TSentryPrivilege privilege3_1 = new TSentryPrivilege(privilege_tbl1); + privilege3_1.setAction("*"); + + TSentryPrivilege privilege_server = new TSentryPrivilege(); + privilege_server.setPrivilegeScope("SERVER"); + privilege_server.setServerName("server1"); + privilege_server.setCreateTime(System.currentTimeMillis()); + + TSentryPrivilege privilege_tbl2 = new TSentryPrivilege(); + privilege_tbl2.setPrivilegeScope("TABLE"); + privilege_tbl2.setServerName("server1"); + privilege_tbl2.setDbName("db1"); + privilege_tbl2.setTableName("tbl2"); + privilege_tbl2.setCreateTime(System.currentTimeMillis()); + + TSentryPrivilege privilege2_3 = new TSentryPrivilege(privilege_tbl2); + privilege2_3.setAction("SELECT"); + + TSentryPrivilege privilege3_2 = new TSentryPrivilege(privilege_tbl2); + privilege3_2.setAction("INSERT"); + + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName1, privilege1); + + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName2, privilege2_1); + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName2, privilege_server); + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName2, privilege2_3); + + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName3, privilege3_1); + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName3, privilege3_2); + + sentryStore.dropPrivilege(toTSentryAuthorizable(privilege_tbl1)); + assertEquals(0, sentryStore.getAllTSentryPrivilegesByRoleName(roleName1) + .size()); + assertEquals(2, sentryStore.getAllTSentryPrivilegesByRoleName(roleName2) + .size()); + assertEquals(1, sentryStore.getAllTSentryPrivilegesByRoleName(roleName3) + .size()); + + sentryStore.dropPrivilege(toTSentryAuthorizable(privilege_tbl2)); + assertEquals(0, sentryStore.getAllTSentryPrivilegesByRoleName(roleName1) + .size()); + assertEquals(1, sentryStore.getAllTSentryPrivilegesByRoleName(roleName2) + .size()); + assertEquals(0, sentryStore.getAllTSentryPrivilegesByRoleName(roleName3) + .size()); + } + + /** + * Regression test for SENTRY-547 and SENTRY-548 + * Use case: + * GRANT INSERT on TABLE tbl1 to ROLE role1 + * GRANT SELECT on TABLE tbl1 to ROLE role1 + * GRANT ALTER on TABLE tbl1 to ROLE role1 + * GRANT DROP on TABLE tbl1 to ROLE role1 + * DROP TABLE tbl1 + * + * After drop tbl1, role1 should have 0 privileges + */ + @Test + public void testDropTableWithMultiAction() throws Exception { + String roleName1 = "role1"; + String grantor = "g1"; + sentryStore.createSentryRole(roleName1); + + TSentryPrivilege privilege_tbl1 = new TSentryPrivilege(); + privilege_tbl1.setPrivilegeScope("TABLE"); + privilege_tbl1.setServerName("server1"); + privilege_tbl1.setDbName("db1"); + privilege_tbl1.setTableName("tbl1"); + privilege_tbl1.setCreateTime(System.currentTimeMillis()); + + TSentryPrivilege privilege_tbl1_insert = new TSentryPrivilege( + privilege_tbl1); + privilege_tbl1_insert.setAction(AccessConstants.INSERT); + + TSentryPrivilege privilege_tbl1_select = new TSentryPrivilege( + privilege_tbl1); + privilege_tbl1_select.setAction(AccessConstants.SELECT); + + TSentryPrivilege privilege_tbl1_alter = new TSentryPrivilege( + privilege_tbl1); + privilege_tbl1_alter.setAction(AccessConstants.ALTER); + + TSentryPrivilege privilege_tbl1_drop = new TSentryPrivilege( + privilege_tbl1); + privilege_tbl1_drop.setAction(AccessConstants.DROP); + + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName1, privilege_tbl1_insert); + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName1, privilege_tbl1_select); + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName1, privilege_tbl1_alter); + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName1, privilege_tbl1_drop); + + assertEquals(4, sentryStore.getAllTSentryPrivilegesByRoleName(roleName1).size()); + + // after drop privilege_tbl1, role1 should have 0 privileges + sentryStore.dropPrivilege(toTSentryAuthorizable(privilege_tbl1)); + assertEquals(0, sentryStore.getAllTSentryPrivilegesByRoleName(roleName1).size()); + } + + @Test + public void testDropTableWithColumn() throws Exception { + String roleName1 = "role1", roleName2 = "role2"; + String grantor = "g1"; + String table1 = "tbl1"; + + sentryStore.createSentryRole(roleName1); + sentryStore.createSentryRole(roleName2); + + TSentryPrivilege privilege_tbl1 = new TSentryPrivilege(); + privilege_tbl1.setPrivilegeScope("TABLE"); + privilege_tbl1.setServerName("server1"); + privilege_tbl1.setDbName("db1"); + privilege_tbl1.setTableName(table1); + privilege_tbl1.setAction(AccessConstants.SELECT); + privilege_tbl1.setCreateTime(System.currentTimeMillis()); + + TSentryPrivilege privilege_tbl1_c1 = new TSentryPrivilege(privilege_tbl1); + privilege_tbl1_c1.setPrivilegeScope("COLUMN"); + privilege_tbl1_c1.setColumnName("c1"); + privilege_tbl1_c1.setCreateTime(System.currentTimeMillis()); + + TSentryPrivilege privilege_tbl1_c2 = new TSentryPrivilege(privilege_tbl1); + privilege_tbl1_c2.setPrivilegeScope("COLUMN"); + privilege_tbl1_c2.setColumnName("c2"); + privilege_tbl1_c2.setCreateTime(System.currentTimeMillis()); + + TSentryPrivilege privilege_tbl1_c3 = new TSentryPrivilege(privilege_tbl1); + privilege_tbl1_c3.setPrivilegeScope("COLUMN"); + privilege_tbl1_c3.setColumnName("c3"); + privilege_tbl1_c3.setCreateTime(System.currentTimeMillis()); + + sentryStore.alterSentryRoleGrantPrivilege(grantor, roleName1, privilege_tbl1_c1); + sentryStore.alterSentryRoleGra