Java tutorial
/** * 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.time.Instant; 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.commons.lang.StringUtils; 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.SentryOwnerInfo; import org.apache.sentry.api.common.ApiConstants.PrivilegeScope; import org.apache.sentry.api.service.thrift.TSentryPrivilegeMap; import org.apache.sentry.core.common.exception.SentryAccessDeniedException; import org.apache.sentry.core.common.exception.SentryInvalidInputException; import org.apache.sentry.core.common.utils.SentryConstants; import org.apache.sentry.core.model.db.AccessConstants; import org.apache.sentry.core.common.exception.SentryAlreadyExistsException; 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.TPrivilegePrincipal; import org.apache.sentry.hdfs.service.thrift.TPrivilegePrincipalType; 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.provider.db.service.model.MPath; 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.SentryPrincipalType; 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(true); 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<TSentryGroup> 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<String> users = Sets.newHashSet("user1"); createRole(roleName); sentryStore.alterSentryRoleAddGroups(grantor, roleName, groups); sentryStore.alterSentryRoleDeleteGroups(roleName, groups); sentryStore.alterSentryRoleAddUsers(roleName, users); MSentryUser user = sentryStore.getMSentryUserByName(users.iterator().next()); assertNotNull(user); sentryStore.alterSentryRoleDeleteUsers(roleName, users); user = sentryStore.getMSentryUserByName(users.iterator().next(), false); assertNull(user); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(privilege), null); sentryStore.alterSentryRevokePrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(privilege), null); } @Test public void testURI() throws Exception { String roleName1 = "test-role1"; String roleName2 = "test-role2"; String grantor = "g1"; String uri1 = "file:///var/folders/dt/9zm44z9s6bjfxbrm4v36lzdc0000gp/T/1401860678102-0/data/kv1.dat"; String uri2 = "file:///var/folders/dt/9zm44z9s6bjfxbrm4v36lzdc0000gp/T/1401860678102-0/data/kv2.dat"; createRole(roleName1); createRole(roleName2); TSentryPrivilege tSentryPrivilege1 = new TSentryPrivilege("URI", "server1", "ALL"); tSentryPrivilege1.setURI(uri1); TSentryPrivilege tSentryPrivilege2 = new TSentryPrivilege("URI", "server1", "ALL"); tSentryPrivilege2.setURI(uri2); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName1, Sets.newHashSet(tSentryPrivilege1), null); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName2, Sets.newHashSet(tSentryPrivilege2), null); TSentryAuthorizable tSentryAuthorizable1 = new TSentryAuthorizable(); tSentryAuthorizable1.setUri(uri1); tSentryAuthorizable1.setServer("server1"); TSentryAuthorizable tSentryAuthorizable2 = new TSentryAuthorizable(); tSentryAuthorizable2.setUri(uri2); tSentryAuthorizable2.setServer("server1"); Set<TSentryPrivilege> privileges = sentryStore.getTSentryPrivileges(SentryPrincipalType.ROLE, new HashSet<String>(Arrays.asList(roleName1, roleName2)), tSentryAuthorizable1); assertTrue(privileges.size() == 1); //Test with other URI Authorizable privileges = sentryStore.getTSentryPrivileges(SentryPrincipalType.ROLE, new HashSet<String>(Arrays.asList(roleName1, roleName2)), tSentryAuthorizable2); assertTrue(privileges.size() == 1); Set<TSentryGroup> tSentryGroups = new HashSet<TSentryGroup>(); tSentryGroups.add(new TSentryGroup("group1")); sentryStore.alterSentryRoleAddGroups(grantor, roleName1, tSentryGroups); sentryStore.alterSentryRoleAddUsers(roleName1, Sets.newHashSet("user1")); sentryStore.alterSentryRoleAddGroups(grantor, roleName2, tSentryGroups); sentryStore.alterSentryRoleAddUsers(roleName2, Sets.newHashSet("user1")); TSentryActiveRoleSet thriftRoleSet = new TSentryActiveRoleSet(true, new HashSet<String>(Arrays.asList(roleName1, roleName2))); // list privilege for group only Set<String> privs = sentryStore.listSentryPrivilegesForProvider( new HashSet<String>(Arrays.asList("group1")), Sets.newHashSet(""), thriftRoleSet, tSentryAuthorizable1); assertTrue(privs.size() == 1); assertTrue(privs.contains("server=server1->uri=" + uri1 + "->action=all")); privs = sentryStore.listSentryPrivilegesForProvider(new HashSet<String>(Arrays.asList("group1")), Sets.newHashSet(""), thriftRoleSet, tSentryAuthorizable2); assertTrue(privs.size() == 1); assertTrue(privs.contains("server=server1->uri=" + uri2 + "->action=all")); // list privilege for user only privs = sentryStore.listSentryPrivilegesForProvider(new HashSet<String>(Arrays.asList("")), Sets.newHashSet("user1"), thriftRoleSet, tSentryAuthorizable1); assertTrue(privs.size() == 1); assertTrue(privs.contains("server=server1->uri=" + uri1 + "->action=all")); privs = sentryStore.listSentryPrivilegesForProvider(new HashSet<String>(Arrays.asList("")), Sets.newHashSet("user1"), thriftRoleSet, tSentryAuthorizable2); assertTrue(privs.size() == 1); assertTrue(privs.contains("server=server1->uri=" + uri2 + "->action=all")); // list privilege for both user and group privs = sentryStore.listSentryPrivilegesForProvider(new HashSet<String>(Arrays.asList("group1")), Sets.newHashSet("user1"), thriftRoleSet, tSentryAuthorizable1); assertTrue(privs.size() == 1); assertTrue(privs.contains("server=server1->uri=" + uri1 + "->action=all")); privs = sentryStore.listSentryPrivilegesForProvider(new HashSet<String>(Arrays.asList("group1")), Sets.newHashSet("user1"), thriftRoleSet, tSentryAuthorizable2); assertTrue(privs.size() == 1); assertTrue(privs.contains("server=server1->uri=" + uri2 + "->action=all")); } @Test public void testURIGrantRevokeOnEmptyPath() throws Exception { String roleName = "test-empty-uri-role"; String uri = ""; createRole(roleName); TSentryPrivilege tSentryPrivilege = new TSentryPrivilege("URI", "server1", "ALL"); tSentryPrivilege.setURI(uri); //Test grant on empty URI try { sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(tSentryPrivilege), null); fail("Expected SentryInvalidInputException"); } catch (SentryInvalidInputException e) { // expected } //Test revoke on empty URI try { sentryStore.alterSentryRevokePrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(tSentryPrivilege), null); 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"; createRole(roleName); TSentryPrivilege sentryPrivilege = new TSentryPrivilege("Database", "server1", "all"); sentryPrivilege.setDbName("db1"); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(sentryPrivilege), null); } /** * 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<TSentryGroup> groups = Sets.newHashSet(); Set<String> 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<TSentryGroup> 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<String> 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<String, Set<String>> 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<TSentryRole> 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<String> userSet1 = Sets.newHashSet(user1, user2, user3); Set<String> roleSet1 = Sets.newHashSet(roleName1, roleName2, roleName3); Set<String> userSet2 = Sets.newHashSet(user4); Set<String> roleSet2 = Sets.newHashSet(roleName2, roleName3); Set<String> userSet3 = Sets.newHashSet("foo"); Set<String> roleSet3 = Sets.newHashSet(); // Query for multiple users Set<String> 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<String> convertToRoleNameSet(Set<TSentryRole> tSentryRoles) { Set<String> 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<String> groupSet1 = Sets.newHashSet(group1, group2, group3); Set<String> roleSet1 = Sets.newHashSet(roleName1, roleName2); Set<String> groupSet2 = Sets.newHashSet(group1); Set<String> roleSet2 = Sets.newHashSet(roleName1); Set<String> groupSet3 = Sets.newHashSet("foo"); Set<String> roleSet3 = Sets.newHashSet(); // Query for multiple groups Set<String> 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 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.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(privilege), null); MSentryRole role = sentryStore.getMSentryRoleByName(roleName); Set<MSentryPrivilege> privileges = role.getPrivileges(); assertEquals(privileges.toString(), 1, privileges.size()); privilege.setAction(AccessConstants.SELECT); sentryStore.alterSentryRevokePrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(privilege), null); // 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 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.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(priv), null); } // 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<MSentryPrivilege> 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 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.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(priv), null); priv.setAction(AccessConstants.SELECT); priv.setGrantOption(TSentryGrantOption.UNSET); sentryStore.alterSentryRevokePrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(priv), null); // after having ALL and revoking SELECT, we should have INSERT MSentryRole role = sentryStore.getMSentryRoleByName(roleName); Set<MSentryPrivilege> 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<MSentryPrivilege> 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 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.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(priv), null); priv.setAction(AccessConstants.SELECT); priv.setGrantOption(TSentryGrantOption.UNSET); sentryStore.alterSentryRevokePrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(priv), null); 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.alterSentryRevokePrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(priv), null); MSentryRole role = sentryStore.getMSentryRoleByName(roleName); assertEquals("Privilege Count", 0, role.getPrivileges().size()); priv.setAction(AccessConstants.CREATE); sentryStore.alterSentryRevokePrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(priv), null); role = sentryStore.getMSentryRoleByName(roleName); assertEquals("Privilege Count", 0, role.getPrivileges().size()); priv.setAction(AccessConstants.DROP); sentryStore.alterSentryRevokePrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(priv), null); role = sentryStore.getMSentryRoleByName(roleName); assertEquals("Privilege Count", 0, role.getPrivileges().size()); priv.setAction(AccessConstants.ALTER); sentryStore.alterSentryRevokePrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(priv), null); 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<MSentryPrivilege> 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 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.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(priv), null); } // 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.alterSentryRevokePrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(priv), null); //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.alterSentryRevokePrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(priv), null); 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 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.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(priv), null); priv.setAction(AccessConstants.ALTER); sentryStore.alterSentryRevokePrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(priv), null); MSentryRole role = sentryStore.getMSentryRoleByName(roleName); assertEquals("Privilege Count", 0, role.getPrivileges().size()); } //There should not be any Privileges left List<MSentryPrivilege> list = sentryStore.getAllMSentryPrivileges(); assertEquals(list.size(), 0); } @Test public void testDropIndividualPrivilegesWhenGrantAllIsGranted() throws Exception { final String ROLE_NAME = "r1"; final String SERVER_NAME = "server1"; final String DB_NAME = "db1"; final String TABLE_NAME = "table1"; TSentryPrivilege allPrivilege = toTSentryPrivilege(AccessConstants.ACTION_ALL, PrivilegeScope.SERVER.toString(), SERVER_NAME, DB_NAME, TABLE_NAME, TSentryGrantOption.FALSE); TSentryPrivilege allWithGrant = toTSentryPrivilege(AccessConstants.ACTION_ALL, PrivilegeScope.SERVER.toString(), SERVER_NAME, DB_NAME, TABLE_NAME, TSentryGrantOption.TRUE); TSentryPrivilege ownerPrivilege = toTSentryPrivilege(AccessConstants.OWNER, PrivilegeScope.DATABASE.toString(), SERVER_NAME, DB_NAME, TABLE_NAME); Set<TSentryPrivilege> grantPrivileges = Sets.newHashSet( toTSentryPrivilege(AccessConstants.SELECT, PrivilegeScope.SERVER.toString(), SERVER_NAME, DB_NAME, TABLE_NAME), toTSentryPrivilege(AccessConstants.INSERT, PrivilegeScope.SERVER.toString(), SERVER_NAME, DB_NAME, TABLE_NAME), toTSentryPrivilege(AccessConstants.CREATE, PrivilegeScope.SERVER.toString(), SERVER_NAME, DB_NAME, TABLE_NAME), toTSentryPrivilege(AccessConstants.ALTER, PrivilegeScope.SERVER.toString(), SERVER_NAME, DB_NAME, TABLE_NAME), toTSentryPrivilege(AccessConstants.DROP, PrivilegeScope.SERVER.toString(), SERVER_NAME, DB_NAME, TABLE_NAME), toTSentryPrivilege(AccessConstants.INDEX, PrivilegeScope.SERVER.toString(), SERVER_NAME, DB_NAME, TABLE_NAME), toTSentryPrivilege(AccessConstants.LOCK, PrivilegeScope.SERVER.toString(), SERVER_NAME, DB_NAME, TABLE_NAME), // This special privilege will not be removed when granting all privileges ownerPrivilege); // Grant individual privileges to a role createRole(ROLE_NAME); sentryStore.alterSentryRoleGrantPrivileges(ROLE_NAME, grantPrivileges); // Check those individual privileges are granted Set<TSentryPrivilege> rolePrivileges = sentryStore.getAllTSentryPrivilegesByRoleName(ROLE_NAME); assertEquals(grantPrivileges.size(), rolePrivileges.size()); for (TSentryPrivilege privilege : grantPrivileges) { assertTrue(String.format("Privilege %s was not granted.", privilege.getAction()), rolePrivileges.contains(privilege)); } // Grant the ALL privilege (this should remove all individual privileges, and grant only ALL) sentryStore.alterSentryRoleGrantPrivileges(ROLE_NAME, Sets.newHashSet(allPrivilege)); // Check the ALL and OWNER privileges are the only privileges rolePrivileges = sentryStore.getAllTSentryPrivilegesByRoleName(ROLE_NAME); assertEquals(2, rolePrivileges.size()); // ALL and OWNER privileges should be there assertTrue("Privilege ALL was not granted.", rolePrivileges.contains(allPrivilege)); assertTrue("Privilege OWNER was dropped.", rolePrivileges.contains(ownerPrivilege)); // Check the ALL WITH GRANT privilege just replaces the ALL and keeps the OWNER privilege sentryStore.alterSentryRoleGrantPrivileges(ROLE_NAME, Sets.newHashSet(allWithGrant)); rolePrivileges = sentryStore.getAllTSentryPrivilegesByRoleName(ROLE_NAME); assertTrue("Privilege ALL WITH GRANT was not granted.", rolePrivileges.contains(allWithGrant)); assertTrue("Privilege OWNER was dropped.", rolePrivileges.contains(ownerPrivilege)); // Check the ALL privilege just replaces the ALL WITH GRANT and keeps the OWNER privilege sentryStore.alterSentryRoleGrantPrivileges(ROLE_NAME, Sets.newHashSet(allPrivilege)); rolePrivileges = sentryStore.getAllTSentryPrivilegesByRoleName(ROLE_NAME); assertTrue("Privilege ALL was not granted.", rolePrivileges.contains(allPrivilege)); assertTrue("Privilege OWNER was dropped.", rolePrivileges.contains(ownerPrivilege)); // Clean-up test sentryStore.dropSentryRole(ROLE_NAME); } //TODO Use new transaction Manager logic, Instead of @Test public void testGrantRevokeMultiPrivileges() throws Exception { String roleName = "test-privilege"; String server = "server1"; String db = "db1"; String table = "tbl1"; String[] columns = { "c1", "c2", "c3", "c4" }; createRole(roleName); Set<TSentryPrivilege> 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(roleName, tPrivileges); MSentryRole role = sentryStore.getMSentryRoleByName(roleName); Set<MSentryPrivilege> 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(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.alterSentryRevokePrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(privilege), null); // 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 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.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(privilege), null); privilege.setColumnName(column2); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(privilege), null); MSentryRole role = sentryStore.getMSentryRoleByName(roleName); Set<MSentryPrivilege> privileges = role.getPrivileges(); assertEquals(privileges.toString(), 2, privileges.size()); // Revoke SELECT on c2 privilege.setAction(AccessConstants.SELECT); sentryStore.alterSentryRevokePrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(privilege), null); // 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.alterSentryRevokePrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(privilege), null); 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.alterSentryRevokePrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(privilege), null); 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 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.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(privilegeTable1), null); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(privilegeTable2), null); MSentryRole role = sentryStore.getMSentryRoleByName(roleName); Set<MSentryPrivilege> privileges = role.getPrivileges(); assertEquals(privileges.toString(), 2, privileges.size()); // Revoke SELECT on table2 privilegeTable2.setAction(AccessConstants.SELECT); sentryStore.alterSentryRevokePrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(privilegeTable2), null); // 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.alterSentryRevokePrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(privilegeTable2), null); 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 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.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(privilegeCol1), null); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(privilegeCol2), null); MSentryRole role = sentryStore.getMSentryRoleByName(roleName); Set<MSentryPrivilege> privileges = role.getPrivileges(); assertEquals(privileges.toString(), 2, privileges.size()); // Revoke SELECT on column2 privilegeCol2.setAction(AccessConstants.SELECT); sentryStore.alterSentryRevokePrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(privilegeCol2), null); // 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.alterSentryRevokePrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(privilegeCol2), null); 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 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.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(privilege), null); MSentryRole role = sentryStore.getMSentryRoleByName(roleName); Set<MSentryPrivilege> privileges = role.getPrivileges(); assertEquals(privileges.toString(), 1, privileges.size()); assertEquals(Boolean.valueOf(privilege.getGrantOption().toString()), Iterables.get(privileges, 0).getGrantOption()); sentryStore.alterSentryRevokePrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(privilege), null); 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.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(privilege), null); role = sentryStore.getMSentryRoleByName(roleName); privileges = role.getPrivileges(); assertEquals(privileges.toString(), 1, privileges.size()); privilege.setAction(AccessConstants.SELECT); privilege.setGrantOption(TSentryGrantOption.UNSET); sentryStore.alterSentryRevokePrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(privilege), null); // 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 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<TSentryGroup> 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]; 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.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(privilege), null); // 3. g1 grant select on table tb1 to role0, no grant option roleName = roles[0]; privilege.setGrantOption(TSentryGrantOption.FALSE); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(privilege), null); // 4. g1 revoke all privilege from role0 roleName = roles[0]; privilege.setGrantOption(TSentryGrantOption.UNSET); sentryStore.alterSentryRevokePrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(privilege), null); MSentryRole role = sentryStore.getMSentryRoleByName(roleName); Set<MSentryPrivilege> privileges = role.getPrivileges(); assertEquals(privileges.toString(), 0, privileges.size()); } @Test public void testGrantDuplicatePrivilege() throws Exception { String roleName = "test-privilege"; 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.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(privilege), null); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(privilege), null); privilege.setServerName("Server1"); privilege.setDbName("DB1"); privilege.setTableName("TBL1"); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(privilege), null); MSentryRole role = sentryStore.getMSentryRoleByName(roleName); Set<MSentryPrivilege> 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<String> 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.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName1, Sets.newHashSet(privilege1), null); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName2, Sets.newHashSet(privilege1), null); TSentryPrivilege privilege2 = new TSentryPrivilege(); privilege2.setPrivilegeScope("SERVER"); privilege2.setServerName("server1"); privilege2.setCreateTime(System.currentTimeMillis()); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName2, Sets.newHashSet(privilege2), null); Set<TSentryGroup> groups = Sets.newHashSet(); Set<String> 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<String>())))); // 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<String>())))); // 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<String>())))); // 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<String>())))); // 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<String>())))); // 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<String>())))); // 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<String>())))); // 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<String>())))); // 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<String>())))); // 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<String>())))); // 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<String>())))); } @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 and users * drop privilege for the object verify that it's removed correctly * @throws Exception */ @Test public void testDropDbObject() throws Exception { String roleName1 = "list-privs-r1", roleName2 = "list-privs-r2", roleName3 = "list-privs-r3"; String userName1 = "user-1", userName2 = "user-2"; sentryStore.createSentryRole(roleName1); sentryStore.createSentryRole(roleName2); sentryStore.createSentryRole(roleName3); sentryStore.createSentryUser(userName1); sentryStore.createSentryUser(userName2); 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.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName1, Sets.newHashSet(privilege1), null); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName2, Sets.newHashSet(privilege2_1), null); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName2, Sets.newHashSet(privilege_server), null); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName2, Sets.newHashSet(privilege2_3), null); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName3, Sets.newHashSet(privilege3_1), null); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName3, Sets.newHashSet(privilege3_2), null); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.USER, userName1, Sets.newHashSet(privilege1), null); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.USER, userName2, Sets.newHashSet(privilege2_3), null); sentryStore.dropPrivilege(toTSentryAuthorizable(privilege_tbl1)); assertEquals(0, sentryStore.getAllTSentryPrivilegesByRoleName(roleName1).size()); assertEquals(2, sentryStore.getAllTSentryPrivilegesByRoleName(roleName2).size()); assertEquals(1, sentryStore.getAllTSentryPrivilegesByRoleName(roleName3).size()); try { sentryStore.getAllTSentryPrivilegesByUserName(userName1); fail("Should have received an exception"); } catch (Exception e) { } assertEquals(1, sentryStore.getAllTSentryPrivilegesByUserName(userName2).size()); sentryStore.dropPrivilege(toTSentryAuthorizable(privilege_tbl2)); assertEquals(0, sentryStore.getAllTSentryPrivilegesByRoleName(roleName1).size()); assertEquals(1, sentryStore.getAllTSentryPrivilegesByRoleName(roleName2).size()); assertEquals(0, sentryStore.getAllTSentryPrivilegesByRoleName(roleName3).size()); try { sentryStore.getAllTSentryPrivilegesByUserName(userName2); fail("Should have received an exception"); } catch (Exception e) { } } /** * Grants owner privileges to role/user and updates the owner * and makes sure that the owner privilege is updated. * @throws Exception */ @Test public void testUpdateOwnerPrivilege() throws Exception { String roleName1 = "list-privs-r1", roleName2 = "list-privs-r2", roleName3 = "list-privs-r3"; String userName1 = "user1", userName2 = "user2"; List<SentryOwnerInfo> ownerInfoList = null; sentryStore.createSentryRole(roleName1); sentryStore.createSentryRole(roleName2); sentryStore.createSentryRole(roleName3); sentryStore.createSentryUser(userName1); sentryStore.createSentryUser(userName2); 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()); privilege_tbl1.setAction("OWNER"); TSentryAuthorizable tSentryAuthorizable = new TSentryAuthorizable(); tSentryAuthorizable.setServer("server1"); tSentryAuthorizable.setDb("db1"); tSentryAuthorizable.setTable("tbl1"); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName1, Sets.newHashSet(privilege_tbl1), null); assertEquals(1, sentryStore.getAllTSentryPrivilegesByRoleName(roleName1).size()); assertEquals(0, sentryStore.getAllTSentryPrivilegesByRoleName(roleName2).size()); ownerInfoList = sentryStore.listOwnersByAuthorizable(tSentryAuthorizable); assertEquals(1, ownerInfoList.size()); assertEquals(SentryPrincipalType.ROLE, ownerInfoList.get(0).getOwnerType()); assertEquals(roleName1, ownerInfoList.get(0).getOwnerName()); // Change owner from a one role to another role sentryStore.updateOwnerPrivilege(tSentryAuthorizable, roleName2, SentryPrincipalType.ROLE, null); ownerInfoList = sentryStore.listOwnersByAuthorizable(tSentryAuthorizable); assertEquals(1, ownerInfoList.size()); assertEquals(SentryPrincipalType.ROLE, ownerInfoList.get(0).getOwnerType()); assertEquals(roleName2, ownerInfoList.get(0).getOwnerName()); assertEquals(0, sentryStore.getAllTSentryPrivilegesByRoleName(roleName1).size()); assertEquals(1, sentryStore.getAllTSentryPrivilegesByRoleName(roleName2).size()); tSentryAuthorizable.setTable("tbl2"); TSentryPrivilege privilege_tbl2 = new TSentryPrivilege(privilege_tbl1); privilege_tbl2.setTableName("tbl2"); // Change owner from a one user to another user sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.USER, userName1, Sets.newHashSet(privilege_tbl2), null); assertEquals(1, sentryStore.getAllTSentryPrivilegesByUserName(userName1).size()); sentryStore.updateOwnerPrivilege(tSentryAuthorizable, userName2, SentryPrincipalType.USER, null); assertEquals(1, sentryStore.getAllTSentryPrivilegesByUserName(userName2).size()); ownerInfoList = sentryStore.listOwnersByAuthorizable(tSentryAuthorizable); assertEquals(1, ownerInfoList.size()); assertEquals(SentryPrincipalType.USER, ownerInfoList.get(0).getOwnerType()); assertEquals(userName2, ownerInfoList.get(0).getOwnerName()); // Change owner from a user to role sentryStore.updateOwnerPrivilege(tSentryAuthorizable, roleName1, SentryPrincipalType.ROLE, null); assertEquals(1, sentryStore.getAllTSentryPrivilegesByRoleName(roleName1).size()); // At this point roleName1 has owner privilege on db1.tb2 //Add all privilege to roleName1 and make sure that owner privilege is not effected. TSentryPrivilege privilege_tbl2_all = new TSentryPrivilege(privilege_tbl2); privilege_tbl2_all.setAction(AccessConstants.ALL); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName1, Sets.newHashSet(privilege_tbl2_all), null); // Verify that there are two privileges. assertEquals(2, sentryStore.getAllTSentryPrivilegesByRoleName(roleName1).size()); tSentryAuthorizable.setTable("tbl3"); TSentryPrivilege privilege_tbl3_all = new TSentryPrivilege(privilege_tbl2); privilege_tbl3_all.setAction(AccessConstants.ALL); privilege_tbl3_all.setTableName("tbl3"); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName3, Sets.newHashSet(privilege_tbl3_all), null); assertEquals(1, sentryStore.getAllTSentryPrivilegesByRoleName(roleName3).size()); TSentryPrivilege privilege_tbl3_owner = new TSentryPrivilege(privilege_tbl3_all); privilege_tbl3_owner.setAction(AccessConstants.OWNER); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName3, Sets.newHashSet(privilege_tbl3_owner), null); assertEquals(2, sentryStore.getAllTSentryPrivilegesByRoleName(roleName3).size()); } @Test public void testListSentryOwnerPrivilegesByAuthorizable() throws Exception { String roleName1 = "list-privs-r1"; String userName1 = "user1"; sentryStore.createSentryRole(roleName1); sentryStore.createSentryUser(userName1); 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()); privilege_tbl1.setAction("OWNER"); privilege_tbl1.setGrantOption(TSentryGrantOption.TRUE); TSentryAuthorizable tSentryAuthorizable = new TSentryAuthorizable(); tSentryAuthorizable.setServer("server1"); tSentryAuthorizable.setDb("db1"); tSentryAuthorizable.setTable("tbl1"); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName1, Sets.newHashSet(privilege_tbl1), null); sentryStore.updateOwnerPrivilege(tSentryAuthorizable, userName1, SentryPrincipalType.USER, null); assertEquals(1, sentryStore.getAllTSentryPrivilegesByUserName(userName1).size()); } @Test public void testRevokeOwnerPrivilege() throws Exception { String roleName1 = "list-privs-r1"; String userName1 = "user1"; sentryStore.createSentryRole(roleName1); sentryStore.createSentryUser(userName1); 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()); privilege_tbl1.setAction("OWNER"); privilege_tbl1.setGrantOption(TSentryGrantOption.TRUE); TSentryAuthorizable tSentryAuthorizable = new TSentryAuthorizable(); tSentryAuthorizable.setServer("server1"); tSentryAuthorizable.setDb("db1"); tSentryAuthorizable.setTable("tbl1"); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName1, Sets.newHashSet(privilege_tbl1), null); sentryStore.revokeOwnerPrivileges(tSentryAuthorizable, null); assertEquals(0, sentryStore.getAllTSentryPrivilegesByUserName(userName1).size()); } @Test public void testgetPrivilegesForAuthorizables() throws Exception { String roleName1 = "list-privs-r1"; String userName1 = "user1"; String uri1 = "file:///var/folders/dt/9zm44z9s6bjfxbrm4v36lzdc0000gp/T/1401860678102-0/data/kv1.dat"; sentryStore.createSentryRole(roleName1); sentryStore.createSentryUser(userName1); 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()); privilege_tbl1.setAction("SELECT"); privilege_tbl1.setGrantOption(TSentryGrantOption.TRUE); TSentryAuthorizable tSentryAuthorizable = new TSentryAuthorizable(); tSentryAuthorizable.setServer("server1"); tSentryAuthorizable.setDb("db1"); tSentryAuthorizable.setTable("tbl1"); 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()); privilege_tbl2.setAction("SELECT"); privilege_tbl2.setGrantOption(TSentryGrantOption.TRUE); TSentryAuthorizable tSentryAuthorizable2 = new TSentryAuthorizable(); tSentryAuthorizable2.setServer("server1"); tSentryAuthorizable2.setDb("db1"); tSentryAuthorizable2.setTable("tbl2"); TSentryPrivilege privilege_col1 = new TSentryPrivilege(privilege_tbl2); privilege_col1.setPrivilegeScope("TABLE"); privilege_col1.setServerName("server1"); privilege_col1.setDbName("db3"); privilege_col1.setTableName("tbl3"); privilege_col1.setCreateTime(System.currentTimeMillis()); privilege_col1.setAction("SELECT"); privilege_col1.setGrantOption(TSentryGrantOption.TRUE); privilege_col1.setColumnName("Column1"); TSentryAuthorizable tSentryAuthorizable3 = new TSentryAuthorizable(); tSentryAuthorizable3.setServer("server1"); tSentryAuthorizable3.setDb("db3"); tSentryAuthorizable3.setTable("tbl3"); tSentryAuthorizable3.setColumn("Column1"); TSentryPrivilege tSentryUriPrivilege = new TSentryPrivilege("URI", "server1", "ALL"); tSentryUriPrivilege.setURI(uri1); TSentryAuthorizable tSentryUriAuthorizable = new TSentryAuthorizable(); tSentryUriAuthorizable.setUri(uri1); tSentryUriAuthorizable.setServer("server1"); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName1, Sets.newHashSet(privilege_tbl1, privilege_tbl2, privilege_col1, tSentryUriPrivilege), null); // Verify the privilege count List<MSentryPrivilege> privilege = sentryStore.getPrivilegesForAuthorizables(Lists.newArrayList( tSentryAuthorizable, tSentryAuthorizable2, tSentryUriAuthorizable, tSentryAuthorizable3)); assertEquals(4, privilege.size()); // Verify the behavior when the empty authorizable list provided. privilege = sentryStore.getPrivilegesForAuthorizables(Collections.EMPTY_LIST); assertNotNull(privilege); assertEquals(4, privilege.size()); // Verify the behvaior when the authorizable list is null. privilege = sentryStore.getPrivilegesForAuthorizables(null); assertNotNull(privilege); assertEquals(4, privilege.size()); // Verify the privilege granted to URI is returned privilege = sentryStore.getPrivilegesForAuthorizables(Lists.newArrayList(tSentryAuthorizable2)); assertEquals(1, privilege.size()); TSentryAuthorizable tSentrDbAuthorizable = new TSentryAuthorizable(); tSentrDbAuthorizable.setServer("server1"); tSentrDbAuthorizable.setDb("db1"); // Verify that all the privileges granted to tables in database db1 are returned. privilege = sentryStore.getPrivilegesForAuthorizables(Lists.newArrayList(tSentrDbAuthorizable)); assertEquals(2, privilege.size()); // Verify that all the privileges granted to server are returned. privilege = sentryStore.getPrivilegesForAuthorizables(Lists.newArrayList(tSentryAuthorizable3)); assertEquals(1, privilege.size()); TSentryAuthorizable tSentrServerAuthorizable = new TSentryAuthorizable(); tSentrServerAuthorizable.setServer("server1"); // Verify that all the privileges granted to server are returned. privilege = sentryStore.getPrivilegesForAuthorizables(Lists.newArrayList(tSentrServerAuthorizable)); assertEquals(4, privilege.size()); // Grant user1 same privileges granted to role1 and make sure that there are no duplicates in the privileges. sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.USER, userName1, Sets.newHashSet(privilege_tbl1, privilege_tbl2, tSentryUriPrivilege), null); // Verify that all the privileges granted to server are returned. privilege = sentryStore.getPrivilegesForAuthorizables(Lists.newArrayList(tSentrServerAuthorizable)); assertEquals(4, privilege.size()); } @Test public void testgetPrivilegesForURIs() throws Exception { String roleName1 = "list-privs-r1"; String uriPrefix = "file:///var/folders/dt/9zm44z9s6bjfxbrm4v36lzdc0000gp/T/1401860678102-0/"; String uri1 = "file:///var/folders/dt/9zm44z9s6bjfxbrm4v36lzdc0000gp/T/1401860678102-0/data/kv1.dat"; String uri2 = "file:///var/folders/dt/9zm44z9s6bjfxbrm4v36lzdc0000gp/T/1401860678102-0/data/kv2.dat"; sentryStore.createSentryRole(roleName1); TSentryPrivilege tSentryUriPrivilege1 = new TSentryPrivilege("URI", "server1", "ALL"); tSentryUriPrivilege1.setURI(uri1); TSentryPrivilege tSentryUriPrivilege2 = new TSentryPrivilege("URI", "server1", "ALL"); tSentryUriPrivilege2.setURI(uri2); TSentryAuthorizable tSentryUriAuthorizable = new TSentryAuthorizable(); tSentryUriAuthorizable.setUri(uriPrefix); tSentryUriAuthorizable.setServer("server1"); // Grant user1 same privileges granted to role1 and make sure that there are no duplicates in the privileges. sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName1, Sets.newHashSet(tSentryUriPrivilege1, tSentryUriPrivilege2), null); // Verify that all the privileges granted to all the URI;s under given prefix are returned. List<MSentryPrivilege> privilege = sentryStore .getPrivilegesForAuthorizables(Lists.newArrayList(tSentryUriAuthorizable)); assertEquals(2, privilege.size()); } @Test public void testDropUserOnUpdateOwnerPrivilege() throws Exception { String userName1 = "user1", userName2 = "user2"; sentryStore.createSentryUser(userName1); sentryStore.createSentryUser(userName2); 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()); privilege_tbl1.setAction("OWNER"); TSentryAuthorizable tSentryAuthorizable = new TSentryAuthorizable(); tSentryAuthorizable.setServer("server1"); tSentryAuthorizable.setDb("db1"); tSentryAuthorizable.setTable("tbl1"); // Change owner from a one user to another user sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.USER, userName1, Sets.newHashSet(privilege_tbl1), null); assertEquals(1, sentryStore.getAllTSentryPrivilegesByUserName(userName1).size()); sentryStore.updateOwnerPrivilege(tSentryAuthorizable, userName2, SentryPrincipalType.USER, null); assertEquals(1, sentryStore.getAllTSentryPrivilegesByUserName(userName2).size()); try { sentryStore.createSentryUser(userName1); } catch (Exception e) { fail("Exception should not be seen asthe user: " + userName1 + " should have been deleted."); } } /** * 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"; 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.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName1, Sets.newHashSet(privilege_tbl1_insert), null); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName1, Sets.newHashSet(privilege_tbl1_select), null); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName1, Sets.newHashSet(privilege_tbl1_alter), null); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName1, Sets.newHashSet(privilege_tbl1_drop), null); 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 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.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName1, Sets.newHashSet(privilege_tbl1_c1), null); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName1, Sets.newHashSet(privilege_tbl1_c2), null); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName2, Sets.newHashSet(privilege_tbl1_c3), null); Set<TSentryPrivilege> privilegeSet = sentryStore.getAllTSentryPrivilegesByRoleName(roleName1); assertEquals(2, privilegeSet.size()); privilegeSet = sentryStore.getAllTSentryPrivilegesByRoleName(roleName2); assertEquals(1, privilegeSet.size()); TSentryAuthorizable tableAuthorizable = toTSentryAuthorizable(privilege_tbl1); sentryStore.dropPrivilege(tableAuthorizable); privilegeSet = sentryStore.getAllTSentryPrivilegesByRoleName(roleName1); assertEquals(0, privilegeSet.size()); privilegeSet = sentryStore.getAllTSentryPrivilegesByRoleName(roleName2); assertEquals(0, privilegeSet.size()); } @Test public void testDropOverlappedPrivileges() throws Exception { String roleName1 = "list-privs-r1"; 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("INSERT"); TSentryPrivilege privilege_tbl1_all = new TSentryPrivilege(privilege_tbl1); privilege_tbl1_all.setAction("*"); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName1, Sets.newHashSet(privilege_tbl1_insert), null); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName1, Sets.newHashSet(privilege_tbl1_all), null); sentryStore.dropPrivilege(toTSentryAuthorizable(privilege_tbl1)); assertEquals(0, sentryStore.getAllTSentryPrivilegesByRoleName(roleName1).size()); } private TSentryAuthorizable toTSentryAuthorizable(TSentryPrivilege tSentryPrivilege) { TSentryAuthorizable tSentryAuthorizable = new TSentryAuthorizable(); tSentryAuthorizable.setServer(tSentryPrivilege.getServerName()); tSentryAuthorizable.setDb(tSentryPrivilege.getDbName()); tSentryAuthorizable.setTable(tSentryPrivilege.getTableName()); tSentryAuthorizable.setUri(tSentryPrivilege.getURI()); return tSentryAuthorizable; } /*** * Create roles and users and assign privileges for same table rename the privileges for * the table and verify the new privileges * @throws Exception */ @Test public void testRenameTable() throws Exception { String roleName1 = "role1", roleName2 = "role2", roleName3 = "role3"; String userName1 = "user-1", userName2 = "user-2", userName3 = "user-3"; String table1 = "tbl1", table2 = "tbl2"; sentryStore.createSentryRole(roleName1); sentryStore.createSentryRole(roleName2); sentryStore.createSentryRole(roleName3); sentryStore.createSentryUser(userName1); sentryStore.createSentryUser(userName2); sentryStore.createSentryUser(userName3); TSentryPrivilege privilege_tbl1 = new TSentryPrivilege(); privilege_tbl1.setPrivilegeScope("TABLE"); privilege_tbl1.setServerName("server1"); privilege_tbl1.setDbName("db1"); privilege_tbl1.setTableName(table1); 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_all = new TSentryPrivilege(privilege_tbl1); privilege_tbl1_all.setAction(AccessConstants.ALL); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName1, Sets.newHashSet(privilege_tbl1_insert), null); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName2, Sets.newHashSet(privilege_tbl1_select), null); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName3, Sets.newHashSet(privilege_tbl1_all), null); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.USER, userName1, Sets.newHashSet(privilege_tbl1_insert), null); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.USER, userName2, Sets.newHashSet(privilege_tbl1_select), null); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.USER, userName3, Sets.newHashSet(privilege_tbl1_all), null); TSentryAuthorizable oldTable = toTSentryAuthorizable(privilege_tbl1); TSentryAuthorizable newTable = toTSentryAuthorizable(privilege_tbl1); newTable.setTable(table2); sentryStore.renamePrivilege(oldTable, newTable); for (String roleName : Sets.newHashSet(roleName1, roleName2, roleName3)) { Set<TSentryPrivilege> privilegeSet = sentryStore.getAllTSentryPrivilegesByRoleName(roleName); assertEquals(1, privilegeSet.size()); for (TSentryPrivilege privilege : privilegeSet) { assertTrue(table2.equalsIgnoreCase(privilege.getTableName())); } } for (String userName : Sets.newHashSet(userName1, userName2, userName3)) { Set<TSentryPrivilege> privilegeSet = sentryStore.getAllTSentryPrivilegesByUserName(userName); assertEquals(1, privilegeSet.size()); for (TSentryPrivilege privilege : privilegeSet) { assertTrue(table2.equalsIgnoreCase(privilege.getTableName())); } } } /** * Regression test for SENTRY-550 * 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 * RENAME TABLE tbl1 to tbl2 * * After rename tbl1 to tbl2, table name of all role1's privileges should be "tbl2" */ @Test public void testRenameTableWithMultiAction() throws Exception { String roleName1 = "role1"; String table1 = "tbl1", table2 = "tbl2"; sentryStore.createSentryRole(roleName1); TSentryPrivilege privilege_tbl1 = new TSentryPrivilege(); privilege_tbl1.setPrivilegeScope("TABLE"); privilege_tbl1.setServerName("server1"); privilege_tbl1.setDbName("db1"); privilege_tbl1.setTableName(table1); 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.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName1, Sets.newHashSet(privilege_tbl1_insert), null); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName1, Sets.newHashSet(privilege_tbl1_select), null); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName1, Sets.newHashSet(privilege_tbl1_alter), null); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName1, Sets.newHashSet(privilege_tbl1_drop), null); TSentryAuthorizable oldTable = toTSentryAuthorizable(privilege_tbl1); TSentryAuthorizable newTable = toTSentryAuthorizable(privilege_tbl1); newTable.setTable(table2); sentryStore.renamePrivilege(oldTable, newTable); // after rename tbl1 to tbl2, all table name of role's privilege will be tbl2 Set<TSentryPrivilege> privilegeSet = sentryStore.getAllTSentryPrivilegesByRoleName(roleName1); assertEquals(4, privilegeSet.size()); for (TSentryPrivilege privilege : privilegeSet) { assertTrue(table2.equalsIgnoreCase(privilege.getTableName())); } } @Test public void testSentryRoleSize() throws Exception { for (long i = 0; i < 5; i++) { assertEquals((Long) i, sentryStore.getRoleCountGauge().getValue()); sentryStore.createSentryRole("role" + i); } } @Test public void testSentryPrivilegeSize() throws Exception { String role1 = "role1"; String role2 = "role2"; sentryStore.createSentryRole(role1); sentryStore.createSentryRole(role2); TSentryPrivilege privilege = new TSentryPrivilege(); privilege.setPrivilegeScope("TABLE"); privilege.setServerName("server1"); privilege.setDbName("db1"); privilege.setTableName("tb1"); privilege.setCreateTime(System.currentTimeMillis()); assertEquals(Long.valueOf(0), sentryStore.getPrivilegeCountGauge().getValue()); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, role1, Sets.newHashSet(privilege), null); assertEquals(Long.valueOf(1), sentryStore.getPrivilegeCountGauge().getValue()); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, role2, Sets.newHashSet(privilege), null); assertEquals(Long.valueOf(1), sentryStore.getPrivilegeCountGauge().getValue()); privilege.setTableName("tb2"); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, role2, Sets.newHashSet(privilege), null); assertEquals(Long.valueOf(2), sentryStore.getPrivilegeCountGauge().getValue()); } @Test public void testSentryGroupsSize() throws Exception { String role1 = "role1"; String role2 = "role2"; sentryStore.createSentryRole(role1); sentryStore.createSentryRole(role2); Set<TSentryGroup> groups = Sets.newHashSet(); TSentryGroup group = new TSentryGroup(); group.setGroupName("group1"); groups.add(group); String grantor = "g1"; sentryStore.alterSentryRoleAddGroups(grantor, role1, groups); assertEquals(Long.valueOf(1), sentryStore.getGroupCountGauge().getValue()); sentryStore.alterSentryRoleAddGroups(grantor, role2, groups); assertEquals(Long.valueOf(1), sentryStore.getGroupCountGauge().getValue()); groups.add(new TSentryGroup("group2")); sentryStore.alterSentryRoleAddGroups(grantor, role2, groups); assertEquals(Long.valueOf(2), sentryStore.getGroupCountGauge().getValue()); } @Test public void testSentryUsersSize() throws Exception { String role1 = "role1"; String role2 = "role2"; sentryStore.createSentryRole(role1); sentryStore.createSentryRole(role2); Set<String> users = Sets.newHashSet("user1"); sentryStore.alterSentryRoleAddUsers(role1, users); assertEquals(Long.valueOf(1), sentryStore.getUserCountGauge().getValue()); sentryStore.alterSentryRoleAddUsers(role2, users); assertEquals(Long.valueOf(1), sentryStore.getUserCountGauge().getValue()); users.add("user2"); sentryStore.alterSentryRoleAddUsers(role2, users); assertEquals(Long.valueOf(2), sentryStore.getUserCountGauge().getValue()); } @Test public void testRenameTableWithColumn() throws Exception { String roleName1 = "role1", roleName2 = "role2"; String table1 = "tbl1", table2 = "tbl2"; 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.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName1, Sets.newHashSet(privilege_tbl1_c1), null); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName1, Sets.newHashSet(privilege_tbl1_c2), null); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName2, Sets.newHashSet(privilege_tbl1_c3), null); Set<TSentryPrivilege> privilegeSet = sentryStore.getAllTSentryPrivilegesByRoleName(roleName1); assertEquals(2, privilegeSet.size()); privilegeSet = sentryStore.getAllTSentryPrivilegesByRoleName(roleName2); assertEquals(1, privilegeSet.size()); TSentryAuthorizable oldTable = toTSentryAuthorizable(privilege_tbl1); TSentryAuthorizable newTable = toTSentryAuthorizable(privilege_tbl1); newTable.setTable(table2); sentryStore.renamePrivilege(oldTable, newTable); privilegeSet = sentryStore.getAllTSentryPrivilegesByRoleName(roleName1); assertEquals(2, privilegeSet.size()); for (TSentryPrivilege privilege : privilegeSet) { assertTrue(table2.equalsIgnoreCase(privilege.getTableName())); } privilegeSet = sentryStore.getAllTSentryPrivilegesByRoleName(roleName2); assertEquals(1, privilegeSet.size()); } @Test public void testSentryTablePrivilegeSome() throws Exception { String roleName = "test-table-privilege-some"; String grantor = "g1"; String dbName = "db1"; String table = "tb1"; createRole(roleName); TSentryPrivilege tSentryPrivilege = new TSentryPrivilege("TABLE", "server1", "ALL"); tSentryPrivilege.setDbName(dbName); tSentryPrivilege.setTableName(table); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(tSentryPrivilege), null); TSentryAuthorizable tSentryAuthorizable = new TSentryAuthorizable(); tSentryAuthorizable.setDb(dbName); tSentryAuthorizable.setTable(AccessConstants.SOME); tSentryAuthorizable.setServer("server1"); Set<TSentryPrivilege> privileges = sentryStore.getTSentryPrivileges(SentryPrincipalType.ROLE, new HashSet<String>(Arrays.asList(roleName)), tSentryAuthorizable); assertTrue(privileges.size() == 1); Set<TSentryGroup> tSentryGroups = new HashSet<TSentryGroup>(); tSentryGroups.add(new TSentryGroup("group1")); sentryStore.alterSentryRoleAddGroups(grantor, roleName, tSentryGroups); TSentryActiveRoleSet thriftRoleSet = new TSentryActiveRoleSet(true, new HashSet<String>(Arrays.asList(roleName))); Set<String> privs = sentryStore.listSentryPrivilegesForProvider( new HashSet<String>(Arrays.asList("group1")), Sets.newHashSet(grantor), thriftRoleSet, tSentryAuthorizable); assertTrue(privs.size() == 1); assertTrue(privs.contains("server=server1->db=" + dbName + "->table=" + table + "->action=all")); } @Test public void testSentryColumnPrivilegeSome() throws Exception { String roleName = "test-column-privilege-some"; String grantor = "g1"; String dbName = "db1"; String table = "tb1"; String column = "col1"; createRole(roleName); TSentryPrivilege tSentryPrivilege = new TSentryPrivilege("TABLE", "server1", "ALL"); tSentryPrivilege.setDbName(dbName); tSentryPrivilege.setTableName(table); tSentryPrivilege.setColumnName(column); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(tSentryPrivilege), null); TSentryAuthorizable tSentryAuthorizable = new TSentryAuthorizable(); tSentryAuthorizable.setDb(dbName); tSentryAuthorizable.setTable(table); tSentryAuthorizable.setColumn(AccessConstants.SOME); tSentryAuthorizable.setServer("server1"); Set<TSentryPrivilege> privileges = sentryStore.getTSentryPrivileges(SentryPrincipalType.ROLE, new HashSet<String>(Arrays.asList(roleName)), tSentryAuthorizable); assertTrue(privileges.size() == 1); Set<TSentryGroup> tSentryGroups = new HashSet<TSentryGroup>(); tSentryGroups.add(new TSentryGroup("group1")); sentryStore.alterSentryRoleAddGroups(grantor, roleName, tSentryGroups); TSentryActiveRoleSet thriftRoleSet = new TSentryActiveRoleSet(true, new HashSet<String>(Arrays.asList(roleName))); Set<String> privs = sentryStore.listSentryPrivilegesForProvider( new HashSet<String>(Arrays.asList("group1")), Sets.newHashSet(grantor), thriftRoleSet, tSentryAuthorizable); assertTrue(privs.size() == 1); assertTrue(privs.contains( "server=server1->db=" + dbName + "->table=" + table + "->column=" + column + "->action=all")); } @Test public void testSentryVersionCheck() throws Exception { // don't verify version, the current version willll be set in MSentryVersion sentryStore.verifySentryStoreSchema(false); assertEquals(sentryStore.getSentryVersion(), SentryStoreSchemaInfo.getSentryVersion()); // verify the version with the same value sentryStore.verifySentryStoreSchema(true); // verify the version with the different value sentryStore.setSentryVersion("test-version", "test-version"); try { sentryStore.verifySentryStoreSchema(true); fail("SentryAccessDeniedException should be thrown."); } catch (SentryAccessDeniedException e) { // the excepted exception, recover the version sentryStore.verifySentryStoreSchema(false); } } @Test public void testRetrieveFullPermssionsImage() throws Exception { // Create roles String roleName1 = "privs-r1", roleName2 = "privs-r2"; String groupName1 = "privs-g1"; String grantor = "g1"; sentryStore.createSentryRole(roleName1); sentryStore.createSentryRole(roleName2); // Grant Privileges to the roles TSentryPrivilege privilege1 = new TSentryPrivilege(); privilege1.setPrivilegeScope("TABLE"); privilege1.setServerName("server1"); privilege1.setDbName("db1"); privilege1.setTableName("tbl1"); privilege1.setAction("SELECT"); privilege1.setCreateTime(System.currentTimeMillis()); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName1, Sets.newHashSet(privilege1), null); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName2, Sets.newHashSet(privilege1), null); TSentryPrivilege privilege2 = new TSentryPrivilege(); privilege2.setPrivilegeScope("SERVER"); privilege2.setServerName("server1"); privilege1.setDbName("db2"); privilege1.setAction("ALL"); privilege2.setCreateTime(System.currentTimeMillis()); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName2, Sets.newHashSet(privilege2), null); // Grant roles to the groups Set<TSentryGroup> groups = Sets.newHashSet(); TSentryGroup group = new TSentryGroup(); group.setGroupName(groupName1); groups.add(group); sentryStore.alterSentryRoleAddGroups(grantor, roleName1, groups); sentryStore.alterSentryRoleAddGroups(grantor, roleName2, groups); //Grant owner privilege to role TSentryPrivilege privilege3 = new TSentryPrivilege(); privilege3.setPrivilegeScope("TABLE"); privilege3.setServerName("server1"); privilege3.setDbName("db3"); privilege3.setTableName("tbl1"); privilege3.setAction("OWNER"); privilege3.setCreateTime(System.currentTimeMillis()); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName1, Sets.newHashSet(privilege3), null); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName2, Sets.newHashSet(privilege3), null); PermissionsImage permImage = sentryStore.retrieveFullPermssionsImage(); Map<String, Map<TPrivilegePrincipal, String>> privs = permImage.getPrivilegeImage(); Map<String, List<String>> roles = permImage.getRoleImage(); assertEquals(2, privs.get("db1.tbl1").size()); assertEquals(2, roles.size()); assertEquals(2, privs.get("db3.tbl1").size()); assertEquals("ALL", privs.get("db3.tbl1").get(new TPrivilegePrincipal(TPrivilegePrincipalType.ROLE, roleName1))); assertEquals("ALL", privs.get("db3.tbl1").get(new TPrivilegePrincipal(TPrivilegePrincipalType.ROLE, roleName2))); } @Test public void testRetrieveFullPermssionsImageWithMultiplePrivielgesPerRolePerObject() throws Exception { // Create roles String roleName1 = "privs-r1"; String groupName1 = "privs-g1"; String grantor = "g1"; sentryStore.createSentryRole(roleName1); // Grant roles to the groups Set<TSentryGroup> groups = Sets.newHashSet(); TSentryGroup group = new TSentryGroup(); group.setGroupName(groupName1); groups.add(group); sentryStore.alterSentryRoleAddGroups(grantor, roleName1, groups); // Grant multiple privileges to a role on one object TSentryPrivilege privilege1 = new TSentryPrivilege(); privilege1.setPrivilegeScope("TABLE"); privilege1.setServerName("server1"); privilege1.setDbName("db1"); privilege1.setTableName("tbl1"); privilege1.setAction("SELECT"); privilege1.setCreateTime(System.currentTimeMillis()); TSentryPrivilege privilege2 = new TSentryPrivilege(); privilege2.setPrivilegeScope("TABLE"); privilege2.setServerName("server1"); privilege2.setDbName("db1"); privilege2.setTableName("tbl1"); privilege2.setAction("INSERT"); privilege2.setCreateTime(System.currentTimeMillis()); TSentryPrivilege privilege3 = new TSentryPrivilege(); privilege3.setPrivilegeScope("TABLE"); privilege3.setServerName("server1"); privilege3.setDbName("db1"); privilege3.setTableName("tbl1"); privilege3.setAction("REFRESH"); privilege3.setCreateTime(System.currentTimeMillis()); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName1, Sets.newHashSet(privilege1), null); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName1, Sets.newHashSet(privilege2), null); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName1, Sets.newHashSet(privilege3), null); PermissionsImage permImage = sentryStore.retrieveFullPermssionsImage(); Map<String, Map<TPrivilegePrincipal, String>> privs = permImage.getPrivilegeImage(); assertEquals(1, privs.get("db1.tbl1").size()); assertEquals("REFRESH,INSERT,SELECT", privs.get("db1.tbl1").get(new TPrivilegePrincipal(TPrivilegePrincipalType.ROLE, roleName1))); } /** * Verifies complete snapshot of HMS Paths can be persisted and retrieved properly. */ @Test public void testPersistFullPathsImage() throws Exception { Map<String, Collection<String>> authzPaths = new HashMap<>(); String[] prefixes = { "/user/hive/warehouse" }; // Makes sure that authorizable object could be associated // with different paths and can be properly persisted into database. authzPaths.put("db1.table1", Sets.newHashSet("/user/hive/warehouse/db2.db/table1.1", "/user/hive/warehouse/db2.db/table1.2")); // Makes sure that the same MPaths object could be associated // with multiple authorizable and can be properly persisted into database. authzPaths.put("db1.table2", Sets.newHashSet("/user/hive/warehouse/db2.db/table2.1", "/user/hive/warehouse/db2.db/table2.2")); authzPaths.put("db2.table2", Sets.newHashSet("/user/hive/warehouse/db2.db/table2.1", "/user/hive/warehouse/db2.db/table2.3")); long notificationID = 11; sentryStore.persistFullPathsImage(authzPaths, notificationID); PathsUpdate pathsUpdate = sentryStore.retrieveFullPathsImageUpdate(prefixes); long savedNotificationID = sentryStore.getLastProcessedNotificationID(); assertEquals(1, pathsUpdate.getImgNum()); TPathsDump pathDump = pathsUpdate.toThrift().getPathsDump(); Map<Integer, TPathEntry> nodeMap = pathDump.getNodeMap(); assertEquals(10, nodeMap.size()); //First element is "/" int rootId = pathDump.getRootId(); TPathEntry root = nodeMap.get(rootId); assertEquals("/", root.getPathElement()); Map<String, Collection<String>> pathImage = new HashMap<>(); buildPathsImageMap(nodeMap, root, "", pathImage, true); assertEquals(3, pathImage.size()); for (Map.Entry<String, Collection<String>> entry : pathImage.entrySet()) { assertEquals(2, entry.getValue().size()); } assertEquals(2, pathImage.get("db2.table2").size()); assertTrue(CollectionUtils.isEqualCollection( Lists.newArrayList("/user/hive/warehouse/db2.db/table1.1", "/user/hive/warehouse/db2.db/table1.2"), pathImage.get("db1.table1"))); assertTrue(CollectionUtils.isEqualCollection( Lists.newArrayList("/user/hive/warehouse/db2.db/table2.1", "/user/hive/warehouse/db2.db/table2.2"), pathImage.get("db1.table2"))); assertTrue(CollectionUtils.isEqualCollection( Lists.newArrayList("/user/hive/warehouse/db2.db/table2.1", "/user/hive/warehouse/db2.db/table2.3"), pathImage.get("db2.table2"))); assertEquals(6, sentryStore.getPathCount()); assertEquals(notificationID, savedNotificationID); } @Test public void testAddAuthzPathsMapping() throws Exception { Set<MPath> paths; // Persist an empty image so that we can add paths to it. sentryStore.persistFullPathsImage(new HashMap<String, Collection<String>>(), 0); // Check the latest persisted ID matches to both the path updates long latestID = sentryStore.getCurrentAuthzPathsSnapshotID(); // Persist the path sentryStore.addAuthzPathsMapping("db1.tb1", Arrays.asList("/hive/db1/tb1"), null); paths = sentryStore.getMAuthzPaths(latestID, "db1.tb1"); // Verify that mapping is been added assertEquals(paths.size(), 1); assertTrue(paths.stream().anyMatch(x -> x.getPath().equalsIgnoreCase("/hive/db1/tb1"))); // Add new path to an existing mapping sentryStore.addAuthzPathsMapping("db1.tb1", Arrays.asList("/hive/db1/tb1/par1"), null); paths = sentryStore.getMAuthzPaths(latestID, "db1.tb1"); // Verify that mapping is been updated with the new path assertEquals(paths.size(), 2); assertTrue(paths.stream().anyMatch(x -> x.getPath().equalsIgnoreCase("/hive/db1/tb1/par1"))); // Add multiples path to an existing mapping sentryStore.addAuthzPathsMapping("db1.tb1", Arrays.asList("/hive/db1/tb1/par2", "/hive/db1/tb1/par3"), null); paths = sentryStore.getMAuthzPaths(latestID, "db1.tb1"); // Verify that mapping is been updated with the new path assertEquals(paths.size(), 4); assertTrue(paths.stream().anyMatch(x -> x.getPath().equalsIgnoreCase("/hive/db1/tb1/par2"))); assertTrue(paths.stream().anyMatch(x -> x.getPath().equalsIgnoreCase("/hive/db1/tb1/par3"))); //Add null paths to an existing mapping and verify that there are no exceptions try { sentryStore.addAuthzPathsMapping("db1.tb1", null, null); } catch (Exception e) { fail("Exception occurred while adding mapping with null paths"); } //Add new mapping with null paths and verify that there are no exceptions try { sentryStore.addAuthzPathsMapping("db1.tb5", null, null); } catch (Exception e) { fail("Exception occurred while adding mapping with null paths"); } //Add empty paths collection to existing mapping verify that there are no exceptions try { sentryStore.addAuthzPathsMapping("db1.tb6", Collections.EMPTY_SET, null); } catch (Exception e) { fail("Exception occurred while adding mapping with empty path collection"); } //Add new mapping with empty paths collection and verify that there are no exceptions try { sentryStore.addAuthzPathsMapping("db1.tb1", Collections.EMPTY_SET, null); } catch (Exception e) { fail("Exception occurred while adding mapping with empty path collection"); } } @Test public void testAddPathsWithDuplicatedNotificationIdShouldBeAllowed() throws Exception { long notificationID = 1; // Persist an empty image so that we can add paths to it. sentryStore.persistFullPathsImage(new HashMap<String, Collection<String>>(), 0); // Create two path updates with the same sequence ID UniquePathsUpdate update1 = new UniquePathsUpdate("u1", notificationID, false); UniquePathsUpdate update2 = new UniquePathsUpdate("u2", notificationID, false); // Populate the path updates with different objects and paths update1.newPathChange("db1").addToAddPaths(Arrays.asList("/hive/db1")); update2.newPathChange("db2").addToAddPaths(Arrays.asList("/hive/db2")); // Persist both path updates. Persisting should be allowed, and paths should be // persisted even if they have the same sequence ID sentryStore.addAuthzPathsMapping("db1", Arrays.asList("/hive/db1"), update1); sentryStore.addAuthzPathsMapping("db2", Arrays.asList("/hive/db2"), update2); // Check the latest persisted ID matches to both the path updates long latestID = sentryStore.getLastProcessedNotificationID(); assertEquals(notificationID, latestID); String[] prefixes = { "/hive" }; PathsUpdate pathsUpdate = sentryStore.retrieveFullPathsImageUpdate(prefixes); TPathsDump pathDump = pathsUpdate.toThrift().getPathsDump(); Map<Integer, TPathEntry> nodeMap = pathDump.getNodeMap(); assertEquals(4, nodeMap.size()); int rootId = pathDump.getRootId(); TPathEntry root = nodeMap.get(rootId); assertEquals("/", root.getPathElement()); Map<String, Collection<String>> pathsImage = new HashMap<>(); buildPathsImageMap(nodeMap, root, "", pathsImage, true); // Check that retrieving a full paths image returns both paths updates assertEquals(2, pathsImage.size()); assertEquals(1, pathsImage.get("db1").size()); assertTrue(pathsImage.get("db1").contains("/hive/db1")); assertEquals(1, pathsImage.get("db2").size()); assertTrue(pathsImage.get("db2").contains("/hive/db2")); // Check that retrieving delta changes returns both patch updates List<MSentryPathChange> pathsChanges = sentryStore.getMSentryPathChanges(); assertEquals(2, pathsChanges.size()); assertEquals(1, pathsChanges.get(0).getChangeID()); // changeID = 1 assertTrue(pathsChanges.get(0).getPathChange().contains("/hive/db1")); assertEquals(2, pathsChanges.get(1).getChangeID()); // changeID = 2 assertTrue(pathsChanges.get(1).getPathChange().contains("/hive/db2")); // Check that the SHA1 hash calculated for unique notifications is correct assertEquals("u1", pathsChanges.get(0).getNotificationHash()); assertEquals("u2", pathsChanges.get(1).getNotificationHash()); } private void buildPathsImageMap(Map<Integer, TPathEntry> nodeMap, TPathEntry node, String path, Map<String, Collection<String>> pathsImage, boolean includeLeadingSlash) { path = path.isEmpty() ? node.getPathElement() : (path + node.getPathElement() + "/"); TPathEntry tempNode = node; for (int childVal : node.getChildren()) { node = nodeMap.get(childVal); buildPathsImageMap(nodeMap, node, path, pathsImage, includeLeadingSlash); } if (tempNode.getChildren().isEmpty() && node.getAuthzObjs() != null) { for (String authz : node.getAuthzObjs()) { if (!pathsImage.containsKey(authz)) { pathsImage.put(authz, new LinkedList<>()); } if (includeLeadingSlash) { pathsImage.get(authz).add(path.replaceAll("(/+$)", "")); } else { pathsImage.get(authz).add(path.replaceAll("(^/+)|(/+$)", "")); } } } } @Test public void testPersistDuplicatedNotificationIdShouldBeAllowed() throws Exception { long notificationID = 1; // Persist the same ID twice should not cause any issues sentryStore.persistLastProcessedNotificationID(notificationID); sentryStore.persistLastProcessedNotificationID(notificationID); // Retrieving latest peristed ID should match with the previous persisted ID long latestID = sentryStore.getLastProcessedNotificationID(); assertEquals(notificationID, latestID); } @Test public void testAddDeleteAuthzPathsMapping() throws Exception { long notificationID = 0; // Persist an empty image so that we can add paths to it. sentryStore.persistFullPathsImage(new HashMap<String, Collection<String>>(), notificationID); // Add "db1.table1" authzObj Long lastNotificationId = sentryStore.getLastProcessedNotificationID(); UniquePathsUpdate addUpdate = new UniquePathsUpdate("u1", 1, false); addUpdate.newPathChange("db1.table").addToAddPaths(Arrays.asList("db1", "tbl1")); addUpdate.newPathChange("db1.table").addToAddPaths(Arrays.asList("db1", "tbl2")); sentryStore.addAuthzPathsMapping("db1.table", Sets.newHashSet("db1/tbl1", "db1/tbl2"), addUpdate); String[] prefixes = { "/" }; PathsUpdate pathsUpdate = sentryStore.retrieveFullPathsImageUpdate(prefixes); TPathsDump pathsDump = pathsUpdate.toThrift().getPathsDump(); Map<Integer, TPathEntry> nodeMap = pathsDump.getNodeMap(); TPathEntry root = nodeMap.get(pathsDump.getRootId()); Map<String, Collection<String>> pathImage = new HashMap<>(); buildPathsImageMap(nodeMap, root, "", pathImage, false); assertEquals(4, nodeMap.size());//Tree size assertEquals("/", root.getPathElement()); assertEquals(1, pathImage.size()); assertEquals(2, pathImage.get("db1.table").size()); assertEquals(2, sentryStore.getMPaths().size()); // Query the persisted path change and ensure it equals to the original one long lastChangeID = sentryStore.getLastProcessedPathChangeID(); MSentryPathChange addPathChange = sentryStore.getMSentryPathChangeByID(lastChangeID); assertEquals(addUpdate.JSONSerialize(), addPathChange.getPathChange()); lastNotificationId = sentryStore.getLastProcessedNotificationID(); assertEquals(1, lastNotificationId.longValue()); // Delete path 'db1.db/tbl1' from "db1.table1" authzObj. UniquePathsUpdate delUpdate = new UniquePathsUpdate("u2", 2, false); delUpdate.newPathChange("db1.table").addToDelPaths(Arrays.asList("db1", "tbl1")); sentryStore.deleteAuthzPathsMapping("db1.table", Sets.newHashSet("db1/tbl1"), delUpdate); pathsUpdate = sentryStore.retrieveFullPathsImageUpdate(prefixes); pathsDump = pathsUpdate.toThrift().getPathsDump(); nodeMap = pathsDump.getNodeMap(); root = nodeMap.get(pathsDump.getRootId()); pathImage = new HashMap<>(); buildPathsImageMap(nodeMap, root, "", pathImage, false); assertEquals("/", root.getPathElement()); assertEquals(3, nodeMap.size());//Tree size assertEquals(1, pathImage.size()); assertEquals(1, pathImage.get("db1.table").size()); assertEquals(1, sentryStore.getMPaths().size()); // Query the persisted path change and ensure it equals to the original one lastChangeID = sentryStore.getLastProcessedPathChangeID(); MSentryPathChange delPathChange = sentryStore.getMSentryPathChangeByID(lastChangeID); assertEquals(delUpdate.JSONSerialize(), delPathChange.getPathChange()); lastNotificationId = sentryStore.getLastProcessedNotificationID(); assertEquals(2, lastNotificationId.longValue()); // Delete "db1.table" authzObj from the authzObj -> [Paths] mapping. UniquePathsUpdate delAllupdate = new UniquePathsUpdate("u3", 3, false); delAllupdate.newPathChange("db1.table").addToDelPaths(Lists.newArrayList(PathsUpdate.ALL_PATHS)); sentryStore.deleteAllAuthzPathsMapping("db1.table", delAllupdate); pathsUpdate = sentryStore.retrieveFullPathsImageUpdate(prefixes); pathsDump = pathsUpdate.toThrift().getPathsDump(); nodeMap = pathsDump.getNodeMap(); root = nodeMap.get(pathsDump.getRootId()); pathImage = new HashMap<>(); buildPathsImageMap(nodeMap, root, "", pathImage, false); assertEquals("/", root.getPathElement()); assertEquals(1, nodeMap.size());//Tree size assertEquals(0, pathImage.size()); assertEquals(0, sentryStore.getMPaths().size()); assertEquals(0, sentryStore.getCount(MPath.class).intValue()); // Query the persisted path change and ensure it equals to the original one lastChangeID = sentryStore.getLastProcessedPathChangeID(); MSentryPathChange delAllPathChange = sentryStore.getMSentryPathChangeByID(lastChangeID); assertEquals(delAllupdate.JSONSerialize(), delAllPathChange.getPathChange()); lastNotificationId = sentryStore.getLastProcessedNotificationID(); assertEquals(3, lastNotificationId.longValue()); } @Test public void testDeleteAuthzPathsMapping() throws Exception { long notificationID = 0; // Persist an empty image so that we can add paths to it. sentryStore.persistFullPathsImage(new HashMap<String, Collection<String>>(), notificationID); // Add a mapping to two paths sentryStore.addAuthzPathsMapping("db1.table", Sets.newHashSet("db1/tbl1", "db1/tbl2"), null); // Verify the Path count assertEquals(2, sentryStore.getCount(MPath.class).intValue()); // Add a mapping to three paths sentryStore.addAuthzPathsMapping("db2.table", Sets.newHashSet("db2/tbl1", "db2/tbl2", "db2/tbl3"), null); // Verify the Path count assertEquals(5, sentryStore.getCount(MPath.class).intValue()); // deleting the mapping and verifying the MPath count sentryStore.deleteAllAuthzPathsMapping("db1.table", null); // Verify the Path count assertEquals(3, sentryStore.getCount(MPath.class).intValue()); // deleting the mapping and verifying the MPath count sentryStore.deleteAllAuthzPathsMapping("db2.table", null); // Verify the Path count assertEquals(0, sentryStore.getCount(MPath.class).intValue()); // Add a mapping to two paths sentryStore.addAuthzPathsMapping("db1.table", Sets.newHashSet("db1/tbl1", "db1/tbl2"), null); // deleting the mapping with paths as null and verifying that all the paths are deleted. sentryStore.deleteAuthzPathsMapping("db1.table", null, null); // Verify the Path count assertEquals(0, sentryStore.getCount(MPath.class).intValue()); // Add a mapping to two paths sentryStore.addAuthzPathsMapping("db1.table", Sets.newHashSet("db1/tbl1", "db1/tbl2"), null); // deleting the mapping with paths as empty set and verifying that all the paths are deleted. sentryStore.deleteAuthzPathsMapping("db1.table", Collections.EMPTY_SET, null); // Verify the Path count assertEquals(0, sentryStore.getCount(MPath.class).intValue()); } @Test public void testRenameUpdateAuthzPathsMapping() throws Exception { Map<String, Collection<String>> authzPaths = new HashMap<>(); Long lastNotificationId = sentryStore.getLastProcessedNotificationID(); authzPaths.put("db1.table1", Sets.newHashSet("user/hive/warehouse/db1.db/table1", "user/hive/warehouse/db1.db/table1/p1")); authzPaths.put("db1.table2", Sets.newHashSet("user/hive/warehouse/db1.db/table2")); sentryStore.persistFullPathsImage(authzPaths, lastNotificationId); String[] prefixes = { "/user/hive/warehouse" }; PathsUpdate pathsUpdate = sentryStore.retrieveFullPathsImageUpdate(prefixes); TPathsDump pathsDump = pathsUpdate.toThrift().getPathsDump(); Map<Integer, TPathEntry> nodeMap = pathsDump.getNodeMap(); TPathEntry root = nodeMap.get(pathsDump.getRootId()); Map<String, Collection<String>> pathsImage = new HashMap<>(); buildPathsImageMap(nodeMap, root, "", pathsImage, false); assertEquals("/", root.getPathElement()); assertEquals(8, nodeMap.size());//Tree size assertEquals(2, pathsImage.size()); // Rename path of 'db1.table1' from 'db1.table1' to 'db1.newTable1' UniquePathsUpdate renameUpdate = new UniquePathsUpdate("u1", 1, false); renameUpdate.newPathChange("db1.table1") .addToDelPaths(Arrays.asList("user", "hive", "warehouse", "db1.db", "table1")); renameUpdate.newPathChange("db1.newTable1") .addToAddPaths(Arrays.asList("user", "hive", "warehouse", "db1.db", "newTable1")); sentryStore.renameAuthzPathsMapping("db1.table1", "db1.newTable1", "user/hive/warehouse/db1.db/table1", "user/hive/warehouse/db1.db/newTable1", renameUpdate); pathsUpdate = sentryStore.retrieveFullPathsImageUpdate(prefixes); pathsDump = pathsUpdate.toThrift().getPathsDump(); nodeMap = pathsDump.getNodeMap(); root = nodeMap.get(pathsDump.getRootId()); pathsImage = new HashMap<>(); buildPathsImageMap(nodeMap, root, "", pathsImage, false); assertEquals("/", root.getPathElement()); assertEquals(9, nodeMap.size());//Tree size assertEquals(2, pathsImage.size()); assertEquals(3, sentryStore.getMPaths().size()); assertTrue(pathsImage.containsKey("db1.newTable1")); assertTrue(CollectionUtils.isEqualCollection( Lists.newArrayList("user/hive/warehouse/db1.db/table1/p1", "user/hive/warehouse/db1.db/newTable1"), pathsImage.get("db1.newTable1"))); // Query the persisted path change and ensure it equals to the original one long lastChangeID = sentryStore.getLastProcessedPathChangeID(); MSentryPathChange renamePathChange = sentryStore.getMSentryPathChangeByID(lastChangeID); assertEquals(renameUpdate.JSONSerialize(), renamePathChange.getPathChange()); lastNotificationId = sentryStore.getLastProcessedNotificationID(); assertEquals(1, lastNotificationId.longValue()); // Rename 'db1.table1' to "db1.table2" but did not change its location. renameUpdate = new UniquePathsUpdate("u2", 2, false); renameUpdate.newPathChange("db1.newTable1") .addToDelPaths(Arrays.asList("user", "hive", "warehouse", "db1.db", "newTable1")); renameUpdate.newPathChange("db1.newTable2") .addToAddPaths(Arrays.asList("user", "hive", "warehouse", "db1.db", "newTable1")); sentryStore.renameAuthzObj("db1.newTable1", "db1.newTable2", renameUpdate); pathsUpdate = sentryStore.retrieveFullPathsImageUpdate(prefixes); pathsDump = pathsUpdate.toThrift().getPathsDump(); nodeMap = pathsDump.getNodeMap(); root = nodeMap.get(pathsDump.getRootId()); pathsImage = new HashMap<>(); buildPathsImageMap(nodeMap, root, "", pathsImage, false); assertEquals("/", root.getPathElement()); assertEquals(9, nodeMap.size());//Tree size assertEquals(2, pathsImage.size()); assertEquals(3, sentryStore.getMPaths().size()); assertTrue(pathsImage.containsKey("db1.newTable2")); assertTrue(CollectionUtils.isEqualCollection( Lists.newArrayList("user/hive/warehouse/db1.db/table1/p1", "user/hive/warehouse/db1.db/newTable1"), pathsImage.get("db1.newTable2"))); lastNotificationId = sentryStore.getLastProcessedNotificationID(); assertEquals(2, lastNotificationId.longValue()); // Query the persisted path change and ensure it equals to the original one lastChangeID = sentryStore.getLastProcessedPathChangeID(); renamePathChange = sentryStore.getMSentryPathChangeByID(lastChangeID); assertEquals(renameUpdate.JSONSerialize(), renamePathChange.getPathChange()); // Update path of 'db1.newTable2' from 'db1.newTable1' to 'db1.newTable2' UniquePathsUpdate update = new UniquePathsUpdate("u3", 3, false); update.newPathChange("db1.newTable1") .addToDelPaths(Arrays.asList("user", "hive", "warehouse", "db1.db", "newTable1")); update.newPathChange("db1.newTable1") .addToAddPaths(Arrays.asList("user", "hive", "warehouse", "db1.db", "newTable2")); sentryStore.updateAuthzPathsMapping("db1.newTable2", "user/hive/warehouse/db1.db/newTable1", "user/hive/warehouse/db1.db/newTable2", update); pathsUpdate = sentryStore.retrieveFullPathsImageUpdate(prefixes); pathsDump = pathsUpdate.toThrift().getPathsDump(); nodeMap = pathsDump.getNodeMap(); root = nodeMap.get(pathsDump.getRootId()); pathsImage = new HashMap<>(); buildPathsImageMap(nodeMap, root, "", pathsImage, false); assertEquals("/", root.getPathElement()); assertEquals(9, nodeMap.size());//Tree size assertEquals(2, pathsImage.size()); assertEquals(3, sentryStore.getMPaths().size()); assertTrue(pathsImage.containsKey("db1.newTable2")); assertTrue(CollectionUtils.isEqualCollection( Lists.newArrayList("user/hive/warehouse/db1.db/table1/p1", "user/hive/warehouse/db1.db/newTable2"), pathsImage.get("db1.newTable2"))); // Query the persisted path change and ensure it equals to the original one lastChangeID = sentryStore.getLastProcessedPathChangeID(); MSentryPathChange updatePathChange = sentryStore.getMSentryPathChangeByID(lastChangeID); assertEquals(update.JSONSerialize(), updatePathChange.getPathChange()); lastNotificationId = sentryStore.getLastProcessedNotificationID(); assertEquals(3, lastNotificationId.longValue()); } @Test public void testPersistAndReplaceANewPathsImage() throws Exception { Map<String, Collection<String>> authzPaths = new HashMap<>(); long notificationID = 1; // First image to persist (this will be replaced later) authzPaths.put("db1.table1", Sets.newHashSet("/user/hive/warehouse/db2.db/table1.1", "/user/hive/warehouse/db2.db/table1.2")); authzPaths.put("db1.table2", Sets.newHashSet("/user/hive/warehouse/db2.db/table2.1", "/user/hive/warehouse/db2.db/table2.2")); sentryStore.persistFullPathsImage(authzPaths, notificationID); String[] prefixes = { "/user/hive/warehouse" }; PathsUpdate pathsUpdate = sentryStore.retrieveFullPathsImageUpdate(prefixes); TPathsDump pathsDump = pathsUpdate.toThrift().getPathsDump(); Map<Integer, TPathEntry> nodeMap = pathsDump.getNodeMap(); TPathEntry root = nodeMap.get(pathsDump.getRootId()); Map<String, Collection<String>> pathImage = new HashMap<>(); buildPathsImageMap(nodeMap, root, "", pathImage, true); assertEquals("/", root.getPathElement()); assertEquals(9, nodeMap.size());//Tree size assertEquals(1, pathsUpdate.getImgNum()); // Second image to persist (it should replace first image) authzPaths.clear(); authzPaths.put("db3.table1", Sets.newHashSet("/another-warehouse/db2.db/table1.1", "/another-warehouse/db2.db/table1.2")); authzPaths.put("db3.table2", Sets.newHashSet("/another-warehouse/db2.db/table2.1", "/another-warehouse/db2.db/table2.2")); authzPaths.put("db4.table2", Sets.newHashSet("/another-warehouse/db2.db/table2.1", "/another-warehouse/db2.db/table2.3")); sentryStore.persistFullPathsImage(authzPaths, notificationID + 1); prefixes = new String[] { "/another-warehouse" }; pathsUpdate = sentryStore.retrieveFullPathsImageUpdate(prefixes); pathsDump = pathsUpdate.toThrift().getPathsDump(); nodeMap = pathsDump.getNodeMap(); root = nodeMap.get(pathsDump.getRootId()); pathImage = new HashMap<>(); buildPathsImageMap(nodeMap, root, "", pathImage, true); assertEquals("/", root.getPathElement()); assertEquals(8, nodeMap.size());//Tree size assertEquals(2, pathsUpdate.getImgNum()); assertEquals(3, pathImage.size()); for (Map.Entry<String, Collection<String>> entry : pathImage.entrySet()) { assertEquals(2, entry.getValue().size()); } assertEquals(2, pathImage.get("db4.table2").size()); assertTrue(CollectionUtils.isEqualCollection( Lists.newArrayList("/another-warehouse/db2.db/table1.1", "/another-warehouse/db2.db/table1.2"), pathImage.get("db3.table1"))); assertTrue(CollectionUtils.isEqualCollection( Lists.newArrayList("/another-warehouse/db2.db/table2.1", "/another-warehouse/db2.db/table2.2"), pathImage.get("db3.table2"))); assertTrue(CollectionUtils.isEqualCollection( Lists.newArrayList("/another-warehouse/db2.db/table2.1", "/another-warehouse/db2.db/table2.3"), pathImage.get("db4.table2"))); assertEquals(6, sentryStore.getMPaths().size()); } @Test public void testAddDeleteAfterReplacingANewPathsImage() throws Exception { long notificationID = 1; // Add some paths first (these should be replaced) UniquePathsUpdate addUpdate = new UniquePathsUpdate("u1", notificationID, false); addUpdate.newPathChange("db1.table").addToAddPaths(Arrays.asList("db1", "tbl1")); addUpdate.newPathChange("db1.table").addToAddPaths(Arrays.asList("db1", "tbl2")); sentryStore.addAuthzPathsMapping("db1.table", Sets.newHashSet("db1/tbl1", "db1/tbl2"), addUpdate); // Persist a new image that contains a new image ID (it replaces previous paths) notificationID++; Map<String, Collection<String>> authzPaths = new HashMap<>(); authzPaths.put("db2.table3", Sets.newHashSet("/user/hive/warehouse/db2.db/table1.1", "/user/hive/warehouse/db2.db/table1.2")); sentryStore.persistFullPathsImage(authzPaths, notificationID); // Add new paths notificationID++; UniquePathsUpdate newAddUpdate = new UniquePathsUpdate("u2", notificationID, false); newAddUpdate.newPathChange("db2.table").addToAddPaths(Arrays.asList("db2", "tbl1")); newAddUpdate.newPathChange("db2.table").addToAddPaths(Arrays.asList("db2", "tbl2")); sentryStore.addAuthzPathsMapping("db2.table", Sets.newHashSet("db2/tbl1", "db2/tbl2"), newAddUpdate); String[] prefixes = { "/" }; PathsUpdate pathsUpdate = sentryStore.retrieveFullPathsImageUpdate(prefixes); TPathsDump pathsDump = pathsUpdate.toThrift().getPathsDump(); Map<Integer, TPathEntry> nodeMap = pathsDump.getNodeMap(); TPathEntry root = nodeMap.get(pathsDump.getRootId()); Map<String, Collection<String>> pathImage = new HashMap<>(); buildPathsImageMap(nodeMap, root, "", pathImage, false); assertEquals("/", root.getPathElement()); assertEquals(10, nodeMap.size());//Tree size assertEquals(2, pathImage.size()); assertEquals(2, pathImage.get("db2.table").size()); assertEquals(4, sentryStore.getMPaths().size()); // Delete one path notificationID++; UniquePathsUpdate delUpdate = new UniquePathsUpdate("u3", notificationID, false); delUpdate.newPathChange("db2.table").addToDelPaths(Arrays.asList("db2", "tbl1")); sentryStore.deleteAuthzPathsMapping("db2.table", Sets.newHashSet("db2/tbl1"), delUpdate); pathsUpdate = sentryStore.retrieveFullPathsImageUpdate(prefixes); pathsDump = pathsUpdate.toThrift().getPathsDump(); nodeMap = pathsDump.getNodeMap(); root = nodeMap.get(pathsDump.getRootId()); pathImage = new HashMap<>(); buildPathsImageMap(nodeMap, root, "", pathImage, false); assertEquals("/", root.getPathElement()); assertEquals(9, nodeMap.size());//Tree size assertEquals(2, pathImage.size()); assertEquals(1, pathImage.get("db2.table").size()); assertEquals(3, sentryStore.getMPaths().size()); Long lastNotificationId = sentryStore.getLastProcessedNotificationID(); assertEquals(notificationID, lastNotificationId.longValue()); } @Test public void testRenameUpdateAfterReplacingANewPathsImage() throws Exception { long notificationID = 1; Map<String, Collection<String>> authzPaths = new HashMap<>(); // First image to persist (this will be replaced later) authzPaths.put("db1.table1", Sets.newHashSet("/user/hive/warehouse/db2.db/table1.1", "/user/hive/warehouse/db2.db/table1.2")); authzPaths.put("db1.table2", Sets.newHashSet("/user/hive/warehouse/db2.db/table2.1", "/user/hive/warehouse/db2.db/table2.2")); sentryStore.persistFullPathsImage(authzPaths, notificationID); // Second image to persist (it should replace first image) notificationID++; authzPaths.clear(); authzPaths.put("db3.table1", Sets.newHashSet("/another-warehouse/db3.db/table1.1", "/another-warehouse/db3.db/table1.2")); authzPaths.put("db3.table2", Sets.newHashSet("/another-warehouse/db3.db/table2.1", "/another-warehouse/db3.db/table2.2")); sentryStore.persistFullPathsImage(authzPaths, notificationID); // Rename path of 'db1.table1' from 'db1.table1' to 'db1.newTable1' notificationID++; UniquePathsUpdate renameUpdate = new UniquePathsUpdate("u1", notificationID, false); renameUpdate.newPathChange("db3.table1") .addToDelPaths(Arrays.asList("another-warehouse", "db3.db", "table1.1")); renameUpdate.newPathChange("db1.newTable1") .addToAddPaths(Arrays.asList("user", "hive", "warehouse", "db1.db", "newTable1")); sentryStore.renameAuthzPathsMapping("db3.table1", "db1.newTable1", "/another-warehouse/db3.db/table1.1", "user/hive/warehouse/db1.db/newTable1", renameUpdate); String[] prefixes = { "/" }; PathsUpdate pathsUpdate = sentryStore.retrieveFullPathsImageUpdate(prefixes); TPathsDump pathsDump = pathsUpdate.toThrift().getPathsDump(); Map<Integer, TPathEntry> nodeMap = pathsDump.getNodeMap(); TPathEntry root = nodeMap.get(pathsDump.getRootId()); Map<String, Collection<String>> pathsImage = new HashMap<>(); buildPathsImageMap(nodeMap, root, "", pathsImage, true); assertEquals("/", root.getPathElement()); assertEquals(11, nodeMap.size());//Tree size assertEquals(2, pathsImage.size()); assertEquals(4, sentryStore.getMPaths().size()); assertTrue(pathsImage.containsKey("db1.newTable1")); assertTrue(CollectionUtils.isEqualCollection( Lists.newArrayList("/another-warehouse/db3.db/table1.2", "/user/hive/warehouse/db1.db/newTable1"), pathsImage.get("db1.newTable1"))); // Update path of 'db1.newTable2' from 'db1.newTable1' to 'db1.newTable2' notificationID++; UniquePathsUpdate update = new UniquePathsUpdate("u2", notificationID, false); update.newPathChange("db1.newTable1") .addToDelPaths(Arrays.asList("user", "hive", "warehouse", "db1.db", "newTable1")); update.newPathChange("db1.newTable1") .addToAddPaths(Arrays.asList("user", "hive", "warehouse", "db1.db", "newTable2")); sentryStore.updateAuthzPathsMapping("db1.newTable2", "user/hive/warehouse/db1.db/newTable1", "user/hive/warehouse/db1.db/newTable2", update); pathsUpdate = sentryStore.retrieveFullPathsImageUpdate(prefixes); pathsDump = pathsUpdate.toThrift().getPathsDump(); nodeMap = pathsDump.getNodeMap(); root = nodeMap.get(pathsDump.getRootId()); pathsImage = new HashMap<>(); buildPathsImageMap(nodeMap, root, "", pathsImage, false); assertEquals("/", root.getPathElement()); assertEquals(12, nodeMap.size());//Tree size assertEquals(3, pathsImage.size()); assertEquals(5, sentryStore.getMPaths().size()); assertTrue(pathsImage.containsKey("db1.newTable2")); assertEquals(Lists.newArrayList("user/hive/warehouse/db1.db/newTable2"), pathsImage.get("db1.newTable2")); } @Test public void testQueryParamBuilder() { QueryParamBuilder paramBuilder; paramBuilder = newQueryParamBuilder(); // Try single parameter paramBuilder.add("key", "val"); assertEquals("(this.key == :key)", paramBuilder.toString()); // Try adding second parameter plus add trimming and conversion // to lower case paramBuilder.add("key1", " Val1 ", true); assertEquals("(this.key == :key && this.key1 == :key1)", paramBuilder.toString()); Map<String, Object> params = paramBuilder.getArguments(); assertEquals("val", params.get("key")); assertEquals("Val1", params.get("key1")); paramBuilder = newQueryParamBuilder(QueryParamBuilder.Op.OR); paramBuilder.add("key", " Val ", true); paramBuilder.addNotNull("notNullField"); paramBuilder.addNull("nullField"); assertEquals("(this.key == :key || this.notNullField != \"__NULL__\" || this.nullField == \"__NULL__\")", paramBuilder.toString()); params = paramBuilder.getArguments(); assertEquals("Val", params.get("key")); paramBuilder = newQueryParamBuilder().addNull("var1").addNotNull("var2"); assertEquals("(this.var1 == \"__NULL__\" && this.var2 != \"__NULL__\")", paramBuilder.toString()); // Test newChild() paramBuilder = newQueryParamBuilder(); paramBuilder.addString("e1").addString("e2").newChild().add("v3", "e3").add("v4", "e4").newChild() .addString("e5").addString("e6"); assertEquals("(e1 && e2 && (this.v3 == :v3 || this.v4 == :v4 || (e5 && e6)))", paramBuilder.toString()); paramBuilder = newQueryParamBuilder(); paramBuilder.addString("e1").addString("e2").newChild().add("v3", "e3").add("v4", "e4").newChild() .addString("e5").addString("e6"); params = paramBuilder.getArguments(); assertEquals("e3", params.get("v3")); assertEquals("e4", params.get("v4")); // Test addSet paramBuilder = newQueryParamBuilder(); Set<String> names = new HashSet<>(); names.add("foo"); names.add("bar"); names.add("bob"); paramBuilder.addSet("prefix == ", names, true); assertEquals("(prefix == :var0 && prefix == :var1 && prefix == :var2)", paramBuilder.toString()); params = paramBuilder.getArguments(); Set<String> result = new HashSet<>(); result.add((String) params.get("var0")); result.add((String) params.get("var1")); result.add((String) params.get("var2")); assertTrue(result.containsAll(names)); assertTrue(names.containsAll(result)); } @Test public void testPrivilegesWithPermUpdate() throws Exception { String roleName = "test-privilege"; String server = "server1"; String db = "db1"; String table = "tbl1"; String authzObj = "db1.tbl1"; createRole(roleName); TSentryPrivilege privilege = new TSentryPrivilege(); privilege.setPrivilegeScope("Column"); privilege.setServerName(server); privilege.setDbName(db); privilege.setTableName(table); privilege.setAction(AccessConstants.SELECT); privilege.setCreateTime(System.currentTimeMillis()); // Generate the permission add update authzObj "db1.tbl1" PermissionsUpdate addUpdate = new PermissionsUpdate(0, false); addUpdate.addPrivilegeUpdate(authzObj).putToAddPrivileges( new TPrivilegePrincipal(TPrivilegePrincipalType.ROLE, roleName), privilege.getAction().toUpperCase()); // Grant the privilege to role test-privilege and verify it has been persisted. Map<TSentryPrivilege, Updateable.Update> addPrivilegesUpdateMap = Maps.newHashMap(); addPrivilegesUpdateMap.put(privilege, addUpdate); sentryStore.alterSentryRoleGrantPrivileges(roleName, Sets.newHashSet(privilege), addPrivilegesUpdateMap); MSentryRole role = sentryStore.getMSentryRoleByName(roleName); Set<MSentryPrivilege> privileges = role.getPrivileges(); assertEquals(privileges.toString(), 1, privileges.size()); // Query the persisted perm change and ensure it equals to the original one long lastChangeID = sentryStore.getLastProcessedPermChangeID(); long initialID = lastChangeID; MSentryPermChange addPermChange = sentryStore.getMSentryPermChangeByID(lastChangeID); assertEquals(addUpdate.JSONSerialize(), addPermChange.getPermChange()); // Generate the permission delete update authzObj "db1.tbl1" PermissionsUpdate delUpdate = new PermissionsUpdate(0, false); delUpdate.addPrivilegeUpdate(authzObj).putToDelPrivileges( new TPrivilegePrincipal(TPrivilegePrincipalType.ROLE, roleName), privilege.getAction().toUpperCase()); // Revoke the same privilege and verify it has been removed. Map<TSentryPrivilege, Updateable.Update> delPrivilegesUpdateMap = Maps.newHashMap(); delPrivilegesUpdateMap.put(privilege, delUpdate); sentryStore.alterSentryRoleRevokePrivileges(roleName, Sets.newHashSet(privilege), delPrivilegesUpdateMap); role = sentryStore.getMSentryRoleByName(roleName); privileges = role.getPrivileges(); assertEquals(0, privileges.size()); // Query the persisted perm change and ensure it equals to the original one lastChangeID = sentryStore.getLastProcessedPermChangeID(); MSentryPermChange delPermChange = sentryStore.getMSentryPermChangeByID(lastChangeID); assertEquals(delUpdate.JSONSerialize(), delPermChange.getPermChange()); // Verify getMSentryPermChanges will return all MSentryPermChanges up // to the given changeID. List<MSentryPermChange> mSentryPermChanges = sentryStore.getMSentryPermChanges(initialID); assertEquals(lastChangeID - initialID + 1, mSentryPermChanges.size()); // Verify ifPermChangeExists will return true for persisted MSentryPermChange. assertEquals(true, sentryStore.permChangeExists(1)); } @Test public void testAddDeleteGroupsWithPermUpdate() throws Exception { String roleName = "test-groups"; String grantor = "g1"; createRole(roleName); Set<TSentryGroup> 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); // Generate the permission add update for role "test-groups" PermissionsUpdate addUpdate = new PermissionsUpdate(0, false); TRoleChanges addrUpdate = addUpdate.addRoleUpdate(roleName); for (TSentryGroup g : groups) { addrUpdate.addToAddGroups(g.getGroupName()); } // Assign the role "test-groups" to the groups and verify. sentryStore.alterSentryRoleAddGroups(grantor, roleName, groups, addUpdate); MSentryRole role = sentryStore.getMSentryRoleByName(roleName); assertEquals(2, role.getGroups().size()); // Query the persisted perm change and ensure it equals to the original one long lastChangeID = sentryStore.getLastProcessedPermChangeID(); MSentryPermChange addPermChange = sentryStore.getMSentryPermChangeByID(lastChangeID); assertEquals(addUpdate.JSONSerialize(), addPermChange.getPermChange()); // Generate the permission add update for role "test-groups" PermissionsUpdate delUpdate = new PermissionsUpdate(0, false); TRoleChanges delrUpdate = delUpdate.addRoleUpdate(roleName); for (TSentryGroup g : groups) { delrUpdate.addToDelGroups(g.getGroupName()); } // Revoke the role "test-groups" to the groups and verify. sentryStore.alterSentryRoleDeleteGroups(roleName, groups, delUpdate); role = sentryStore.getMSentryRoleByName(roleName); assertEquals(Collections.emptySet(), role.getGroups()); // Query the persisted perm change and ensure it equals to the original one MSentryPermChange delPermChange = sentryStore.getMSentryPermChangeByID(lastChangeID + 1); assertEquals(delUpdate.JSONSerialize(), delPermChange.getPermChange()); } @Test public void testCreateDropRoleWithPermUpdate() throws Exception { String roleName = "test-drop-role"; createRole(roleName); // Generate the permission del update for dropping role "test-drop-role" PermissionsUpdate delUpdate = new PermissionsUpdate(0, false); delUpdate.addPrivilegeUpdate(PermissionsUpdate.ALL_AUTHZ_OBJ).putToDelPrivileges( new TPrivilegePrincipal(TPrivilegePrincipalType.ROLE, roleName), PermissionsUpdate.ALL_AUTHZ_OBJ); delUpdate.addRoleUpdate(roleName).addToDelGroups(PermissionsUpdate.ALL_GROUPS); // Drop the role and verify. sentryStore.dropSentryRole(roleName, delUpdate); checkRoleDoesNotExist(roleName); // Query the persisted perm change and ensure it equals to the original one long lastChangeID = sentryStore.getLastProcessedPermChangeID(); MSentryPermChange delPermChange = sentryStore.getMSentryPermChangeByID(lastChangeID); assertEquals(delUpdate.JSONSerialize(), delPermChange.getPermChange()); } @Test public void testDropObjWithPermUpdate() throws Exception { String roleName1 = "list-privs-r1", roleName2 = "list-privs-r2"; sentryStore.createSentryRole(roleName1); sentryStore.createSentryRole(roleName2); String authzObj = "db1.tbl1"; 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()); privilege_tbl1.setAction("SELECT"); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName1, Sets.newHashSet(privilege_tbl1), null); // Generate the permission drop update for dropping privilege for "db1.tbl1" PermissionsUpdate dropUpdate = new PermissionsUpdate(0, false); dropUpdate.addPrivilegeUpdate(authzObj).putToDelPrivileges( new TPrivilegePrincipal(TPrivilegePrincipalType.ROLE, PermissionsUpdate.ALL_ROLES), PermissionsUpdate.ALL_ROLES); // Drop the privilege and verify. sentryStore.dropPrivilege(toTSentryAuthorizable(privilege_tbl1), dropUpdate); assertEquals(0, sentryStore.getAllTSentryPrivilegesByRoleName(roleName1).size()); assertEquals(0, sentryStore.getAllTSentryPrivilegesByRoleName(roleName2).size()); // Query the persisted perm change and ensure it equals to the original one long lastChangeID = sentryStore.getLastProcessedPermChangeID(); MSentryPermChange dropPermChange = sentryStore.getMSentryPermChangeByID(lastChangeID); assertEquals(dropUpdate.JSONSerialize(), dropPermChange.getPermChange()); } @Test public void testRenameObjWithPermUpdate() throws Exception { String roleName1 = "role1"; String table1 = "tbl1", table2 = "tbl2"; sentryStore.createSentryRole(roleName1); TSentryPrivilege privilege_tbl1 = new TSentryPrivilege(); privilege_tbl1.setPrivilegeScope("TABLE"); privilege_tbl1.setServerName("server1"); privilege_tbl1.setDbName("db1"); privilege_tbl1.setTableName(table1); privilege_tbl1.setCreateTime(System.currentTimeMillis()); privilege_tbl1.setAction(AccessConstants.ALL); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName1, Sets.newHashSet(privilege_tbl1), null); // Generate the permission rename update for renaming privilege for "db1.tbl1" String oldAuthz = "db1.tbl1"; String newAuthz = "db1.tbl2"; PermissionsUpdate renameUpdate = new PermissionsUpdate(0, false); TPrivilegeChanges privUpdate = renameUpdate.addPrivilegeUpdate(PermissionsUpdate.RENAME_PRIVS); privUpdate.putToAddPrivileges(new TPrivilegePrincipal(TPrivilegePrincipalType.AUTHZ_OBJ, newAuthz), newAuthz); privUpdate.putToDelPrivileges(new TPrivilegePrincipal(TPrivilegePrincipalType.AUTHZ_OBJ, oldAuthz), oldAuthz); // Rename the privilege and verify. TSentryAuthorizable oldTable = toTSentryAuthorizable(privilege_tbl1); TSentryAuthorizable newTable = toTSentryAuthorizable(privilege_tbl1); newTable.setTable(table2); sentryStore.renamePrivilege(oldTable, newTable, renameUpdate); Set<TSentryPrivilege> privilegeSet = sentryStore.getAllTSentryPrivilegesByRoleName(roleName1); assertEquals(1, privilegeSet.size()); for (TSentryPrivilege privilege : privilegeSet) { assertTrue(table2.equalsIgnoreCase(privilege.getTableName())); } // Query the persisted perm change and ensure it equals to the original one long lastChangeID = sentryStore.getLastProcessedPermChangeID(); MSentryPermChange renamePermChange = sentryStore.getMSentryPermChangeByID(lastChangeID); assertEquals(renameUpdate.JSONSerialize(), renamePermChange.getPermChange()); } protected static void addGroupsToUser(String user, String... groupNames) { policyFile.addGroupsToUser(user, groupNames); } protected static void writePolicyFile() throws Exception { policyFile.write(policyFilePath); } @Test public void testPurgeDeltaChanges() throws Exception { String role = "purgeRole"; String table = "purgeTable"; assertEquals(0, sentryStore.getMSentryPermChanges().size()); assertEquals(0, sentryStore.getMSentryPathChanges().size()); sentryStore.createSentryRole(role); int privCleanCount = ServerConfig.SENTRY_DELTA_KEEP_COUNT_DEFAULT; int extraPrivs = 5; final int numPermChanges = extraPrivs + privCleanCount; for (int i = 0; i < numPermChanges; i++) { 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()); PermissionsUpdate update = new PermissionsUpdate(i + 1, false); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, role, Sets.newHashSet(privilege), Lists.newArrayList(update)); } assertEquals(numPermChanges, sentryStore.getMSentryPermChanges().size()); sentryStore.purgeDeltaChangeTables(); assertEquals(privCleanCount, sentryStore.getMSentryPermChanges().size()); // TODO: verify MSentryPathChange being purged. // assertEquals(1, sentryStore.getMSentryPathChanges().size()); } @Test public void testpurgeNotificationIdTable() throws Exception { int totalentires = 200; int remainingEntires = ServerConfig.SENTRY_HMS_NOTIFICATION_ID_KEEP_COUNT_DEFAULT; assertTrue(sentryStore.isHmsNotificationEmpty()); for (int id = 1; id <= totalentires; id++) { sentryStore.persistLastProcessedNotificationID((long) id); } assertEquals(totalentires, sentryStore.getMSentryHmsNotificationCore().size()); sentryStore.purgeNotificationIdTable(); // Make sure that sentry store still hold entries based on SENTRY_HMS_NOTIFICATION_ID_KEEP_COUNT_DEFAULT assertEquals(remainingEntires, sentryStore.getMSentryHmsNotificationCore().size()); sentryStore.purgeNotificationIdTable(); // Make sure that sentry store still hold entries based on SENTRY_HMS_NOTIFICATION_ID_KEEP_COUNT_DEFAULT assertEquals(remainingEntires, sentryStore.getMSentryHmsNotificationCore().size()); sentryStore.clearAllTables(); totalentires = 50; for (int id = 1; id <= totalentires; id++) { sentryStore.persistLastProcessedNotificationID((long) id); } assertEquals(totalentires, sentryStore.getMSentryHmsNotificationCore().size()); sentryStore.purgeNotificationIdTable(); // Make sure that sentry store still holds all the entries as total entries is less than // SENTRY_HMS_NOTIFICATION_ID_KEEP_COUNT_DEFAULT. assertEquals(totalentires, sentryStore.getMSentryHmsNotificationCore().size()); } /** * This test verifies that in the case of concurrently updating delta change tables, no gap * between change ID was made. All the change IDs must be consecutive ({@see SENTRY-1643}). * * @throws Exception */ @Test(timeout = 60000) public void testConcurrentUpdateChanges() throws Exception { final int numThreads = 20; final int numChangesPerThread = 100; final TransactionManager tm = sentryStore.getTransactionManager(); final AtomicLong seqNumGenerator = new AtomicLong(0); final CyclicBarrier barrier = new CyclicBarrier(numThreads); ExecutorService executor = Executors.newFixedThreadPool(numThreads); for (int i = 0; i < numThreads; i++) { executor.submit(new Runnable() { @Override public void run() { try { barrier.await(); } catch (Exception e) { LOGGER.error("Barrier failed to await", e); return; } for (int j = 0; j < numChangesPerThread; j++) { List<TransactionBlock<Object>> tbs = new ArrayList<>(); PermissionsUpdate update = new PermissionsUpdate(seqNumGenerator.getAndIncrement(), false); tbs.add(new DeltaTransactionBlock(update)); try { tm.executeTransactionBlocksWithRetry(tbs); } catch (Exception e) { LOGGER.error("Failed to execute permission update transaction", e); fail(String.format("Transaction failed: %s", e.getMessage())); } } } }); } executor.shutdown(); executor.awaitTermination(60, TimeUnit.SECONDS); List<MSentryPermChange> changes = sentryStore.getMSentryPermChanges(); int actualSize = changes.size(); if (actualSize != (numThreads * numChangesPerThread)) { LOGGER.warn("Detected {} dropped changes", ((numChangesPerThread * numThreads) - actualSize)); } TreeSet<Long> changeIDs = new TreeSet<>(); for (MSentryPermChange change : changes) { changeIDs.add(change.getChangeID()); } assertEquals("duplicated change ID", actualSize, changeIDs.size()); long prevId = changeIDs.first() - 1; for (Long changeId : changeIDs) { assertTrue(String.format("Found non-consecutive number: prev=%d cur=%d", prevId, changeId), changeId - prevId == 1); prevId = changeId; } } @Test public void testDuplicateNotification() throws Exception { Map<String, Collection<String>> authzPaths = new HashMap<>(); Long lastNotificationId = sentryStore.getLastProcessedNotificationID(); lastNotificationId++; authzPaths.put("db1.table1", Sets.newHashSet("user/hive/warehouse/db1.db/table1", "user/hive/warehouse/db1.db/table1/p1")); authzPaths.put("db1.table2", Sets.newHashSet("user/hive/warehouse/db1.db/table2")); sentryStore.persistFullPathsImage(authzPaths, lastNotificationId); String[] prefixes = { "/user/hive/warehouse" }; PathsUpdate pathsUpdate = sentryStore.retrieveFullPathsImageUpdate(prefixes); TPathsDump pathsDump = pathsUpdate.toThrift().getPathsDump(); Map<Integer, TPathEntry> nodeMap = pathsDump.getNodeMap(); TPathEntry root = nodeMap.get(pathsDump.getRootId()); Map<String, Collection<String>> pathsImage = new HashMap<>(); buildPathsImageMap(nodeMap, root, "", pathsImage, false); assertEquals("/", root.getPathElement()); assertEquals(8, nodeMap.size());//Tree size assertEquals(2, pathsImage.size()); if (lastNotificationId == null) { lastNotificationId = SentryConstants.EMPTY_NOTIFICATION_ID; } // Rename path of 'db1.table1' from 'db1.table1' to 'db1.newTable1' lastNotificationId++; UniquePathsUpdate renameUpdate = new UniquePathsUpdate("u1", lastNotificationId, false); renameUpdate.newPathChange("db1.table1") .addToDelPaths(Arrays.asList("user", "hive", "warehouse", "db1.db", "table1")); renameUpdate.newPathChange("db1.newTable1") .addToAddPaths(Arrays.asList("user", "hive", "warehouse", "db1.db", "newTable1")); sentryStore.renameAuthzPathsMapping("db1.table1", "db1.newTable1", "user/hive/warehouse/db1.db/table1", "user/hive/warehouse/db1.db/newTable1", renameUpdate); pathsUpdate = sentryStore.retrieveFullPathsImageUpdate(prefixes); pathsDump = pathsUpdate.toThrift().getPathsDump(); nodeMap = pathsDump.getNodeMap(); root = nodeMap.get(pathsDump.getRootId()); pathsImage = new HashMap<>(); buildPathsImageMap(nodeMap, root, "", pathsImage, false); assertEquals("/", root.getPathElement()); assertEquals(9, nodeMap.size());//Tree size assertEquals(2, pathsImage.size()); assertEquals(3, sentryStore.getMPaths().size()); assertTrue(pathsImage.containsKey("db1.newTable1")); assertTrue(CollectionUtils.isEqualCollection( Lists.newArrayList("user/hive/warehouse/db1.db/table1/p1", "user/hive/warehouse/db1.db/newTable1"), pathsImage.get("db1.newTable1"))); // Query the persisted path change and ensure it equals to the original one long lastChangeID = sentryStore.getLastProcessedPathChangeID(); MSentryPathChange renamePathChange = sentryStore.getMSentryPathChangeByID(lastChangeID); assertEquals(renameUpdate.JSONSerialize(), renamePathChange.getPathChange()); Long savedLastNotificationId = sentryStore.getLastProcessedNotificationID(); assertEquals(lastNotificationId.longValue(), savedLastNotificationId.longValue()); // Process the notificaiton second time try { sentryStore.renameAuthzPathsMapping("db1.table1", "db1.newTable1", "user/hive/warehouse/db1.db/table1", "user/hive/warehouse/db1.db/newTable1", renameUpdate); } catch (Exception e) { if (!(e.getCause() instanceof JDODataStoreException)) { fail("Unexpected failure occured while processing duplicate notification"); } } } @Test public void testIsAuthzPathsMappingEmpty() throws Exception { // Add "db1.table1" authzObj UniquePathsUpdate addUpdate = new UniquePathsUpdate("u1", 1, false); addUpdate.newPathChange("db1.table").addToAddPaths(Arrays.asList("db1", "tbl1")); addUpdate.newPathChange("db1.table").addToAddPaths(Arrays.asList("db1", "tbl2")); // Persist an empty image so that we can add paths to it. sentryStore.persistFullPathsImage(new HashMap<String, Collection<String>>(), 0); assertEquals(sentryStore.isAuthzPathsMappingEmpty(), true); sentryStore.addAuthzPathsMapping("db1.table", Sets.newHashSet("db1/tbl1", "db1/tbl2"), addUpdate); String[] prefixes = { "/" }; PathsUpdate pathsUpdate = sentryStore.retrieveFullPathsImageUpdate(prefixes); TPathsDump pathsDump = pathsUpdate.toThrift().getPathsDump(); Map<Integer, TPathEntry> nodeMap = pathsDump.getNodeMap(); TPathEntry root = nodeMap.get(pathsDump.getRootId()); Map<String, Collection<String>> pathImage = new HashMap<>(); buildPathsImageMap(nodeMap, root, "", pathImage, false); assertEquals("/", root.getPathElement()); assertEquals(4, nodeMap.size());//Tree size assertEquals(1, pathImage.size()); assertEquals(2, pathImage.get("db1.table").size()); assertEquals(2, sentryStore.getMPaths().size()); assertEquals(sentryStore.isAuthzPathsMappingEmpty(), false); sentryStore.clearAllTables(); assertEquals(sentryStore.isAuthzPathsMappingEmpty(), true); } @Test public void testAddDeleteAuthzPathsMappingNoDeltaSavedWithoutHDFSSync() throws Exception { // disable HDFS conf.set(ServiceConstants.ServerConfig.PROCESSOR_FACTORIES, ""); conf.set(ServiceConstants.ServerConfig.SENTRY_POLICY_STORE_PLUGINS, ""); SentryStore localSentryStore = new SentryStore(conf); // Persist an empty image so that we can add paths to it. localSentryStore.persistFullPathsImage(new HashMap<String, Collection<String>>(), 0); // Add "db1.table1" authzObj Long lastNotificationId = sentryStore.getLastProcessedNotificationID(); UniquePathsUpdate addUpdate = new UniquePathsUpdate("u1", 1, false); addUpdate.newPathChange("db1.table").addToAddPaths(Arrays.asList("db1", "tbl1")); addUpdate.newPathChange("db1.table").addToAddPaths(Arrays.asList("db1", "tbl2")); localSentryStore.addAuthzPathsMapping("db1.table", Sets.newHashSet("db1/tbl1", "db1/tbl2"), addUpdate); String[] prefixes = { "/" }; PathsUpdate pathsUpdate = localSentryStore.retrieveFullPathsImageUpdate(prefixes); TPathsDump pathsDump = pathsUpdate.toThrift().getPathsDump(); Map<Integer, TPathEntry> nodeMap = pathsDump.getNodeMap(); TPathEntry root = nodeMap.get(pathsDump.getRootId()); Map<String, Collection<String>> pathImage = new HashMap<>(); buildPathsImageMap(nodeMap, root, "", pathImage, false); assertEquals("/", root.getPathElement()); assertEquals(4, nodeMap.size());//Tree size assertEquals(1, pathImage.size()); assertEquals(2, pathImage.get("db1.table").size()); assertEquals(2, localSentryStore.getMPaths().size()); // Query the persisted path change and ensure it is not saved long lastChangeID = localSentryStore.getLastProcessedPathChangeID(); assertEquals(0, lastChangeID); // Delete path 'db1.db/tbl1' from "db1.table1" authzObj. UniquePathsUpdate delUpdate = new UniquePathsUpdate("u2", 2, false); delUpdate.newPathChange("db1.table").addToDelPaths(Arrays.asList("db1", "tbl1")); localSentryStore.deleteAuthzPathsMapping("db1.table", Sets.newHashSet("db1/tbl1"), delUpdate); pathsUpdate = localSentryStore.retrieveFullPathsImageUpdate(prefixes); pathsDump = pathsUpdate.toThrift().getPathsDump(); nodeMap = pathsDump.getNodeMap(); root = nodeMap.get(pathsDump.getRootId()); pathImage = new HashMap<>(); buildPathsImageMap(nodeMap, root, "", pathImage, false); assertEquals("/", root.getPathElement()); assertEquals(3, nodeMap.size());//Tree size assertEquals(1, pathImage.size()); assertEquals(1, pathImage.get("db1.table").size()); assertEquals(1, localSentryStore.getMPaths().size()); // Query the persisted path change and ensure it is not saved lastChangeID = localSentryStore.getLastProcessedPathChangeID(); assertEquals(0, lastChangeID); // Delete "db1.table" authzObj from the authzObj -> [Paths] mapping. UniquePathsUpdate delAllupdate = new UniquePathsUpdate("u3", 3, false); delAllupdate.newPathChange("db1.table").addToDelPaths(Lists.newArrayList(PathsUpdate.ALL_PATHS)); localSentryStore.deleteAllAuthzPathsMapping("db1.table", delAllupdate); pathsUpdate = localSentryStore.retrieveFullPathsImageUpdate(prefixes); pathsDump = pathsUpdate.toThrift().getPathsDump(); nodeMap = pathsDump.getNodeMap(); root = nodeMap.get(pathsDump.getRootId()); pathImage = new HashMap<>(); buildPathsImageMap(nodeMap, root, "", pathImage, false); assertEquals("/", root.getPathElement()); assertEquals(1, nodeMap.size());//Tree size assertEquals(0, pathImage.size()); assertEquals(0, localSentryStore.getMPaths().size()); // Query the persisted path change and ensure it is not saved lastChangeID = localSentryStore.getLastProcessedPathChangeID(); assertEquals(0, lastChangeID); lastNotificationId = localSentryStore.getLastProcessedNotificationID(); assertEquals(0, lastNotificationId.longValue()); // enable HDFS for other tests conf.set(ServiceConstants.ServerConfig.PROCESSOR_FACTORIES, "org.apache.sentry.hdfs.SentryHDFSServiceProcessorFactory"); conf.set(ServiceConstants.ServerConfig.SENTRY_POLICY_STORE_PLUGINS, "org.apache.sentry.hdfs.SentryPlugin"); } /** * Test retrieveFullPathsImageUpdate() when no image is present. * @throws Exception */ @Test public void testRetrieveEmptyPathImage() throws Exception { String[] prefixes = {}; PathsUpdate pathsUpdate = sentryStore.retrieveFullPathsImageUpdate(prefixes); TPathsUpdate tPathsUpdate = pathsUpdate.toThrift(); TPathsDump pathDump = tPathsUpdate.getPathsDump(); Map<Integer, TPathEntry> nodeMap = pathDump.getNodeMap(); assertEquals(1, nodeMap.size()); System.out.printf(nodeMap.toString()); } /** * Test retrieveFullPathsImageUpdate() when a single path is present. * @throws Exception */ @Test public void testRetrievePathImageWithSingleEntry() throws Exception { String prefix = "user/hive/warehouse"; String[] prefixes = { "/" + prefix }; Map<String, Collection<String>> authzPaths = new HashMap<>(); // Makes sure that authorizable object could be associated // with different paths and can be properly persisted into database. String tablePath = prefix + "/db2.db/table1.1"; authzPaths.put("db1.table1", Sets.newHashSet(tablePath)); long notificationID = 1; sentryStore.persistFullPathsImage(authzPaths, notificationID); PathsUpdate pathsUpdate = sentryStore.retrieveFullPathsImageUpdate(prefixes); assertEquals(notificationID, pathsUpdate.getImgNum()); TPathsUpdate tPathsUpdate = pathsUpdate.toThrift(); TPathsDump pathDump = tPathsUpdate.getPathsDump(); Map<Integer, TPathEntry> nodeMap = pathDump.getNodeMap(); System.out.printf(nodeMap.toString()); assertEquals(6, nodeMap.size()); int rootId = pathDump.getRootId(); TPathEntry root = nodeMap.get(rootId); assertEquals("/", root.getPathElement()); List<Integer> children; TPathEntry child = root; // Walk tree down and verify elements for (String path : tablePath.split("/")) { children = child.getChildren(); assertEquals(1, children.size()); child = nodeMap.get(children.get(0)); assertEquals(path, child.getPathElement()); } } /** * Test paths with multiple leading slashes * @throws Exception */ @Test public void testRetrievePathImageWithMultipleLeadingSlashes() throws Exception { //Test with no leading slashes String prefix = "user/hive/warehouse"; String[] prefixes = { "/" + prefix }; Map<String, Collection<String>> authzPaths = new HashMap<>(); // Makes sure that authorizable object could be associated // with different paths and can be properly persisted into database. String tablePath = prefix + "/loc1/db2.db/table1.1"; authzPaths.put("db1.table1", Sets.newHashSet(tablePath)); long notificationID = 1; sentryStore.persistFullPathsImage(authzPaths, notificationID); PathsUpdate pathsUpdate = sentryStore.retrieveFullPathsImageUpdate(prefixes); assertEquals(notificationID, pathsUpdate.getImgNum()); TPathsUpdate tPathsUpdate = pathsUpdate.toThrift(); TPathsDump pathDump = tPathsUpdate.getPathsDump(); Map<Integer, TPathEntry> nodeMap = pathDump.getNodeMap(); assertEquals(7, nodeMap.size()); //Test with single leading slashes prefix = "/user/hive/warehouse"; prefixes = new String[] { prefix }; authzPaths = new HashMap<>(); // Makes sure that authorizable object could be associated // with different paths and can be properly persisted into database. tablePath = prefix + "/loc1/db2.db/table1.1"; authzPaths.put("db1.table1", Sets.newHashSet(tablePath)); notificationID = 2; sentryStore.persistFullPathsImage(authzPaths, notificationID); pathsUpdate = sentryStore.retrieveFullPathsImageUpdate(prefixes); assertEquals(notificationID, pathsUpdate.getImgNum()); tPathsUpdate = pathsUpdate.toThrift(); pathDump = tPathsUpdate.getPathsDump(); nodeMap = pathDump.getNodeMap(); assertEquals(7, nodeMap.size()); //Test with multiple leading slash prefix = "///user/hive/warehouse"; prefixes = new String[] { prefix }; authzPaths = new HashMap<>(); // Makes sure that authorizable object could be associated // with different paths and can be properly persisted into database. tablePath = prefix + "/loc1/db2.db/table1.1"; authzPaths.put("db1.table1", Sets.newHashSet(tablePath)); notificationID = 3; sentryStore.persistFullPathsImage(authzPaths, notificationID); pathsUpdate = sentryStore.retrieveFullPathsImageUpdate(prefixes); assertEquals(notificationID, pathsUpdate.getImgNum()); tPathsUpdate = pathsUpdate.toThrift(); pathDump = tPathsUpdate.getPathsDump(); nodeMap = pathDump.getNodeMap(); assertEquals(7, nodeMap.size()); } /** * Create a user with the given name and verify that it is created * * @param userName * @throws Exception */ private void createUser(String userName) throws Exception { checkUserDoesNotExist(userName); sentryStore.createSentryUser(userName); checkUserExists(userName); } /** * Fail test if user already exists * @param userName User name to checl * @throws Exception */ private void checkUserDoesNotExist(String userName) throws Exception { try { sentryStore.getMSentryUserByName(userName); fail("User " + userName + "already exists"); } catch (SentryNoSuchObjectException e) { // Ok } } /** * Fail test if user doesn't exist * @param userName User name to checl * @throws Exception */ private void checkUserExists(String userName) throws Exception { assertEquals(userName.toLowerCase(), sentryStore.getMSentryUserByName(userName).getUserName()); } @Test public void testGrantRevokePrivilegeForUser() throws Exception { String userName = "test-privilege"; String server = "server1"; String db = "db1"; String table = "tbl1"; createUser(userName); 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.alterSentryGrantPrivileges(SentryPrincipalType.USER, userName, Sets.newHashSet(privilege), null); MSentryUser user = sentryStore.getMSentryUserByName(userName); Set<MSentryPrivilege> privileges = user.getPrivileges(); assertEquals(privileges.toString(), 1, privileges.size()); privilege.setAction(AccessConstants.SELECT); sentryStore.alterSentryRevokePrivileges(SentryPrincipalType.USER, userName, Sets.newHashSet(privilege), null); // after having ALL and revoking SELECT, we should have (INSERT) user = sentryStore.getMSentryUserByName(userName); privileges = user.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); privilege.setAction(AccessConstants.INSERT); sentryStore.alterSentryRevokePrivileges(SentryPrincipalType.USER, userName, Sets.newHashSet(privilege), null); user = sentryStore.getMSentryUserByName(userName, false); assertNull(user); } /** * Test after granting DB ALL privilege, can still grant table ALL privilege * @throws Exception */ @Test public void testGrantDuplicatePrivilegeHierchy() throws Exception { // grant database all privilege String roleName = "test-privilege"; String server = "server1"; String db = "db1"; String table = "tbl1"; createRole(roleName); TSentryPrivilege privilege = new TSentryPrivilege(); privilege.setPrivilegeScope("DATABASE"); privilege.setServerName(server); privilege.setDbName(db); privilege.setAction(AccessConstants.ALL); privilege.setCreateTime(System.currentTimeMillis()); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(privilege), null); MSentryRole role = sentryStore.getMSentryRoleByName(roleName); Set<MSentryPrivilege> privileges = role.getPrivileges(); assertEquals(privileges.toString(), 1, privileges.size()); // grant table all privlege privilege.setPrivilegeScope("TABLE"); privilege.setServerName(server.toUpperCase()); privilege.setDbName(db.toUpperCase()); privilege.setTableName(table.toUpperCase()); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(privilege), null); // check if the table privilege is created role = sentryStore.getMSentryRoleByName(roleName); privileges = role.getPrivileges(); assertEquals(privileges.toString(), 2, privileges.size()); } @Test public void testListSentryPrivilegesForUsersAndGroups() throws Exception { String roleName = "role1"; String groupName = "list-privs-g1"; String userName = "u1"; String grantor = "g1"; sentryStore.createSentryRole(roleName); TSentryPrivilege privilege1 = new TSentryPrivilege(); privilege1.setPrivilegeScope("TABLE"); privilege1.setServerName("server1"); privilege1.setDbName("db1"); privilege1.setTableName("tbl1"); privilege1.setAction("SELECT"); privilege1.setCreateTime(System.currentTimeMillis()); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(privilege1), null); TSentryPrivilege privilege2 = new TSentryPrivilege(); privilege2.setPrivilegeScope("SERVER"); privilege2.setServerName("server1"); privilege2.setCreateTime(System.currentTimeMillis()); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.USER, userName, Sets.newHashSet(privilege2), null); Set<TSentryGroup> groups = Sets.newHashSet(); TSentryGroup group = new TSentryGroup(); group.setGroupName(groupName); groups.add(group); sentryStore.alterSentryRoleAddGroups(grantor, roleName, groups); // list-privs-g1 has privilege1 // u1 has privilege2 Set<TSentryPrivilege> expectedPrivs = new HashSet<>(); expectedPrivs.add(privilege1); expectedPrivs.add(privilege2); assertEquals(expectedPrivs, sentryStore.listSentryPrivilegesByUsersAndGroups(Sets.newHashSet(groupName), Sets.newHashSet(userName), new TSentryActiveRoleSet(true, new HashSet<>()), null)); } @Test public void testListSentryPrivilegesForProviderForUser() throws Exception { String userName1 = "list-privs-user1"; String userName2 = "list-privs-user2"; sentryStore.createSentryUser(userName1); sentryStore.createSentryUser(userName2); TSentryPrivilege privilege1 = new TSentryPrivilege(); privilege1.setPrivilegeScope("TABLE"); privilege1.setServerName("server1"); privilege1.setDbName("db1"); privilege1.setTableName("tbl1"); privilege1.setAction("SELECT"); privilege1.setCreateTime(System.currentTimeMillis()); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.USER, userName1, Sets.newHashSet(privilege1), null); privilege1.setAction("ALL"); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.USER, userName2, Sets.newHashSet(privilege1), null); assertEquals(Sets.newHashSet("server=server1->db=db1->table=tbl1->action=select"), SentryStore.toTrimedLower(sentryStore.listAllSentryPrivilegesForProvider(new HashSet<String>(), Sets.newHashSet(userName1), new TSentryActiveRoleSet(true, new HashSet<String>())))); } @Test public void testListSentryPrivilegesByAuthorizableForUser() throws Exception { String userName1 = "list-privs-user1"; sentryStore.createSentryUser(userName1); TSentryPrivilege privilege1 = new TSentryPrivilege(); privilege1.setPrivilegeScope("TABLE"); privilege1.setServerName("server1"); privilege1.setDbName("db1"); privilege1.setTableName("tbl1"); privilege1.setAction("SELECT"); privilege1.setCreateTime(System.currentTimeMillis()); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.USER, userName1, Sets.newHashSet(privilege1), null); TSentryAuthorizable tSentryAuthorizable = new TSentryAuthorizable(); tSentryAuthorizable.setServer("server1"); tSentryAuthorizable.setDb("db1"); tSentryAuthorizable.setTable("tbl1"); TSentryPrivilegeMap map = sentryStore.listSentryPrivilegesByAuthorizableForUser(Sets.newHashSet(userName1), tSentryAuthorizable, false); assertEquals(1, map.getPrivilegeMapSize()); assertEquals(Sets.newHashSet(userName1), map.getPrivilegeMap().keySet()); } @Test public void testGrantRevokePrivilegeMultipleTimesForRole() throws Exception { String roleName = "test-privilege"; 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.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(privilege), null); MSentryRole role = sentryStore.getMSentryRoleByName(roleName); Set<MSentryPrivilege> privileges = role.getPrivileges(); assertEquals(privileges.toString(), 1, privileges.size()); privilege.setAction(AccessConstants.SELECT); sentryStore.alterSentryRevokePrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(privilege), null); // after having ALL and revoking SELECT, we should have (INSERT) role = sentryStore.getMSentryRoleByName(roleName); privileges = role.getPrivileges(); assertEquals(privileges.toString(), 1, privileges.size()); // second round privilege.setAction(AccessConstants.ALL); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(privilege), null); List<MSentryPrivilege> totalPrivileges = sentryStore.getAllMSentryPrivileges(); assertEquals(totalPrivileges.toString(), 1, totalPrivileges.size()); role = sentryStore.getMSentryRoleByName(roleName); privileges = role.getPrivileges(); assertEquals(privileges.toString(), 1, privileges.size()); privilege.setAction(AccessConstants.INSERT); sentryStore.alterSentryRevokePrivileges(SentryPrincipalType.ROLE, roleName, Sets.newHashSet(privilege), null); // after having ALL and revoking INSERT, we should have (SELECT) totalPrivileges = sentryStore.getAllMSentryPrivileges(); assertEquals(totalPrivileges.toString(), 1, totalPrivileges.size()); role = sentryStore.getMSentryRoleByName(roleName); privileges = role.getPrivileges(); assertEquals(privileges.toString(), 1, privileges.size()); sentryStore.dropSentryRole(roleName); } @Test public void testGrantRevokePrivilegeMultipleTimesForUser() throws Exception { String userName = "test-privilege"; String server = "server1"; String db = "db1"; String table = "tbl1"; createUser(userName); 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.alterSentryGrantPrivileges(SentryPrincipalType.USER, userName, Sets.newHashSet(privilege), null); MSentryUser user = sentryStore.getMSentryUserByName(userName); Set<MSentryPrivilege> privileges = user.getPrivileges(); assertEquals(privileges.toString(), 1, privileges.size()); privilege.setAction(AccessConstants.SELECT); sentryStore.alterSentryRevokePrivileges(SentryPrincipalType.USER, userName, Sets.newHashSet(privilege), null); // after having ALL and revoking SELECT, we should have (INSERT) user = sentryStore.getMSentryUserByName(userName); privileges = user.getPrivileges(); assertEquals(privileges.toString(), 1, privileges.size()); // second round privilege.setAction(AccessConstants.ALL); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.USER, userName, Sets.newHashSet(privilege), null); List<MSentryPrivilege> totalPrivileges = sentryStore.getAllMSentryPrivileges(); assertEquals(totalPrivileges.toString(), 1, totalPrivileges.size()); user = sentryStore.getMSentryUserByName(userName); privileges = user.getPrivileges(); assertEquals(privileges.toString(), 1, privileges.size()); privilege.setAction(AccessConstants.INSERT); sentryStore.alterSentryRevokePrivileges(SentryPrincipalType.USER, userName, Sets.newHashSet(privilege), null); // after having ALL and revoking INSERT, we should have (SELECT) totalPrivileges = sentryStore.getAllMSentryPrivileges(); assertEquals(totalPrivileges.toString(), 1, totalPrivileges.size()); user = sentryStore.getMSentryUserByName(userName); privileges = user.getPrivileges(); assertEquals(privileges.toString(), 1, privileges.size()); privilege.setAction(AccessConstants.SELECT); sentryStore.alterSentryRevokePrivileges(SentryPrincipalType.USER, userName, Sets.newHashSet(privilege), null); // after having ALL and revoking INSERT and SELECT, we should have NO privileges // user should be removed automatically user = sentryStore.getMSentryUserByName(userName, false); assertNull(user); } @Test public void testGetAllRolesPrivileges() throws Exception { Map<String, Set<TSentryPrivilege>> allPrivileges; // The map must be empty (no null) if no roles exist on the system yet allPrivileges = sentryStore.getAllRolesPrivileges(); assertNotNull(allPrivileges); assertTrue(allPrivileges.isEmpty()); final String ROLE1 = "role1"; final TSentryPrivilege ROLE1_PRIV1 = toTSentryPrivilege("ALL", "TABLE", "server1", "db1", "table1"); final TSentryPrivilege ROLE1_PRIV2 = toTSentryPrivilege("SELECT", "TABLE", "server1", "db1", "table2"); createRole(ROLE1); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, ROLE1, Sets.newHashSet(ROLE1_PRIV1), null); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, ROLE1, Sets.newHashSet(ROLE1_PRIV2), null); final String ROLE2 = "role2"; final TSentryPrivilege ROLE2_PRIV1 = toTSentryPrivilege("INSERT", "DATABASE", "server1", "db1", ""); final TSentryPrivilege ROLE2_PRIV2 = toTSentryPrivilege("ALL", "SERVER", "server1", "", ""); createRole(ROLE2); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, ROLE2, Sets.newHashSet(ROLE2_PRIV1), null); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, ROLE2, Sets.newHashSet(ROLE2_PRIV2), null); final String ROLE3 = "role3"; createRole(ROLE3); allPrivileges = sentryStore.getAllRolesPrivileges(); // Must return 3 roles, 2 roles has 2 privileges each, 1 role has no privileges assertEquals(3, allPrivileges.size()); assertEquals(2, allPrivileges.get(ROLE1).size()); assertTrue(allPrivileges.get(ROLE1).contains(ROLE1_PRIV1)); assertTrue(allPrivileges.get(ROLE1).contains(ROLE1_PRIV2)); assertEquals(2, allPrivileges.get(ROLE2).size()); assertTrue(allPrivileges.get(ROLE2).contains(ROLE2_PRIV1)); assertTrue(allPrivileges.get(ROLE2).contains(ROLE2_PRIV2)); assertEquals(0, allPrivileges.get(ROLE3).size()); } @Test public void testGetAllUsersPrivileges() throws Exception { Map<String, Set<TSentryPrivilege>> allPrivileges; // The map must be empty (no null) if no roles exist on the system yet allPrivileges = sentryStore.getAllUsersPrivileges(); assertNotNull(allPrivileges); assertTrue(allPrivileges.isEmpty()); final String USER1 = "user1"; final TSentryPrivilege USER1_PRIV1 = toTSentryPrivilege("ALL", "TABLE", "server1", "db1", "table1"); final TSentryPrivilege USER1_PRIV2 = toTSentryPrivilege("SELECT", "TABLE", "server1", "db1", "table2"); createUser(USER1); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.USER, USER1, Sets.newHashSet(USER1_PRIV1), null); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.USER, USER1, Sets.newHashSet(USER1_PRIV2), null); final String USER2 = "user2"; final TSentryPrivilege USER2_PRIV1 = toTSentryPrivilege("INSERT", "DATABASE", "server1", "db1", ""); final TSentryPrivilege USER2_PRIV2 = toTSentryPrivilege("ALL", "SERVER", "server1", "", ""); createUser(USER2); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.USER, USER2, Sets.newHashSet(USER2_PRIV1), null); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.USER, USER2, Sets.newHashSet(USER2_PRIV2), null); final String USER3 = "user3"; createUser(USER3); allPrivileges = sentryStore.getAllUsersPrivileges(); // Must return 3 roles, 2 roles has 2 privileges each, 1 role has no privileges assertEquals(3, allPrivileges.size()); assertEquals(2, allPrivileges.get(USER1).size()); assertTrue(allPrivileges.get(USER1).contains(USER1_PRIV1)); assertTrue(allPrivileges.get(USER1).contains(USER1_PRIV2)); assertEquals(2, allPrivileges.get(USER2).size()); assertTrue(allPrivileges.get(USER2).contains(USER2_PRIV1)); assertTrue(allPrivileges.get(USER2).contains(USER2_PRIV2)); assertEquals(0, allPrivileges.get(USER3).size()); } @Test public void testPersistFullPathsImageWithHugeData() throws Exception { Map<String, Collection<String>> authzPaths = new HashMap<>(); String[] prefixes = { "/user/hive/warehouse/" }; int dbCount = 10, tableCount = 10, partitionCount = 10, prefixSize; prefixSize = StringUtils.countMatches(prefixes[0], "/"); // Makes sure that authorizable object could be associated // with different paths and can be properly persisted into database. for (int db_index = 1; db_index <= dbCount; db_index++) { String db_name = "db" + db_index; for (int table_index = 1; table_index <= tableCount; table_index++) { Set<String> paths = Sets.newHashSet(); String table_name = "tb" + table_index; String location = prefixes[0] + db_name + "/" + table_name; paths.add(location); for (int part_index = 1; part_index <= partitionCount; part_index++) { paths.add(location + "/" + part_index); } authzPaths.put(db_name + table_name, paths); } } long notificationID = 110000; LOGGER.debug("Before " + Instant.now()); sentryStore.persistFullPathsImage(authzPaths, notificationID); LOGGER.debug("After " + Instant.now()); PathsUpdate pathsUpdate = sentryStore.retrieveFullPathsImageUpdate(prefixes); assertTrue(pathsUpdate.hasFullImage()); long savedNotificationID = sentryStore.getLastProcessedNotificationID(); assertEquals(1, pathsUpdate.getImgNum()); TPathsDump pathDump = pathsUpdate.toThrift().getPathsDump(); assertNotNull(pathDump); Map<Integer, TPathEntry> nodeMap = pathDump.getNodeMap(); int nodeCount = prefixSize + dbCount + (dbCount * tableCount) + (dbCount * tableCount * partitionCount); assertTrue(nodeMap.size() == nodeCount); assertEquals(notificationID, savedNotificationID); } @Test public void testRevokeHiveAllPrivilegeFromImpalaUnset() throws Exception { String roleName1 = "impala-r1"; String serverName = "server1"; String dbName = "db1"; String tableName = "tbl1"; String hiveAll = "*"; sentryStore.createSentryRole(roleName1); TSentryPrivilege hive_privilege_tbl1 = new TSentryPrivilege(); hive_privilege_tbl1.setPrivilegeScope("TABLE"); hive_privilege_tbl1.setServerName(serverName); hive_privilege_tbl1.setDbName(dbName); hive_privilege_tbl1.setTableName(tableName); hive_privilege_tbl1.setCreateTime(System.currentTimeMillis()); hive_privilege_tbl1.setAction(hiveAll); hive_privilege_tbl1.setGrantOption(TSentryGrantOption.FALSE); TSentryPrivilege impala_privilege_tbl1_unset = new TSentryPrivilege(); impala_privilege_tbl1_unset.setPrivilegeScope("TABLE"); impala_privilege_tbl1_unset.setServerName(serverName); impala_privilege_tbl1_unset.setDbName(dbName); impala_privilege_tbl1_unset.setTableName(tableName); impala_privilege_tbl1_unset.setCreateTime(System.currentTimeMillis()); impala_privilege_tbl1_unset.setAction("ALL"); impala_privilege_tbl1_unset.setGrantOption(TSentryGrantOption.UNSET); TSentryAuthorizable tSentryAuthorizable = new TSentryAuthorizable(); tSentryAuthorizable.setServer(serverName); tSentryAuthorizable.setDb(dbName); tSentryAuthorizable.setTable(tableName); // grant hive ALL privilege to role roleName1 sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName1, Sets.newHashSet(hive_privilege_tbl1), null); // revoke impala ALL privilege to role roleName1 sentryStore.alterSentryRoleRevokePrivileges(roleName1, Sets.newHashSet(impala_privilege_tbl1_unset)); Map<String, Set<TSentryPrivilege>> rolePrivilegesMap = sentryStore.getRoleNameTPrivilegesMap(dbName, tableName); assertNotNull(rolePrivilegesMap); Set<TSentryPrivilege> rolePrivileges = rolePrivilegesMap.get(roleName1); boolean privilegeRevoked = (rolePrivileges == null) || (rolePrivileges.size() == 0); assertTrue(privilegeRevoked); } @Test public void testRevokeHiveAllPrivilegeGrantOptionFromImpalaUnset() throws Exception { String roleName1 = "impala-r1"; String serverName = "server1"; String dbName = "db1"; String tableName = "tbl1"; String hiveAll = "*"; sentryStore.createSentryRole(roleName1); TSentryPrivilege hive_privilege_tbl1 = new TSentryPrivilege(); hive_privilege_tbl1.setPrivilegeScope("TABLE"); hive_privilege_tbl1.setServerName(serverName); hive_privilege_tbl1.setDbName(dbName); hive_privilege_tbl1.setTableName(tableName); hive_privilege_tbl1.setCreateTime(System.currentTimeMillis()); hive_privilege_tbl1.setAction(hiveAll); hive_privilege_tbl1.setGrantOption(TSentryGrantOption.FALSE); TSentryPrivilege impala_privilege_tbl1_unset = new TSentryPrivilege(); impala_privilege_tbl1_unset.setPrivilegeScope("TABLE"); impala_privilege_tbl1_unset.setServerName(serverName); impala_privilege_tbl1_unset.setDbName(dbName); impala_privilege_tbl1_unset.setTableName(tableName); impala_privilege_tbl1_unset.setCreateTime(System.currentTimeMillis()); impala_privilege_tbl1_unset.setAction("ALL"); impala_privilege_tbl1_unset.setGrantOption(TSentryGrantOption.UNSET); TSentryAuthorizable tSentryAuthorizable = new TSentryAuthorizable(); tSentryAuthorizable.setServer(serverName); tSentryAuthorizable.setDb(dbName); tSentryAuthorizable.setTable(tableName); // grant hive ALL privilege to role roleName1 hive_privilege_tbl1.setGrantOption(TSentryGrantOption.FALSE); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName1, Sets.newHashSet(hive_privilege_tbl1), null); hive_privilege_tbl1.setGrantOption(TSentryGrantOption.TRUE); sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName1, Sets.newHashSet(hive_privilege_tbl1), null); // revoke impala ALL privilege to role roleName1 sentryStore.alterSentryRoleRevokePrivileges(roleName1, Sets.newHashSet(impala_privilege_tbl1_unset)); Map<String, Set<TSentryPrivilege>> rolePrivilegesMap = sentryStore.getRoleNameTPrivilegesMap(dbName, tableName); assertNotNull(rolePrivilegesMap); Set<TSentryPrivilege> rolePrivileges = rolePrivilegesMap.get(roleName1); boolean privilegeRevoked = (rolePrivileges == null) || (rolePrivileges.size() == 0); assertTrue(privilegeRevoked); } @Test public void testRevokeHiveAllPrivilegeFromImpala() throws Exception { String roleName1 = "impala-r1"; String serverName = "server1"; String dbName = "db1"; String tableName = "tbl1"; sentryStore.createSentryRole(roleName1); TSentryPrivilege hive_privilege_tbl1 = new TSentryPrivilege(); hive_privilege_tbl1.setPrivilegeScope("TABLE"); hive_privilege_tbl1.setServerName(serverName); hive_privilege_tbl1.setDbName(dbName); hive_privilege_tbl1.setTableName(tableName); hive_privilege_tbl1.setCreateTime(System.currentTimeMillis()); hive_privilege_tbl1.setAction("*"); hive_privilege_tbl1.setGrantOption(TSentryGrantOption.FALSE); TSentryPrivilege impala_privilege_tbl1 = new TSentryPrivilege(); impala_privilege_tbl1.setPrivilegeScope("TABLE"); impala_privilege_tbl1.setServerName(serverName); impala_privilege_tbl1.setDbName(dbName); impala_privilege_tbl1.setTableName(tableName); impala_privilege_tbl1.setCreateTime(System.currentTimeMillis()); impala_privilege_tbl1.setAction("ALL"); impala_privilege_tbl1.setGrantOption(TSentryGrantOption.FALSE); TSentryAuthorizable tSentryAuthorizable = new TSentryAuthorizable(); tSentryAuthorizable.setServer(serverName); tSentryAuthorizable.setDb(dbName); tSentryAuthorizable.setTable(tableName); // grant hive ALL privilege to role roleName1 sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName1, Sets.newHashSet(hive_privilege_tbl1), null); // revoke impala ALL privilege to role roleName1 sentryStore.alterSentryRoleRevokePrivileges(roleName1, Sets.newHashSet(impala_privilege_tbl1)); Map<String, Set<TSentryPrivilege>> rolePrivilegesMap = sentryStore.getRoleNameTPrivilegesMap(dbName, tableName); assertNotNull(rolePrivilegesMap); Set<TSentryPrivilege> rolePrivileges = rolePrivilegesMap.get(roleName1); boolean privilegeRevoked = (rolePrivileges == null) || (rolePrivileges.size() == 0); assertTrue(privilegeRevoked); } @Test public void testRevokeImpalaAllPrivilegeFromHive() throws Exception { String roleName1 = "impala-r1"; String serverName = "server1"; String dbName = "db1"; String tableName = "tbl1"; sentryStore.createSentryRole(roleName1); TSentryPrivilege hive_privilege_tbl1 = new TSentryPrivilege(); hive_privilege_tbl1.setPrivilegeScope("TABLE"); hive_privilege_tbl1.setServerName(serverName); hive_privilege_tbl1.setDbName(dbName); hive_privilege_tbl1.setTableName(tableName); hive_privilege_tbl1.setCreateTime(System.currentTimeMillis()); hive_privilege_tbl1.setAction("*"); hive_privilege_tbl1.setGrantOption(TSentryGrantOption.FALSE); TSentryPrivilege impala_privilege_tbl1 = new TSentryPrivilege(); impala_privilege_tbl1.setPrivilegeScope("TABLE"); impala_privilege_tbl1.setServerName(serverName); impala_privilege_tbl1.setDbName(dbName); impala_privilege_tbl1.setTableName(tableName); impala_privilege_tbl1.setCreateTime(System.currentTimeMillis()); impala_privilege_tbl1.setAction("ALL"); impala_privilege_tbl1.setGrantOption(TSentryGrantOption.FALSE); TSentryAuthorizable tSentryAuthorizable = new TSentryAuthorizable(); tSentryAuthorizable.setServer(serverName); tSentryAuthorizable.setDb(dbName); tSentryAuthorizable.setTable(tableName); // grant impala ALL privilege to role roleName1 sentryStore.alterSentryGrantPrivileges(SentryPrincipalType.ROLE, roleName1, Sets.newHashSet(impala_privilege_tbl1), null); // revoke hive ALL privilege to role roleName1 sentryStore.alterSentryRoleRevokePrivileges(roleName1, Sets.newHashSet(hive_privilege_tbl1)); Map<String, Set<TSentryPrivilege>> rolePrivilegesMap = sentryStore.getRoleNameTPrivilegesMap(dbName, tableName); assertNotNull(rolePrivilegesMap); Set<TSentryPrivilege> rolePrivileges = rolePrivilegesMap.get(roleName1); boolean privilegeRevoked = (rolePrivileges == null) || (rolePrivileges.size() == 0); assertTrue(privilegeRevoked); } private TSentryPrivilege toTSentryPrivilege(String action, String scope, String server, String dbName, String tableName) { TSentryPrivilege privilege = new TSentryPrivilege(); privilege.setPrivilegeScope(scope); privilege.setServerName(server); privilege.setDbName(dbName); privilege.setTableName(tableName); privilege.setAction(action); privilege.setCreateTime(System.currentTimeMillis()); return privilege; } private TSentryPrivilege toTSentryPrivilege(String action, String scope, String server, String dbName, String tableName, TSentryGrantOption grantOption) { TSentryPrivilege privilege = toTSentryPrivilege(action, scope, server, dbName, tableName); privilege.setGrantOption(grantOption); return privilege; } }