http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestPermissionsMigrationToolSolr.java ---------------------------------------------------------------------- diff --git a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestPermissionsMigrationToolSolr.java b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestPermissionsMigrationToolSolr.java new file mode 100644 index 0000000..a275d18 --- /dev/null +++ b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestPermissionsMigrationToolSolr.java @@ -0,0 +1,362 @@ + /** + * 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.cli.tools; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.io.FileUtils; +import org.apache.sentry.core.common.exception.SentryUserException; +import org.apache.sentry.provider.common.ProviderBackendContext; +import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceIntegrationBase; +import org.apache.sentry.provider.db.generic.service.thrift.TAuthorizable; +import org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege; +import org.apache.sentry.provider.db.generic.service.thrift.TSentryRole; +import org.apache.sentry.provider.db.generic.tools.GenericPrivilegeConverter;import org.apache.sentry.provider.file.PolicyFile; +import org.apache.sentry.provider.file.SimpleFileProviderBackend; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.google.common.collect.Sets; +import com.google.common.collect.Table; +import com.google.common.io.Files; + +public class TestPermissionsMigrationToolSolr extends SentryGenericServiceIntegrationBase { + private File confDir; + private File confPath; + private String requestorName = ""; + private String service = "service1"; + + @Before + public void prepareForTest() throws Exception { + confDir = Files.createTempDir(); + confPath = new File(confDir, "sentry-site.xml"); + if (confPath.createNewFile()) { + FileOutputStream to = new FileOutputStream(confPath); + conf.writeXml(to); + to.close(); + } + requestorName = clientUgi.getShortUserName();//System.getProperty("user.name", ""); + Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP); + setLocalGroupMapping(requestorName, requestorUserGroupNames); + // add ADMIN_USER for the after() in SentryServiceIntegrationBase + setLocalGroupMapping(ADMIN_USER, requestorUserGroupNames); + setLocalGroupMapping("dev", Sets.newHashSet("dev_group")); + setLocalGroupMapping("user", Sets.newHashSet("user_group")); + writePolicyFile(); + } + + @After + public void clearTestData() throws Exception { + FileUtils.deleteQuietly(confDir); + + // clear roles and privileges + Set<TSentryRole> tRoles = client.listAllRoles(requestorName, SOLR); + for (TSentryRole tRole : tRoles) { + String role = tRole.getRoleName(); + Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName( + requestorName, role, SOLR, service); + for (TSentryPrivilege privilege : privileges) { + client.revokePrivilege(requestorName, role, SOLR, privilege); + } + client.dropRole(requestorName, role, SOLR); + } + } + + @Test + public void testPermissionsMigrationFromSentrySvc_v1() throws Exception { + initializeSentryService(); + + String[] args = { "-s", "1.8.0", "-c", confPath.getAbsolutePath()}; + PermissionsMigrationToolSolr sentryTool = new PermissionsMigrationToolSolr(); + sentryTool.executeConfigTool(args); + + Map<String, Set<String>> groupMapping = new HashMap<String, Set<String>>(); + groupMapping.put("admin_role", Sets.newHashSet("admin_group")); + groupMapping.put("dev_role", Sets.newHashSet("dev_group")); + groupMapping.put("user_role", Sets.newHashSet("user_group")); + + Map<String, Set<String>> privilegeMapping = new HashMap<String, Set<String>>(); + privilegeMapping.put("admin_role", + Sets.newHashSet("admin=collections->action=*", "admin=cores->action=*")); + privilegeMapping.put("dev_role", + Sets.newHashSet("collection=*->action=*", "admin=collections->action=*", "admin=cores->action=*")); + privilegeMapping.put("user_role", + Sets.newHashSet("collection=foo->action=*")); + + verifySentryServiceState(groupMapping, privilegeMapping); + } + + @Test + public void testPermissionsMigrationFromSentryPolicyFile_v1() throws Exception { + Path policyFilePath = initializeSentryPolicyFile(); + Path outputFilePath = Paths.get(confDir.getAbsolutePath(), "sentry-provider_migrated.ini"); + + String[] args = { "-s", "1.8.0", "-p", policyFilePath.toFile().getAbsolutePath(), + "-o", outputFilePath.toFile().getAbsolutePath() }; + PermissionsMigrationToolSolr sentryTool = new PermissionsMigrationToolSolr(); + assertTrue(sentryTool.executeConfigTool(args)); + + Set<String> groups = new HashSet<>(); + groups.add("admin_group"); + groups.add("dev_group"); + groups.add("user_group"); + + Map<String, Set<String>> privilegeMapping = new HashMap<String, Set<String>>(); + privilegeMapping.put("admin_role", + Sets.newHashSet("admin=collections->action=*", "admin=cores->action=*")); + privilegeMapping.put("dev_role", + Sets.newHashSet("collection=*->action=*", "admin=collections->action=*", "admin=cores->action=*")); + privilegeMapping.put("user_role", + Sets.newHashSet("collection=foo->action=*")); + + verifySentryPolicyFile(groups, privilegeMapping, outputFilePath); + } + + @Test + // For permissions created with Sentry 2.x, no migration necessary + public void testPermissionsMigrationFromSentrySvc_v2() throws Exception { + initializeSentryService(); + + String[] args = { "-s", "2.0.0", "-c", confPath.getAbsolutePath()}; + PermissionsMigrationToolSolr sentryTool = new PermissionsMigrationToolSolr(); + sentryTool.executeConfigTool(args); + + Map<String, Set<String>> groupMapping = new HashMap<String, Set<String>>(); + groupMapping.put("admin_role", Sets.newHashSet("admin_group")); + groupMapping.put("dev_role", Sets.newHashSet("dev_group")); + groupMapping.put("user_role", Sets.newHashSet("user_group")); + + Map<String, Set<String>> privilegeMapping = new HashMap<String, Set<String>>(); + privilegeMapping.put("admin_role", + Sets.newHashSet("collection=admin->action=*")); + privilegeMapping.put("dev_role", + Sets.newHashSet("collection=*->action=*")); + privilegeMapping.put("user_role", + Sets.newHashSet("collection=foo->action=*")); + + verifySentryServiceState(groupMapping, privilegeMapping); + } + + @Test + // For permissions created with Sentry 2.x, no migration necessary + public void testPermissionsMigrationFromSentryPolicyFile_v2() throws Exception { + Path policyFilePath = initializeSentryPolicyFile(); + Path outputFilePath = Paths.get(confDir.getAbsolutePath(), "sentry-provider_migrated.ini"); + + String[] args = { "-s", "2.0.0", "-p", policyFilePath.toFile().getAbsolutePath(), + "-o", outputFilePath.toFile().getAbsolutePath() }; + PermissionsMigrationToolSolr sentryTool = new PermissionsMigrationToolSolr(); + assertTrue(sentryTool.executeConfigTool(args)); + + Set<String> groups = new HashSet<>(); + groups.add("admin_group"); + groups.add("dev_group"); + groups.add("user_group"); + + Map<String, Set<String>> privilegeMapping = new HashMap<String, Set<String>>(); + privilegeMapping.put("admin_role", + Sets.newHashSet("collection=admin->action=*")); + privilegeMapping.put("dev_role", + Sets.newHashSet("collection=*->action=*")); + privilegeMapping.put("user_role", + Sets.newHashSet("collection=foo->action=*")); + + verifySentryPolicyFile(groups, privilegeMapping, outputFilePath); + } + + @Test + public void testDryRunOption() throws Exception { + initializeSentryService(); + + String[] args = { "-s", "1.8.0", "-c", confPath.getAbsolutePath(), "--dry_run"}; + PermissionsMigrationToolSolr sentryTool = new PermissionsMigrationToolSolr(); + sentryTool.executeConfigTool(args); + + Map<String, Set<String>> groupMapping = new HashMap<String, Set<String>>(); + groupMapping.put("admin_role", Sets.newHashSet("admin_group")); + groupMapping.put("dev_role", Sets.newHashSet("dev_group")); + groupMapping.put("user_role", Sets.newHashSet("user_group")); + + // No change in the privileges + Map<String, Set<String>> privilegeMapping = new HashMap<String, Set<String>>(); + privilegeMapping.put("admin_role", + Sets.newHashSet("collection=admin->action=*")); + privilegeMapping.put("dev_role", + Sets.newHashSet("collection=*->action=*")); + privilegeMapping.put("user_role", + Sets.newHashSet("collection=foo->action=*")); + + verifySentryServiceState(groupMapping, privilegeMapping); + } + + @Test + public void testInvalidToolArguments() throws Exception { + PermissionsMigrationToolSolr sentryTool = new PermissionsMigrationToolSolr(); + + { + String[] args = { "-c", confPath.getAbsolutePath()}; + assertFalse("The execution should have failed due to missing source version", + sentryTool.executeConfigTool(args)); + } + + { + String[] args = { "-s", "1.8.0" }; + sentryTool.executeConfigTool(args); + assertFalse("The execution should have failed due to missing Sentry config file" + + " (or policy file) path", + sentryTool.executeConfigTool(args)); + } + + { + String[] args = { "-s", "1.8.0", "-p", "/test/path" }; + sentryTool.executeConfigTool(args); + assertFalse("The execution should have failed due to missing Sentry config output file path", + sentryTool.executeConfigTool(args)); + } + + { + String[] args = { "-s", "1.8.0", "-c", "/test/path1", "-p", "/test/path2" }; + sentryTool.executeConfigTool(args); + assertFalse("The execution should have failed due to providing both Sentry config file" + + " as well as policy file params", + sentryTool.executeConfigTool(args)); + } + } + + private void initializeSentryService() throws SentryUserException { + // Define an admin role + client.createRoleIfNotExist(requestorName, "admin_role", SOLR); + client.grantRoleToGroups(requestorName, "admin_role", SOLR, Sets.newHashSet("admin_group")); + + // Define a developer role + client.createRoleIfNotExist(requestorName, "dev_role", SOLR); + client.grantRoleToGroups(requestorName, "dev_role", SOLR, Sets.newHashSet("dev_group")); + + // Define a user role + client.createRoleIfNotExist(requestorName, "user_role", SOLR); + client.grantRoleToGroups(requestorName, "user_role", SOLR, Sets.newHashSet("user_group")); + + // Grant permissions + client.grantPrivilege(requestorName, "admin_role", SOLR, + new TSentryPrivilege(SOLR, "service1", + Arrays.asList(new TAuthorizable("collection", "admin")), "*")); + client.grantPrivilege(requestorName, "dev_role", SOLR, + new TSentryPrivilege(SOLR, "service1", + Arrays.asList(new TAuthorizable("collection", "*")), "*")); + client.grantPrivilege(requestorName, "user_role", SOLR, + new TSentryPrivilege(SOLR, "service1", + Arrays.asList(new TAuthorizable("collection", "foo")), "*")); + } + + private void verifySentryServiceState(Map<String, Set<String>> groupMapping, + Map<String, Set<String>> privilegeMapping) throws SentryUserException { + // check roles + Set<TSentryRole> tRoles = client.listAllRoles(requestorName, SOLR); + assertEquals("Unexpected number of roles", groupMapping.keySet().size(), tRoles.size()); + Set<String> roles = new HashSet<String>(); + for (TSentryRole tRole : tRoles) { + roles.add(tRole.getRoleName()); + } + + for (String expectedRole : groupMapping.keySet()) { + assertTrue("Didn't find expected role: " + expectedRole, roles.contains(expectedRole)); + } + + // check groups + for (TSentryRole tRole : tRoles) { + Set<String> expectedGroups = groupMapping.get(tRole.getRoleName()); + assertEquals("Group size doesn't match for role: " + tRole.getRoleName(), + expectedGroups.size(), tRole.getGroups().size()); + assertTrue("Group does not contain all expected members for role: " + tRole.getRoleName(), + tRole.getGroups().containsAll(expectedGroups)); + } + + // check privileges + GenericPrivilegeConverter convert = new GenericPrivilegeConverter(SOLR, service); + for (String role : roles) { + Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName( + requestorName, role, SOLR, service); + Set<String> expectedPrivileges = privilegeMapping.get(role); + assertEquals("Privilege set size doesn't match for role: " + role + " Actual permissions : " + privileges, + expectedPrivileges.size(), privileges.size()); + + Set<String> privilegeStrs = new HashSet<String>(); + for (TSentryPrivilege privilege : privileges) { + privilegeStrs.add(convert.toString(privilege).toLowerCase()); + } + + for (String expectedPrivilege : expectedPrivileges) { + assertTrue("Did not find expected privilege: " + expectedPrivilege + " in " + privilegeStrs, + privilegeStrs.contains(expectedPrivilege)); + } + } + } + + private Path initializeSentryPolicyFile() throws Exception { + PolicyFile file = new PolicyFile(); + + file.addRolesToGroup("admin_group", "admin_role"); + file.addRolesToGroup("dev_group", "dev_role"); + file.addRolesToGroup("user_group", "user_role"); + + file.addPermissionsToRole("admin_role", "collection=admin->action=*"); + file.addPermissionsToRole("dev_role", "collection=*->action=*"); + file.addPermissionsToRole("user_role", "collection=foo->action=*"); + + Path policyFilePath = Paths.get(confDir.getAbsolutePath(), "sentry-provider.ini"); + file.write(policyFilePath.toFile()); + + return policyFilePath; + } + + private void verifySentryPolicyFile (Set<String> groups, Map<String, Set<String>> privilegeMapping, + Path policyFilePath) throws IOException { + SimpleFileProviderBackend policyFileBackend = new SimpleFileProviderBackend(conf, + new org.apache.hadoop.fs.Path(policyFilePath.toUri())); + policyFileBackend.initialize(new ProviderBackendContext()); + Table<String, String, Set<String>> groupRolePrivilegeTable = + policyFileBackend.getGroupRolePrivilegeTable(); + + assertEquals(groups, groupRolePrivilegeTable.rowKeySet()); + assertEquals(privilegeMapping.keySet(), groupRolePrivilegeTable.columnKeySet()); + + for (String groupName : groupRolePrivilegeTable.rowKeySet()) { + for (String roleName : groupRolePrivilegeTable.columnKeySet()) { + if (groupRolePrivilegeTable.contains(groupName, roleName)) { + Set<String> privileges = groupRolePrivilegeTable.get(groupName, roleName); + assertEquals(privilegeMapping.get(roleName), privileges); + } + } + } + } +}
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryConfigToolIndexer.java ---------------------------------------------------------------------- diff --git a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryConfigToolIndexer.java b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryConfigToolIndexer.java new file mode 100644 index 0000000..40df736 --- /dev/null +++ b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryConfigToolIndexer.java @@ -0,0 +1,263 @@ + /** + * 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.cli.tools; + + import com.google.common.collect.Sets; + import com.google.common.io.Files; + import org.apache.commons.io.FileUtils; + import org.apache.sentry.core.common.exception.SentryConfigurationException; + import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceIntegrationBase; + import org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege; + import org.apache.sentry.provider.db.generic.service.thrift.TSentryRole; + import org.apache.sentry.provider.db.generic.tools.GenericPrivilegeConverter; + import org.apache.sentry.service.thrift.ServiceConstants; + import org.junit.After; + import org.junit.Before; + import org.junit.Test; + + import java.io.File; + import java.io.FileOutputStream; + import java.util.HashMap; + import java.util.HashSet; + import java.util.Map; + import java.util.Set; + + import static org.apache.sentry.provider.common.AuthorizationComponent.HBASE_INDEXER; + import static org.junit.Assert.assertEquals; + import static org.junit.Assert.assertTrue; + import static org.junit.Assert.fail; + + public class TestSentryConfigToolIndexer extends SentryGenericServiceIntegrationBase { + private static String VALID_POLICY_INI = TestSentryConfigToolIndexer.class.getClassLoader().getResource("indexer_config_import_tool.ini").getPath() ; + private static String INVALID_POLICY_INI = TestSentryConfigToolIndexer.class.getClassLoader().getResource("indexer_invalid.ini").getPath(); + private static String CASE_POLICY_INI = TestSentryConfigToolIndexer.class.getClassLoader().getResource("indexer_case.ini").getPath(); + private File confDir; + private File confPath; + private String requestorName = ""; + private String service = "service1"; + + @Before + public void prepareForTest() throws Exception { + confDir = Files.createTempDir(); + confPath = new File(confDir, "sentry-site.xml"); + conf.set(ServiceConstants.ClientConfig.SERVICE_NAME, service); + if (confPath.createNewFile()) { + FileOutputStream to = new FileOutputStream(confPath); + conf.writeXml(to); + to.close(); + } + requestorName = clientUgi.getShortUserName();//System.getProperty("user.name", ""); + Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP); + setLocalGroupMapping(requestorName, requestorUserGroupNames); + // add ADMIN_USER for the after() in SentryServiceIntegrationBase + setLocalGroupMapping(ADMIN_USER, requestorUserGroupNames); + writePolicyFile(); + } + + @After + public void clearTestData() throws Exception { + FileUtils.deleteQuietly(confDir); + + // clear roles and privileges + Set<TSentryRole> tRoles = client.listAllRoles(requestorName, HBASE_INDEXER); + for (TSentryRole tRole : tRoles) { + String role = tRole.getRoleName(); + Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName( + requestorName, role, HBASE_INDEXER, service); + for (TSentryPrivilege privilege : privileges) { + client.revokePrivilege(requestorName, role, HBASE_INDEXER, privilege); + } + client.dropRole(requestorName, role, HBASE_INDEXER); + } + } + + @Test + public void testConvertIni() throws Exception { + runTestAsSubject(new TestOperation() { + @Override + public void runTestAsSubject() throws Exception { + String[] args = {"-mgr", "-f", VALID_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-v", "-i"}; + SentryShellIndexer sentryTool = new SentryShellIndexer(); + sentryTool.executeShell(args); + + Map<String, Set<String>> groupMapping = new HashMap<String, Set<String>>(); + groupMapping.put("corporal_role", Sets.newHashSet("corporal", "sergeant", "general", "commander_in_chief")); + groupMapping.put("sergeant_role", Sets.newHashSet("sergeant", "general", "commander_in_chief")); + groupMapping.put("general_role", Sets.newHashSet("general", "commander_in_chief")); + groupMapping.put("commander_in_chief_role", Sets.newHashSet("commander_in_chief")); + + + Map<String, Set<String>> privilegeMapping = new HashMap<String, Set<String>>(); + privilegeMapping.put("corporal_role", + Sets.newHashSet("Indexer=info->action=read", "Indexer=info->action=write")); + privilegeMapping.put("sergeant_role", + Sets.newHashSet("Indexer=info->action=write")); + privilegeMapping.put("general_role", + Sets.newHashSet("Indexer=info->action=*")); + privilegeMapping.put("commander_in_chief_role", + Sets.newHashSet("Indexer=*->action=*")); + + // check roles + Set<TSentryRole> tRoles = client.listAllRoles(requestorName, HBASE_INDEXER); + assertEquals("Unexpected number of roles", groupMapping.keySet().size(), tRoles.size()); + Set<String> roles = new HashSet<String>(); + for (TSentryRole tRole : tRoles) { + roles.add(tRole.getRoleName()); + } + + for (String expectedRole : groupMapping.keySet()) { + assertTrue("Didn't find expected role: " + expectedRole, roles.contains(expectedRole)); + } + + // check groups + for (TSentryRole tRole : tRoles) { + Set<String> expectedGroups = groupMapping.get(tRole.getRoleName()); + assertEquals("Group size doesn't match for role: " + tRole.getRoleName(), + expectedGroups.size(), tRole.getGroups().size()); + assertTrue("Group does not contain all expected members for role: " + tRole.getRoleName(), + tRole.getGroups().containsAll(expectedGroups)); + } + + // check privileges + GenericPrivilegeConverter convert = new GenericPrivilegeConverter(HBASE_INDEXER, service); + for (String role : roles) { + Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName( + requestorName, role, HBASE_INDEXER, service); + Set<String> expectedPrivileges = privilegeMapping.get(role); + assertEquals("Privilege set size doesn't match for role: " + role, + expectedPrivileges.size(), privileges.size()); + + Set<String> privilegeStrs = new HashSet<String>(); + for (TSentryPrivilege privilege : privileges) { + privilegeStrs.add(convert.toString(privilege)); + } + + for (String expectedPrivilege : expectedPrivileges) { + assertTrue("Did not find expected privilege: " + expectedPrivilege, + privilegeStrs.contains(expectedPrivilege)); + } + } + } + }); + } + + @Test + public void testNoPolicyFile() throws Exception { + runTestAsSubject(new TestOperation() { + @Override + public void runTestAsSubject() throws Exception { + String[] args = { "-mgr", "-f", INVALID_POLICY_INI + "Foobar", "-conf", confPath.getAbsolutePath(), "-v", "-i"}; + SentryShellIndexer sentryTool = new SentryShellIndexer(); + try { + sentryTool.executeShell(args); + fail("Exception should be thrown for nonexistant ini"); + } catch (SentryConfigurationException e) { + // expected exception + } + } + }); + } + + @Test + public void testNoValidateNorImport() throws Exception { + runTestAsSubject(new TestOperation() { + @Override + public void runTestAsSubject() throws Exception { + String[] args = { "-mgr", "-f", INVALID_POLICY_INI, "-conf", confPath.getAbsolutePath()}; + SentryShellIndexer sentryTool = new SentryShellIndexer(); + try { + sentryTool.executeShell(args); + fail("Exception should be thrown for validating invalid ini"); + } catch (IllegalArgumentException e) { + // expected exception + } + } + }); + } + + @Test + public void testConvertInvalidIni() throws Exception { + runTestAsSubject(new TestOperation() { + @Override + public void runTestAsSubject() throws Exception { + // test: validate an invalid ini + String[] args = { "-mgr", "-f", INVALID_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-v", "-i"}; + SentryShellIndexer sentryTool = new SentryShellIndexer(); + try { + sentryTool.executeShell(args); + fail("Exception should be thrown for validating invalid ini"); + } catch (SentryConfigurationException e) { + // expected exception + } + + // test without validating, should not error + args = new String[] { "-mgr", "-f", INVALID_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-i"}; + sentryTool = new SentryShellIndexer(); + sentryTool.executeShell(args); + } + }); + } + + @Test + public void testCompatCheck() throws Exception { + runTestAsSubject(new TestOperation() { + @Override + public void runTestAsSubject() throws Exception { + // test: validate an invalid ini + String[] args = { "-mgr", "-f", CASE_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-v", "-i", "-c"}; + SentryShellIndexer sentryTool = new SentryShellIndexer(); + try { + sentryTool.executeShell(args); + fail("Exception should be thrown for validating invalid ini"); + } catch (SentryConfigurationException e) { + assertEquals("Expected error", 1, e.getConfigErrors().size()); + String error = e.getConfigErrors().get(0); + assertCasedRoleNamesInMessage(error, "RoLe1", "rOlE1"); + String warning = e.getConfigWarnings().get(0); + assertCasedRoleNamesInMessage(warning, "ROLE2", "RoLe1", "rOlE1"); + assertEquals("Expected warning", 1, e.getConfigWarnings().size()); + } + + // test without compat checking + args = new String[] { "-mgr", "-f", CASE_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-i", "-v"}; + sentryTool = new SentryShellIndexer(); + sentryTool.executeShell(args); + } + }); + } + + // Test that a valid compat check doesn't throw an exception + @Test + public void testCompatCheckValid() throws Exception { + runTestAsSubject(new TestOperation() { + @Override + public void runTestAsSubject() throws Exception { + String[] args = { "-mgr", "-f", VALID_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-v", "-i", "-c"}; + SentryShellIndexer sentryTool = new SentryShellIndexer(); + sentryTool.executeShell(args); + } + }); + } + + private void assertCasedRoleNamesInMessage(String message, String ... casedRoleNames) { + for (String casedRoleName : casedRoleNames) { + assertTrue("Expected cased role name: " + casedRoleName, message.contains(casedRoleName)); + } + } + } http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryConfigToolSolr.java ---------------------------------------------------------------------- diff --git a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryConfigToolSolr.java b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryConfigToolSolr.java new file mode 100644 index 0000000..292521d --- /dev/null +++ b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryConfigToolSolr.java @@ -0,0 +1,260 @@ + /** + * 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.cli.tools; + +import com.google.common.io.Files; +import com.google.common.collect.Sets; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.File; +import java.io.FileOutputStream; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.io.FileUtils; +import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceIntegrationBase; +import org.apache.sentry.provider.db.generic.service.thrift.TSentryRole; +import org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege; +import org.apache.sentry.core.common.exception.SentryConfigurationException; + +import org.apache.sentry.provider.db.generic.tools.GenericPrivilegeConverter;import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class TestSentryConfigToolSolr extends SentryGenericServiceIntegrationBase { + private static String VALID_POLICY_INI = TestSentryConfigToolSolr.class.getClassLoader().getResource("solr_config_import_tool.ini").getPath(); + private static String INVALID_POLICY_INI = TestSentryConfigToolSolr.class.getClassLoader().getResource("solr_invalid.ini").getPath(); + private static String CASE_POLICY_INI = TestSentryConfigToolSolr.class.getClassLoader().getResource("solr_case.ini").getPath(); + private File confDir; + private File confPath; + private String requestorName = ""; + private String service = "service1"; + + @Before + public void prepareForTest() throws Exception { + confDir = Files.createTempDir(); + confPath = new File(confDir, "sentry-site.xml"); + if (confPath.createNewFile()) { + FileOutputStream to = new FileOutputStream(confPath); + conf.writeXml(to); + to.close(); + } + requestorName = clientUgi.getShortUserName();//System.getProperty("user.name", ""); + Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP); + setLocalGroupMapping(requestorName, requestorUserGroupNames); + // add ADMIN_USER for the after() in SentryServiceIntegrationBase + setLocalGroupMapping(ADMIN_USER, requestorUserGroupNames); + writePolicyFile(); + } + + @After + public void clearTestData() throws Exception { + FileUtils.deleteQuietly(confDir); + + // clear roles and privileges + Set<TSentryRole> tRoles = client.listAllRoles(requestorName, SOLR); + for (TSentryRole tRole : tRoles) { + String role = tRole.getRoleName(); + Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName( + requestorName, role, SOLR, service); + for (TSentryPrivilege privilege : privileges) { + client.revokePrivilege(requestorName, role, SOLR, privilege); + } + client.dropRole(requestorName, role, SOLR); + } + } + + @Test + public void testConvertIni() throws Exception { + runTestAsSubject(new TestOperation() { + @Override + public void runTestAsSubject() throws Exception { + String[] args = { "-p", VALID_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-v", "-i"}; + SentryConfigToolSolr sentryTool = new SentryConfigToolSolr(); + sentryTool.executeConfigTool(args); + + Map<String, Set<String>> groupMapping = new HashMap<String, Set<String>>(); + groupMapping.put("corporal_role", Sets.newHashSet("corporal", "sergeant", "general", "commander_in_chief")); + groupMapping.put("sergeant_role", Sets.newHashSet("sergeant", "general", "commander_in_chief")); + groupMapping.put("general_role", Sets.newHashSet("general", "commander_in_chief")); + groupMapping.put("commander_in_chief_role", Sets.newHashSet("commander_in_chief")); + + Map<String, Set<String>> privilegeMapping = new HashMap<String, Set<String>>(); + privilegeMapping.put("corporal_role", + Sets.newHashSet("Collection=info->action=query", "Collection=info->action=update")); + privilegeMapping.put("sergeant_role", + Sets.newHashSet("Collection=info->action=update")); + privilegeMapping.put("general_role", + Sets.newHashSet("Collection=info->action=*")); + privilegeMapping.put("commander_in_chief_role", + Sets.newHashSet("Collection=*->action=*")); + + // check roles + Set<TSentryRole> tRoles = client.listAllRoles(requestorName, SOLR); + assertEquals("Unexpected number of roles", groupMapping.keySet().size(), tRoles.size()); + Set<String> roles = new HashSet<String>(); + for (TSentryRole tRole : tRoles) { + roles.add(tRole.getRoleName()); + } + + for (String expectedRole : groupMapping.keySet()) { + assertTrue("Didn't find expected role: " + expectedRole, roles.contains(expectedRole)); + } + + // check groups + for (TSentryRole tRole : tRoles) { + Set<String> expectedGroups = groupMapping.get(tRole.getRoleName()); + assertEquals("Group size doesn't match for role: " + tRole.getRoleName(), + expectedGroups.size(), tRole.getGroups().size()); + assertTrue("Group does not contain all expected members for role: " + tRole.getRoleName(), + tRole.getGroups().containsAll(expectedGroups)); + } + + // check privileges + GenericPrivilegeConverter convert = new GenericPrivilegeConverter(SOLR, service); + for (String role : roles) { + Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName( + requestorName, role, SOLR, service); + Set<String> expectedPrivileges = privilegeMapping.get(role); + assertEquals("Privilege set size doesn't match for role: " + role, + expectedPrivileges.size(), privileges.size()); + + Set<String> privilegeStrs = new HashSet<String>(); + for (TSentryPrivilege privilege : privileges) { + privilegeStrs.add(convert.toString(privilege)); + } + + for (String expectedPrivilege : expectedPrivileges) { + assertTrue("Did not find expected privilege: " + expectedPrivilege + " in " + privilegeStrs, + privilegeStrs.contains(expectedPrivilege)); + } + } + } + }); + } + + @Test + public void testNoPolicyFile() throws Exception { + runTestAsSubject(new TestOperation() { + @Override + public void runTestAsSubject() throws Exception { + String[] args = { "-p", INVALID_POLICY_INI + "Foobar", "-conf", confPath.getAbsolutePath(), "-v", "-i"}; + SentryConfigToolSolr sentryTool = new SentryConfigToolSolr(); + try { + sentryTool.executeConfigTool(args); + fail("Exception should be thrown for nonexistant ini"); + } catch (SentryConfigurationException e) { + // expected exception + } + } + }); + } + + @Test + public void testNoValidateNorImport() throws Exception { + runTestAsSubject(new TestOperation() { + @Override + public void runTestAsSubject() throws Exception { + String[] args = { "-p", INVALID_POLICY_INI, "-conf", confPath.getAbsolutePath()}; + SentryConfigToolSolr sentryTool = new SentryConfigToolSolr(); + try { + sentryTool.executeConfigTool(args); + fail("Exception should be thrown for validating invalid ini"); + } catch (IllegalArgumentException e) { + // expected exception + } + } + }); + } + + @Test + public void testConvertInvalidIni() throws Exception { + runTestAsSubject(new TestOperation() { + @Override + public void runTestAsSubject() throws Exception { + // test: validate an invalid ini + String[] args = { "-p", INVALID_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-v", "-i"}; + SentryConfigToolSolr sentryTool = new SentryConfigToolSolr(); + try { + sentryTool.executeConfigTool(args); + fail("Exception should be thrown for validating invalid ini"); + } catch (SentryConfigurationException e) { + // expected exception + } + + // test without validating, should not error + args = new String[] { "-p", INVALID_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-i"}; + sentryTool = new SentryConfigToolSolr(); + sentryTool.executeConfigTool(args); + } + }); + } + + @Test + public void testCompatCheck() throws Exception { + runTestAsSubject(new TestOperation() { + @Override + public void runTestAsSubject() throws Exception { + // test: validate an invalid ini + String[] args = { "-p", CASE_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-v", "-i", "-c"}; + SentryConfigToolSolr sentryTool = new SentryConfigToolSolr(); + try { + sentryTool.executeConfigTool(args); + fail("Exception should be thrown for validating invalid ini"); + } catch (SentryConfigurationException e) { + assertEquals("Expected error", 1, e.getConfigErrors().size()); + String error = e.getConfigErrors().get(0); + assertCasedRoleNamesInMessage(error, "RoLe1", "rOlE1"); + String warning = e.getConfigWarnings().get(0); + assertCasedRoleNamesInMessage(warning, "ROLE2", "RoLe1", "rOlE1"); + assertEquals("Expected warning", 1, e.getConfigWarnings().size()); + } + + // test without compat checking + args = new String[] { "-p", CASE_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-i", "-v"}; + sentryTool = new SentryConfigToolSolr(); + sentryTool.executeConfigTool(args); + } + }); + } + + // Test that a valid compat check doesn't throw an exception + @Test + public void testCompatCheckValid() throws Exception { + runTestAsSubject(new TestOperation() { + @Override + public void runTestAsSubject() throws Exception { + String[] args = { "-p", VALID_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-v", "-i", "-c"}; + SentryConfigToolSolr sentryTool = new SentryConfigToolSolr(); + sentryTool.executeConfigTool(args); + } + }); + } + + private void assertCasedRoleNamesInMessage(String message, String ... casedRoleNames) { + for (String casedRoleName : casedRoleNames) { + assertTrue("Expected cased role name: " + casedRoleName, message.contains(casedRoleName)); + } + } +} http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentrySchemaTool.java ---------------------------------------------------------------------- diff --git a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentrySchemaTool.java b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentrySchemaTool.java new file mode 100644 index 0000000..657a8fe --- /dev/null +++ b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentrySchemaTool.java @@ -0,0 +1,113 @@ +/** + * 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.cli.tools; + +import java.io.File; + +import org.apache.hadoop.conf.Configuration; +import org.apache.sentry.core.common.exception.SentryUserException; +import org.apache.sentry.provider.db.service.persistent.SentryStoreSchemaInfo; +import org.apache.sentry.service.thrift.ServiceConstants.ServerConfig; +import org.junit.Before; +import org.junit.Test; + +import com.google.common.io.Files; + +public class TestSentrySchemaTool { + private Configuration sentryConf; + private SentrySchemaTool schemaTool; + + private static final String OLDEST_INIT_VERSION = "1.4.0"; + private static final String sentry_db_resources = findSentryProviderDBDir()+"/sentry-provider/sentry-provider-db/src/main/resources"; + + @Before + public void defaultSetup() throws Exception { + System.out.println(System.getProperty("user.dir")); + sentryConf = new Configuration(); + File dbDir = new File(Files.createTempDir(), "sentry_policy_db"); + sentryConf.set(ServerConfig.SENTRY_STORE_JDBC_URL, + "jdbc:derby:;databaseName=" + dbDir.getPath() + ";create=true"); + sentryConf.set(ServerConfig.SENTRY_STORE_JDBC_PASS, "dummy"); + schemaTool = new SentrySchemaTool(sentry_db_resources, sentryConf, + "derby"); + } + + private void nonDefaultsetup() throws Exception { + System.out.println(System.getProperty("user.dir")); + sentryConf = new Configuration(); + File dbDir = new File(Files.createTempDir(), "sentry_policy_db"); + sentryConf.set(ServerConfig.SENTRY_STORE_JDBC_URL, + "jdbc:derby:;databaseName=" + dbDir.getPath() + ";create=true"); + sentryConf.set(ServerConfig.SENTRY_STORE_JDBC_PASS, "dummy"); + schemaTool = new SentrySchemaTool(sentry_db_resources, sentryConf, + "derby"); + } + + /**This is a pretty ugly hack. Since the derby files are in sentry-provider-db, + * we need to go back a few directories to get to it. Running in Intellij defaults + * to the root dir of the project, while running the unit tests on the command line + * defaults to the root/sentry-tools dir. Using the .class.getResource() defaults to + * the target/test-classes/blah dir. So that's not usable. + * + * @return + */ + private static String findSentryProviderDBDir() { + + String pathToSentryProject = System.getProperty("user.dir"); + if(pathToSentryProject.endsWith("/sentry-tools")) { + return pathToSentryProject.substring(0, pathToSentryProject.length()- "/sentry-tools".length()); + } + return pathToSentryProject; + } + @Test + public void testInitNonDefault() throws Exception { + nonDefaultsetup(); + schemaTool.doInit(); + schemaTool.verifySchemaVersion(); + } + + @Test + public void testInit() throws Exception { + schemaTool.doInit(); + schemaTool.verifySchemaVersion(); + } + + @Test + public void testInitTo() throws Exception { + schemaTool.doInit(SentryStoreSchemaInfo.getSentryVersion()); + schemaTool.verifySchemaVersion(); + } + + @Test(expected = SentryUserException.class) + public void testDryRun() throws Exception { + schemaTool.setDryRun(true); + schemaTool.doInit(); + schemaTool.setDryRun(false); + // verification should fail since dryRun didn't create the actual schema + schemaTool.verifySchemaVersion(); + } + + @Test + public void testUpgrade() throws Exception { + schemaTool.doInit(OLDEST_INIT_VERSION); + schemaTool.doUpgrade(); + schemaTool.verifySchemaVersion(); + } + +} http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellHive.java ---------------------------------------------------------------------- diff --git a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellHive.java b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellHive.java new file mode 100644 index 0000000..46dc436 --- /dev/null +++ b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellHive.java @@ -0,0 +1,613 @@ +/** + * 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.cli.tools; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.PrintStream; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import org.apache.commons.io.FileUtils; +import org.apache.sentry.core.common.exception.SentryUserException; +import org.apache.sentry.provider.db.service.thrift.TSentryPrivilege; +import org.apache.sentry.provider.db.service.thrift.TSentryRole; +import org.apache.sentry.service.thrift.SentryServiceIntegrationBase; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.google.common.collect.Sets; +import com.google.common.io.Files; + +public class TestSentryShellHive extends SentryServiceIntegrationBase { + + private File confDir; + private File confPath; + private static String TEST_ROLE_NAME_1 = "testRole1"; + private static String TEST_ROLE_NAME_2 = "testRole2"; + private String requestorName = ""; + + @Before + public void prepareForTest() throws Exception { + confDir = Files.createTempDir(); + confPath = new File(confDir, "sentry-site.xml"); + if (confPath.createNewFile()) { + FileOutputStream to = new FileOutputStream(confPath); + conf.writeXml(to); + to.close(); + } + requestorName = clientUgi.getShortUserName(); + Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP); + setLocalGroupMapping(requestorName, requestorUserGroupNames); + // add ADMIN_USER for the after() in SentryServiceIntegrationBase + setLocalGroupMapping(ADMIN_USER, requestorUserGroupNames); + writePolicyFile(); + } + + @After + public void clearTestData() throws Exception { + FileUtils.deleteQuietly(confDir); + } + + @Test + public void testCreateDropRole() throws Exception { + runTestAsSubject(new TestOperation() { + @Override + public void runTestAsSubject() throws Exception { + // test: create role with -cr + String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() }; + SentryShellHive.main(args); + // test: create role with --create_role + args = new String[] { "--create_role", "-r", TEST_ROLE_NAME_2, "-conf", + confPath.getAbsolutePath() }; + SentryShellHive.main(args); + + // validate the result, list roles with -lr + args = new String[] { "-lr", "-conf", confPath.getAbsolutePath() }; + SentryShellHive sentryShell = new SentryShellHive(); + Set<String> roleNames = getShellResultWithOSRedirect(sentryShell, args, true); + validateRoleNames(roleNames, TEST_ROLE_NAME_1, TEST_ROLE_NAME_2); + + // validate the result, list roles with --list_role + args = new String[] { "--list_role", "-conf", confPath.getAbsolutePath() }; + sentryShell = new SentryShellHive(); + roleNames = getShellResultWithOSRedirect(sentryShell, args, true); + validateRoleNames(roleNames, TEST_ROLE_NAME_1, TEST_ROLE_NAME_2); + + // test: drop role with -dr + args = new String[] { "-dr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() }; + SentryShellHive.main(args); + // test: drop role with --drop_role + args = new String[] { "--drop_role", "-r", TEST_ROLE_NAME_2, "-conf", + confPath.getAbsolutePath() }; + SentryShellHive.main(args); + + // validate the result + Set<TSentryRole> roles = client.listAllRoles(requestorName); + assertEquals("Incorrect number of roles", 0, roles.size()); + } + }); + } + + @Test + public void testAddDeleteRoleForGroup() throws Exception { + runTestAsSubject(new TestOperation() { + @Override + public void runTestAsSubject() throws Exception { + // create the role for test + client.createRole(requestorName, TEST_ROLE_NAME_1); + client.createRole(requestorName, TEST_ROLE_NAME_2); + // test: add role to group with -arg + String[] args = { "-arg", "-r", TEST_ROLE_NAME_1, "-g", "testGroup1", "-conf", + confPath.getAbsolutePath() }; + SentryShellHive.main(args); + // test: add role to multiple groups + args = new String[] { "-arg", "-r", TEST_ROLE_NAME_1, "-g", "testGroup2,testGroup3", + "-conf", + confPath.getAbsolutePath() }; + SentryShellHive.main(args); + // test: add role to group with --add_role_group + args = new String[] { "--add_role_group", "-r", TEST_ROLE_NAME_2, "-g", "testGroup1", + "-conf", + confPath.getAbsolutePath() }; + SentryShellHive.main(args); + + // validate the result list roles with -lr and -g + args = new String[] { "-lr", "-g", "testGroup1", "-conf", confPath.getAbsolutePath() }; + SentryShellHive sentryShell = new SentryShellHive(); + Set<String> roleNames = getShellResultWithOSRedirect(sentryShell, args, true); + validateRoleNames(roleNames, TEST_ROLE_NAME_1, TEST_ROLE_NAME_2); + + + // list roles with --list_role and -g + args = new String[] { "--list_role", "-g", "testGroup2", "-conf", + confPath.getAbsolutePath() }; + sentryShell = new SentryShellHive(); + roleNames = getShellResultWithOSRedirect(sentryShell, args, true); + validateRoleNames(roleNames, TEST_ROLE_NAME_1); + + args = new String[] { "--list_role", "-g", "testGroup3", "-conf", + confPath.getAbsolutePath() }; + sentryShell = new SentryShellHive(); + roleNames = getShellResultWithOSRedirect(sentryShell, args, true); + validateRoleNames(roleNames, TEST_ROLE_NAME_1); + + // List the groups and roles via listGroups + args = new String[] { "--list_group", "-conf", confPath.getAbsolutePath()}; + sentryShell = new SentryShellHive(); + Set<String> groups = getShellResultWithOSRedirect(sentryShell, args, true); + assertEquals(3, groups.size()); + assertTrue(groups.contains("testGroup3 = testrole1")); + assertTrue(groups.contains("testGroup2 = testrole1")); + assertTrue(groups.contains("testGroup1 = testrole2, testrole1")); + + // test: delete role from group with -drg + args = new String[] { "-drg", "-r", TEST_ROLE_NAME_1, "-g", "testGroup1", "-conf", + confPath.getAbsolutePath() }; + SentryShellHive.main(args); + // test: delete role to multiple groups + args = new String[] { "-drg", "-r", TEST_ROLE_NAME_1, "-g", "testGroup2,testGroup3", + "-conf", + confPath.getAbsolutePath() }; + SentryShellHive.main(args); + // test: delete role from group with --delete_role_group + args = new String[] { "--delete_role_group", "-r", TEST_ROLE_NAME_2, "-g", "testGroup1", + "-conf", confPath.getAbsolutePath() }; + SentryShellHive.main(args); + + // validate the result + Set<TSentryRole> roles = client.listRolesByGroupName(requestorName, "testGroup1"); + assertEquals("Incorrect number of roles", 0, roles.size()); + roles = client.listRolesByGroupName(requestorName, "testGroup2"); + assertEquals("Incorrect number of roles", 0, roles.size()); + roles = client.listRolesByGroupName(requestorName, "testGroup3"); + assertEquals("Incorrect number of roles", 0, roles.size()); + // clear the test data + client.dropRole(requestorName, TEST_ROLE_NAME_1); + client.dropRole(requestorName, TEST_ROLE_NAME_2); + } + }); + } + + @Test + public void testGrantRevokePrivilegeWithShortOption() throws Exception { + runTestAsSubject(new TestOperation() { + @Override + public void runTestAsSubject() throws Exception { + // create the role for test + client.createRole(requestorName, TEST_ROLE_NAME_1); + client.createRole(requestorName, TEST_ROLE_NAME_2); + + // test: grant privilege to role with -gpr + String[] args = { "-gpr", "-r", TEST_ROLE_NAME_1, "-p", + "server=server1->action=*", + "-conf", confPath.getAbsolutePath() }; + SentryShellHive.main(args); + args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p", + "server=server1->db=db1->action=select", "-conf", confPath.getAbsolutePath() }; + SentryShellHive.main(args); + args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p", + "server=server1->db=db1->table=tbl1->action=insert", "-conf", + confPath.getAbsolutePath() }; + SentryShellHive.main(args); + args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p", + "server=server1->db=db1->table=tbl1->column=col1->action=insert", "-conf", + confPath.getAbsolutePath() }; + SentryShellHive.main(args); + args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p", + "server=server1->db=db1->table=tbl1->column=col2->action=insert->grantoption=true", + "-conf", confPath.getAbsolutePath() }; + SentryShellHive.main(args); + args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p", + "server=server1->uri=hdfs://path/testuri->action=*", "-conf", confPath.getAbsolutePath() }; + SentryShellHive.main(args); + + // test the list privilege with -lp + args = new String[] { "-lp", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() }; + SentryShellHive sentryShell = new SentryShellHive(); + Set<String> privilegeStrs = getShellResultWithOSRedirect(sentryShell, args, true); + // validate the result for -lp + assertEquals("Incorrect number of privileges", 6, privilegeStrs.size()); + assertTrue(privilegeStrs.contains("server=server1->action=*")); + assertTrue(privilegeStrs.contains("server=server1->db=db1->action=select")); + assertTrue(privilegeStrs.contains("server=server1->db=db1->table=tbl1->action=insert")); + assertTrue(privilegeStrs + .contains("server=server1->db=db1->table=tbl1->column=col1->action=insert")); + assertTrue(privilegeStrs + .contains("server=server1->db=db1->table=tbl1->column=col2->action=insert->grantoption=true")); + assertTrue(privilegeStrs.contains("server=server1->uri=hdfs://path/testuri->action=*")); + + // test: revoke privilege from role with -rpr + args = new String[] { "-rpr", "-r", TEST_ROLE_NAME_1, "-p", + "server=server1->db=db1->table=tbl1->column=col1->action=insert", "-conf", + confPath.getAbsolutePath() }; + SentryShellHive.main(args); + Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(requestorName, + TEST_ROLE_NAME_1); + assertEquals("Incorrect number of privileges", 5, privileges.size()); + + args = new String[] { "-rpr", "-r", TEST_ROLE_NAME_1, "-p", + "server=server1->db=db1->table=tbl1->column=col2->action=insert->grantoption=true", + "-conf", confPath.getAbsolutePath() }; + SentryShellHive.main(args); + privileges = client.listAllPrivilegesByRoleName(requestorName, TEST_ROLE_NAME_1); + assertEquals("Incorrect number of privileges", 4, privileges.size()); + + args = new String[] { "-rpr", "-r", TEST_ROLE_NAME_1, "-p", + "server=server1->uri=hdfs://path/testuri->action=*", "-conf", confPath.getAbsolutePath() }; + SentryShellHive.main(args); + privileges = client.listAllPrivilegesByRoleName(requestorName, TEST_ROLE_NAME_1); + assertEquals("Incorrect number of privileges", 3, privileges.size()); + + args = new String[] { "-rpr", "-r", TEST_ROLE_NAME_1, "-p", + "server=server1->db=db1->table=tbl1->action=insert", "-conf", + confPath.getAbsolutePath() }; + SentryShellHive.main(args); + privileges = client.listAllPrivilegesByRoleName(requestorName, TEST_ROLE_NAME_1); + assertEquals("Incorrect number of privileges", 2, privileges.size()); + + args = new String[] { "-rpr", "-r", TEST_ROLE_NAME_1, "-p", + "server=server1->db=db1->action=select", "-conf", confPath.getAbsolutePath() }; + SentryShellHive.main(args); + privileges = client.listAllPrivilegesByRoleName(requestorName, TEST_ROLE_NAME_1); + assertEquals("Incorrect number of privileges", 1, privileges.size()); + + args = new String[] { "-rpr", "-r", TEST_ROLE_NAME_1, "-p", "server=server1->action=*", + "-conf", + confPath.getAbsolutePath() }; + SentryShellHive.main(args); + privileges = client.listAllPrivilegesByRoleName(requestorName, TEST_ROLE_NAME_1); + assertEquals("Incorrect number of privileges", 0, privileges.size()); + + // clear the test data + client.dropRole(requestorName, TEST_ROLE_NAME_1); + client.dropRole(requestorName, TEST_ROLE_NAME_2); + } + }); + } + + @Test + public void testGrantRevokePrivilegeWithLongOption() throws Exception { + runTestAsSubject(new TestOperation() { + @Override + public void runTestAsSubject() throws Exception { + // create the role for test + client.createRole(requestorName, TEST_ROLE_NAME_1); + client.createRole(requestorName, TEST_ROLE_NAME_2); + + // test: grant privilege to role with -gpr + String[] args = { "--grant_privilege_role", "-r", TEST_ROLE_NAME_1, "-p", + "server=server1->action=*", "-conf", confPath.getAbsolutePath() }; + SentryShellHive.main(args); + args = new String[] { "--grant_privilege_role", "-r", TEST_ROLE_NAME_1, "-p", + "server=server1->db=db1->action=select", "-conf", confPath.getAbsolutePath() }; + SentryShellHive.main(args); + args = new String[] { "--grant_privilege_role", "-r", TEST_ROLE_NAME_1, "-p", + "server=server1->db=db1->table=tbl1->action=insert", "-conf", + confPath.getAbsolutePath() }; + SentryShellHive.main(args); + args = new String[] { "--grant_privilege_role", "-r", TEST_ROLE_NAME_1, "-p", + "server=server1->db=db1->table=tbl1->column=col1->action=insert", "-conf", + confPath.getAbsolutePath() }; + SentryShellHive.main(args); + args = new String[] { "--grant_privilege_role", "-r", TEST_ROLE_NAME_1, "-p", + "server=server1->db=db1->table=tbl1->column=col2->action=insert->grantoption=true", + "-conf", confPath.getAbsolutePath() }; + SentryShellHive.main(args); + args = new String[] { "--grant_privilege_role", "-r", TEST_ROLE_NAME_1, "-p", + "server=server1->uri=hdfs://path/testuri->action=*", "-conf", confPath.getAbsolutePath() }; + SentryShellHive.main(args); + + // test the list privilege with -lp + args = new String[] { "--list_privilege", "-r", TEST_ROLE_NAME_1, "-conf", + confPath.getAbsolutePath() }; + SentryShellHive sentryShell = new SentryShellHive(); + Set<String> privilegeStrs = getShellResultWithOSRedirect(sentryShell, args, true); + // validate the result for -lp + assertEquals("Incorrect number of privileges", 6, privilegeStrs.size()); + assertTrue(privilegeStrs.contains("server=server1->action=*")); + assertTrue(privilegeStrs.contains("server=server1->db=db1->action=select")); + assertTrue(privilegeStrs.contains("server=server1->db=db1->table=tbl1->action=insert")); + assertTrue(privilegeStrs + .contains("server=server1->db=db1->table=tbl1->column=col1->action=insert")); + assertTrue(privilegeStrs + .contains("server=server1->db=db1->table=tbl1->column=col2->action=insert->grantoption=true")); + assertTrue(privilegeStrs.contains("server=server1->uri=hdfs://path/testuri->action=*")); + + // test: revoke privilege from role with -rpr + args = new String[] { "--revoke_privilege_role", "-r", TEST_ROLE_NAME_1, "-p", + "server=server1->db=db1->table=tbl1->column=col1->action=insert", "-conf", + confPath.getAbsolutePath() }; + SentryShellHive.main(args); + Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(requestorName, + TEST_ROLE_NAME_1); + assertEquals("Incorrect number of privileges", 5, privileges.size()); + + args = new String[] { "--revoke_privilege_role", "-r", TEST_ROLE_NAME_1, "-p", + "server=server1->db=db1->table=tbl1->column=col2->action=insert->grantoption=true", + "-conf", confPath.getAbsolutePath() }; + SentryShellHive.main(args); + privileges = client.listAllPrivilegesByRoleName(requestorName, TEST_ROLE_NAME_1); + assertEquals("Incorrect number of privileges", 4, privileges.size()); + + args = new String[] { "--revoke_privilege_role", "-r", TEST_ROLE_NAME_1, "-p", + "server=server1->uri=hdfs://path/testuri->action=*", "-conf", confPath.getAbsolutePath() }; + SentryShellHive.main(args); + privileges = client.listAllPrivilegesByRoleName(requestorName, TEST_ROLE_NAME_1); + assertEquals("Incorrect number of privileges", 3, privileges.size()); + + args = new String[] { "--revoke_privilege_role", "-r", TEST_ROLE_NAME_1, "-p", + "server=server1->db=db1->table=tbl1->action=insert", "-conf", + confPath.getAbsolutePath() }; + SentryShellHive.main(args); + privileges = client.listAllPrivilegesByRoleName(requestorName, TEST_ROLE_NAME_1); + assertEquals("Incorrect number of privileges", 2, privileges.size()); + + args = new String[] { "--revoke_privilege_role", "-r", TEST_ROLE_NAME_1, "-p", + "server=server1->db=db1->action=select", "-conf", confPath.getAbsolutePath() }; + SentryShellHive.main(args); + privileges = client.listAllPrivilegesByRoleName(requestorName, TEST_ROLE_NAME_1); + assertEquals("Incorrect number of privileges", 1, privileges.size()); + + args = new String[] { "--revoke_privilege_role", "-r", TEST_ROLE_NAME_1, "-p", + "server=server1->action=*", "-conf", confPath.getAbsolutePath() }; + SentryShellHive.main(args); + privileges = client.listAllPrivilegesByRoleName(requestorName, TEST_ROLE_NAME_1); + assertEquals("Incorrect number of privileges", 0, privileges.size()); + + // clear the test data + client.dropRole(requestorName, TEST_ROLE_NAME_1); + client.dropRole(requestorName, TEST_ROLE_NAME_2); + } + }); + } + + @Test + public void testNegativeCaseWithInvalidArgument() throws Exception { + runTestAsSubject(new TestOperation() { + @Override + public void runTestAsSubject() throws Exception { + client.createRole(requestorName, TEST_ROLE_NAME_1); + // test: create duplicate role with -cr + String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() }; + SentryShellHive sentryShell = new SentryShellHive(); + try { + sentryShell.executeShell(args); + fail("Exception should be thrown for creating duplicate role"); + } catch (SentryUserException e) { + // excepted exception + } + + // test: drop non-exist role with -dr + args = new String[] { "-dr", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath() }; + sentryShell = new SentryShellHive(); + try { + sentryShell.executeShell(args); + fail("Exception should be thrown for dropping non-exist role"); + } catch (SentryUserException e) { + // excepted exception + } + + // test: add non-exist role to group with -arg + args = new String[] { "-arg", "-r", TEST_ROLE_NAME_2, "-g", "testGroup1", "-conf", + confPath.getAbsolutePath() }; + sentryShell = new SentryShellHive(); + try { + sentryShell.executeShell(args); + fail("Exception should be thrown for granting non-exist role to group"); + } catch (SentryUserException e) { + // excepted exception + } + + // test: drop group from non-exist role with -drg + args = new String[] { "-drg", "-r", TEST_ROLE_NAME_2, "-g", "testGroup1", "-conf", + confPath.getAbsolutePath() }; + sentryShell = new SentryShellHive(); + try { + sentryShell.executeShell(args); + fail("Exception should be thrown for drop group from non-exist role"); + } catch (SentryUserException e) { + // excepted exception + } + + // test: grant privilege to role with the error privilege format + args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p", "serverserver1->action=*", + "-conf", confPath.getAbsolutePath() }; + sentryShell = new SentryShellHive(); + try { + sentryShell.executeShell(args); + fail("Exception should be thrown for the error privilege format, invalid key value."); + } catch (IllegalArgumentException e) { + // excepted exception + } + + // test: grant privilege to role with the error privilege hierarchy + args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p", + "server=server1->table=tbl1->column=col2->action=insert", "-conf", + confPath.getAbsolutePath() }; + sentryShell = new SentryShellHive(); + try { + sentryShell.executeShell(args); + fail("Exception should be thrown for the error privilege format, invalid key value."); + } catch (IllegalArgumentException e) { + // excepted exception + } + + // clear the test data + client.dropRole(requestorName, TEST_ROLE_NAME_1); + } + }); + } + + @Test + public void testNegativeCaseWithoutRequiredArgument() throws Exception { + runTestAsSubject(new TestOperation() { + @Override + public void runTestAsSubject() throws Exception { + String strOptionConf = "conf"; + client.createRole(requestorName, TEST_ROLE_NAME_1); + // test: the conf is required argument + String[] args = { "-cr", "-r", TEST_ROLE_NAME_1 }; + SentryShellHive sentryShell = new SentryShellHive(); + validateMissingParameterMsg(sentryShell, args, + SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + strOptionConf); + + // test: -r is required when create role + args = new String[] { "-cr", "-conf", confPath.getAbsolutePath() }; + sentryShell = new SentryShellHive(); + validateMissingParameterMsg(sentryShell, args, + SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME); + + // test: -r is required when drop role + args = new String[] { "-dr", "-conf", confPath.getAbsolutePath() }; + sentryShell = new SentryShellHive(); + validateMissingParameterMsg(sentryShell, args, + SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME); + + // test: -r is required when add role to group + args = new String[] { "-arg", "-g", "testGroup1", "-conf", confPath.getAbsolutePath() }; + sentryShell = new SentryShellHive(); + validateMissingParameterMsg(sentryShell, args, + SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME); + + // test: -g is required when add role to group + args = new String[] { "-arg", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath() }; + sentryShell = new SentryShellHive(); + validateMissingParameterMsg(sentryShell, args, + SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_GROUP_NAME); + + // test: -r is required when delete role from group + args = new String[] { "-drg", "-g", "testGroup1", "-conf", confPath.getAbsolutePath() }; + sentryShell = new SentryShellHive(); + validateMissingParameterMsg(sentryShell, args, + SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME); + + // test: -g is required when delete role from group + args = new String[] { "-drg", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath() }; + sentryShell = new SentryShellHive(); + validateMissingParameterMsg(sentryShell, args, + SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_GROUP_NAME); + + // test: -r is required when grant privilege to role + args = new String[] { "-gpr", "-p", "server=server1", "-conf", confPath.getAbsolutePath() }; + sentryShell = new SentryShellHive(); + validateMissingParameterMsg(sentryShell, args, + SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME); + + // test: -p is required when grant privilege to role + args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() }; + sentryShell = new SentryShellHive(); + validateMissingParameterMsg(sentryShell, args, + SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_PRIVILEGE); + + // test: -r is required when revoke privilege from role + args = new String[] { "-rpr", "-p", "server=server1", "-conf", confPath.getAbsolutePath() }; + sentryShell = new SentryShellHive(); + validateMissingParameterMsg(sentryShell, args, + SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME); + + // test: -p is required when revoke privilege from role + args = new String[] { "-rpr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() }; + sentryShell = new SentryShellHive(); + validateMissingParameterMsg(sentryShell, args, + SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_PRIVILEGE); + + // test: command option is required for shell + args = new String[] {"-conf", confPath.getAbsolutePath() }; + sentryShell = new SentryShellHive(); + validateMissingParameterMsgsContains(sentryShell, args, + SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + "[", + "-arg Add role to group", + "-cr Create role", + "-rpr Revoke privilege from role", + "-drg Delete role from group", + "-lr List role", + "-lp List privilege", + "-gpr Grant privilege to role", + "-dr Drop role"); + + // clear the test data + client.dropRole(requestorName, TEST_ROLE_NAME_1); + } + }); + } + + // redirect the System.out to ByteArrayOutputStream, then execute the command and parse the result. + private Set<String> getShellResultWithOSRedirect(SentryShellHive sentryShell, + String[] args, boolean exceptedExecuteResult) throws Exception { + PrintStream oldOut = System.out; + ByteArrayOutputStream outContent = new ByteArrayOutputStream(); + System.setOut(new PrintStream(outContent)); + assertEquals(exceptedExecuteResult, sentryShell.executeShell(args)); + Set<String> resultSet = Sets.newHashSet(outContent.toString().split("\n")); + System.setOut(oldOut); + return resultSet; + } + + private void validateRoleNames(Set<String> roleNames, String ... expectedRoleNames) { + if (expectedRoleNames != null && expectedRoleNames.length > 0) { + assertEquals("Found: " + roleNames.size() + " roles, expected: " + expectedRoleNames.length, + expectedRoleNames.length, roleNames.size()); + Set<String> lowerCaseRoles = new HashSet<String>(); + for (String role : roleNames) { + lowerCaseRoles.add(role.toLowerCase()); + } + + for (String expectedRole : expectedRoleNames) { + assertTrue("Expected role: " + expectedRole, + lowerCaseRoles.contains(expectedRole.toLowerCase())); + } + } + } + + private void validateMissingParameterMsg(SentryShellHive sentryShell, String[] args, + String exceptedErrorMsg) throws Exception { + Set<String> errorMsgs = getShellResultWithOSRedirect(sentryShell, args, false); + assertTrue(errorMsgs.contains(exceptedErrorMsg)); + } + + private void validateMissingParameterMsgsContains(SentryShellHive sentryShell, String[] args, + String ... expectedErrorMsgsContains) throws Exception { + Set<String> errorMsgs = getShellResultWithOSRedirect(sentryShell, args, false); + boolean foundAllMessages = false; + Iterator<String> it = errorMsgs.iterator(); + while (it.hasNext()) { + String errorMessage = it.next(); + boolean missingExpected = false; + for (String expectedContains : expectedErrorMsgsContains) { + if (!errorMessage.contains(expectedContains)) { + missingExpected = true; + break; + } + } + if (!missingExpected) { + foundAllMessages = true; + break; + } + } + assertTrue(foundAllMessages); + } +}
