You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sentry.apache.org by co...@apache.org on 2018/04/30 16:35:37 UTC
[1/9] sentry git commit: SENTRY-2207 Refactor out Sentry CLI from
sentry-provider-db into own module. Steve Moist,
reviewed by Colm O hEigeartaigh.
Repository: sentry
Updated Branches:
refs/heads/master 0668237aa -> 6752f14aa
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellSqoop.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellSqoop.java b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellSqoop.java
new file mode 100644
index 0000000..91b173d
--- /dev/null
+++ b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellSqoop.java
@@ -0,0 +1,531 @@
+/**
+ * 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.SentryUserException;
+import org.apache.sentry.provider.common.AuthorizationComponent;
+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.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import static org.junit.Assert.*;
+
+public class TestSentryShellSqoop extends SentryGenericServiceIntegrationBase {
+ 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 = "";
+ private String service = "sqoopServer1";
+
+ @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();//.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);
+ }
+
+ @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(), "-t", "sqoop" };
+ SentryShellGeneric.main(args);
+ // test: create role with --create_role
+ args = new String[] { "--create_role", "-r", TEST_ROLE_NAME_2, "-conf",
+ confPath.getAbsolutePath(), "-t", "sqoop" };
+ SentryShellGeneric.main(args);
+
+ // validate the result, list roles with -lr
+ args = new String[] { "-lr", "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
+ SentryShellGeneric sentryShell = new SentryShellGeneric();
+ 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(), "-t", "sqoop" };
+ sentryShell = new SentryShellGeneric();
+ 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(), "-t", "sqoop" };
+ SentryShellGeneric.main(args);
+ // test: drop role with --drop_role
+ args = new String[] { "--drop_role", "-r", TEST_ROLE_NAME_2, "-conf",
+ confPath.getAbsolutePath(), "-t", "sqoop" };
+ SentryShellGeneric.main(args);
+
+ // validate the result
+ Set<TSentryRole> roles = client.listAllRoles(requestorName, AuthorizationComponent.SQOOP);
+ assertEquals("Incorrect number of roles", 0, roles.size());
+ }
+ });
+ }
+
+ @Test
+ public void testAddDeleteRoleForGroup() throws Exception {
+ runTestAsSubject(new TestOperation() {
+ @Override
+ public void runTestAsSubject() throws Exception {
+ // Group names are case sensitive - mixed case names should work
+ String TEST_GROUP_1 = "testGroup1";
+ String TEST_GROUP_2 = "testGroup2";
+ String TEST_GROUP_3 = "testGroup3";
+
+ // create the role for test
+ client.createRole(requestorName, TEST_ROLE_NAME_1, AuthorizationComponent.SQOOP);
+ client.createRole(requestorName, TEST_ROLE_NAME_2, AuthorizationComponent.SQOOP);
+ // test: add role to group with -arg
+ String[] args = { "-arg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_1, "-conf",
+ confPath.getAbsolutePath(), "-t", "sqoop" };
+ SentryShellGeneric.main(args);
+ // test: add role to multiple groups
+ args = new String[] { "-arg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_2 + "," + TEST_GROUP_3,
+ "-conf",
+ confPath.getAbsolutePath(), "-t", "sqoop" };
+ SentryShellGeneric.main(args);
+ // test: add role to group with --add_role_group
+ args = new String[] { "--add_role_group", "-r", TEST_ROLE_NAME_2, "-g", TEST_GROUP_1,
+ "-conf",
+ confPath.getAbsolutePath(), "-t", "sqoop" };
+ SentryShellGeneric.main(args);
+
+ // validate the result list roles with -lr and -g
+ args = new String[] { "-lr", "-g", TEST_GROUP_1, "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
+ SentryShellGeneric sentryShell = new SentryShellGeneric();
+ 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", TEST_GROUP_2, "-conf",
+ confPath.getAbsolutePath(), "-t", "sqoop" };
+ sentryShell = new SentryShellGeneric();
+ roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+ validateRoleNames(roleNames, TEST_ROLE_NAME_1);
+
+ args = new String[] { "--list_role", "-g", TEST_GROUP_3, "-conf",
+ confPath.getAbsolutePath(), "-t", "sqoop" };
+ sentryShell = new SentryShellGeneric();
+ 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(), "-t", "sqoop" };
+ sentryShell = new SentryShellGeneric();
+ 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", TEST_GROUP_1, "-conf",
+ confPath.getAbsolutePath(), "-t", "sqoop" };
+ SentryShellGeneric.main(args);
+ // test: delete role to multiple groups
+ args = new String[] { "-drg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_2 + "," + TEST_GROUP_3,
+ "-conf",
+ confPath.getAbsolutePath(), "-t", "sqoop" };
+ SentryShellGeneric.main(args);
+ // test: delete role from group with --delete_role_group
+ args = new String[] { "--delete_role_group", "-r", TEST_ROLE_NAME_2, "-g", TEST_GROUP_1,
+ "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
+ SentryShellGeneric.main(args);
+
+ // validate the result
+ Set<TSentryRole> roles = client.listRolesByGroupName(requestorName, TEST_GROUP_1, AuthorizationComponent.SQOOP);
+ assertEquals("Incorrect number of roles", 0, roles.size());
+ roles = client.listRolesByGroupName(requestorName, TEST_GROUP_2, AuthorizationComponent.SQOOP);
+ assertEquals("Incorrect number of roles", 0, roles.size());
+ roles = client.listRolesByGroupName(requestorName, TEST_GROUP_3, AuthorizationComponent.SQOOP);
+ assertEquals("Incorrect number of roles", 0, roles.size());
+ // clear the test data
+ client.dropRole(requestorName, TEST_ROLE_NAME_1, AuthorizationComponent.SQOOP);
+ client.dropRole(requestorName, TEST_ROLE_NAME_2, AuthorizationComponent.SQOOP);
+ }
+ });
+ }
+
+ @Test
+ public void testCaseSensitiveGroupName() throws Exception {
+ runTestAsSubject(new TestOperation() {
+ @Override
+ public void runTestAsSubject() throws Exception {
+
+ // create the role for test
+ client.createRole(requestorName, TEST_ROLE_NAME_1, AuthorizationComponent.SQOOP);
+ // add role to a group (lower case)
+ String[] args = {"-arg", "-r", TEST_ROLE_NAME_1, "-g", "group1", "-conf",
+ confPath.getAbsolutePath(), "-t", "sqoop"};
+ SentryShellGeneric.main(args);
+
+ // validate the roles when group name is same case as above
+ args = new String[]{"-lr", "-g", "group1", "-conf", confPath.getAbsolutePath(), "-t", "sqoop"};
+ SentryShellGeneric sentryShell = new SentryShellGeneric();
+ Set<String> roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+ validateRoleNames(roleNames, TEST_ROLE_NAME_1);
+
+ // roles should be empty when group name is different case than above
+ args = new String[]{"-lr", "-g", "GROUP1", "-conf", confPath.getAbsolutePath(), "-t", "sqoop"};
+ roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+ validateRoleNames(roleNames);
+ }
+ });
+ }
+
+ public static String grant(boolean shortOption) {
+ return shortOption ? "-gpr" : "--grant_privilege_role";
+ }
+
+ public static String revoke(boolean shortOption) {
+ return shortOption ? "-rpr" : "--revoke_privilege_role";
+ }
+
+ public static String list(boolean shortOption) {
+ return shortOption ? "-lp" : "--list_privilege";
+ }
+
+ private void assertGrantRevokePrivilege(final boolean shortOption) throws Exception {
+ runTestAsSubject(new TestOperation() {
+ @Override
+ public void runTestAsSubject() throws Exception {
+ // create the role for test
+ client.createRole(requestorName, TEST_ROLE_NAME_1, AuthorizationComponent.SQOOP);
+ client.createRole(requestorName, TEST_ROLE_NAME_2, AuthorizationComponent.SQOOP);
+
+ String [] privs = {
+ "SERVER=sqoopserver1->CONNECTOR=c1->action=read",
+ "SERVER=sqoopserver1->JOB=j1->action=write",
+ "SERVER=sqoopserver1->LINK=l1->action=read",
+ };
+ for (int i = 0; i < privs.length; ++i) {
+ // test: grant privilege to role
+ String [] args = new String [] { grant(shortOption), "-r", TEST_ROLE_NAME_1, "-p",
+ privs[ i ],
+ "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
+ SentryShellGeneric.main(args);
+ }
+
+ // test the list privilege
+ String [] args = new String[] { list(shortOption), "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
+ SentryShellGeneric sentryShell = new SentryShellGeneric();
+ Set<String> privilegeStrs = getShellResultWithOSRedirect(sentryShell, args, true);
+
+ assertEquals("Incorrect number of privileges", privs.length, privilegeStrs.size());
+ for (int i = 0; i < privs.length; ++i) {
+ assertTrue("Expected privilege: " + privs[i] + " in " + Arrays.toString(privilegeStrs.toArray()), privilegeStrs.contains(privs[i]));
+ }
+
+ for (int i = 0; i < privs.length; ++i) {
+ args = new String[] { revoke(shortOption), "-r", TEST_ROLE_NAME_1, "-p",
+ privs[ i ], "-conf",
+ confPath.getAbsolutePath(), "-t", "sqoop" };
+ SentryShellGeneric.main(args);
+ Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(requestorName,
+ TEST_ROLE_NAME_1, AuthorizationComponent.SQOOP, service);
+ assertEquals("Incorrect number of privileges. Received privileges: " + Arrays.toString(privileges.toArray()), privs.length - (i + 1), privileges.size());
+ }
+
+ // clear the test data
+ client.dropRole(requestorName, TEST_ROLE_NAME_1, AuthorizationComponent.SQOOP);
+ client.dropRole(requestorName, TEST_ROLE_NAME_2, AuthorizationComponent.SQOOP);
+ }
+ });
+ }
+
+
+ @Test
+ public void testGrantRevokePrivilegeWithShortOption() throws Exception {
+ assertGrantRevokePrivilege(true);
+ }
+
+ @Test
+ public void testGrantRevokePrivilegeWithLongOption() throws Exception {
+ assertGrantRevokePrivilege(false);
+ }
+
+ @Test
+ public void testNegativeCaseWithInvalidArgument() throws Exception {
+ runTestAsSubject(new TestOperation() {
+ @Override
+ public void runTestAsSubject() throws Exception {
+ client.createRole(requestorName, TEST_ROLE_NAME_1, AuthorizationComponent.SQOOP);
+ // test: create duplicate role with -cr
+ String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
+ SentryShellGeneric sentryShell = new SentryShellGeneric();
+ try {
+ sentryShell.executeShell(args);
+ fail("Exception should be thrown for creating duplicate role");
+ } catch (SentryUserException e) {
+ // expected exception
+ } catch (Exception e) {
+ fail ("Unexpected exception received. " + e);
+ }
+
+ // test: drop non-exist role with -dr
+ args = new String[] { "-dr", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
+ sentryShell = new SentryShellGeneric();
+ try {
+ sentryShell.executeShell(args);
+ fail("Exception should be thrown for dropping non-exist role");
+ } catch (SentryUserException e) {
+ // excepted exception
+ } catch (Exception e) {
+ fail ("Unexpected exception received. " + e);
+ }
+
+ // test: add non-exist role to group with -arg
+ args = new String[] { "-arg", "-r", TEST_ROLE_NAME_2, "-g", "testGroup1", "-conf",
+ confPath.getAbsolutePath(), "-t", "sqoop" };
+ sentryShell = new SentryShellGeneric();
+ try {
+ sentryShell.executeShell(args);
+ fail("Exception should be thrown for granting non-exist role to group");
+ } catch (SentryUserException e) {
+ // excepted exception
+ } catch (Exception e) {
+ fail ("Unexpected exception received. " + e);
+ }
+
+ // test: drop group from non-exist role with -drg
+ args = new String[] { "-drg", "-r", TEST_ROLE_NAME_2, "-g", "testGroup1", "-conf",
+ confPath.getAbsolutePath(), "-t", "sqoop" };
+ sentryShell = new SentryShellGeneric();
+ try {
+ sentryShell.executeShell(args);
+ fail("Exception should be thrown for drop group from non-exist role");
+ } catch (SentryUserException e) {
+ // excepted exception
+ } catch (Exception e) {
+ fail ("Unexpected exception received. " + e);
+ }
+
+ // test: grant privilege to role with the error privilege format
+ args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p", "serverserver1->action=all",
+ "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
+ sentryShell = new SentryShellGeneric();
+ try {
+ sentryShell.executeShell(args);
+ fail("Exception should be thrown for the error privilege format, invalid key value.");
+ } catch (IllegalArgumentException e) {
+ // excepted exception
+ } catch (Exception e) {
+ fail ("Unexpected exception received. " + e);
+ }
+
+ // clear the test data
+ client.dropRole(requestorName, TEST_ROLE_NAME_1, AuthorizationComponent.SQOOP);
+ }
+ });
+ }
+
+ @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, AuthorizationComponent.SQOOP);
+ // test: the conf is required argument
+ String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-t", "sqoop" };
+ SentryShellGeneric sentryShell = new SentryShellGeneric();
+ validateMissingParameterMsg(sentryShell, args,
+ SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + strOptionConf);
+
+ // test: -r is required when create role
+ args = new String[] { "-cr", "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
+ sentryShell = new SentryShellGeneric();
+ 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(), "-t", "sqoop" };
+ sentryShell = new SentryShellGeneric();
+ 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(), "-t", "sqoop" };
+ sentryShell = new SentryShellGeneric();
+ 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(), "-t", "sqoop" };
+ sentryShell = new SentryShellGeneric();
+ 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(), "-t", "sqoop" };
+ sentryShell = new SentryShellGeneric();
+ 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(), "-t", "sqoop" };
+ sentryShell = new SentryShellGeneric();
+ 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(), "-t", "sqoop" };
+ sentryShell = new SentryShellGeneric();
+ 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(), "-t", "sqoop" };
+ sentryShell = new SentryShellGeneric();
+ validateMissingParameterMsg(sentryShell, args,
+ SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_PRIVILEGE);
+
+ // test: action is required in privilege
+ args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-p", "Server=sqoopServer1->Connector", "-t", "sqoop" };
+ sentryShell = new SentryShellGeneric();
+ try {
+ getShellResultWithOSRedirect(sentryShell, args, false);
+ fail("Expected IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ } catch (Exception e) {
+ fail ("Unexpected exception received. " + e);
+ }
+
+ // test: -r is required when revoke privilege from role
+ args = new String[] { "-rpr", "-p", "Server=sqoopServer1->Connector->action=*", "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
+ sentryShell = new SentryShellGeneric();
+ 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(), "-t", "sqoop" };
+ sentryShell = new SentryShellGeneric();
+ 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(), "-t", "sqoop" };
+ sentryShell = new SentryShellGeneric();
+ 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, AuthorizationComponent.SQOOP);
+ }
+ });
+ }
+
+ // redirect the System.out to ByteArrayOutputStream, then execute the command and parse the result.
+ private Set<String> getShellResultWithOSRedirect(SentryShellGeneric sentryShell,
+ String[] args, boolean expectedExecuteResult) throws Exception {
+ PrintStream oldOut = System.out;
+ ByteArrayOutputStream outContent = new ByteArrayOutputStream();
+ System.setOut(new PrintStream(outContent));
+ assertEquals(expectedExecuteResult, 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(SentryShellGeneric sentryShell, String[] args,
+ String expectedErrorMsg) throws Exception {
+ Set<String> errorMsgs = getShellResultWithOSRedirect(sentryShell, args, false);
+ assertTrue("Expected error message: " + expectedErrorMsg, errorMsgs.contains(expectedErrorMsg));
+ }
+
+ private void validateMissingParameterMsgsContains(SentryShellGeneric 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);
+ }
+}
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/resources/cacerts.jks
----------------------------------------------------------------------
diff --git a/sentry-tools/src/test/resources/cacerts.jks b/sentry-tools/src/test/resources/cacerts.jks
new file mode 100644
index 0000000..6ac6495
Binary files /dev/null and b/sentry-tools/src/test/resources/cacerts.jks differ
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/resources/indexer_case.ini
----------------------------------------------------------------------
diff --git a/sentry-tools/src/test/resources/indexer_case.ini b/sentry-tools/src/test/resources/indexer_case.ini
new file mode 100644
index 0000000..f1afe1f
--- /dev/null
+++ b/sentry-tools/src/test/resources/indexer_case.ini
@@ -0,0 +1,26 @@
+# 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.
+
+[groups]
+groupa = RoLe1
+groupb = rOlE1
+groupc = ROLE2
+
+[roles]
+RoLe1 = indexer=*
+rOlE1 = indexer=*
+ROLE2 = indexer=*
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/resources/indexer_config_import_tool.ini
----------------------------------------------------------------------
diff --git a/sentry-tools/src/test/resources/indexer_config_import_tool.ini b/sentry-tools/src/test/resources/indexer_config_import_tool.ini
new file mode 100644
index 0000000..c1bfe4b
--- /dev/null
+++ b/sentry-tools/src/test/resources/indexer_config_import_tool.ini
@@ -0,0 +1,29 @@
+# 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.
+
+[groups]
+corporal = corporal_role
+sergeant = corporal_role, sergeant_role
+general = corporal_role, sergeant_role, general_role
+commander_in_chief = corporal_role, sergeant_role, general_role, commander_in_chief_role
+
+[roles]
+corporal_role = indexer=info->action=read, \
+ indexer=info->action=write
+sergeant_role = indexer=info->action=write
+general_role = indexer=info->action=*
+commander_in_chief_role = indexer=*
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/resources/indexer_invalid.ini
----------------------------------------------------------------------
diff --git a/sentry-tools/src/test/resources/indexer_invalid.ini b/sentry-tools/src/test/resources/indexer_invalid.ini
new file mode 100644
index 0000000..03083a7
--- /dev/null
+++ b/sentry-tools/src/test/resources/indexer_invalid.ini
@@ -0,0 +1,21 @@
+# 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.
+
+[groups]
+
+[roles]
+
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/resources/keystore.jks
----------------------------------------------------------------------
diff --git a/sentry-tools/src/test/resources/keystore.jks b/sentry-tools/src/test/resources/keystore.jks
new file mode 100644
index 0000000..a6beece
Binary files /dev/null and b/sentry-tools/src/test/resources/keystore.jks differ
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/sentry-tools/src/test/resources/log4j.properties b/sentry-tools/src/test/resources/log4j.properties
new file mode 100644
index 0000000..9766758
--- /dev/null
+++ b/sentry-tools/src/test/resources/log4j.properties
@@ -0,0 +1,34 @@
+#
+# 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.
+#
+
+# Define some default values that can be overridden by system properties.
+#
+# For testing, it may also be convenient to specify
+
+log4j.rootLogger=DEBUG,console
+
+log4j.appender.console=org.apache.log4j.ConsoleAppender
+log4j.appender.console.target=System.err
+log4j.appender.console.layout=org.apache.log4j.PatternLayout
+log4j.appender.console.layout.ConversionPattern=%d (%t) [%p - %l] %m%n
+
+log4j.logger.org.apache.hadoop.conf.Configuration=INFO
+log4j.logger.org.apache.hadoop.metrics2=INFO
+log4j.logger.org.apache.directory=INFO
+log4j.logger.org.apache.directory.api.ldap.model.entry.AbstractValue=WARN
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/resources/solr_case.ini
----------------------------------------------------------------------
diff --git a/sentry-tools/src/test/resources/solr_case.ini b/sentry-tools/src/test/resources/solr_case.ini
new file mode 100644
index 0000000..fbbebfc
--- /dev/null
+++ b/sentry-tools/src/test/resources/solr_case.ini
@@ -0,0 +1,26 @@
+# 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.
+
+[groups]
+groupa = RoLe1
+groupb = rOlE1
+groupc = ROLE2
+
+[roles]
+RoLe1 = collection=*
+rOlE1 = collection=*
+ROLE2 = collection=*
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/resources/solr_config_import_tool.ini
----------------------------------------------------------------------
diff --git a/sentry-tools/src/test/resources/solr_config_import_tool.ini b/sentry-tools/src/test/resources/solr_config_import_tool.ini
new file mode 100644
index 0000000..da7df4c
--- /dev/null
+++ b/sentry-tools/src/test/resources/solr_config_import_tool.ini
@@ -0,0 +1,29 @@
+# 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.
+
+[groups]
+corporal = corporal_role
+sergeant = corporal_role, sergeant_role
+general = corporal_role, sergeant_role, general_role
+commander_in_chief = corporal_role, sergeant_role, general_role, commander_in_chief_role
+
+[roles]
+corporal_role = collection=info->action=query, \
+ collection=info->action=update
+sergeant_role = collection=info->action=update
+general_role = collection=info->action=*
+commander_in_chief_role = collection=*
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/resources/solr_invalid.ini
----------------------------------------------------------------------
diff --git a/sentry-tools/src/test/resources/solr_invalid.ini b/sentry-tools/src/test/resources/solr_invalid.ini
new file mode 100644
index 0000000..03083a7
--- /dev/null
+++ b/sentry-tools/src/test/resources/solr_invalid.ini
@@ -0,0 +1,21 @@
+# 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.
+
+[groups]
+
+[roles]
+
[4/9] sentry git commit: SENTRY-2207 Refactor out Sentry CLI from
sentry-provider-db into own module. Steve Moist,
reviewed by Colm O hEigeartaigh.
Posted by co...@apache.org.
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentrySchemaTool.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentrySchemaTool.java b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentrySchemaTool.java
new file mode 100644
index 0000000..893f80b
--- /dev/null
+++ b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentrySchemaTool.java
@@ -0,0 +1,595 @@
+/**
+ * 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.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.net.MalformedURLException;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.IllegalFormatException;
+import java.util.List;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.GnuParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.OptionBuilder;
+import org.apache.commons.cli.OptionGroup;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.apache.commons.io.output.NullOutputStream;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hive.beeline.BeeLine;
+import org.apache.sentry.Command;
+import org.apache.sentry.core.common.exception.SentryUserException;
+import org.apache.sentry.core.common.exception.SentrySiteConfigurationException;
+import org.apache.sentry.provider.db.service.persistent.SentryStoreSchemaInfo;
+import org.apache.sentry.cli.tools.SentrySchemaHelper.NestedScriptParser;
+import org.apache.sentry.service.thrift.SentryService;
+import org.apache.sentry.service.thrift.ServiceConstants;
+
+public class SentrySchemaTool {
+ private static final String SENTRY_SCRIP_DIR = File.separatorChar + "scripts"
+ + File.separatorChar + "sentrystore" + File.separatorChar + "upgrade";
+ private String userName = null;
+ private String passWord = null;
+ private String connectionURL = null;
+ private String driver = null;
+ private boolean dryRun = false;
+ private String dbOpts = null;
+ private boolean verbose = false;
+ private final Configuration sentryConf;
+ private final String dbType;
+ private final SentryStoreSchemaInfo sentryStoreSchemaInfo;
+
+ public SentrySchemaTool(Configuration sentryConf, String dbType)
+ throws SentryUserException, IOException {
+ this(System.getenv("SENTRY_HOME") + SENTRY_SCRIP_DIR, sentryConf, dbType);
+ }
+
+ public SentrySchemaTool(String sentryScripPath, Configuration sentryConf,
+ String dbType) throws SentryUserException, IOException {
+ if (sentryScripPath == null || sentryScripPath.isEmpty()) {
+ throw new SentryUserException("No Sentry script dir provided");
+ }
+ this.sentryConf = sentryConf;
+ this.dbType = dbType;
+ this.sentryStoreSchemaInfo = new SentryStoreSchemaInfo(sentryScripPath,
+ dbType);
+ userName = sentryConf.get(ServiceConstants.ServerConfig.SENTRY_STORE_JDBC_USER,
+ ServiceConstants.ServerConfig.SENTRY_STORE_JDBC_USER_DEFAULT);
+ //Password will be read from Credential provider specified using property
+ // CREDENTIAL_PROVIDER_PATH("hadoop.security.credential.provider.path" in sentry-site.xml
+ // it falls back to reading directly from sentry-site.xml
+ char[] passTmp = sentryConf.getPassword(ServiceConstants.ServerConfig.SENTRY_STORE_JDBC_PASS);
+ if(passTmp != null) {
+ passWord = new String(passTmp);
+ } else {
+ throw new SentrySiteConfigurationException("Error reading " + ServiceConstants.ServerConfig.SENTRY_STORE_JDBC_PASS);
+ }
+
+ try {
+ connectionURL = getValidConfVar(ServiceConstants.ServerConfig.SENTRY_STORE_JDBC_URL);
+ if(dbType.equalsIgnoreCase(SentrySchemaHelper.DB_DERBY)) {
+ driver = sentryConf.get(ServiceConstants.ServerConfig.SENTRY_STORE_JDBC_DRIVER,
+ ServiceConstants.ServerConfig.SENTRY_STORE_JDBC_DRIVER_DEFAULT);
+ } else {
+ driver = getValidConfVar(ServiceConstants.ServerConfig.SENTRY_STORE_JDBC_DRIVER);
+ }
+ // load required JDBC driver
+ Class.forName(driver);
+ } catch (IOException e) {
+ throw new SentryUserException("Missing property: " + e.getMessage());
+ } catch (ClassNotFoundException e) {
+ throw new SentryUserException("Failed to load driver", e);
+ }
+ }
+
+ public Configuration getConfiguration() {
+ return sentryConf;
+ }
+
+ public void setUserName(String userName) {
+ this.userName = userName;
+ }
+
+ public void setPassWord(String passWord) {
+ this.passWord = passWord;
+ }
+
+ public void setDryRun(boolean dryRun) {
+ this.dryRun = dryRun;
+ }
+
+ public void setVerbose(boolean verbose) {
+ this.verbose = verbose;
+ }
+
+ public String getDbOpts() {
+ return dbOpts;
+ }
+
+ public void setDbOpts(String dbOpts) {
+ this.dbOpts = dbOpts;
+ }
+
+ private static void printAndExit(Options cmdLineOptions) {
+ HelpFormatter formatter = new HelpFormatter();
+ formatter.printHelp("schemaTool", cmdLineOptions);
+ System.exit(1);
+ }
+
+ /***
+ * Print Hive version and schema version
+ * @throws SentryUserException
+ */
+ public void showInfo() throws SentryUserException {
+ Connection sentryStoreConn = getConnectionToMetastore(true);
+ System.out.println("Sentry distribution version:\t "
+ + SentryStoreSchemaInfo.getSentryVersion());
+ System.out.println("SentryStore schema version:\t "
+ + getMetaStoreSchemaVersion(sentryStoreConn));
+ }
+
+ // read schema version from sentry store
+ private String getMetaStoreSchemaVersion(Connection sentryStoreConn)
+ throws SentryUserException {
+ String versionQuery;
+ if (SentrySchemaHelper.getDbCommandParser(dbType).needsQuotedIdentifier()) {
+ versionQuery = "select t.\"SCHEMA_VERSION\" from \"SENTRY_VERSION\" t";
+ } else {
+ versionQuery = "select t.SCHEMA_VERSION from SENTRY_VERSION t";
+ }
+ try (Statement stmt = sentryStoreConn.createStatement();
+ ResultSet res = stmt.executeQuery(versionQuery)) {
+ if (!res.next()) {
+ throw new SentryUserException("Didn't find version data in sentry store");
+ }
+ String currentSchemaVersion = res.getString(1);
+ sentryStoreConn.close();
+ return currentSchemaVersion;
+ } catch (SQLException e) {
+ throw new SentryUserException("Failed to get schema version.", e);
+ }
+ }
+
+ // test the connection sentry store using the config property
+ private void testConnectionToMetastore() throws SentryUserException {
+ try (Connection conn = getConnectionToMetastore(true)) {
+ conn.close();
+ } catch (SQLException e) {
+ throw new SentryUserException("Failed to close sentry store connection", e);
+ }
+ }
+
+ /***
+ * get JDBC connection to sentry store db
+ *
+ * @param printInfo print connection parameters
+ * @return
+ * @throws SentryUserException
+ */
+ private Connection getConnectionToMetastore(boolean printInfo)
+ throws SentryUserException {
+ if (printInfo) {
+ System.out.println("Sentry store connection URL:\t " + connectionURL);
+ System.out.println("Sentry store Connection Driver :\t " + driver);
+ System.out.println("Sentry store connection User:\t " + userName);
+ }
+ if (userName == null || userName.isEmpty()) {
+ throw new SentryUserException("UserName empty ");
+ }
+ try {
+ // Connect using the JDBC URL and user/pass from conf
+ return DriverManager.getConnection(connectionURL, userName, passWord);
+ } catch (SQLException e) {
+ throw new SentryUserException("Failed to make connection to Sentry store.", e);
+ }
+ }
+
+ /**
+ * check if the current schema version in sentry store matches the Hive version
+ * @throws SentryUserException
+ */
+ public void verifySchemaVersion() throws SentryUserException {
+ // don't check version if its a dry run
+ if (dryRun) {
+ return;
+ }
+ String newSchemaVersion =
+ getMetaStoreSchemaVersion(getConnectionToMetastore(false));
+ // verify that the new version is added to schema
+ if (!sentryStoreSchemaInfo.getSentrySchemaVersion().equalsIgnoreCase(
+ newSchemaVersion)) {
+ throw new SentryUserException("Found unexpected schema version "
+ + newSchemaVersion);
+ }
+ }
+
+ /**
+ * Perform sentry store schema upgrade. extract the current schema version from sentry store
+ * @throws SentryUserException
+ */
+ public void doUpgrade() throws SentryUserException {
+ String fromVersion = getMetaStoreSchemaVersion(getConnectionToMetastore(false));
+ if (fromVersion == null || fromVersion.isEmpty()) {
+ throw new SentryUserException(
+ "Schema version not stored in the sentry store. "
+ +
+ "Metastore schema is too old or corrupt. Try specifying the version manually");
+ }
+ doUpgrade(fromVersion);
+ }
+
+ /**
+ * Perform sentry store schema upgrade
+ *
+ * @param fromSchemaVer
+ * Existing version of the sentry store. If null, then read from the sentry store
+ * @throws SentryUserException
+ */
+ public void doUpgrade(String fromSchemaVer) throws SentryUserException {
+ if (sentryStoreSchemaInfo.getSentrySchemaVersion().equals(fromSchemaVer)) {
+ System.out.println("No schema upgrade required from version " + fromSchemaVer);
+ return;
+ }
+ // Find the list of scripts to execute for this upgrade
+ List<String> upgradeScripts =
+ sentryStoreSchemaInfo.getUpgradeScripts(fromSchemaVer);
+ testConnectionToMetastore();
+ System.out.println("Starting upgrade sentry store schema from version " +
+ fromSchemaVer + " to "
+ + sentryStoreSchemaInfo.getSentrySchemaVersion());
+ String scriptDir = sentryStoreSchemaInfo.getSentryStoreScriptDir();
+ try {
+ for (String scriptFile : upgradeScripts) {
+ System.out.println("Upgrade script " + scriptFile);
+ if (!dryRun) {
+ runBeeLine(scriptDir, scriptFile);
+ System.out.println("Completed " + scriptFile);
+ }
+ }
+ } catch (IOException eIO) {
+ throw new SentryUserException(
+ "Upgrade FAILED! Metastore state would be inconsistent !!", eIO);
+ }
+
+ // Revalidated the new version after upgrade
+ verifySchemaVersion();
+ }
+
+ /**
+ * Initialize the sentry store schema to current version
+ *
+ * @throws SentryUserException
+ */
+ public void doInit() throws SentryUserException {
+ doInit(sentryStoreSchemaInfo.getSentrySchemaVersion());
+
+ // Revalidated the new version after upgrade
+ verifySchemaVersion();
+ }
+
+ /**
+ * Initialize the sentry store schema
+ *
+ * @param toVersion
+ * If null then current hive version is used
+ * @throws SentryUserException
+ */
+ public void doInit(String toVersion) throws SentryUserException {
+ testConnectionToMetastore();
+ System.out.println("Starting sentry store schema initialization to " + toVersion);
+
+ String initScriptDir = sentryStoreSchemaInfo.getSentryStoreScriptDir();
+ String initScriptFile = sentryStoreSchemaInfo.generateInitFileName(toVersion);
+
+ try {
+ System.out.println("Initialization script " + initScriptFile);
+ if (!dryRun) {
+ runBeeLine(initScriptDir, initScriptFile);
+ System.out.println("Initialization script completed");
+ }
+ } catch (IOException e) {
+ throw new SentryUserException("Schema initialization FAILED!"
+ + " Metastore state would be inconsistent !!", e);
+ }
+ }
+
+ // Flatten the nested upgrade script into a buffer
+ public static String buildCommand(NestedScriptParser dbCommandParser,
+ String scriptDir, String scriptFile) throws IllegalFormatException, IOException {
+
+ BufferedReader bfReader =
+ new BufferedReader(new FileReader(scriptDir + File.separatorChar + scriptFile));
+ String currLine;
+ StringBuilder sb = new StringBuilder();
+ String currentCommand = null;
+ while ((currLine = bfReader.readLine()) != null) {
+ currLine = currLine.trim();
+ if (currLine.isEmpty()) {
+ continue; // skip empty lines
+ }
+
+ if (currentCommand == null) {
+ currentCommand = currLine;
+ } else {
+ currentCommand = currentCommand + " " + currLine;
+ }
+ if (dbCommandParser.isPartialCommand(currLine)) {
+ // if its a partial line, continue collecting the pieces
+ continue;
+ }
+
+ // if this is a valid executable command then add it to the buffer
+ if (!dbCommandParser.isNonExecCommand(currentCommand)) {
+ currentCommand = dbCommandParser.cleanseCommand(currentCommand);
+
+ if (dbCommandParser.isNestedScript(currentCommand)) {
+ // if this is a nested sql script then flatten it
+ String currScript = dbCommandParser.getScriptName(currentCommand);
+ sb.append(buildCommand(dbCommandParser, scriptDir, currScript));
+ } else {
+ // Now we have a complete statement, process it
+ // write the line to buffer
+ sb.append(currentCommand);
+ sb.append(System.getProperty("line.separator"));
+ }
+ }
+ currentCommand = null;
+ }
+ bfReader.close();
+ return sb.toString();
+ }
+
+ // run beeline on the given sentry store scrip, flatten the nested scripts into single file
+ private void runBeeLine(String scriptDir, String scriptFile) throws IOException {
+ NestedScriptParser dbCommandParser =
+ SentrySchemaHelper.getDbCommandParser(dbType);
+ dbCommandParser.setDbOpts(getDbOpts());
+ // expand the nested script
+ String sqlCommands = buildCommand(dbCommandParser, scriptDir, scriptFile);
+ File tmpFile = File.createTempFile("schematool", ".sql");
+ tmpFile.deleteOnExit();
+
+ // write out the buffer into a file. Add beeline commands for autocommit and close
+ try (FileWriter fstream = new FileWriter(tmpFile.getPath());
+ BufferedWriter out = new BufferedWriter(fstream)) {
+
+ out.write("!set Silent " + verbose + System.getProperty("line.separator"));
+ out.write("!autocommit on" + System.getProperty("line.separator"));
+ out.write("!set Isolation TRANSACTION_READ_COMMITTED"
+ + System.getProperty("line.separator"));
+ out.write("!set AllowMultiLineCommand false"
+ + System.getProperty("line.separator"));
+ out.write(sqlCommands);
+ out.write("!closeall" + System.getProperty("line.separator"));
+ out.close();
+ }
+ runBeeLine(tmpFile.getPath());
+ }
+
+ // Generate the beeline args per hive conf and execute the given script
+ public void runBeeLine(String sqlScriptFile) throws IOException {
+ List<String> argList = new ArrayList<String>();
+ argList.add("-u");
+ argList.add(connectionURL);
+ argList.add("-d");
+ argList
+ .add(driver);
+ argList.add("-n");
+ argList.add(userName);
+ argList.add("-p");
+ argList.add(passWord);
+ argList.add("-f");
+ argList.add(sqlScriptFile);
+
+ BeeLine beeLine = new BeeLine();
+ if (!verbose) {
+ beeLine.setOutputStream(new PrintStream(new NullOutputStream()));
+ // beeLine.getOpts().setSilent(true);
+ }
+ // beeLine.getOpts().setAllowMultiLineCommand(false);
+ // beeLine.getOpts().setIsolation("TRANSACTION_READ_COMMITTED");
+ int status = beeLine.begin(argList.toArray(new String[0]), null);
+ if (status != 0) {
+ throw new IOException("Schema script failed, errorcode " + status);
+ }
+ }
+
+ private String getValidConfVar(String confVar) throws IOException {
+ String confVarKey = confVar;
+ String confVarValue = sentryConf.get(confVarKey);
+ if (confVarValue == null || confVarValue.isEmpty()) {
+ throw new IOException("Empty " + confVar);
+ }
+ return confVarValue;
+ }
+
+ // Create the required command line options
+ @SuppressWarnings("static-access")
+ private static void initOptions(Options cmdLineOptions) {
+ Option help = new Option("help", "print this message");
+ Option upgradeOpt = new Option("upgradeSchema", "Schema upgrade");
+ Option upgradeFromOpt = OptionBuilder.withArgName("upgradeFrom").hasArg().
+ withDescription("Schema upgrade from a version").
+ create("upgradeSchemaFrom");
+ Option initOpt = new Option("initSchema", "Schema initialization");
+ Option initToOpt = OptionBuilder.withArgName("initTo").hasArg().
+ withDescription("Schema initialization to a version").
+ create("initSchemaTo");
+ Option infoOpt = new Option("info", "Show config and schema details");
+
+ OptionGroup optGroup = new OptionGroup();
+ optGroup.addOption(upgradeOpt).addOption(initOpt).
+ addOption(help).addOption(upgradeFromOpt).
+ addOption(initToOpt).addOption(infoOpt);
+ optGroup.setRequired(true);
+
+ Option userNameOpt = OptionBuilder.withArgName("user")
+ .hasArg()
+ .withDescription("Override config file user name")
+ .create("userName");
+ Option passwdOpt = OptionBuilder.withArgName("password")
+ .hasArg()
+ .withDescription("Override config file password")
+ .create("passWord");
+ Option dbTypeOpt = OptionBuilder.withArgName("databaseType")
+ .hasArg().withDescription("Metastore database type [" +
+ SentrySchemaHelper.DB_DERBY + "," +
+ SentrySchemaHelper.DB_MYSQL + "," +
+ SentrySchemaHelper.DB_ORACLE + "," +
+ SentrySchemaHelper.DB_POSTGRACE + "," +
+ SentrySchemaHelper.DB_DB2 + "]")
+ .create("dbType");
+ Option dbOpts = OptionBuilder.withArgName("databaseOpts")
+ .hasArgs().withDescription("Backend DB specific options")
+ .create("dbOpts");
+
+ Option dryRunOpt = new Option("dryRun", "list SQL scripts (no execute)");
+ Option verboseOpt = new Option("verbose", "only print SQL statements");
+
+ Option configOpt = OptionBuilder.withArgName("confName").hasArgs()
+ .withDescription("Sentry Service configuration file").isRequired(true)
+ .create(ServiceConstants.ServiceArgs.CONFIG_FILE_LONG);
+
+ cmdLineOptions.addOption(help);
+ cmdLineOptions.addOption(dryRunOpt);
+ cmdLineOptions.addOption(userNameOpt);
+ cmdLineOptions.addOption(passwdOpt);
+ cmdLineOptions.addOption(dbTypeOpt);
+ cmdLineOptions.addOption(verboseOpt);
+ cmdLineOptions.addOption(dbOpts);
+ cmdLineOptions.addOption(configOpt);
+ cmdLineOptions.addOptionGroup(optGroup);
+ }
+
+ public static class CommandImpl implements Command {
+ @Override
+ public void run(String[] args) throws Exception {
+ CommandLineParser parser = new GnuParser();
+ CommandLine line = null;
+ String dbType = null;
+ String schemaVer = null;
+ Options cmdLineOptions = new Options();
+ String configFileName = null;
+
+ // Argument handling
+ initOptions(cmdLineOptions);
+ try {
+ line = parser.parse(cmdLineOptions, args);
+ } catch (ParseException e) {
+ System.err.println("SentrySchemaTool:Parsing failed. Reason: "
+ + e.getLocalizedMessage());
+ printAndExit(cmdLineOptions);
+ }
+
+ if (line.hasOption("help")) {
+ HelpFormatter formatter = new HelpFormatter();
+ formatter.printHelp("schemaTool", cmdLineOptions);
+ return;
+ }
+
+ if (line.hasOption("dbType")) {
+ dbType = line.getOptionValue("dbType");
+ if (!dbType.equalsIgnoreCase(SentrySchemaHelper.DB_DERBY)
+ && !dbType.equalsIgnoreCase(SentrySchemaHelper.DB_MYSQL)
+ && !dbType.equalsIgnoreCase(SentrySchemaHelper.DB_POSTGRACE)
+ && !dbType.equalsIgnoreCase(SentrySchemaHelper.DB_ORACLE)
+ && !dbType.equalsIgnoreCase(SentrySchemaHelper.DB_DB2)) {
+ System.err.println("Unsupported dbType " + dbType);
+ printAndExit(cmdLineOptions);
+ }
+ } else {
+ System.err.println("no dbType supplied");
+ printAndExit(cmdLineOptions);
+ }
+ if (line.hasOption(ServiceConstants.ServiceArgs.CONFIG_FILE_LONG)) {
+ configFileName = line
+ .getOptionValue(ServiceConstants.ServiceArgs.CONFIG_FILE_LONG);
+ } else {
+ System.err.println("no config file specified");
+ printAndExit(cmdLineOptions);
+ }
+ try {
+ SentrySchemaTool schemaTool = new SentrySchemaTool(
+ SentryService.loadConfig(configFileName), dbType);
+
+ if (line.hasOption("userName")) {
+ schemaTool.setUserName(line.getOptionValue("userName"));
+ }
+ if (line.hasOption("passWord")) {
+ schemaTool.setPassWord(line.getOptionValue("passWord"));
+ }
+ if (line.hasOption("dryRun")) {
+ schemaTool.setDryRun(true);
+ }
+ if (line.hasOption("verbose")) {
+ schemaTool.setVerbose(true);
+ }
+ if (line.hasOption("dbOpts")) {
+ schemaTool.setDbOpts(line.getOptionValue("dbOpts"));
+ }
+
+ if (line.hasOption("info")) {
+ schemaTool.showInfo();
+ } else if (line.hasOption("upgradeSchema")) {
+ schemaTool.doUpgrade();
+ } else if (line.hasOption("upgradeSchemaFrom")) {
+ schemaVer = line.getOptionValue("upgradeSchemaFrom");
+ schemaTool.doUpgrade(schemaVer);
+ } else if (line.hasOption("initSchema")) {
+ schemaTool.doInit();
+ } else if (line.hasOption("initSchemaTo")) {
+ schemaVer = line.getOptionValue("initSchemaTo");
+ schemaTool.doInit(schemaVer);
+ } else {
+ System.err.println("no valid option supplied");
+ printAndExit(cmdLineOptions);
+ }
+ } catch (SentryUserException e) {
+ System.err.println(e);
+ if (line.hasOption("verbose")) {
+ e.printStackTrace();
+ }
+ System.err.println("*** Sentry schemaTool failed ***");
+ System.exit(1);
+ } catch (MalformedURLException e) {
+ System.err.println(e);
+ if (line.hasOption("verbose")) {
+ e.printStackTrace();
+ }
+ System.err.println("*** Sentry schemaTool failed ***");
+ System.exit(1);
+ }
+ System.out.println("Sentry schemaTool completed");
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryShellCommon.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryShellCommon.java b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryShellCommon.java
new file mode 100644
index 0000000..94800a4
--- /dev/null
+++ b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryShellCommon.java
@@ -0,0 +1,284 @@
+/**
+ * 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.annotations.VisibleForTesting;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.GnuParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.OptionGroup;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.apache.commons.cli.Parser;
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * SentryShellCommon provides the function for parsing the argument.
+ * For hive model and generic model, child class should be implemented as a sentry admin tool.
+ */
+abstract public class SentryShellCommon {
+
+ public enum TYPE { kafka, hive, solr, sqoop };
+
+ public static final String OPTION_DESC_HELP = "Shell usage";
+ public static final String OPTION_DESC_CONF = "sentry-site file path";
+ public static final String OPTION_DESC_ROLE_NAME = "Role name";
+ public static final String OPTION_DESC_GROUP_NAME = "Group name";
+ public static final String OPTION_DESC_PRIVILEGE = "Privilege string";
+ public final static String OPTION_DESC_SERVICE = "Name of the service being managed";
+ public static final String PREFIX_MESSAGE_MISSING_OPTION = "Missing required option: ";
+
+ public static final String GROUP_SPLIT_CHAR = ",";
+
+ protected String roleName;
+ protected String serviceName;
+ protected String groupName;
+ protected String privilegeStr;
+ protected String confPath;
+ // flag for the command
+ protected boolean isCreateRole;
+ protected boolean isDropRole;
+ protected boolean isAddRoleGroup;
+ protected boolean isDeleteRoleGroup;
+ protected boolean isGrantPrivilegeRole;
+ protected boolean isRevokePrivilegeRole;
+ protected boolean isListRole;
+ protected boolean isListPrivilege;
+ protected boolean isListGroup;
+ protected boolean isPrintHelp;
+ // flag for the parameter check
+ protected boolean roleNameRequired;
+ protected boolean groupNameRequired;
+ protected boolean privilegeStrRequired;
+ protected TYPE type;
+
+ /**
+ * parse arguments
+ *
+ * <pre>
+ * -conf,--sentry_conf <filepath> sentry config file path
+ * -cr,--create_role -r <rolename> create role
+ * -dr,--drop_role -r <rolename> drop role
+ * -arg,--add_role_group -r <rolename> -g <groupname> add role to group
+ * -drg,--delete_role_group -r <rolename> -g <groupname> delete role from group
+ * -gpr,--grant_privilege_role -r <rolename> -p <privilege> grant privilege to role
+ * -rpr,--revoke_privilege_role -r <rolename> -p <privilege> revoke privilege from role
+ * -lr,--list_role -g <groupname> list roles for group
+ * -lp,--list_privilege -r <rolename> list privilege for role
+ * -lg,--list_group list all groups associated with all roles
+ * -t,--type <typename> the shell for hive model or generic model
+ * </pre>
+ *
+ * @param args
+ */
+ protected boolean parseArgs(String[] args) {
+ Options simpleShellOptions = new Options();
+
+ setupOptions(simpleShellOptions);
+
+
+
+ // help option
+ Option helpOpt = new Option("h", "help", false, OPTION_DESC_HELP);
+ helpOpt.setRequired(false);
+ simpleShellOptions.addOption(helpOpt);
+
+ // this Options is parsed first for help option
+ Options helpOptions = new Options();
+ helpOptions.addOption(helpOpt);
+
+ try {
+ Parser parser = new GnuParser();
+
+ // parse help option first
+ CommandLine cmd = parser.parse(helpOptions, args, true);
+ for (Option opt : cmd.getOptions()) {
+ if (opt.getOpt().equals("h")) {
+ // get the help option, print the usage and exit
+ usage(simpleShellOptions);
+ return false;
+ }
+ }
+
+ // without help option
+ cmd = parser.parse(simpleShellOptions, args);
+
+ parseOptions(cmd);
+ } catch (ParseException pe) {
+ System.out.println(pe.getMessage());
+ usage(simpleShellOptions);
+ return false;
+ }
+ return true;
+ }
+
+ protected void setupOptions(Options simpleShellOptions) {
+ OptionGroup simpleShellOptGroup = getMainOptions();
+ simpleShellOptions.addOptionGroup(simpleShellOptGroup);
+
+ Option sOpt = new Option("s", "service", true, OPTION_DESC_SERVICE);
+ sOpt.setRequired(false);
+ simpleShellOptions.addOption(sOpt);
+
+ // optional args
+ Option pOpt = new Option("p", "privilege", true, OPTION_DESC_PRIVILEGE);
+ pOpt.setRequired(false);
+ simpleShellOptions.addOption(pOpt);
+
+ Option gOpt = new Option("g", "groupname", true, OPTION_DESC_GROUP_NAME);
+ gOpt.setRequired(false);
+ simpleShellOptions.addOption(gOpt);
+
+ Option rOpt = new Option("r", "rolename", true, OPTION_DESC_ROLE_NAME);
+ rOpt.setRequired(false);
+ simpleShellOptions.addOption(rOpt);
+
+ // this argument should also be parsed in the bin/sentryShell
+ Option tOpt = new Option("t", "type", true, "[hive|solr|sqoop|.....]");
+ tOpt.setRequired(false);
+ simpleShellOptions.addOption(tOpt);
+
+ // file path of sentry-site
+ Option sentrySitePathOpt = new Option("conf", "sentry_conf", true, OPTION_DESC_CONF);
+ sentrySitePathOpt.setRequired(true);
+ simpleShellOptions.addOption(sentrySitePathOpt);
+ }
+
+ protected OptionGroup getMainOptions() {
+ OptionGroup simpleShellOptGroup = new OptionGroup();
+ Option crOpt = new Option("cr", "create_role", false, "Create role");
+ crOpt.setRequired(false);
+
+ Option drOpt = new Option("dr", "drop_role", false, "Drop role");
+ drOpt.setRequired(false);
+
+ Option argOpt = new Option("arg", "add_role_group", false, "Add role to group");
+ argOpt.setRequired(false);
+
+ Option drgOpt = new Option("drg", "delete_role_group", false, "Delete role from group");
+ drgOpt.setRequired(false);
+
+ Option gprOpt = new Option("gpr", "grant_privilege_role", false, "Grant privilege to role");
+ gprOpt.setRequired(false);
+
+ Option rprOpt = new Option("rpr", "revoke_privilege_role", false, "Revoke privilege from role");
+ rprOpt.setRequired(false);
+
+ Option lrOpt = new Option("lr", "list_role", false, "List role");
+ lrOpt.setRequired(false);
+
+ Option lpOpt = new Option("lp", "list_privilege", false, "List privilege");
+ lpOpt.setRequired(false);
+
+ Option lgOpt = new Option("lg", "list_group", false, "List groups");
+ lgOpt.setRequired(false);
+
+
+ // required args group
+ simpleShellOptGroup.addOption(crOpt);
+ simpleShellOptGroup.addOption(drOpt);
+ simpleShellOptGroup.addOption(argOpt);
+ simpleShellOptGroup.addOption(drgOpt);
+ simpleShellOptGroup.addOption(gprOpt);
+ simpleShellOptGroup.addOption(rprOpt);
+ simpleShellOptGroup.addOption(lrOpt);
+ simpleShellOptGroup.addOption(lpOpt);
+ simpleShellOptGroup.addOption(lgOpt);
+ simpleShellOptGroup.setRequired(true);
+ return simpleShellOptGroup;
+ }
+
+ protected void parseOptions(CommandLine cmd) throws ParseException {
+ for (Option opt : cmd.getOptions()) {
+ if (opt.getOpt().equals("p")) {
+ privilegeStr = opt.getValue();
+ } else if (opt.getOpt().equals("g")) {
+ groupName = opt.getValue();
+ } else if (opt.getOpt().equals("r")) {
+ roleName = opt.getValue();
+ } else if (opt.getOpt().equals("s")) {
+ serviceName = opt.getValue();
+ } else if (opt.getOpt().equals("cr")) {
+ isCreateRole = true;
+ roleNameRequired = true;
+ } else if (opt.getOpt().equals("dr")) {
+ isDropRole = true;
+ roleNameRequired = true;
+ } else if (opt.getOpt().equals("arg")) {
+ isAddRoleGroup = true;
+ roleNameRequired = true;
+ groupNameRequired = true;
+ } else if (opt.getOpt().equals("drg")) {
+ isDeleteRoleGroup = true;
+ roleNameRequired = true;
+ groupNameRequired = true;
+ } else if (opt.getOpt().equals("gpr")) {
+ isGrantPrivilegeRole = true;
+ roleNameRequired = true;
+ privilegeStrRequired = true;
+ } else if (opt.getOpt().equals("rpr")) {
+ isRevokePrivilegeRole = true;
+ roleNameRequired = true;
+ privilegeStrRequired = true;
+ } else if (opt.getOpt().equals("lr")) {
+ isListRole = true;
+ } else if (opt.getOpt().equals("lp")) {
+ isListPrivilege = true;
+ roleNameRequired = true;
+ } else if (opt.getOpt().equals("lg")) {
+ isListGroup = true;
+ } else if (opt.getOpt().equals("conf")) {
+ confPath = opt.getValue();
+ } else if (opt.getOpt().equals("t")) {
+ type = TYPE.valueOf(opt.getValue());
+ }
+ }
+ checkRequiredParameter(roleNameRequired, roleName, OPTION_DESC_ROLE_NAME);
+ checkRequiredParameter(groupNameRequired, groupName, OPTION_DESC_GROUP_NAME);
+ checkRequiredParameter(privilegeStrRequired, privilegeStr, OPTION_DESC_PRIVILEGE);
+ }
+
+ protected void checkRequiredParameter(boolean isRequired, String paramValue, String paramName) throws ParseException {
+ if (isRequired && StringUtils.isEmpty(paramValue)) {
+ throw new ParseException(PREFIX_MESSAGE_MISSING_OPTION + paramName);
+ }
+ }
+
+ // print usage
+ private void usage(Options sentryOptions) {
+ HelpFormatter formatter = new HelpFormatter();
+ formatter.printHelp("sentryShell", sentryOptions);
+ }
+
+ // hive model and generic model should implement this method
+ public abstract void run() throws Exception;
+
+ @VisibleForTesting
+ public boolean executeShell(String[] args) throws Exception {
+ boolean result = true;
+ if (parseArgs(args)) {
+ run();
+ } else {
+ result = false;
+ }
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryShellGeneric.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryShellGeneric.java b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryShellGeneric.java
new file mode 100644
index 0000000..6d25617
--- /dev/null
+++ b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryShellGeneric.java
@@ -0,0 +1,157 @@
+/**
+ * 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 org.apache.commons.lang.StringUtils;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.sentry.provider.common.AuthorizationComponent;
+import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClient;
+import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClientFactory;
+import org.apache.sentry.cli.tools.command.GenericShellCommand;
+import org.apache.sentry.provider.db.generic.tools.GenericPrivilegeConverter;
+import org.apache.sentry.provider.db.generic.tools.TSentryPrivilegeConverter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * SentryShellGeneric is an admin tool, and responsible for the management of repository.
+ * The following commands are supported:
+ * create role, drop role, add group to role, grant privilege to role,
+ * revoke privilege from role, list roles, list privilege for role.
+ */
+public class SentryShellGeneric extends SentryShellCommon {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(SentryShellGeneric.class);
+ private static final String KAFKA_SERVICE_NAME = "sentry.service.client.kafka.service.name";
+ private static final String SOLR_SERVICE_NAME = "sentry.service.client.solr.service.name";
+ private static final String SQOOP_SERVICE_NAME = "sentry.service.client.sqoop.service.name";
+
+ @Override
+ public void run() throws Exception {
+ String component = getComponent();
+ Configuration conf = getSentryConf();
+
+ String service = getService(conf);
+ try (SentryGenericServiceClient client =
+ SentryGenericServiceClientFactory.create(conf)) {
+ UserGroupInformation ugi = UserGroupInformation.getLoginUser();
+ String requestorName = ugi.getShortUserName();
+ TSentryPrivilegeConverter converter = getPrivilegeConverter(component, service);
+ ShellCommand command = new GenericShellCommand(client, component, service, converter);
+
+ // check the requestor name
+ if (StringUtils.isEmpty(requestorName)) {
+ // The exception message will be recorded in log file.
+ throw new Exception("The requestor name is empty.");
+ }
+
+ if (isCreateRole) {
+ command.createRole(requestorName, roleName);
+ } else if (isDropRole) {
+ command.dropRole(requestorName, roleName);
+ } else if (isAddRoleGroup) {
+ Set<String> groups = Sets.newHashSet(groupName.split(SentryShellCommon.GROUP_SPLIT_CHAR));
+ command.grantRoleToGroups(requestorName, roleName, groups);
+ } else if (isDeleteRoleGroup) {
+ Set<String> groups = Sets.newHashSet(groupName.split(SentryShellCommon.GROUP_SPLIT_CHAR));
+ command.revokeRoleFromGroups(requestorName, roleName, groups);
+ } else if (isGrantPrivilegeRole) {
+ command.grantPrivilegeToRole(requestorName, roleName, privilegeStr);
+ } else if (isRevokePrivilegeRole) {
+ command.revokePrivilegeFromRole(requestorName, roleName, privilegeStr);
+ } else if (isListRole) {
+ List<String> roles = command.listRoles(requestorName, groupName);
+ for (String role : roles) {
+ System.out.println(role);
+ }
+ } else if (isListPrivilege) {
+ List<String> privileges = command.listPrivileges(requestorName, roleName);
+ for (String privilege : privileges) {
+ System.out.println(privilege);
+ }
+ } else if (isListGroup) {
+ List<String> groups = command.listGroupRoles(requestorName);
+ for (String group : groups) {
+ System.out.println(group);
+ }
+ }
+ }
+ }
+
+ protected GenericPrivilegeConverter getPrivilegeConverter(String component, String service) {
+ return new GenericPrivilegeConverter(component, service);
+ }
+
+ protected String getComponent() throws Exception {
+ if (type == TYPE.kafka) {
+ return AuthorizationComponent.KAFKA;
+ } else if (type == TYPE.solr) {
+ return "SOLR";
+ } else if (type == TYPE.sqoop) {
+ return AuthorizationComponent.SQOOP;
+ }
+
+ throw new Exception("Invalid type specified for SentryShellGeneric: " + type);
+ }
+
+ protected String getService(Configuration conf) throws Exception {
+ if (type == TYPE.kafka) {
+ return conf.get(KAFKA_SERVICE_NAME, AuthorizationComponent.KAFKA);
+ } else if (type == TYPE.solr) {
+ return conf.get(SOLR_SERVICE_NAME, "service1");
+ } else if (type == TYPE.sqoop) {
+ return conf.get(SQOOP_SERVICE_NAME, "sqoopServer1");
+ }
+
+ throw new Exception("Invalid type specified for SentryShellGeneric: " + type);
+ }
+
+ private Configuration getSentryConf() {
+ Configuration conf = new Configuration();
+ conf.addResource(new Path(confPath), true);
+ return conf;
+ }
+
+ public static void main(String[] args) throws Exception {
+ SentryShellGeneric sentryShell = new SentryShellGeneric();
+ try {
+ sentryShell.executeShell(args);
+ } catch (Exception e) {
+ LOGGER.error(e.getMessage(), e);
+ Throwable current = e;
+ // find the first printable message;
+ while (current != null && current.getMessage() == null) {
+ current = current.getCause();
+ }
+ String error = "";
+ if (current != null && current.getMessage() != null) {
+ error = "Message: " + current.getMessage();
+ }
+ System.out.println("The operation failed. " + error);
+ System.exit(1);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryShellHive.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryShellHive.java b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryShellHive.java
new file mode 100644
index 0000000..884ed91
--- /dev/null
+++ b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryShellHive.java
@@ -0,0 +1,118 @@
+/**
+ * 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.util.List;
+import java.util.Set;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
+import org.apache.sentry.cli.tools.command.hive.*;
+import org.apache.sentry.service.thrift.SentryServiceClientFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Sets;
+
+/**
+ * SentryShellHive is an admin tool, and responsible for the management of repository.
+ * The following function are supported:
+ * create role, drop role, add group to role, delete group from role, grant privilege to role,
+ * revoke privilege from role, list roles for group, list privilege for role.
+ */
+public class SentryShellHive extends SentryShellCommon {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(SentryShellHive.class);
+
+ public void run() throws Exception {
+
+ try(SentryPolicyServiceClient client =
+ SentryServiceClientFactory.create(getSentryConf())) {
+ UserGroupInformation ugi = UserGroupInformation.getLoginUser();
+ String requestorName = ugi.getShortUserName();
+ ShellCommand command = new HiveShellCommand(client);
+
+ // check the requestor name
+ if (StringUtils.isEmpty(requestorName)) {
+ // The exception message will be recorded in the log file.
+ throw new Exception("The requestor name is empty.");
+ }
+
+ if (isCreateRole) {
+ command.createRole(requestorName, roleName);
+ } else if (isDropRole) {
+ command.dropRole(requestorName, roleName);
+ } else if (isAddRoleGroup) {
+ Set<String> groups = Sets.newHashSet(groupName.split(SentryShellCommon.GROUP_SPLIT_CHAR));
+ command.grantRoleToGroups(requestorName, roleName, groups);
+ } else if (isDeleteRoleGroup) {
+ Set<String> groups = Sets.newHashSet(groupName.split(SentryShellCommon.GROUP_SPLIT_CHAR));
+ command.revokeRoleFromGroups(requestorName, roleName, groups);
+ } else if (isGrantPrivilegeRole) {
+ command.grantPrivilegeToRole(requestorName, roleName, privilegeStr);
+ } else if (isRevokePrivilegeRole) {
+ command.revokePrivilegeFromRole(requestorName, roleName, privilegeStr);
+ } else if (isListRole) {
+ List<String> roles = command.listRoles(requestorName, groupName);
+ for (String role : roles) {
+ System.out.println(role);
+ }
+ } else if (isListPrivilege) {
+ List<String> privileges = command.listPrivileges(requestorName, roleName);
+ for (String privilege : privileges) {
+ System.out.println(privilege);
+ }
+ } else if (isListGroup) {
+ List<String> groups = command.listGroupRoles(requestorName);
+ for (String group : groups) {
+ System.out.println(group);
+ }
+ }
+ }
+ }
+
+ private Configuration getSentryConf() {
+ Configuration conf = new Configuration();
+ conf.addResource(new Path(confPath), true);
+ return conf;
+ }
+
+ public static void main(String[] args) throws Exception {
+ SentryShellHive sentryShell = new SentryShellHive();
+ try {
+ sentryShell.executeShell(args);
+ } catch (Exception e) {
+ LOGGER.error(e.getMessage(), e);
+ Throwable current = e;
+ // find the first printable message;
+ while (current != null && current.getMessage() == null) {
+ current = current.getCause();
+ }
+
+ if (current != null) {
+ System.out.println("The operation failed." +
+ (current.getMessage() == null ? "" : " Message: " + current.getMessage()));
+ }
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryShellIndexer.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryShellIndexer.java b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryShellIndexer.java
new file mode 100644
index 0000000..c7f854f
--- /dev/null
+++ b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryShellIndexer.java
@@ -0,0 +1,124 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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 org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.OptionGroup;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.apache.hadoop.conf.Configuration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.apache.sentry.provider.common.AuthorizationComponent.HBASE_INDEXER;
+import static org.apache.sentry.service.thrift.ServiceConstants.ClientConfig.SERVICE_NAME;
+
+/**
+ * SentryShellIndexer is an admin tool, and responsible for the management of repository.
+ * The following commands are supported:
+ * create role, drop role, add group to role, grant privilege to role,
+ * revoke privilege from role, list roles, list privilege for role.
+ */
+public class SentryShellIndexer extends SentryShellGeneric {
+
+ protected boolean isMigration = false;
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(SentryShellIndexer.class);
+
+ private final SentryConfigToolIndexer configTool = new SentryConfigToolIndexer();
+
+ @Override
+ protected void setupOptions(Options simpleShellOptions) {
+ super.setupOptions(simpleShellOptions);
+ configTool.setupOptions(simpleShellOptions);
+ }
+
+ @Override
+ protected void parseOptions(CommandLine cmd) throws ParseException {
+ super.parseOptions(cmd);
+ configTool.parseOptions(cmd);
+ for (Option opt : cmd.getOptions()) {
+ if (opt.getOpt().equals("mgr")) {
+ isMigration = true;
+ }
+ }
+ }
+
+ @Override
+ protected OptionGroup getMainOptions() {
+ OptionGroup mainOptions = super.getMainOptions();
+ Option mgrOpt = new Option("mgr", "migrate", false, "Migrate ini file to Sentry service");
+ mgrOpt.setRequired(false);
+ mainOptions.addOption(mgrOpt);
+ return mainOptions;
+ }
+
+ /**
+ * Processes the necessary command based on the arguments parsed earlier.
+ * @throws Exception
+ */
+ @Override
+ public void run() throws Exception {
+
+ if (isMigration) {
+ configTool.run();
+ return;
+ }
+
+ super.run();
+ }
+
+ @Override
+ protected String getComponent() throws Exception {
+ return HBASE_INDEXER;
+ }
+
+ @Override
+ protected String getService(Configuration conf) throws Exception {
+ String service = conf.get(SERVICE_NAME, serviceName);
+ if (service == null) {
+ throw new IllegalArgumentException("Service was not defined. Please, use -s command option, or sentry.provider.backend.generic.service-name configuration entry.");
+ }
+ return service;
+ }
+
+ /**
+ * Entry-point for Hbase indexer cli tool.
+ * @param args
+ * @throws Exception
+ */
+ public static void main(String[] args) throws Exception {
+ SentryShellIndexer sentryShell = new SentryShellIndexer();
+ try {
+ sentryShell.executeShell(args);
+ } catch (Exception e) {
+ LOGGER.error(e.getMessage(), e);
+ Throwable current = e;
+ // find the first printable message;
+ while (current != null && current.getMessage() == null) {
+ current = current.getCause();
+ }
+ System.out.println("The operation failed." +
+ (current.getMessage() == null ? "" : " Message: " + current.getMessage()));
+ System.exit(1);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/ShellCommand.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/ShellCommand.java b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/ShellCommand.java
new file mode 100644
index 0000000..9a141c3
--- /dev/null
+++ b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/ShellCommand.java
@@ -0,0 +1,47 @@
+/**
+ * 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.util.List;
+import java.util.Set;
+
+import org.apache.sentry.core.common.exception.SentryUserException;
+
+/**
+ * The interface for all admin commands, eg, CreateRoleCmd. It is independent of the underlying mechanism (i.e. Generic or Hive)
+ */
+public interface ShellCommand {
+
+ void createRole(String requestorName, String roleName) throws SentryUserException;
+
+ void dropRole(String requestorName, String roleName) throws SentryUserException;
+
+ void grantPrivilegeToRole(String requestorName, String roleName, String privilege) throws SentryUserException;
+
+ void grantRoleToGroups(String requestorName, String roleName, Set<String> groups) throws SentryUserException;
+
+ void revokePrivilegeFromRole(String requestorName, String roleName, String privilege) throws SentryUserException;
+
+ void revokeRoleFromGroups(String requestorName, String roleName, Set<String> groups) throws SentryUserException;
+
+ List<String> listRoles(String requestorName, String group) throws SentryUserException;
+
+ List<String> listPrivileges(String requestorName, String roleName) throws SentryUserException;
+
+ List<String> listGroupRoles(String requestorName) throws SentryUserException;
+}
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/command/GenericShellCommand.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/command/GenericShellCommand.java b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/command/GenericShellCommand.java
new file mode 100644
index 0000000..3e0da50
--- /dev/null
+++ b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/command/GenericShellCommand.java
@@ -0,0 +1,156 @@
+/**
+ * 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.command;
+
+import java.util.ArrayList;
+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 org.apache.commons.lang.StringUtils;
+import org.apache.sentry.core.common.exception.SentryUserException;
+import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClient;
+import org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege;
+import org.apache.sentry.provider.db.generic.service.thrift.TSentryRole;
+import org.apache.sentry.cli.tools.ShellCommand;
+import org.apache.sentry.provider.db.generic.tools.TSentryPrivilegeConverter;
+
+/**
+ * The ShellCommand implementation for the Generic clients
+ */
+public class GenericShellCommand implements ShellCommand {
+
+ private final SentryGenericServiceClient client;
+ private final String component;
+ private final TSentryPrivilegeConverter converter;
+ private final String serviceName;
+
+ public GenericShellCommand(SentryGenericServiceClient client, String component, String serviceName,
+ TSentryPrivilegeConverter converter) {
+ this.client = client;
+ this.component = component;
+ this.serviceName = serviceName;
+ this.converter = converter;
+ }
+
+ public void createRole(String requestorName, String roleName) throws SentryUserException {
+ client.createRole(requestorName, roleName, component);
+ }
+
+ public void dropRole(String requestorName, String roleName) throws SentryUserException {
+ client.dropRole(requestorName, roleName, component);
+ }
+
+ public void grantPrivilegeToRole(String requestorName, String roleName, String privilege) throws SentryUserException {
+ TSentryPrivilege sentryPrivilege = converter.fromString(privilege);
+ client.grantPrivilege(requestorName, roleName, component, sentryPrivilege);
+ }
+
+ public void grantRoleToGroups(String requestorName, String roleName, Set<String> groups) throws SentryUserException {
+ client.grantRoleToGroups(requestorName, roleName, component, groups);
+ }
+
+ public void revokePrivilegeFromRole(String requestorName, String roleName, String privilege) throws SentryUserException {
+ TSentryPrivilege sentryPrivilege = converter.fromString(privilege);
+ client.revokePrivilege(requestorName, roleName, component, sentryPrivilege);
+ }
+
+ public void revokeRoleFromGroups(String requestorName, String roleName, Set<String> groups) throws SentryUserException {
+ client.revokeRoleFromGroups(requestorName, roleName, component, groups);
+ }
+
+ public List<String> listRoles(String requestorName, String group) throws SentryUserException {
+ Set<TSentryRole> roles;
+ if (StringUtils.isEmpty(group)) {
+ roles = client.listAllRoles(requestorName, component);
+ } else {
+ roles = client.listRolesByGroupName(requestorName, group, component);
+ }
+
+ List<String> result = new ArrayList<>();
+ if (roles != null) {
+ for (TSentryRole role : roles) {
+ result.add(role.getRoleName());
+ }
+ }
+
+ return result;
+ }
+
+ public List<String> listPrivileges(String requestorName, String roleName) throws SentryUserException {
+ Set<TSentryPrivilege> privileges = client
+ .listAllPrivilegesByRoleName(requestorName, roleName, component, serviceName);
+
+ List<String> result = new ArrayList<>();
+ if (privileges != null) {
+ for (TSentryPrivilege privilege : privileges) {
+ String privilegeStr = converter.toString(privilege);
+ result.add(privilegeStr);
+ }
+ }
+
+ return result;
+ }
+
+ public List<String> listGroupRoles(String requestorName) throws SentryUserException {
+ Set<TSentryRole> roles = client.listAllRoles(requestorName, component);
+ if (roles == null || roles.isEmpty()) {
+ return Collections.emptyList();
+ }
+
+ // Set of all group names
+ Set<String> groupNames = new HashSet<>();
+
+ // Map group to set of roles
+ Map<String, Set<String>> groupInfo = new HashMap<>();
+
+ // Get all group names
+ for (TSentryRole role: roles) {
+ for (String group : role.getGroups()) {
+ groupNames.add(group);
+ Set<String> groupRoles = groupInfo.get(group);
+ if (groupRoles != null) {
+ // Add a new or existing role
+ groupRoles.add(role.getRoleName());
+ continue;
+ }
+ // Never seen this group before
+ groupRoles = new HashSet<>();
+ groupRoles.add(role.getRoleName());
+ groupInfo.put(group, groupRoles);
+ }
+ }
+
+ List<String> groups = new ArrayList<>(groupNames);
+
+ // Produce printable result as
+ // group1 = role1, role2, ...
+ // group2 = ...
+ List<String> result = new LinkedList<>();
+ for (String groupName: groups) {
+ result.add(groupName + " = " + StringUtils.join(groupInfo.get(groupName), ", "));
+ }
+
+ return result;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/command/hive/CommandUtil.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/command/hive/CommandUtil.java b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/command/hive/CommandUtil.java
new file mode 100644
index 0000000..b06732e
--- /dev/null
+++ b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/command/hive/CommandUtil.java
@@ -0,0 +1,63 @@
+/**
+ * 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.command.hive;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.sentry.provider.db.service.thrift.TSentryPrivilege;
+import org.apache.sentry.service.thrift.ServiceConstants;
+
+public final class CommandUtil {
+
+ public static final String SPLIT_CHAR = ",";
+
+ private CommandUtil() {
+ // Make constructor private to avoid instantiation
+ }
+
+ // check the privilege value for the specific privilege scope
+ // eg, for the table scope, server and database can't be empty
+ public static void validatePrivilegeHierarchy(TSentryPrivilege tSentryPrivilege) throws IllegalArgumentException {
+ String serverName = tSentryPrivilege.getServerName();
+ String dbName = tSentryPrivilege.getDbName();
+ String tableName = tSentryPrivilege.getTableName();
+ String columnName = tSentryPrivilege.getColumnName();
+ String uri = tSentryPrivilege.getURI();
+ if (ServiceConstants.PrivilegeScope.SERVER.toString().equals(tSentryPrivilege.getPrivilegeScope())) {
+ if (StringUtils.isEmpty(serverName)) {
+ throw new IllegalArgumentException("The hierarchy of privilege is not correct.");
+ }
+ } else if (ServiceConstants.PrivilegeScope.URI.toString().equals(tSentryPrivilege.getPrivilegeScope())) {
+ if (StringUtils.isEmpty(serverName) || StringUtils.isEmpty(uri)) {
+ throw new IllegalArgumentException("The hierarchy of privilege is not correct.");
+ }
+ } else if (ServiceConstants.PrivilegeScope.DATABASE.toString().equals(tSentryPrivilege.getPrivilegeScope())) {
+ if (StringUtils.isEmpty(serverName) || StringUtils.isEmpty(dbName)) {
+ throw new IllegalArgumentException("The hierarchy of privilege is not correct.");
+ }
+ } else if (ServiceConstants.PrivilegeScope.TABLE.toString().equals(tSentryPrivilege.getPrivilegeScope())) {
+ if (StringUtils.isEmpty(serverName) || StringUtils.isEmpty(dbName)
+ || StringUtils.isEmpty(tableName)) {
+ throw new IllegalArgumentException("The hierarchy of privilege is not correct.");
+ }
+ } else if (ServiceConstants.PrivilegeScope.COLUMN.toString().equals(tSentryPrivilege.getPrivilegeScope())
+ && (StringUtils.isEmpty(serverName) || StringUtils.isEmpty(dbName)
+ || StringUtils.isEmpty(tableName) || StringUtils.isEmpty(columnName))) {
+ throw new IllegalArgumentException("The hierarchy of privilege is not correct.");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/command/hive/HiveShellCommand.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/command/hive/HiveShellCommand.java b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/command/hive/HiveShellCommand.java
new file mode 100644
index 0000000..1d11c3b
--- /dev/null
+++ b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/command/hive/HiveShellCommand.java
@@ -0,0 +1,152 @@
+/**
+ * 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.command.hive;
+
+import java.util.ArrayList;
+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 org.apache.commons.lang.StringUtils;
+import org.apache.sentry.core.common.exception.SentryUserException;
+import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
+import org.apache.sentry.provider.db.service.thrift.TSentryGroup;
+import org.apache.sentry.provider.db.service.thrift.TSentryPrivilege;
+import org.apache.sentry.provider.db.service.thrift.TSentryRole;
+import org.apache.sentry.cli.tools.ShellCommand;
+import org.apache.sentry.service.thrift.SentryServiceUtil;
+
+/**
+ * The ShellCommand implementation for Hive.
+ */
+public class HiveShellCommand implements ShellCommand {
+
+ private final SentryPolicyServiceClient client;
+
+ public HiveShellCommand(SentryPolicyServiceClient client) {
+ this.client = client;
+ }
+
+ public void createRole(String requestorName, String roleName) throws SentryUserException {
+ client.createRole(requestorName, roleName);
+ }
+
+ public void dropRole(String requestorName, String roleName) throws SentryUserException {
+ client.dropRole(requestorName, roleName);
+ }
+
+ public void grantPrivilegeToRole(String requestorName, String roleName, String privilege) throws SentryUserException {
+ TSentryPrivilege tSentryPrivilege = SentryServiceUtil.convertToTSentryPrivilege(privilege);
+ CommandUtil.validatePrivilegeHierarchy(tSentryPrivilege);
+ client.grantPrivilege(requestorName, roleName, tSentryPrivilege);
+ }
+
+ public void grantRoleToGroups(String requestorName, String roleName, Set<String> groups) throws SentryUserException {
+ client.grantRoleToGroups(requestorName, roleName, groups);
+ }
+
+ public void revokePrivilegeFromRole(String requestorName, String roleName, String privilege) throws SentryUserException {
+ TSentryPrivilege tSentryPrivilege = SentryServiceUtil.convertToTSentryPrivilege(privilege);
+ CommandUtil.validatePrivilegeHierarchy(tSentryPrivilege);
+ client.revokePrivilege(requestorName, roleName, tSentryPrivilege);
+ }
+
+ public void revokeRoleFromGroups(String requestorName, String roleName, Set<String> groups) throws SentryUserException {
+ client.revokeRoleFromGroups(requestorName, roleName, groups);
+ }
+
+ public List<String> listRoles(String requestorName, String group) throws SentryUserException {
+ Set<TSentryRole> roles;
+ if (StringUtils.isEmpty(group)) {
+ roles = client.listAllRoles(requestorName);
+ } else {
+ roles = client.listRolesByGroupName(requestorName, group);
+ }
+
+ List<String> result = new ArrayList<>();
+ if (roles != null) {
+ for (TSentryRole role : roles) {
+ result.add(role.getRoleName());
+ }
+ }
+
+ return result;
+ }
+
+ public List<String> listPrivileges(String requestorName, String roleName) throws SentryUserException {
+ Set<TSentryPrivilege> privileges = client
+ .listAllPrivilegesByRoleName(requestorName, roleName);
+
+ List<String> result = new ArrayList<>();
+ if (privileges != null) {
+ for (TSentryPrivilege privilege : privileges) {
+ String privilegeStr = SentryServiceUtil.convertTSentryPrivilegeToStr(privilege);
+ result.add(privilegeStr);
+ }
+ }
+ return result;
+ }
+
+ public List<String> listGroupRoles(String requestorName) throws SentryUserException {
+ Set<TSentryRole> roles = client.listAllRoles(requestorName);
+ if (roles == null || roles.isEmpty()) {
+ return Collections.emptyList();
+ }
+
+ // Set of all group names
+ Set<String> groupNames = new HashSet<>();
+
+ // Map group to set of roles
+ Map<String, Set<String>> groupInfo = new HashMap<>();
+
+ // Get all group names
+ for (TSentryRole role: roles) {
+ for (TSentryGroup group : role.getGroups()) {
+ String groupName = group.getGroupName();
+ groupNames.add(groupName);
+ Set<String> groupRoles = groupInfo.get(groupName);
+ if (groupRoles != null) {
+ // Add a new or existing role
+ groupRoles.add(role.getRoleName());
+ continue;
+ }
+ // Never seen this group before
+ groupRoles = new HashSet<>();
+ groupRoles.add(role.getRoleName());
+ groupInfo.put(groupName, groupRoles);
+ }
+ }
+
+ List<String> groups = new ArrayList<>(groupNames);
+
+ // Produce printable result as
+ // group1 = role1, role2, ...
+ // group2 = ...
+ List<String> result = new LinkedList<>();
+ for (String groupName: groups) {
+ result.add(groupName + " = " + StringUtils.join(groupInfo.get(groupName), ", "));
+ }
+
+ return result;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/main/java/org/apache/sentry/shell/GroupShell.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/shell/GroupShell.java b/sentry-tools/src/main/java/org/apache/sentry/shell/GroupShell.java
index b7652a5..863f992 100644
--- a/sentry-tools/src/main/java/org/apache/sentry/shell/GroupShell.java
+++ b/sentry-tools/src/main/java/org/apache/sentry/shell/GroupShell.java
@@ -23,7 +23,7 @@ import com.budhash.cliche.Shell;
import com.budhash.cliche.ShellDependent;
import org.apache.sentry.core.common.exception.SentryUserException;
-import org.apache.sentry.provider.db.tools.ShellCommand;
+import org.apache.sentry.cli.tools.ShellCommand;
import java.util.Arrays;
import java.util.Collections;
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/main/java/org/apache/sentry/shell/PrivsShell.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/shell/PrivsShell.java b/sentry-tools/src/main/java/org/apache/sentry/shell/PrivsShell.java
index 8b8898f..3ff6737 100644
--- a/sentry-tools/src/main/java/org/apache/sentry/shell/PrivsShell.java
+++ b/sentry-tools/src/main/java/org/apache/sentry/shell/PrivsShell.java
@@ -24,7 +24,7 @@ import com.budhash.cliche.Shell;
import com.budhash.cliche.ShellDependent;
import org.apache.sentry.core.common.exception.SentryUserException;
-import org.apache.sentry.provider.db.tools.ShellCommand;
+import org.apache.sentry.cli.tools.ShellCommand;
import java.util.Collections;
import java.util.List;
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/main/java/org/apache/sentry/shell/RolesShell.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/shell/RolesShell.java b/sentry-tools/src/main/java/org/apache/sentry/shell/RolesShell.java
index c014a30..42bce19 100644
--- a/sentry-tools/src/main/java/org/apache/sentry/shell/RolesShell.java
+++ b/sentry-tools/src/main/java/org/apache/sentry/shell/RolesShell.java
@@ -24,7 +24,7 @@ import com.budhash.cliche.Shell;
import com.budhash.cliche.ShellDependent;
import org.apache.sentry.core.common.exception.SentryUserException;
-import org.apache.sentry.provider.db.tools.ShellCommand;
+import org.apache.sentry.cli.tools.ShellCommand;
import java.util.Collections;
import java.util.List;
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java b/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java
index d9952a9..04d65bd 100644
--- a/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java
+++ b/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java
@@ -22,11 +22,11 @@ import org.apache.sentry.core.common.exception.SentryUserException;
import org.apache.sentry.provider.common.AuthorizationComponent;
import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClient;
import org.apache.sentry.provider.db.generic.tools.GenericPrivilegeConverter;
-import org.apache.sentry.provider.db.generic.tools.command.GenericShellCommand;
-import org.apache.sentry.provider.db.generic.tools.command.TSentryPrivilegeConverter;
+import org.apache.sentry.cli.tools.command.GenericShellCommand;
+import org.apache.sentry.provider.db.generic.tools.TSentryPrivilegeConverter;
import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
-import org.apache.sentry.provider.db.tools.ShellCommand;
-import org.apache.sentry.provider.db.tools.command.hive.HiveShellCommand;
+import org.apache.sentry.cli.tools.ShellCommand;
+import org.apache.sentry.cli.tools.command.hive.HiveShellCommand;
import com.budhash.cliche.Command;
import com.budhash.cliche.Param;
[3/9] sentry git commit: SENTRY-2207 Refactor out Sentry CLI from
sentry-provider-db into own module. Steve Moist,
reviewed by Colm O hEigeartaigh.
Posted by co...@apache.org.
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);
+ }
+}
[9/9] sentry git commit: SENTRY-2207 Refactor out Sentry CLI from
sentry-provider-db into own module. Steve Moist,
reviewed by Colm O hEigeartaigh.
Posted by co...@apache.org.
SENTRY-2207 Refactor out Sentry CLI from sentry-provider-db into own module. Steve Moist, reviewed by Colm O hEigeartaigh.
Project: http://git-wip-us.apache.org/repos/asf/sentry/repo
Commit: http://git-wip-us.apache.org/repos/asf/sentry/commit/6752f14a
Tree: http://git-wip-us.apache.org/repos/asf/sentry/tree/6752f14a
Diff: http://git-wip-us.apache.org/repos/asf/sentry/diff/6752f14a
Branch: refs/heads/master
Commit: 6752f14aafad2f9ead0198f2f840db120182b268
Parents: 0668237
Author: Colm O hEigeartaigh <co...@apache.org>
Authored: Mon Apr 30 17:34:56 2018 +0100
Committer: Colm O hEigeartaigh <co...@apache.org>
Committed: Mon Apr 30 17:35:33 2018 +0100
----------------------------------------------------------------------
bin/sentryShell | 10 +-
pom.xml | 2 +-
sentry-provider/sentry-provider-db/pom.xml | 13 +
.../generic/SentryGenericProviderBackend.java | 2 +-
.../provider/db/generic/UpdatableCache.java | 2 +-
.../tools/GenericPrivilegeConverter.java | 6 +-
.../tools/PermissionsMigrationToolCommon.java | 348 -----------
.../tools/PermissionsMigrationToolSolr.java | 109 ----
.../generic/tools/SentryConfigToolCommon.java | 152 -----
.../generic/tools/SentryConfigToolIndexer.java | 340 ----------
.../db/generic/tools/SentryConfigToolSolr.java | 264 --------
.../db/generic/tools/SentryShellGeneric.java | 158 -----
.../db/generic/tools/SentryShellIndexer.java | 124 ----
.../tools/TSentryPrivilegeConverter.java | 35 ++
.../tools/command/GenericShellCommand.java | 155 -----
.../command/TSentryPrivilegeConverter.java | 34 -
.../provider/db/tools/SentrySchemaHelper.java | 315 ----------
.../provider/db/tools/SentrySchemaTool.java | 595 ------------------
.../provider/db/tools/SentryShellCommon.java | 284 ---------
.../provider/db/tools/SentryShellHive.java | 118 ----
.../sentry/provider/db/tools/ShellCommand.java | 47 --
.../db/tools/command/hive/CommandUtil.java | 63 --
.../db/tools/command/hive/HiveShellCommand.java | 152 -----
.../tools/TestPermissionsMigrationToolSolr.java | 362 -----------
.../tools/TestSentryConfigToolIndexer.java | 263 --------
.../generic/tools/TestSentryConfigToolSolr.java | 261 --------
.../generic/tools/TestSentryShellIndexer.java | 526 ----------------
.../db/generic/tools/TestSentryShellKafka.java | 550 -----------------
.../db/generic/tools/TestSentryShellSolr.java | 534 ----------------
.../db/generic/tools/TestSentryShellSqoop.java | 532 ----------------
.../provider/db/tools/TestSentrySchemaTool.java | 94 ---
.../provider/db/tools/TestSentryShellHive.java | 613 -------------------
.../src/test/resources/indexer_case.ini | 26 -
.../resources/indexer_config_import_tool.ini | 29 -
.../src/test/resources/indexer_invalid.ini | 21 -
.../src/test/resources/solr_case.ini | 26 -
.../test/resources/solr_config_import_tool.ini | 29 -
.../src/test/resources/solr_invalid.ini | 21 -
sentry-tools/pom.xml | 44 +-
.../main/java/org/apache/sentry/SentryMain.java | 2 +-
.../tools/PermissionsMigrationToolCommon.java | 349 +++++++++++
.../cli/tools/PermissionsMigrationToolSolr.java | 109 ++++
.../cli/tools/SentryConfigToolCommon.java | 152 +++++
.../cli/tools/SentryConfigToolIndexer.java | 341 +++++++++++
.../sentry/cli/tools/SentryConfigToolSolr.java | 265 ++++++++
.../sentry/cli/tools/SentrySchemaHelper.java | 315 ++++++++++
.../sentry/cli/tools/SentrySchemaTool.java | 595 ++++++++++++++++++
.../sentry/cli/tools/SentryShellCommon.java | 284 +++++++++
.../sentry/cli/tools/SentryShellGeneric.java | 157 +++++
.../sentry/cli/tools/SentryShellHive.java | 118 ++++
.../sentry/cli/tools/SentryShellIndexer.java | 124 ++++
.../apache/sentry/cli/tools/ShellCommand.java | 47 ++
.../cli/tools/command/GenericShellCommand.java | 156 +++++
.../cli/tools/command/hive/CommandUtil.java | 63 ++
.../tools/command/hive/HiveShellCommand.java | 152 +++++
.../org/apache/sentry/shell/GroupShell.java | 2 +-
.../org/apache/sentry/shell/PrivsShell.java | 2 +-
.../org/apache/sentry/shell/RolesShell.java | 2 +-
.../org/apache/sentry/shell/TopLevelShell.java | 8 +-
.../tools/TestPermissionsMigrationToolSolr.java | 362 +++++++++++
.../cli/tools/TestSentryConfigToolIndexer.java | 263 ++++++++
.../cli/tools/TestSentryConfigToolSolr.java | 260 ++++++++
.../sentry/cli/tools/TestSentrySchemaTool.java | 113 ++++
.../sentry/cli/tools/TestSentryShellHive.java | 613 +++++++++++++++++++
.../cli/tools/TestSentryShellIndexer.java | 525 ++++++++++++++++
.../sentry/cli/tools/TestSentryShellKafka.java | 549 +++++++++++++++++
.../sentry/cli/tools/TestSentryShellSolr.java | 533 ++++++++++++++++
.../sentry/cli/tools/TestSentryShellSqoop.java | 531 ++++++++++++++++
sentry-tools/src/test/resources/cacerts.jks | Bin 0 -> 954 bytes
.../src/test/resources/indexer_case.ini | 26 +
.../resources/indexer_config_import_tool.ini | 29 +
.../src/test/resources/indexer_invalid.ini | 21 +
sentry-tools/src/test/resources/keystore.jks | Bin 0 -> 2245 bytes
.../src/test/resources/log4j.properties | 34 +
sentry-tools/src/test/resources/solr_case.ini | 26 +
.../test/resources/solr_config_import_tool.ini | 29 +
.../src/test/resources/solr_invalid.ini | 21 +
77 files changed, 7266 insertions(+), 7171 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/bin/sentryShell
----------------------------------------------------------------------
diff --git a/bin/sentryShell b/bin/sentryShell
index 17b1429..140f7ce 100755
--- a/bin/sentryShell
+++ b/bin/sentryShell
@@ -54,15 +54,15 @@ for f in ${SENTRY_HOME}/lib/plugins/*.jar; do
done
args=()
-shell=org.apache.sentry.provider.db.tools.SentryShellHive
+shell=org.apache.sentry.cli.tools.SentryShellHive
# get the type argument for the command
while [ $# -gt 0 ]; do # Until you run out of parameters . . .
if [[ "$1" = "-t" || "$1" = "--type" ]]; then
case $2 in
- "hive") shell=org.apache.sentry.provider.db.tools.SentryShellHive ;;
- "kafka") shell=org.apache.sentry.provider.db.generic.tools.SentryShellGeneric ;;
- "solr") shell=org.apache.sentry.provider.db.generic.tools.SentryShellGeneric ;;
- "sqoop") shell=org.apache.sentry.provider.db.generic.tools.SentryShellGeneric ;;
+ "hive") shell=org.apache.sentry.cli.tools.SentryShellHive ;;
+ "kafka") shell=org.apache.sentry.cli.tools.SentryShellGeneric ;;
+ "solr") shell=org.apache.sentry.cli.tools.SentryShellGeneric ;;
+ "sqoop") shell=org.apache.sentry.cli.tools.SentryShellGeneric ;;
*) echo "Doesn't support the type $2!"; exit 1 ;;
esac
fi
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 16a3838..262a9d8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1048,7 +1048,7 @@ limitations under the License.
<exclude>%regex[org.apache.sentry.provider.db.service.thrift.*.class]</exclude>
<exclude>%regex[org.apache.solr.handler.admin.*.class]</exclude>
<exclude>%regex[org.apache.sentry.provider.db.generic.service.thrift.*.class]</exclude>
- <exclude>%regex[org.apache.sentry.provider.db.generic.tools.*.class]</exclude>
+ <exclude>%regex[org.apache.sentry.cli.tools.*.class]</exclude>
</excludes>
</configuration>
</plugin>
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/pom.xml
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/pom.xml b/sentry-provider/sentry-provider-db/pom.xml
index b8cccfa..369e262 100644
--- a/sentry-provider/sentry-provider-db/pom.xml
+++ b/sentry-provider/sentry-provider-db/pom.xml
@@ -398,6 +398,19 @@ limitations under the License.
</execution>
</executions>
</plugin>
+ <!--This is to export SentryGenericServiceIntegrationBase across Modules -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>2.2</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>test-jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
</plugins>
<pluginManagement>
<plugins>
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/SentryGenericProviderBackend.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/SentryGenericProviderBackend.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/SentryGenericProviderBackend.java
index cf552b1..fe0eb07 100644
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/SentryGenericProviderBackend.java
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/SentryGenericProviderBackend.java
@@ -35,7 +35,7 @@ import org.apache.sentry.provider.common.ProviderBackendContext;
import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClient;
import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClientFactory;
import org.apache.sentry.provider.db.generic.service.thrift.TSentryRole;
-import org.apache.sentry.provider.db.generic.tools.command.TSentryPrivilegeConverter;
+import org.apache.sentry.provider.db.generic.tools.TSentryPrivilegeConverter;
import org.apache.sentry.service.thrift.ServiceConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/UpdatableCache.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/UpdatableCache.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/UpdatableCache.java
index edf0934..31fcfc7 100644
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/UpdatableCache.java
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/UpdatableCache.java
@@ -18,7 +18,7 @@ import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.sentry.provider.common.TableCache;
import org.apache.sentry.provider.db.generic.service.thrift.*;
-import org.apache.sentry.provider.db.generic.tools.command.TSentryPrivilegeConverter;
+import org.apache.sentry.provider.db.generic.tools.TSentryPrivilegeConverter;
import org.apache.sentry.service.thrift.ServiceConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/GenericPrivilegeConverter.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/GenericPrivilegeConverter.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/GenericPrivilegeConverter.java
index 8de543c..82b21ef 100644
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/GenericPrivilegeConverter.java
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/GenericPrivilegeConverter.java
@@ -1,4 +1,5 @@
-/**
+/*
+ *
* 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
@@ -7,7 +8,7 @@
* "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
+ * 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,
@@ -48,7 +49,6 @@ import org.apache.sentry.provider.common.AuthorizationComponent;
import org.apache.sentry.provider.db.generic.service.thrift.TAuthorizable;
import org.apache.sentry.provider.db.generic.service.thrift.TSentryGrantOption;
import org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege;
-import org.apache.sentry.provider.db.generic.tools.command.TSentryPrivilegeConverter;
import org.apache.shiro.config.ConfigurationException;
/**
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/PermissionsMigrationToolCommon.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/PermissionsMigrationToolCommon.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/PermissionsMigrationToolCommon.java
deleted file mode 100644
index e3d81f8..0000000
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/PermissionsMigrationToolCommon.java
+++ /dev/null
@@ -1,348 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.sentry.provider.db.generic.tools;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Optional;
-import java.util.Set;
-
-import org.apache.commons.cli.CommandLine;
-import org.apache.commons.cli.GnuParser;
-import org.apache.commons.cli.HelpFormatter;
-import org.apache.commons.cli.Option;
-import org.apache.commons.cli.Options;
-import org.apache.commons.cli.ParseException;
-import org.apache.commons.cli.Parser;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.security.UserGroupInformation;
-import org.apache.sentry.core.common.ActiveRoleSet;
-import org.apache.sentry.core.common.utils.PolicyFileConstants;
-import org.apache.sentry.core.common.utils.PolicyFiles;
-import org.apache.sentry.core.common.utils.Version;
-import org.apache.sentry.policy.common.PrivilegeUtils;
-import org.apache.sentry.provider.common.ProviderBackendContext;
-import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClient;
-import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClientFactory;
-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.file.SimpleFileProviderBackend;
-import org.apache.shiro.config.Ini;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.Sets;
-import com.google.common.collect.Table;
-
-/**
- * This class provides basic framework required to migrate permissions between different Sentry
- * versions. Individual components (e.g. SOLR, KAFKA) needs to override the this class
- * to provide component specific migration functionality.
- */
-public abstract class PermissionsMigrationToolCommon {
- private static final Logger LOGGER = LoggerFactory.getLogger(PermissionsMigrationToolCommon.class);
- public static final String SOLR_SERVICE_NAME = "sentry.service.client.solr.service.name";
-
- private Version sourceVersion;
- private Optional<String> confPath = Optional.empty();
- private Optional<String> policyFile = Optional.empty();
- private Optional<String> outputFile = Optional.empty();
- private boolean dryRun = false;
-
- /**
- * @return version of Sentry for which the privileges need to be migrated.
- */
- public final Version getSourceVersion() {
- return sourceVersion;
- }
-
- /**
- * This method returns the name of the component for the migration purpose.
- * @param conf The Sentry configuration
- * @return the name of the component
- */
- protected abstract String getComponent(Configuration conf);
-
-
- /**
- * This method returns the name of the service name for the migration purpose.
- *
- * @param conf The Sentry configuration
- * @return the name of the service
- */
- protected abstract String getServiceName(Configuration conf);
-
- /**
- * Migrate the privileges specified via <code>privileges</code>.
- *
- * @param privileges A collection of privileges to be migrated.
- * @return A collection of migrated privileges
- * An empty collection if migration is not necessary for the specified privileges.
- */
- protected abstract Collection<String> transformPrivileges (Collection<String> privileges);
-
- /**
- * parse arguments
- * <pre>
- * -s,--source Sentry source version
- * -c,--sentry_conf <filepath> sentry config file path
- * -p --policy_file <filepath> sentry (source) policy file path
- * -o --output <filepath> sentry (target) policy file path
- * -d --dry_run provides the output the migration for inspection without
- * making any configuration changes.
- * -h,--help print usage
- * </pre>
- * @param args
- */
- protected boolean parseArgs(String [] args) {
- Options options = new Options();
-
- Option sourceVersionOpt = new Option("s", "source", true, "Source Sentry version");
- sourceVersionOpt.setRequired(true);
- options.addOption(sourceVersionOpt);
-
- Option sentryConfPathOpt = new Option("c", "sentry_conf", true,
- "sentry-site.xml file path (only required in case of Sentry service)");
- sentryConfPathOpt.setRequired(false);
- options.addOption(sentryConfPathOpt);
-
- Option sentryPolicyFileOpt = new Option("p", "policy_file", true,
- "sentry (source) policy file path (only in case of file based Sentry configuration)");
- sentryPolicyFileOpt.setRequired(false);
- options.addOption(sentryPolicyFileOpt);
-
- Option sentryOutputFileOpt = new Option("o", "output", true,
- "sentry (target) policy file path (only in case of file based Sentry configuration)");
- sentryOutputFileOpt.setRequired(false);
- options.addOption(sentryOutputFileOpt);
-
- Option dryRunOpt = new Option("d", "dry_run", false,
- "provides the output the migration for inspection without making actual configuration changes");
- dryRunOpt.setRequired(false);
- options.addOption(dryRunOpt);
-
- // help option
- Option helpOpt = new Option("h", "help", false, "Shell usage");
- helpOpt.setRequired(false);
- options.addOption(helpOpt);
-
- // this Option is parsed first for help option
- Options helpOptions = new Options();
- helpOptions.addOption(helpOpt);
-
- try {
- Parser parser = new GnuParser();
-
- // parse help option first
- CommandLine cmd = parser.parse(helpOptions, args, true);
- for (Option opt : cmd.getOptions()) {
- if (opt.getOpt().equals("h")) {
- // get the help option, print the usage and exit
- usage(options);
- return false;
- }
- }
-
- // without help option
- cmd = parser.parse(options, args);
-
- String sourceVersionStr = null;
-
- for (Option opt : cmd.getOptions()) {
- if (opt.getOpt().equals("s")) {
- sourceVersionStr = opt.getValue();
- } else if (opt.getOpt().equals("c")) {
- confPath = Optional.of(opt.getValue());
- } else if (opt.getOpt().equals("p")) {
- policyFile = Optional.of(opt.getValue());
- } else if (opt.getOpt().equals("o")) {
- outputFile = Optional.of(opt.getValue());
- } else if (opt.getOpt().equals("d")) {
- dryRun = true;
- }
- }
-
- sourceVersion = Version.parse(sourceVersionStr);
-
- if (!(confPath.isPresent() || policyFile.isPresent())) {
- System.out.println("Please select either file-based Sentry configuration (-p and -o flags)"
- + " or Sentry service (-c flag) for migration.");
- usage(options);
- return false;
- }
-
- if (confPath.isPresent() && (policyFile.isPresent() || outputFile.isPresent())) {
- System.out.println("In order to migrate service based Sentry configuration,"
- + " do not specify either -p or -o parameters");
- usage(options);
- return false;
- }
-
- if (!confPath.isPresent() && (policyFile.isPresent() ^ outputFile.isPresent())) {
- System.out.println("In order to migrate file based Sentry configuration,"
- + " please make sure to specify both -p and -o parameters.");
- usage(options);
- return false;
- }
-
- } catch (ParseException | java.text.ParseException pe) {
- System.out.println(pe.getMessage());
- usage(options);
- return false;
- }
- return true;
- }
-
- // print usage
- private void usage(Options sentryOptions) {
- HelpFormatter formatter = new HelpFormatter();
- formatter.printHelp("sentryMigrationTool", sentryOptions);
- }
-
- public void run() throws Exception {
- if (policyFile.isPresent()) {
- migratePolicyFile();
- } else {
- migrateSentryServiceConfig();
- }
- }
-
- private void migrateSentryServiceConfig() throws Exception {
- Configuration conf = getSentryConf();
- String component = getComponent(conf);
- String serviceName = getServiceName(conf);
- GenericPrivilegeConverter converter = new GenericPrivilegeConverter(component, serviceName, false);
-
- // instantiate a client for sentry service. This sets the ugi, so must
- // be done before getting the ugi below.
- try(SentryGenericServiceClient client =
- SentryGenericServiceClientFactory.create(getSentryConf())) {
- UserGroupInformation ugi = UserGroupInformation.getLoginUser();
- String requestorName = ugi.getShortUserName();
-
- for (TSentryRole r : client.listAllRoles(requestorName, component)) {
- for (TSentryPrivilege p : client.listAllPrivilegesByRoleName(requestorName,
- r.getRoleName(), component, serviceName)) {
-
- String privilegeStr = converter.toString(p);
- Collection<String> privileges = Collections.singleton(privilegeStr);
- Collection<String> migrated = transformPrivileges(privileges);
- if (!migrated.isEmpty()) {
- LOGGER.info("{} For role {} migrating privileges from {} to {}", getDryRunMessage(), r.getRoleName(),
- privileges, migrated);
-
- /*
- * Note that it is not possible to provide transactional (all-or-nothing) behavior for these configuration
- * changes since the Sentry client/server protocol does not support. e.g. under certain failure conditions
- * like crash of Sentry server or network disconnect between client/server, it is possible that the migration
- * can not complete but can also not be rolled back. Hence this migration tool relies on the fact that privilege
- * grant/revoke operations are idempotent and hence re-execution of the migration tool will fix any inconsistency
- * due to such failures.
- **/
- boolean originalPermPresent = false;
- for (String perm : migrated) {
- if (perm.equalsIgnoreCase(privilegeStr)) {
- originalPermPresent = true;
- continue;
- }
- TSentryPrivilege x = converter.fromString(perm);
- LOGGER.info("{} GRANT permission {}", getDryRunMessage(), perm);
- if (!dryRun) {
- client.grantPrivilege(requestorName, r.getRoleName(), component, x);
- }
- }
-
- // Revoke old permission (only if not part of migrated permissions)
- if (!originalPermPresent) {
- LOGGER.info("{} REVOKE permission {}", getDryRunMessage(), privilegeStr);
- if (!dryRun) {
- client.revokePrivilege(requestorName, r.getRoleName(), component, p);
- }
- }
- }
- }
- }
- }
- }
-
- private void migratePolicyFile () throws Exception {
- Configuration conf = getSentryConf();
- Path sourceFile = new Path (policyFile.get());
- SimpleFileProviderBackend policyFileBackend = new SimpleFileProviderBackend(conf, sourceFile);
- ProviderBackendContext ctx = new ProviderBackendContext();
- policyFileBackend.initialize(ctx);
-
- Set<String> roles = Sets.newHashSet();
- Table<String, String, Set<String>> groupRolePrivilegeTable =
- policyFileBackend.getGroupRolePrivilegeTable();
-
- Ini output = PolicyFiles.loadFromPath(sourceFile.getFileSystem(conf), sourceFile);
- Ini.Section rolesSection = output.get(PolicyFileConstants.ROLES);
-
- for (String groupName : groupRolePrivilegeTable.rowKeySet()) {
- for (String roleName : policyFileBackend.getRoles(Collections.singleton(groupName), ActiveRoleSet.ALL)) {
- if (!roles.contains(roleName)) {
- // Do the actual migration
- Set<String> privileges = groupRolePrivilegeTable.get(groupName, roleName);
- Collection<String> migrated = transformPrivileges(privileges);
-
- if (!migrated.isEmpty()) {
- LOGGER.info("{} For role {} migrating privileges from {} to {}", getDryRunMessage(),
- roleName, privileges, migrated);
- if (!dryRun) {
- rolesSection.put(roleName, PrivilegeUtils.fromPrivilegeStrings(migrated));
- }
- }
-
- roles.add(roleName);
- }
- }
- }
-
- if (!dryRun) {
- Path targetFile = new Path (outputFile.get());
- PolicyFiles.writeToPath(output, targetFile.getFileSystem(conf), targetFile);
- LOGGER.info("Successfully saved migrated Sentry policy file at {}", outputFile.get());
- }
- }
-
- private String getDryRunMessage() {
- return dryRun ? "[Dry Run]" : "";
- }
-
- private Configuration getSentryConf() {
- Configuration conf = new Configuration();
- if (confPath.isPresent()) {
- conf.addResource(new Path(confPath.get()), true);
- }
- return conf;
- }
-
- @VisibleForTesting
- public boolean executeConfigTool(String [] args) throws Exception {
- boolean result = true;
- if (parseArgs(args)) {
- run();
- } else {
- result = false;
- }
- return result;
- }
-}
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/PermissionsMigrationToolSolr.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/PermissionsMigrationToolSolr.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/PermissionsMigrationToolSolr.java
deleted file mode 100644
index 5799993..0000000
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/PermissionsMigrationToolSolr.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.sentry.provider.db.generic.tools;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.hadoop.conf.Configuration;
-import org.apache.sentry.core.common.utils.SentryConstants;
-import org.apache.sentry.core.model.solr.validator.SolrPrivilegeValidator;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * This class provides SOLR specific functionality required for migrating Sentry privileges.
- */
-public class PermissionsMigrationToolSolr extends PermissionsMigrationToolCommon {
- private static final Logger LOGGER = LoggerFactory.getLogger(PermissionsMigrationToolSolr.class);
-
-
- @Override
- protected String getComponent(Configuration conf) {
- return "SOLR";
- }
-
- @Override
- protected String getServiceName(Configuration conf) {
- return conf.get(SOLR_SERVICE_NAME, "service1");
- }
-
- @Override
- protected Collection<String> transformPrivileges(Collection<String> privileges) {
- List<String> result = new ArrayList<>();
- boolean migrated = false;
-
- if (getSourceVersion().major == 1) { // Migrate only Sentry 1.x permissions
- for (String p : privileges) {
- SolrPrivilegeValidator v = new SolrPrivilegeValidator();
- v.validate(p, false);
-
- if ("collection".equalsIgnoreCase(v.getEntityType()) && "admin".equalsIgnoreCase(v.getEntityName())) {
- result.add(getPermissionStr("admin", "collections", v.getActionName()));
- result.add(getPermissionStr("admin", "cores", v.getActionName()));
- migrated = true;
- } else if ("collection".equalsIgnoreCase(v.getEntityType()) && "*".equals(v.getEntityName())) {
- result.add(getPermissionStr("admin", "collections", v.getActionName()));
- result.add(getPermissionStr("admin", "cores", v.getActionName()));
- result.add(p);
- migrated = true;
- } else {
- result.add(p);
- }
- }
- }
-
- return migrated ? result : Collections.emptyList();
- }
-
- private String getPermissionStr (String entityType, String entityName, String action) {
- StringBuilder builder = new StringBuilder();
- builder.append(entityType);
- builder.append(SentryConstants.KV_SEPARATOR);
- builder.append(entityName);
- if (action != null) {
- builder.append(SentryConstants.AUTHORIZABLE_SEPARATOR);
- builder.append(SentryConstants.PRIVILEGE_NAME);
- builder.append(SentryConstants.KV_SEPARATOR);
- builder.append(action);
- }
- return builder.toString();
- }
-
- public static void main(String[] args) throws Exception {
- PermissionsMigrationToolSolr solrTool = new PermissionsMigrationToolSolr();
- try {
- solrTool.executeConfigTool(args);
- } catch (Exception e) {
- LOGGER.error(e.getMessage(), e);
- Throwable current = e;
- // find the first printable message;
- while (current != null && current.getMessage() == null) {
- current = current.getCause();
- }
- String error = "";
- if (current != null && current.getMessage() != null) {
- error = "Message: " + current.getMessage();
- }
- System.out.println("The operation failed. " + error);
- System.exit(1);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/SentryConfigToolCommon.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/SentryConfigToolCommon.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/SentryConfigToolCommon.java
deleted file mode 100644
index 013e824..0000000
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/SentryConfigToolCommon.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.sentry.provider.db.generic.tools;
-
-import com.google.common.annotations.VisibleForTesting;
-
-import org.apache.commons.cli.CommandLine;
-import org.apache.commons.cli.GnuParser;
-import org.apache.commons.cli.HelpFormatter;
-import org.apache.commons.cli.Option;
-import org.apache.commons.cli.Options;
-import org.apache.commons.cli.ParseException;
-import org.apache.commons.cli.Parser;
-
-abstract public class SentryConfigToolCommon {
- private String policyFile;
- private boolean validate;
- private boolean importPolicy;
- private boolean checkCompat;
- private String confPath;
-
- /**
- * parse arguments
- * <pre>
- * -conf,--sentry_conf <filepath> sentry config file path
- * -p,--policy_ini <arg> policy file path
- * -v,--validate validate policy file
- * -c,--checkcompat check compatibility with service
- * -i,--import import policy file
- * -h,--help print usage
- * </pre>
- * @param args
- */
- protected boolean parseArgs(String [] args) {
- Options options = new Options();
-
- Option globalPolicyPath = new Option("p", "policy_ini", true,
- "Policy file path");
- globalPolicyPath.setRequired(true);
- options.addOption(globalPolicyPath);
-
- Option validateOpt = new Option("v", "validate", false,
- "Validate policy file");
- validateOpt.setRequired(false);
- options.addOption(validateOpt);
-
- Option checkCompatOpt = new Option("c","checkcompat",false,
- "Check compatibility with Sentry Service");
- checkCompatOpt.setRequired(false);
- options.addOption(checkCompatOpt);
-
- Option importOpt = new Option("i", "import", false,
- "Import policy file");
- importOpt.setRequired(false);
- options.addOption(importOpt);
-
- // file path of sentry-site
- Option sentrySitePathOpt = new Option("conf", "sentry_conf", true, "sentry-site file path");
- sentrySitePathOpt.setRequired(true);
- options.addOption(sentrySitePathOpt);
-
- // help option
- Option helpOpt = new Option("h", "help", false, "Shell usage");
- helpOpt.setRequired(false);
- options.addOption(helpOpt);
-
- // this Options is parsed first for help option
- Options helpOptions = new Options();
- helpOptions.addOption(helpOpt);
-
- try {
- Parser parser = new GnuParser();
-
- // parse help option first
- CommandLine cmd = parser.parse(helpOptions, args, true);
- for (Option opt : cmd.getOptions()) {
- if (opt.getOpt().equals("h")) {
- // get the help option, print the usage and exit
- usage(options);
- return false;
- }
- }
-
- // without help option
- cmd = parser.parse(options, args);
-
- for (Option opt : cmd.getOptions()) {
- if (opt.getOpt().equals("p")) {
- policyFile = opt.getValue();
- } else if (opt.getOpt().equals("v")) {
- validate = true;
- } else if (opt.getOpt().equals("i")) {
- importPolicy = true;
- } else if (opt.getOpt().equals("c")) {
- checkCompat = true;
- } else if (opt.getOpt().equals("conf")) {
- confPath = opt.getValue();
- }
- }
-
- if (!validate && !importPolicy) {
- throw new IllegalArgumentException("No action specified; at least one of action or import must be specified");
- }
- } catch (ParseException pe) {
- System.out.println(pe.getMessage());
- usage(options);
- return false;
- }
- return true;
- }
-
- // print usage
- private void usage(Options sentryOptions) {
- HelpFormatter formatter = new HelpFormatter();
- formatter.printHelp("sentryConfigTool", sentryOptions);
- }
-
- public abstract void run() throws Exception;
-
- @VisibleForTesting
- public boolean executeConfigTool(String [] args) throws Exception {
- boolean result = true;
- if (parseArgs(args)) {
- run();
- } else {
- result = false;
- }
- return result;
- }
-
- public String getPolicyFile() { return policyFile; }
- public boolean getValidate() { return validate; }
- public boolean getImportPolicy() { return importPolicy; }
- public boolean getCheckCompat() { return checkCompat; }
- public String getConfPath() { return confPath; }
-}
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/SentryConfigToolIndexer.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/SentryConfigToolIndexer.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/SentryConfigToolIndexer.java
deleted file mode 100644
index a5996a7..0000000
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/SentryConfigToolIndexer.java
+++ /dev/null
@@ -1,340 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.sentry.provider.db.generic.tools;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-import com.google.common.collect.Table;
-import org.apache.commons.cli.CommandLine;
-import org.apache.commons.cli.Option;
-import org.apache.commons.cli.Options;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.security.UserGroupInformation;
-import org.apache.sentry.core.common.Action;
-import org.apache.sentry.core.common.exception.SentryConfigurationException;
-import org.apache.sentry.core.common.utils.KeyValue;
-import org.apache.sentry.core.model.indexer.IndexerPrivilegeModel;
-import org.apache.sentry.provider.common.ProviderBackend;
-import org.apache.sentry.provider.common.ProviderBackendContext;
-import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClient;
-import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClientFactory;
-import org.apache.sentry.provider.file.SimpleFileProviderBackend;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-
-import static org.apache.sentry.core.common.utils.SentryConstants.AUTHORIZABLE_SPLITTER;
-import static org.apache.sentry.provider.common.AuthorizationComponent.HBASE_INDEXER;
-import static org.apache.sentry.service.thrift.ServiceConstants.ClientConfig.SERVICE_NAME;
-
-/**
- * SentryConfigToolIndexer is an administrative tool used to parse a HBase Indexer policy file
- * and add the role, group mappings, and privileges therein to the Sentry service.
- */
-public class SentryConfigToolIndexer {
-
- private static final Logger LOGGER = LoggerFactory.getLogger(SentryConfigToolIndexer.class);
-
- private String policyFile;
- private boolean validate;
- private boolean importPolicy;
- private boolean checkCompat;
- private String confPath;
-
- private String serviceName;
-
-
-
- public String getPolicyFile() { return policyFile; }
-
- public boolean getValidate() { return validate; }
- public boolean getImportPolicy() { return importPolicy; }
- public boolean getCheckCompat() { return checkCompat; }
- public String getConfPath() { return confPath; }
- public String getServiceName() {
- return serviceName;
- }
-
- /**
- * Adds command line options for the tool to the passed Options object. Used to extend existing options.
- * @param options
- */
- public void setupOptions(Options options) {
- Option globalPolicyPath = new Option("f", "policy_ini", true,
- "Policy file path");
- globalPolicyPath.setRequired(false);
- options.addOption(globalPolicyPath);
-
- Option validateOpt = new Option("v", "validate", false,
- "Validate policy file");
- validateOpt.setRequired(false);
- options.addOption(validateOpt);
-
- Option checkCompatOpt = new Option("c","checkcompat",false,
- "Check compatibility with Sentry Service");
- checkCompatOpt.setRequired(false);
- options.addOption(checkCompatOpt);
-
- Option importOpt = new Option("i", "import", false,
- "Import policy file");
- importOpt.setRequired(false);
- options.addOption(importOpt);
-
- }
-
- /**
- * Parses and processes the arguments from the given command line object.
- * @param cmd
- */
- public void parseOptions(CommandLine cmd) {
- boolean isToolActive = false;
- for (Option opt : cmd.getOptions()) {
- if (opt.getOpt().equals("mgr")) {
- isToolActive = true;
- }
- }
- if (!isToolActive) {
- return;
- }
- for (Option opt : cmd.getOptions()) {
- if (opt.getOpt().equals("f")) {
- policyFile = opt.getValue();
- } else if (opt.getOpt().equals("v")) {
- validate = true;
- } else if (opt.getOpt().equals("i")) {
- importPolicy = true;
- } else if (opt.getOpt().equals("c")) {
- checkCompat = true;
- } else if (opt.getOpt().equals("conf")) {
- confPath = opt.getValue();
- } else if (opt.getOpt().equals("s")) {
- serviceName = opt.getValue();
- }
- }
- if (policyFile == null) {
- throw new IllegalArgumentException("Missing required option: f");
- }
- if (!validate && !importPolicy) {
- throw new IllegalArgumentException("No action specified; at least one of action or import must be specified");
- }
- }
-
-
- /**
- * Processes the necessary command based on the arguments parsed earlier.
- * @throws Exception
- */
- public void run() throws Exception {
- String component = HBASE_INDEXER;
- Configuration conf = getSentryConf();
-
- String service = conf.get(SERVICE_NAME, getServiceName());
-
- if (service == null) {
- throw new IllegalArgumentException("Service was not defined. Please, use -s command option, or sentry.provider.backend.generic.service-name configuration entry.");
- }
-
- LOGGER.info(String.format("Context: component=%s, service=%s", component, service));
- // instantiate a solr client for sentry service. This sets the ugi, so must
- // be done before getting the ugi below.
- try(SentryGenericServiceClient client =
- SentryGenericServiceClientFactory.create(conf)) {
- UserGroupInformation ugi = UserGroupInformation.getLoginUser();
- String requestorName = ugi.getShortUserName();
-
- convertINIToSentryServiceCmds(component, service, requestorName, conf, client,
- getPolicyFile(), getValidate(), getImportPolicy(), getCheckCompat());
- }
- }
-
- private Configuration getSentryConf() {
- Configuration conf = new Configuration();
- conf.addResource(new Path(getConfPath()), true);
- return conf;
- }
-
- private void convertINIToSentryServiceCmds(String component,
- String service, String requestorName,
- Configuration conf, SentryGenericServiceClient client,
- String policyFile, boolean validate, boolean importPolicy,
- boolean checkCompat) throws Exception {
-
- //instantiate a file providerBackend for parsing
- LOGGER.info("Reading policy file at: " + policyFile);
- SimpleFileProviderBackend policyFileBackend =
- new SimpleFileProviderBackend(conf, policyFile);
- ProviderBackendContext context = new ProviderBackendContext();
- context.setValidators(IndexerPrivilegeModel.getInstance().getPrivilegeValidators());
- policyFileBackend.initialize(context);
- if (validate) {
- validatePolicy(policyFileBackend);
- }
-
- if (checkCompat) {
- checkCompat(policyFileBackend);
- }
-
- //import the relations about group,role and privilege into the DB store
- Set<String> roles = Sets.newHashSet();
- Table<String, String, Set<String>> groupRolePrivilegeTable =
- policyFileBackend.getGroupRolePrivilegeTable();
- GenericPrivilegeConverter converter = new GenericPrivilegeConverter(component, service, false);
-
- for (String groupName : groupRolePrivilegeTable.rowKeySet()) {
- for (String roleName : groupRolePrivilegeTable.columnKeySet()) {
- if (!roles.contains(roleName)) {
- LOGGER.info(dryRunMessage(importPolicy) + "Creating role: " + roleName.toLowerCase(Locale.US));
- if (importPolicy) {
- client.createRoleIfNotExist(requestorName, roleName, component);
- }
- roles.add(roleName);
- }
-
- Set<String> privileges = groupRolePrivilegeTable.get(groupName, roleName);
- if (privileges == null) {
- continue;
- }
- LOGGER.info(dryRunMessage(importPolicy) + "Adding role: " + roleName.toLowerCase(Locale.US) + " to group: " + groupName);
- if (importPolicy) {
- client.grantRoleToGroups(requestorName, roleName, component, Sets.newHashSet(groupName));
- }
-
- for (String permission : privileges) {
- String action = null;
-
- for (String authorizable : AUTHORIZABLE_SPLITTER.
- trimResults().split(permission)) {
- KeyValue kv = new KeyValue(authorizable);
- String key = kv.getKey();
- String value = kv.getValue();
- if ("action".equalsIgnoreCase(key)) {
- action = value;
- }
- }
-
- // Service doesn't support not specifying action
- if (action == null) {
- permission += "->action=" + Action.ALL;
- }
- LOGGER.info(dryRunMessage(importPolicy) + "Adding permission: " + permission + " to role: " + roleName.toLowerCase(Locale.US));
- if (importPolicy) {
- client.grantPrivilege(requestorName, roleName, component, converter.fromString(permission));
- }
- }
- }
- }
- }
-
- private void validatePolicy(ProviderBackend backend) throws Exception {
- try {
- backend.validatePolicy(true);
- } catch (SentryConfigurationException e) {
- printConfigErrorsWarnings(e);
- throw e;
- }
- }
-
- private void printConfigErrorsWarnings(SentryConfigurationException configException) {
- System.out.println(" *** Found configuration problems *** ");
- for (String errMsg : configException.getConfigErrors()) {
- System.out.println("ERROR: " + errMsg);
- }
- for (String warnMsg : configException.getConfigWarnings()) {
- System.out.println("Warning: " + warnMsg);
- }
- }
-
- private void checkCompat(SimpleFileProviderBackend backend) throws Exception {
- Map<String, Set<String>> rolesCaseMapping = new HashMap<String, Set<String>>();
- Table<String, String, Set<String>> groupRolePrivilegeTable =
- backend.getGroupRolePrivilegeTable();
-
- for (String roleName : groupRolePrivilegeTable.columnKeySet()) {
- String roleNameLower = roleName.toLowerCase(Locale.US);
- if (!roleName.equals(roleNameLower)) {
- if (!rolesCaseMapping.containsKey(roleNameLower)) {
- rolesCaseMapping.put(roleNameLower, Sets.newHashSet(roleName));
- } else {
- rolesCaseMapping.get(roleNameLower).add(roleName);
- }
- }
- }
-
- List<String> errors = new LinkedList<String>();
- StringBuilder warningString = new StringBuilder();
- if (!rolesCaseMapping.isEmpty()) {
- warningString.append("The following roles names will be lower cased when added to the Sentry Service.\n");
- warningString.append("This will cause document-level security to fail to match the role tokens.\n");
- warningString.append("Role names: ");
- }
- boolean firstWarning = true;
-
- for (Map.Entry<String, Set<String>> entry : rolesCaseMapping.entrySet()) {
- Set<String> caseMapping = entry.getValue();
- if (caseMapping.size() > 1) {
- StringBuilder errorString = new StringBuilder();
- errorString.append("The following (cased) roles map to the same role in the sentry service: ");
- boolean first = true;
- for (String casedRole : caseMapping) {
- errorString.append(first ? "" : ", ");
- errorString.append(casedRole);
- first = false;
- }
- errorString.append(". Role in service: ").append(entry.getKey());
- errors.add(errorString.toString());
- }
-
- for (String casedRole : caseMapping) {
- warningString.append(firstWarning? "" : ", ");
- warningString.append(casedRole);
- firstWarning = false;
- }
- }
-
- for (String error : errors) {
- System.out.println("ERROR: " + error);
- }
- System.out.println("\n");
-
- System.out.println("Warning: " + warningString.toString());
- if (errors.size() > 0) {
- SentryConfigurationException ex =
- new SentryConfigurationException("Compatibility check failure");
- ex.setConfigErrors(errors);
- ex.setConfigWarnings(Lists.<String>asList(warningString.toString(), new String[0]));
- throw ex;
- }
- }
-
- private String dryRunMessage(boolean importPolicy) {
- if (importPolicy) {
- return "";
- } else {
- return "[Dry Run] ";
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/SentryConfigToolSolr.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/SentryConfigToolSolr.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/SentryConfigToolSolr.java
deleted file mode 100644
index 1a4692e..0000000
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/SentryConfigToolSolr.java
+++ /dev/null
@@ -1,264 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.sentry.provider.db.generic.tools;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-import com.google.common.collect.Table;
-
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.security.UserGroupInformation;
-import org.apache.sentry.core.common.Action;
-import org.apache.sentry.core.common.exception.SentryConfigurationException;
-import org.apache.sentry.core.common.utils.KeyValue;
-import org.apache.sentry.core.common.utils.SentryConstants;
-import org.apache.sentry.core.model.solr.SolrPrivilegeModel;
-import org.apache.sentry.provider.common.ProviderBackend;
-import org.apache.sentry.provider.common.ProviderBackendContext;
-import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClient;
-import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClientFactory;
-import org.apache.sentry.provider.file.SimpleFileProviderBackend;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * SentryConfigToolSolr is an administrative tool used to parse a Solr policy file
- * and add the role, group mappings, and privileges therein to the Sentry service.
- */
-public class SentryConfigToolSolr extends SentryConfigToolCommon {
-
- private static final Logger LOGGER = LoggerFactory.getLogger(SentryConfigToolSolr.class);
- public static final String SOLR_SERVICE_NAME = "sentry.service.client.solr.service.name";
-
- @Override
- public void run() throws Exception {
- String component = "SOLR";
- Configuration conf = getSentryConf();
-
- String service = conf.get(SOLR_SERVICE_NAME, "service1");
- // instantiate a solr client for sentry service. This sets the ugi, so must
- // be done before getting the ugi below.
- try(SentryGenericServiceClient client =
- SentryGenericServiceClientFactory.create(conf)) {
- UserGroupInformation ugi = UserGroupInformation.getLoginUser();
- String requestorName = ugi.getShortUserName();
-
- convertINIToSentryServiceCmds(component, service, requestorName, conf, client,
- getPolicyFile(), getValidate(), getImportPolicy(), getCheckCompat());
- }
- }
-
- private Configuration getSentryConf() {
- Configuration conf = new Configuration();
- conf.addResource(new Path(getConfPath()), true);
- return conf;
- }
-
- /**
- * Convert policy file to solrctl commands -- based on SENTRY-480
- */
- private void convertINIToSentryServiceCmds(String component,
- String service, String requestorName,
- Configuration conf, SentryGenericServiceClient client,
- String policyFile, boolean validate, boolean importPolicy,
- boolean checkCompat) throws Exception {
-
- //instantiate a file providerBackend for parsing
- LOGGER.info("Reading policy file at: " + policyFile);
- SimpleFileProviderBackend policyFileBackend =
- new SimpleFileProviderBackend(conf, policyFile);
- ProviderBackendContext context = new ProviderBackendContext();
- context.setValidators(SolrPrivilegeModel.getInstance().getPrivilegeValidators());
- policyFileBackend.initialize(context);
- if (validate) {
- validatePolicy(policyFileBackend);
- }
-
- if (checkCompat) {
- checkCompat(policyFileBackend);
- }
-
- //import the relations about group,role and privilege into the DB store
- Set<String> roles = Sets.newHashSet();
- Table<String, String, Set<String>> groupRolePrivilegeTable =
- policyFileBackend.getGroupRolePrivilegeTable();
- GenericPrivilegeConverter converter = new GenericPrivilegeConverter(component, service, false);
-
- for (String groupName : groupRolePrivilegeTable.rowKeySet()) {
- for (String roleName : groupRolePrivilegeTable.columnKeySet()) {
- if (!roles.contains(roleName)) {
- LOGGER.info(dryRunMessage(importPolicy) + "Creating role: " + roleName.toLowerCase(Locale.US));
- if (importPolicy) {
- client.createRoleIfNotExist(requestorName, roleName, component);
- }
- roles.add(roleName);
- }
-
- Set<String> privileges = groupRolePrivilegeTable.get(groupName, roleName);
- if (privileges == null) {
- continue;
- }
- LOGGER.info(dryRunMessage(importPolicy) + "Adding role: " + roleName.toLowerCase(Locale.US) + " to group: " + groupName);
- if (importPolicy) {
- client.grantRoleToGroups(requestorName, roleName, component, Sets.newHashSet(groupName));
- }
-
- for (String permission : privileges) {
- String action = null;
-
- for (String authorizable : SentryConstants.AUTHORIZABLE_SPLITTER.
- trimResults().split(permission)) {
- KeyValue kv = new KeyValue(authorizable);
- String key = kv.getKey();
- String value = kv.getValue();
- if ("action".equalsIgnoreCase(key)) {
- action = value;
- }
- }
-
- // Service doesn't support not specifying action
- if (action == null) {
- permission += "->action=" + Action.ALL;
- }
- LOGGER.info(dryRunMessage(importPolicy) + "Adding permission: " + permission + " to role: " + roleName.toLowerCase(Locale.US));
- if (importPolicy) {
- client.grantPrivilege(requestorName, roleName, component, converter.fromString(permission));
- }
- }
- }
- }
- }
-
- private void validatePolicy(ProviderBackend backend) throws Exception {
- try {
- backend.validatePolicy(true);
- } catch (SentryConfigurationException e) {
- printConfigErrorsWarnings(e);
- throw e;
- }
- }
-
- private void printConfigErrorsWarnings(SentryConfigurationException configException) {
- System.out.println(" *** Found configuration problems *** ");
- for (String errMsg : configException.getConfigErrors()) {
- System.out.println("ERROR: " + errMsg);
- }
- for (String warnMsg : configException.getConfigWarnings()) {
- System.out.println("Warning: " + warnMsg);
- }
- }
-
- private void checkCompat(SimpleFileProviderBackend backend) throws Exception {
- Map<String, Set<String>> rolesCaseMapping = new HashMap<String, Set<String>>();
- Table<String, String, Set<String>> groupRolePrivilegeTable =
- backend.getGroupRolePrivilegeTable();
-
- for (String roleName : groupRolePrivilegeTable.columnKeySet()) {
- String roleNameLower = roleName.toLowerCase(Locale.US);
- if (!roleName.equals(roleNameLower)) {
- if (!rolesCaseMapping.containsKey(roleNameLower)) {
- rolesCaseMapping.put(roleNameLower, Sets.newHashSet(roleName));
- } else {
- rolesCaseMapping.get(roleNameLower).add(roleName);
- }
- }
- }
-
- List<String> errors = new LinkedList<String>();
- StringBuilder warningString = new StringBuilder();
- if (!rolesCaseMapping.isEmpty()) {
- warningString.append("The following roles names will be lower cased when added to the Sentry Service.\n");
- warningString.append("This will cause document-level security to fail to match the role tokens.\n");
- warningString.append("Role names: ");
- }
- boolean firstWarning = true;
-
- for (Map.Entry<String, Set<String>> entry : rolesCaseMapping.entrySet()) {
- Set<String> caseMapping = entry.getValue();
- if (caseMapping.size() > 1) {
- StringBuilder errorString = new StringBuilder();
- errorString.append("The following (cased) roles map to the same role in the sentry service: ");
- boolean first = true;
- for (String casedRole : caseMapping) {
- errorString.append(first ? "" : ", ");
- errorString.append(casedRole);
- first = false;
- }
- errorString.append(". Role in service: ").append(entry.getKey());
- errors.add(errorString.toString());
- }
-
- for (String casedRole : caseMapping) {
- warningString.append(firstWarning? "" : ", ");
- warningString.append(casedRole);
- firstWarning = false;
- }
- }
-
- for (String error : errors) {
- System.out.println("ERROR: " + error);
- }
- System.out.println("\n");
-
- System.out.println("Warning: " + warningString.toString());
- if (errors.size() > 0) {
- SentryConfigurationException ex =
- new SentryConfigurationException("Compatibility check failure");
- ex.setConfigErrors(errors);
- ex.setConfigWarnings(Lists.<String>asList(warningString.toString(), new String[0]));
- throw ex;
- }
- }
-
- private String dryRunMessage(boolean importPolicy) {
- if (importPolicy) {
- return "";
- } else {
- return "[Dry Run] ";
- }
- }
-
- public static void main(String[] args) throws Exception {
- SentryConfigToolSolr solrTool = new SentryConfigToolSolr();
- try {
- solrTool.executeConfigTool(args);
- } catch (Exception e) {
- LOGGER.error(e.getMessage(), e);
- Throwable current = e;
- // find the first printable message;
- while (current != null && current.getMessage() == null) {
- current = current.getCause();
- }
- String error = "";
- if (current != null && current.getMessage() != null) {
- error = "Message: " + current.getMessage();
- }
- System.out.println("The operation failed. " + error);
- System.exit(1);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/SentryShellGeneric.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/SentryShellGeneric.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/SentryShellGeneric.java
deleted file mode 100644
index 4487685..0000000
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/SentryShellGeneric.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.sentry.provider.db.generic.tools;
-
-import com.google.common.collect.Sets;
-import org.apache.commons.lang.StringUtils;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.security.UserGroupInformation;
-import org.apache.sentry.provider.common.AuthorizationComponent;
-import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClient;
-import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClientFactory;
-import org.apache.sentry.provider.db.generic.tools.command.GenericShellCommand;
-import org.apache.sentry.provider.db.generic.tools.command.TSentryPrivilegeConverter;
-import org.apache.sentry.provider.db.tools.SentryShellCommon;
-import org.apache.sentry.provider.db.tools.ShellCommand;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.List;
-import java.util.Set;
-
-/**
- * SentryShellGeneric is an admin tool, and responsible for the management of repository.
- * The following commands are supported:
- * create role, drop role, add group to role, grant privilege to role,
- * revoke privilege from role, list roles, list privilege for role.
- */
-public class SentryShellGeneric extends SentryShellCommon {
-
- private static final Logger LOGGER = LoggerFactory.getLogger(SentryShellGeneric.class);
- private static final String KAFKA_SERVICE_NAME = "sentry.service.client.kafka.service.name";
- private static final String SOLR_SERVICE_NAME = "sentry.service.client.solr.service.name";
- private static final String SQOOP_SERVICE_NAME = "sentry.service.client.sqoop.service.name";
-
- @Override
- public void run() throws Exception {
- String component = getComponent();
- Configuration conf = getSentryConf();
-
- String service = getService(conf);
- try (SentryGenericServiceClient client =
- SentryGenericServiceClientFactory.create(conf)) {
- UserGroupInformation ugi = UserGroupInformation.getLoginUser();
- String requestorName = ugi.getShortUserName();
- TSentryPrivilegeConverter converter = getPrivilegeConverter(component, service);
- ShellCommand command = new GenericShellCommand(client, component, service, converter);
-
- // check the requestor name
- if (StringUtils.isEmpty(requestorName)) {
- // The exception message will be recorded in log file.
- throw new Exception("The requestor name is empty.");
- }
-
- if (isCreateRole) {
- command.createRole(requestorName, roleName);
- } else if (isDropRole) {
- command.dropRole(requestorName, roleName);
- } else if (isAddRoleGroup) {
- Set<String> groups = Sets.newHashSet(groupName.split(SentryShellCommon.GROUP_SPLIT_CHAR));
- command.grantRoleToGroups(requestorName, roleName, groups);
- } else if (isDeleteRoleGroup) {
- Set<String> groups = Sets.newHashSet(groupName.split(SentryShellCommon.GROUP_SPLIT_CHAR));
- command.revokeRoleFromGroups(requestorName, roleName, groups);
- } else if (isGrantPrivilegeRole) {
- command.grantPrivilegeToRole(requestorName, roleName, privilegeStr);
- } else if (isRevokePrivilegeRole) {
- command.revokePrivilegeFromRole(requestorName, roleName, privilegeStr);
- } else if (isListRole) {
- List<String> roles = command.listRoles(requestorName, groupName);
- for (String role : roles) {
- System.out.println(role);
- }
- } else if (isListPrivilege) {
- List<String> privileges = command.listPrivileges(requestorName, roleName);
- for (String privilege : privileges) {
- System.out.println(privilege);
- }
- } else if (isListGroup) {
- List<String> groups = command.listGroupRoles(requestorName);
- for (String group : groups) {
- System.out.println(group);
- }
- }
- }
- }
-
- protected GenericPrivilegeConverter getPrivilegeConverter(String component, String service) {
- return new GenericPrivilegeConverter(component, service);
- }
-
- protected String getComponent() throws Exception {
- if (type == TYPE.kafka) {
- return AuthorizationComponent.KAFKA;
- } else if (type == TYPE.solr) {
- return "SOLR";
- } else if (type == TYPE.sqoop) {
- return AuthorizationComponent.SQOOP;
- }
-
- throw new Exception("Invalid type specified for SentryShellGeneric: " + type);
- }
-
- protected String getService(Configuration conf) throws Exception {
- if (type == TYPE.kafka) {
- return conf.get(KAFKA_SERVICE_NAME, AuthorizationComponent.KAFKA);
- } else if (type == TYPE.solr) {
- return conf.get(SOLR_SERVICE_NAME, "service1");
- } else if (type == TYPE.sqoop) {
- return conf.get(SQOOP_SERVICE_NAME, "sqoopServer1");
- }
-
- throw new Exception("Invalid type specified for SentryShellGeneric: " + type);
- }
-
- private Configuration getSentryConf() {
- Configuration conf = new Configuration();
- conf.addResource(new Path(confPath), true);
- return conf;
- }
-
- public static void main(String[] args) throws Exception {
- SentryShellGeneric sentryShell = new SentryShellGeneric();
- try {
- sentryShell.executeShell(args);
- } catch (Exception e) {
- LOGGER.error(e.getMessage(), e);
- Throwable current = e;
- // find the first printable message;
- while (current != null && current.getMessage() == null) {
- current = current.getCause();
- }
- String error = "";
- if (current != null && current.getMessage() != null) {
- error = "Message: " + current.getMessage();
- }
- System.out.println("The operation failed. " + error);
- System.exit(1);
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/SentryShellIndexer.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/SentryShellIndexer.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/SentryShellIndexer.java
deleted file mode 100644
index 5bbe772..0000000
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/SentryShellIndexer.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/**
- * 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
- * <p>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p>
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.sentry.provider.db.generic.tools;
-
-import org.apache.commons.cli.CommandLine;
-import org.apache.commons.cli.Option;
-import org.apache.commons.cli.OptionGroup;
-import org.apache.commons.cli.Options;
-import org.apache.commons.cli.ParseException;
-import org.apache.hadoop.conf.Configuration;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static org.apache.sentry.provider.common.AuthorizationComponent.HBASE_INDEXER;
-import static org.apache.sentry.service.thrift.ServiceConstants.ClientConfig.SERVICE_NAME;
-
-/**
- * SentryShellIndexer is an admin tool, and responsible for the management of repository.
- * The following commands are supported:
- * create role, drop role, add group to role, grant privilege to role,
- * revoke privilege from role, list roles, list privilege for role.
- */
-public class SentryShellIndexer extends SentryShellGeneric {
-
- protected boolean isMigration = false;
-
- private static final Logger LOGGER = LoggerFactory.getLogger(SentryShellIndexer.class);
-
- private final SentryConfigToolIndexer configTool = new SentryConfigToolIndexer();
-
- @Override
- protected void setupOptions(Options simpleShellOptions) {
- super.setupOptions(simpleShellOptions);
- configTool.setupOptions(simpleShellOptions);
- }
-
- @Override
- protected void parseOptions(CommandLine cmd) throws ParseException {
- super.parseOptions(cmd);
- configTool.parseOptions(cmd);
- for (Option opt : cmd.getOptions()) {
- if (opt.getOpt().equals("mgr")) {
- isMigration = true;
- }
- }
- }
-
- @Override
- protected OptionGroup getMainOptions() {
- OptionGroup mainOptions = super.getMainOptions();
- Option mgrOpt = new Option("mgr", "migrate", false, "Migrate ini file to Sentry service");
- mgrOpt.setRequired(false);
- mainOptions.addOption(mgrOpt);
- return mainOptions;
- }
-
- /**
- * Processes the necessary command based on the arguments parsed earlier.
- * @throws Exception
- */
- @Override
- public void run() throws Exception {
-
- if (isMigration) {
- configTool.run();
- return;
- }
-
- super.run();
- }
-
- @Override
- protected String getComponent() throws Exception {
- return HBASE_INDEXER;
- }
-
- @Override
- protected String getService(Configuration conf) throws Exception {
- String service = conf.get(SERVICE_NAME, serviceName);
- if (service == null) {
- throw new IllegalArgumentException("Service was not defined. Please, use -s command option, or sentry.provider.backend.generic.service-name configuration entry.");
- }
- return service;
- }
-
- /**
- * Entry-point for Hbase indexer cli tool.
- * @param args
- * @throws Exception
- */
- public static void main(String[] args) throws Exception {
- SentryShellIndexer sentryShell = new SentryShellIndexer();
- try {
- sentryShell.executeShell(args);
- } catch (Exception e) {
- LOGGER.error(e.getMessage(), e);
- Throwable current = e;
- // find the first printable message;
- while (current != null && current.getMessage() == null) {
- current = current.getCause();
- }
- System.out.println("The operation failed." +
- (current.getMessage() == null ? "" : " Message: " + current.getMessage()));
- System.exit(1);
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/TSentryPrivilegeConverter.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/TSentryPrivilegeConverter.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/TSentryPrivilegeConverter.java
new file mode 100644
index 0000000..5e48483
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/TSentryPrivilegeConverter.java
@@ -0,0 +1,35 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sentry.provider.db.generic.tools;
+
+import org.apache.sentry.core.common.exception.SentryUserException;
+import org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege;
+
+public interface TSentryPrivilegeConverter {
+
+ /**
+ * Convert string to privilege
+ */
+ TSentryPrivilege fromString(String privilegeStr) throws SentryUserException;
+
+ /**
+ * Convert privilege to string
+ */
+ String toString(TSentryPrivilege tSentryPrivilege);
+}
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/command/GenericShellCommand.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/command/GenericShellCommand.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/command/GenericShellCommand.java
deleted file mode 100644
index a792b5c..0000000
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/command/GenericShellCommand.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.sentry.provider.db.generic.tools.command;
-
-import java.util.ArrayList;
-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 org.apache.commons.lang.StringUtils;
-import org.apache.sentry.core.common.exception.SentryUserException;
-import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClient;
-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.tools.ShellCommand;
-
-/**
- * The ShellCommand implementation for the Generic clients
- */
-public class GenericShellCommand implements ShellCommand {
-
- private final SentryGenericServiceClient client;
- private final String component;
- private final TSentryPrivilegeConverter converter;
- private final String serviceName;
-
- public GenericShellCommand(SentryGenericServiceClient client, String component, String serviceName,
- TSentryPrivilegeConverter converter) {
- this.client = client;
- this.component = component;
- this.serviceName = serviceName;
- this.converter = converter;
- }
-
- public void createRole(String requestorName, String roleName) throws SentryUserException {
- client.createRole(requestorName, roleName, component);
- }
-
- public void dropRole(String requestorName, String roleName) throws SentryUserException {
- client.dropRole(requestorName, roleName, component);
- }
-
- public void grantPrivilegeToRole(String requestorName, String roleName, String privilege) throws SentryUserException {
- TSentryPrivilege sentryPrivilege = converter.fromString(privilege);
- client.grantPrivilege(requestorName, roleName, component, sentryPrivilege);
- }
-
- public void grantRoleToGroups(String requestorName, String roleName, Set<String> groups) throws SentryUserException {
- client.grantRoleToGroups(requestorName, roleName, component, groups);
- }
-
- public void revokePrivilegeFromRole(String requestorName, String roleName, String privilege) throws SentryUserException {
- TSentryPrivilege sentryPrivilege = converter.fromString(privilege);
- client.revokePrivilege(requestorName, roleName, component, sentryPrivilege);
- }
-
- public void revokeRoleFromGroups(String requestorName, String roleName, Set<String> groups) throws SentryUserException {
- client.revokeRoleFromGroups(requestorName, roleName, component, groups);
- }
-
- public List<String> listRoles(String requestorName, String group) throws SentryUserException {
- Set<TSentryRole> roles;
- if (StringUtils.isEmpty(group)) {
- roles = client.listAllRoles(requestorName, component);
- } else {
- roles = client.listRolesByGroupName(requestorName, group, component);
- }
-
- List<String> result = new ArrayList<>();
- if (roles != null) {
- for (TSentryRole role : roles) {
- result.add(role.getRoleName());
- }
- }
-
- return result;
- }
-
- public List<String> listPrivileges(String requestorName, String roleName) throws SentryUserException {
- Set<TSentryPrivilege> privileges = client
- .listAllPrivilegesByRoleName(requestorName, roleName, component, serviceName);
-
- List<String> result = new ArrayList<>();
- if (privileges != null) {
- for (TSentryPrivilege privilege : privileges) {
- String privilegeStr = converter.toString(privilege);
- result.add(privilegeStr);
- }
- }
-
- return result;
- }
-
- public List<String> listGroupRoles(String requestorName) throws SentryUserException {
- Set<TSentryRole> roles = client.listAllRoles(requestorName, component);
- if (roles == null || roles.isEmpty()) {
- return Collections.emptyList();
- }
-
- // Set of all group names
- Set<String> groupNames = new HashSet<>();
-
- // Map group to set of roles
- Map<String, Set<String>> groupInfo = new HashMap<>();
-
- // Get all group names
- for (TSentryRole role: roles) {
- for (String group : role.getGroups()) {
- groupNames.add(group);
- Set<String> groupRoles = groupInfo.get(group);
- if (groupRoles != null) {
- // Add a new or existing role
- groupRoles.add(role.getRoleName());
- continue;
- }
- // Never seen this group before
- groupRoles = new HashSet<>();
- groupRoles.add(role.getRoleName());
- groupInfo.put(group, groupRoles);
- }
- }
-
- List<String> groups = new ArrayList<>(groupNames);
-
- // Produce printable result as
- // group1 = role1, role2, ...
- // group2 = ...
- List<String> result = new LinkedList<>();
- for (String groupName: groups) {
- result.add(groupName + " = " + StringUtils.join(groupInfo.get(groupName), ", "));
- }
-
- return result;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/command/TSentryPrivilegeConverter.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/command/TSentryPrivilegeConverter.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/command/TSentryPrivilegeConverter.java
deleted file mode 100644
index 0bfbc44..0000000
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/command/TSentryPrivilegeConverter.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.sentry.provider.db.generic.tools.command;
-
-import org.apache.sentry.core.common.exception.SentryUserException;
-import org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege;
-
-public interface TSentryPrivilegeConverter {
-
- /**
- * Convert string to privilege
- */
- TSentryPrivilege fromString(String privilegeStr) throws SentryUserException;
-
- /**
- * Convert privilege to string
- */
- String toString(TSentryPrivilege tSentryPrivilege);
-}
[7/9] sentry git commit: SENTRY-2207 Refactor out Sentry CLI from
sentry-provider-db into own module. Steve Moist,
reviewed by Colm O hEigeartaigh.
Posted by co...@apache.org.
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryConfigToolIndexer.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryConfigToolIndexer.java b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryConfigToolIndexer.java
deleted file mode 100644
index 4dddf78..0000000
--- a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryConfigToolIndexer.java
+++ /dev/null
@@ -1,263 +0,0 @@
- /**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.sentry.provider.db.generic.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.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 RESOURCES_DIR = "target" + File.separator + "test-classes" + File.separator;
- private static String VALID_POLICY_INI = RESOURCES_DIR + "indexer_config_import_tool.ini";
- private static String INVALID_POLICY_INI = RESOURCES_DIR + "indexer_invalid.ini";
- private static String CASE_POLICY_INI = RESOURCES_DIR + "indexer_case.ini";
- 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-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryConfigToolSolr.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryConfigToolSolr.java b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryConfigToolSolr.java
deleted file mode 100644
index 9e6ff42..0000000
--- a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryConfigToolSolr.java
+++ /dev/null
@@ -1,261 +0,0 @@
- /**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.sentry.provider.db.generic.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.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-public class TestSentryConfigToolSolr extends SentryGenericServiceIntegrationBase {
- private static String RESOURCES_DIR = "target" + File.separator + "test-classes" + File.separator;
- private static String VALID_POLICY_INI = RESOURCES_DIR + "solr_config_import_tool.ini";
- private static String INVALID_POLICY_INI = RESOURCES_DIR + "solr_invalid.ini";
- private static String CASE_POLICY_INI = RESOURCES_DIR + "solr_case.ini";
- 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-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryShellIndexer.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryShellIndexer.java b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryShellIndexer.java
deleted file mode 100644
index f66eb85..0000000
--- a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryShellIndexer.java
+++ /dev/null
@@ -1,526 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.sentry.provider.db.generic.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.SentryUserException;
-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.tools.SentryShellCommon;
-import org.apache.sentry.service.thrift.ServiceConstants;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-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 static junit.framework.Assert.assertEquals;
-import static org.apache.sentry.provider.common.AuthorizationComponent.HBASE_INDEXER;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-public class TestSentryShellIndexer extends SentryGenericServiceIntegrationBase {
- 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 = "";
- 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();
- 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() };
- SentryShellIndexer.main(args);
- // test: create role with --create_role
- args = new String[] { "--create_role", "-r", TEST_ROLE_NAME_2, "-conf",
- confPath.getAbsolutePath() };
- SentryShellIndexer.main(args);
-
- // validate the result, list roles with -lr
- args = new String[] { "-lr", "-conf", confPath.getAbsolutePath() };
- SentryShellIndexer sentryShell = new SentryShellIndexer();
- 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 SentryShellIndexer();
- 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() };
- SentryShellIndexer.main(args);
- // test: drop role with --drop_role
- args = new String[] { "--drop_role", "-r", TEST_ROLE_NAME_2, "-conf",
- confPath.getAbsolutePath() };
- SentryShellIndexer.main(args);
-
- // validate the result
- Set<TSentryRole> roles = client.listAllRoles(requestorName, HBASE_INDEXER);
- assertEquals("Incorrect number of roles", 0, roles.size());
- }
- });
- }
-
- @Test
- public void testAddDeleteRoleForGroup() throws Exception {
- runTestAsSubject(new TestOperation() {
- @Override
- public void runTestAsSubject() throws Exception {
- // Group names are case sensitive - mixed case names should work
- String TEST_GROUP_1 = "testGroup1";
- String TEST_GROUP_2 = "testGroup2";
- String TEST_GROUP_3 = "testGroup3";
-
- // create the role for test
- client.createRole(requestorName, TEST_ROLE_NAME_1, HBASE_INDEXER);
- client.createRole(requestorName, TEST_ROLE_NAME_2, HBASE_INDEXER);
- // test: add role to group with -arg
- String[] args = { "-arg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_1, "-conf",
- confPath.getAbsolutePath() };
- SentryShellIndexer.main(args);
- // test: add role to multiple groups
- args = new String[] { "-arg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_2 + "," + TEST_GROUP_3,
- "-conf",
- confPath.getAbsolutePath() };
- SentryShellIndexer.main(args);
- // test: add role to group with --add_role_group
- args = new String[] { "--add_role_group", "-r", TEST_ROLE_NAME_2, "-g", TEST_GROUP_1,
- "-conf",
- confPath.getAbsolutePath() };
- SentryShellIndexer.main(args);
-
- // validate the result list roles with -lr and -g
- args = new String[] { "-lr", "-g", TEST_GROUP_1, "-conf", confPath.getAbsolutePath() };
- SentryShellIndexer sentryShell = new SentryShellIndexer();
- 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", TEST_GROUP_2, "-conf",
- confPath.getAbsolutePath() };
- sentryShell = new SentryShellIndexer();
- roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
- validateRoleNames(roleNames, TEST_ROLE_NAME_1);
-
- args = new String[] { "--list_role", "-g", TEST_GROUP_3, "-conf",
- confPath.getAbsolutePath() };
- sentryShell = new SentryShellIndexer();
- roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
- validateRoleNames(roleNames, TEST_ROLE_NAME_1);
-
- // test: delete role from group with -drg
- args = new String[] { "-drg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_1, "-conf",
- confPath.getAbsolutePath() };
- SentryShellIndexer.main(args);
- // test: delete role to multiple groups
- args = new String[] { "-drg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_2 + "," + TEST_GROUP_3,
- "-conf",
- confPath.getAbsolutePath() };
- SentryShellIndexer.main(args);
- // test: delete role from group with --delete_role_group
- args = new String[] { "--delete_role_group", "-r", TEST_ROLE_NAME_2, "-g", TEST_GROUP_1,
- "-conf", confPath.getAbsolutePath() };
- SentryShellIndexer.main(args);
-
- // validate the result
- Set<TSentryRole> roles = client.listRolesByGroupName(requestorName, TEST_GROUP_1, HBASE_INDEXER);
- assertEquals("Incorrect number of roles", 0, roles.size());
- roles = client.listRolesByGroupName(requestorName, TEST_GROUP_2, HBASE_INDEXER);
- assertEquals("Incorrect number of roles", 0, roles.size());
- roles = client.listRolesByGroupName(requestorName, TEST_GROUP_3, HBASE_INDEXER);
- assertEquals("Incorrect number of roles", 0, roles.size());
- // clear the test data
- client.dropRole(requestorName, TEST_ROLE_NAME_1, HBASE_INDEXER);
- client.dropRole(requestorName, TEST_ROLE_NAME_2, HBASE_INDEXER);
- }
- });
- }
-
- @Test
- public void testCaseSensitiveGroupName() throws Exception {
- runTestAsSubject(new TestOperation() {
- @Override
- public void runTestAsSubject() throws Exception {
-
- // create the role for test
- client.createRole(requestorName, TEST_ROLE_NAME_1, HBASE_INDEXER);
- // add role to a group (lower case)
- String[] args = { "-arg", "-r", TEST_ROLE_NAME_1, "-g", "group1", "-conf",
- confPath.getAbsolutePath() };
- SentryShellIndexer.main(args);
-
- // validate the roles when group name is same case as above
- args = new String[] { "-lr", "-g", "group1", "-conf", confPath.getAbsolutePath() };
- SentryShellIndexer sentryShell = new SentryShellIndexer();
- Set<String> roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
- validateRoleNames(roleNames, TEST_ROLE_NAME_1);
-
- // roles should be empty when group name is different case than above
- args = new String[] { "-lr", "-g", "GROUP1", "-conf", confPath.getAbsolutePath() };
- roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
- validateRoleNames(roleNames);
- }
- });
- }
-
- public static String grant(boolean shortOption) {
- return shortOption ? "-gpr" : "--grant_privilege_role";
- }
-
- public static String revoke(boolean shortOption) {
- return shortOption ? "-rpr" : "--revoke_privilege_role";
- }
-
- public static String list(boolean shortOption) {
- return shortOption ? "-lp" : "--list_privilege";
- }
-
- private void assertGrantRevokePrivilege(final boolean shortOption) throws Exception {
- runTestAsSubject(new TestOperation() {
- @Override
- public void runTestAsSubject() throws Exception {
- // create the role for test
- client.createRole(requestorName, TEST_ROLE_NAME_1, HBASE_INDEXER);
- client.createRole(requestorName, TEST_ROLE_NAME_2, HBASE_INDEXER);
-
- String [] privs = {
- "Indexer=*->action=*",
- "Indexer=indexer1->action=read",
- "Indexer=indexer2->action=write"
- };
- for (int i = 0; i < privs.length; ++i) {
- // test: grant privilege to role
- String [] args = new String [] { grant(shortOption), "-r", TEST_ROLE_NAME_1, "-p",
- privs[ i ],
- "-conf", confPath.getAbsolutePath() };
- SentryShellIndexer.main(args);
- }
-
- // test the list privilege
- String [] args = new String[] { list(shortOption), "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() };
- SentryShellIndexer sentryShell = new SentryShellIndexer();
- Set<String> privilegeStrs = getShellResultWithOSRedirect(sentryShell, args, true);
- assertEquals("Incorrect number of privileges", privs.length, privilegeStrs.size());
- for (int i = 0; i < privs.length; ++i) {
- assertTrue("Expected privilege: " + privs[ i ], privilegeStrs.contains(privs[ i ]));
- }
-
- for (int i = 0; i < privs.length; ++i) {
- args = new String[] { revoke(shortOption), "-r", TEST_ROLE_NAME_1, "-p",
- privs[ i ], "-conf",
- confPath.getAbsolutePath() };
- SentryShellIndexer.main(args);
- Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(requestorName,
- TEST_ROLE_NAME_1, HBASE_INDEXER, service);
- assertEquals("Incorrect number of privileges", privs.length - (i + 1), privileges.size());
- }
-
- // clear the test data
- client.dropRole(requestorName, TEST_ROLE_NAME_1, HBASE_INDEXER);
- client.dropRole(requestorName, TEST_ROLE_NAME_2, HBASE_INDEXER);
- }
- });
- }
-
-
- @Test
- public void testGrantRevokePrivilegeWithShortOption() throws Exception {
- assertGrantRevokePrivilege(true);
- }
-
- @Test
- public void testGrantRevokePrivilegeWithLongOption() throws Exception {
- assertGrantRevokePrivilege(false);
- }
-
- @Test
- public void testNegativeCaseWithInvalidArgument() throws Exception {
- runTestAsSubject(new TestOperation() {
- @Override
- public void runTestAsSubject() throws Exception {
- client.createRole(requestorName, TEST_ROLE_NAME_1, HBASE_INDEXER);
- // test: create duplicate role with -cr
- String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() };
- SentryShellIndexer sentryShell = new SentryShellIndexer();
- try {
- sentryShell.executeShell(args);
- fail("Exception should be thrown for creating duplicate role");
- } catch (SentryUserException e) {
- // expected exception
- }
-
- // test: drop non-exist role with -dr
- args = new String[] { "-dr", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath() };
- sentryShell = new SentryShellIndexer();
- 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 SentryShellIndexer();
- 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 SentryShellIndexer();
- 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 SentryShellIndexer();
- 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 SentryShellIndexer();
- try {
- sentryShell.executeShell(args);
- fail("Exception should be thrown for the error privilege format, invalid key value.");
- } catch (IllegalArgumentException e) {
- // expected exception
- }
-
- // clear the test data
- client.dropRole(requestorName, TEST_ROLE_NAME_1, HBASE_INDEXER);
- }
- });
- }
-
- @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, HBASE_INDEXER);
- // test: the conf is required argument
- String[] args = { "-cr", "-r", TEST_ROLE_NAME_1 };
- SentryShellIndexer sentryShell = new SentryShellIndexer();
- 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 SentryShellIndexer();
- 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 SentryShellIndexer();
- 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 SentryShellIndexer();
- 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 SentryShellIndexer();
- 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 SentryShellIndexer();
- 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 SentryShellIndexer();
- 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", "indexer=Indexer1", "-conf", confPath.getAbsolutePath() };
- sentryShell = new SentryShellIndexer();
- 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 SentryShellIndexer();
- validateMissingParameterMsg(sentryShell, args,
- SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_PRIVILEGE);
-
- // test: action is required in privilege
- args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-p", "indexer=Indexer1" };
- sentryShell = new SentryShellIndexer();
- try {
- getShellResultWithOSRedirect(sentryShell, args, false);
- fail("Expected IllegalArgumentException");
- } catch (IllegalArgumentException e) {
- assert("Privilege is invalid: action required but not specified.".equals(e.getMessage()));
- }
-
- // test: -r is required when revoke privilege from role
- args = new String[] { "-rpr", "-p", "indexer=Indexer1", "-conf", confPath.getAbsolutePath() };
- sentryShell = new SentryShellIndexer();
- 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 SentryShellIndexer();
- 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 SentryShellIndexer();
- 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, HBASE_INDEXER);
- }
- });
- }
-
- // redirect the System.out to ByteArrayOutputStream, then execute the command and parse the result.
- private Set<String> getShellResultWithOSRedirect(SentryShellIndexer sentryShell,
- String[] args, boolean expectedExecuteResult) throws Exception {
- PrintStream oldOut = System.out;
- ByteArrayOutputStream outContent = new ByteArrayOutputStream();
- System.setOut(new PrintStream(outContent));
- assertEquals(expectedExecuteResult, sentryShell.executeShell(args));
- String outContentStr = outContent.toString();
- Set<String> resultSet = outContentStr.length() > 0 ? Sets.<String>newHashSet(outContentStr.split("\n")) : Sets.<String>newHashSet();
- 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(SentryShellIndexer sentryShell, String[] args,
- String expectedErrorMsg) throws Exception {
- Set<String> errorMsgs = getShellResultWithOSRedirect(sentryShell, args, false);
- assertTrue("Expected error message: " + expectedErrorMsg, errorMsgs.contains(expectedErrorMsg));
- }
-
- private void validateMissingParameterMsgsContains(SentryShellIndexer 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);
- }
-}
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryShellKafka.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryShellKafka.java b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryShellKafka.java
deleted file mode 100644
index a9234fa..0000000
--- a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryShellKafka.java
+++ /dev/null
@@ -1,550 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.sentry.provider.db.generic.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.SentryUserException;
-import org.apache.sentry.core.model.kafka.validator.KafkaPrivilegeValidator;
-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.tools.SentryShellCommon;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.PrintStream;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-
-import static org.junit.Assert.*;
-
-public class TestSentryShellKafka extends SentryGenericServiceIntegrationBase {
- private File confDir;
- private File confPath;
- private static String TEST_ROLE_NAME_1 = "testRole1";
- private static String TEST_ROLE_NAME_2 = "testRole2";
- private static String KAFKA = "kafka";
- private String requestorName = "";
- private String service = "kafka";
-
- @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();//.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);
- }
-
- @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(), "-t", "kafka" };
- SentryShellGeneric.main(args);
- // test: create role with --create_role
- args = new String[] { "--create_role", "-r", TEST_ROLE_NAME_2, "-conf",
- confPath.getAbsolutePath(), "-t", "kafka" };
- SentryShellGeneric.main(args);
-
- // validate the result, list roles with -lr
- args = new String[] { "-lr", "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
- SentryShellGeneric sentryShell = new SentryShellGeneric();
- 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(), "-t", "kafka" };
- sentryShell = new SentryShellGeneric();
- 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(), "-t", "kafka" };
- SentryShellGeneric.main(args);
- // test: drop role with --drop_role
- args = new String[] { "--drop_role", "-r", TEST_ROLE_NAME_2, "-conf",
- confPath.getAbsolutePath(), "-t", "kafka" };
- SentryShellGeneric.main(args);
-
- // validate the result
- Set<TSentryRole> roles = client.listAllRoles(requestorName, KAFKA);
- assertEquals("Incorrect number of roles", 0, roles.size());
- }
- });
- }
-
- @Test
- public void testAddDeleteRoleForGroup() throws Exception {
- runTestAsSubject(new TestOperation() {
- @Override
- public void runTestAsSubject() throws Exception {
- // Group names are case sensitive - mixed case names should work
- String TEST_GROUP_1 = "testGroup1";
- String TEST_GROUP_2 = "testGroup2";
- String TEST_GROUP_3 = "testGroup3";
-
- // create the role for test
- client.createRole(requestorName, TEST_ROLE_NAME_1, KAFKA);
- client.createRole(requestorName, TEST_ROLE_NAME_2, KAFKA);
- // test: add role to group with -arg
- String[] args = { "-arg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_1, "-conf",
- confPath.getAbsolutePath(), "-t", "kafka" };
- SentryShellGeneric.main(args);
- // test: add role to multiple groups
- args = new String[] { "-arg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_2 + "," + TEST_GROUP_3,
- "-conf",
- confPath.getAbsolutePath(), "-t", "kafka" };
- SentryShellGeneric.main(args);
- // test: add role to group with --add_role_group
- args = new String[] { "--add_role_group", "-r", TEST_ROLE_NAME_2, "-g", TEST_GROUP_1,
- "-conf",
- confPath.getAbsolutePath(), "-t", "kafka" };
- SentryShellGeneric.main(args);
-
- // validate the result list roles with -lr and -g
- args = new String[] { "-lr", "-g", TEST_GROUP_1, "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
- SentryShellGeneric sentryShell = new SentryShellGeneric();
- 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", TEST_GROUP_2, "-conf",
- confPath.getAbsolutePath(), "-t", "kafka" };
- sentryShell = new SentryShellGeneric();
- roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
- validateRoleNames(roleNames, TEST_ROLE_NAME_1);
-
- args = new String[] { "--list_role", "-g", TEST_GROUP_3, "-conf",
- confPath.getAbsolutePath(), "-t", "kafka" };
- sentryShell = new SentryShellGeneric();
- 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(), "-t", "kafka" };
- sentryShell = new SentryShellGeneric();
- 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", TEST_GROUP_1, "-conf",
- confPath.getAbsolutePath(), "-t", "kafka" };
- SentryShellGeneric.main(args);
- // test: delete role to multiple groups
- args = new String[] { "-drg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_2 + "," + TEST_GROUP_3,
- "-conf",
- confPath.getAbsolutePath(), "-t", "kafka" };
- SentryShellGeneric.main(args);
- // test: delete role from group with --delete_role_group
- args = new String[] { "--delete_role_group", "-r", TEST_ROLE_NAME_2, "-g", TEST_GROUP_1,
- "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
- SentryShellGeneric.main(args);
-
- // validate the result
- Set<TSentryRole> roles = client.listRolesByGroupName(requestorName, TEST_GROUP_1, KAFKA);
- assertEquals("Incorrect number of roles", 0, roles.size());
- roles = client.listRolesByGroupName(requestorName, TEST_GROUP_2, KAFKA);
- assertEquals("Incorrect number of roles", 0, roles.size());
- roles = client.listRolesByGroupName(requestorName, TEST_GROUP_3, KAFKA);
- assertEquals("Incorrect number of roles", 0, roles.size());
- // clear the test data
- client.dropRole(requestorName, TEST_ROLE_NAME_1, KAFKA);
- client.dropRole(requestorName, TEST_ROLE_NAME_2, KAFKA);
- }
- });
- }
-
- @Test
- public void testCaseSensitiveGroupName() throws Exception {
- runTestAsSubject(new TestOperation() {
- @Override
- public void runTestAsSubject() throws Exception {
-
- // create the role for test
- client.createRole(requestorName, TEST_ROLE_NAME_1, KAFKA);
- // add role to a group (lower case)
- String[] args = {"-arg", "-r", TEST_ROLE_NAME_1, "-g", "group1", "-conf",
- confPath.getAbsolutePath(), "-t", "kafka"};
- SentryShellGeneric.main(args);
-
- // validate the roles when group name is same case as above
- args = new String[]{"-lr", "-g", "group1", "-conf", confPath.getAbsolutePath(), "-t", "kafka"};
- SentryShellGeneric sentryShell = new SentryShellGeneric();
- Set<String> roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
- validateRoleNames(roleNames, TEST_ROLE_NAME_1);
-
- // roles should be empty when group name is different case than above
- args = new String[]{"-lr", "-g", "GROUP1", "-conf", confPath.getAbsolutePath(), "-t", "kafka"};
- roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
- validateRoleNames(roleNames);
- }
- });
- }
-
- public static String grant(boolean shortOption) {
- return shortOption ? "-gpr" : "--grant_privilege_role";
- }
-
- public static String revoke(boolean shortOption) {
- return shortOption ? "-rpr" : "--revoke_privilege_role";
- }
-
- public static String list(boolean shortOption) {
- return shortOption ? "-lp" : "--list_privilege";
- }
-
- private void assertGrantRevokePrivilege(final boolean shortOption) throws Exception {
- runTestAsSubject(new TestOperation() {
- @Override
- public void runTestAsSubject() throws Exception {
- // create the role for test
- client.createRole(requestorName, TEST_ROLE_NAME_1, KAFKA);
- client.createRole(requestorName, TEST_ROLE_NAME_2, KAFKA);
-
- String [] privs = {
- "HOST=*->CLUSTER=kafka-cluster->action=read",
- "HOST=h1->TOPIC=t1->action=write",
- "HOST=*->CONSUMERGROUP=cg1->action=read",
- "CLUSTER=kafka-cluster->action=write",
- "CONSUMERGROUP=cg2->action=write"
- };
- for (int i = 0; i < privs.length; ++i) {
- // test: grant privilege to role
- String [] args = new String [] { grant(shortOption), "-r", TEST_ROLE_NAME_1, "-p",
- privs[ i ],
- "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
- SentryShellGeneric.main(args);
- }
-
- // test the list privilege
- String [] args = new String[] { list(shortOption), "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
- SentryShellGeneric sentryShell = new SentryShellGeneric();
- Set<String> privilegeStrs = getShellResultWithOSRedirect(sentryShell, args, true);
-
- assertEquals("Incorrect number of privileges", privs.length, privilegeStrs.size());
- for (int i = 0; i < privs.length; ++i) {
- assertTrue("Expected privilege: " + privs[i] + " in " + Arrays.toString(privilegeStrs.toArray()), privilegeStrs.contains(privs[i].startsWith("HOST=") ? privs[i] : "HOST=*->" + privs[i]));
- }
-
- for (int i = 0; i < privs.length; ++i) {
- args = new String[] { revoke(shortOption), "-r", TEST_ROLE_NAME_1, "-p",
- privs[ i ], "-conf",
- confPath.getAbsolutePath(), "-t", "kafka" };
- SentryShellGeneric.main(args);
- Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(requestorName,
- TEST_ROLE_NAME_1, KAFKA, service);
- assertEquals("Incorrect number of privileges. Received privileges: " + Arrays.toString(privileges.toArray()), privs.length - (i + 1), privileges.size());
- }
-
- // clear the test data
- client.dropRole(requestorName, TEST_ROLE_NAME_1, KAFKA);
- client.dropRole(requestorName, TEST_ROLE_NAME_2, KAFKA);
- }
- });
- }
-
-
- @Test
- public void testGrantRevokePrivilegeWithShortOption() throws Exception {
- assertGrantRevokePrivilege(true);
- }
-
- @Test
- public void testGrantRevokePrivilegeWithLongOption() throws Exception {
- assertGrantRevokePrivilege(false);
- }
-
-
- @Test
- public void testNegativeCaseWithInvalidArgument() throws Exception {
- runTestAsSubject(new TestOperation() {
- @Override
- public void runTestAsSubject() throws Exception {
- client.createRole(requestorName, TEST_ROLE_NAME_1, KAFKA);
- // test: create duplicate role with -cr
- String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
- SentryShellGeneric sentryShell = new SentryShellGeneric();
- try {
- sentryShell.executeShell(args);
- fail("Exception should be thrown for creating duplicate role");
- } catch (SentryUserException e) {
- // expected exception
- } catch (Exception e) {
- fail ("Unexpected exception received. " + e);
- }
-
- // test: drop non-exist role with -dr
- args = new String[] { "-dr", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
- sentryShell = new SentryShellGeneric();
- try {
- sentryShell.executeShell(args);
- fail("Exception should be thrown for dropping non-exist role");
- } catch (SentryUserException e) {
- // excepted exception
- } catch (Exception e) {
- fail ("Unexpected exception received. " + e);
- }
-
- // test: add non-exist role to group with -arg
- args = new String[] { "-arg", "-r", TEST_ROLE_NAME_2, "-g", "testGroup1", "-conf",
- confPath.getAbsolutePath(), "-t", "kafka" };
- sentryShell = new SentryShellGeneric();
- try {
- sentryShell.executeShell(args);
- fail("Exception should be thrown for granting non-exist role to group");
- } catch (SentryUserException e) {
- // excepted exception
- } catch (Exception e) {
- fail ("Unexpected exception received. " + e);
- }
-
- // test: drop group from non-exist role with -drg
- args = new String[] { "-drg", "-r", TEST_ROLE_NAME_2, "-g", "testGroup1", "-conf",
- confPath.getAbsolutePath(), "-t", "kafka" };
- sentryShell = new SentryShellGeneric();
- try {
- sentryShell.executeShell(args);
- fail("Exception should be thrown for drop group from non-exist role");
- } catch (SentryUserException e) {
- // excepted exception
- } catch (Exception e) {
- fail ("Unexpected exception received. " + e);
- }
-
- // test: grant privilege to role with the error privilege format
- args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p", "serverserver1->action=all",
- "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
- sentryShell = new SentryShellGeneric();
- try {
- sentryShell.executeShell(args);
- fail("Exception should be thrown for the error privilege format, invalid key value.");
- } catch (IllegalArgumentException e) {
- // excepted exception
- } catch (Exception e) {
- fail ("Unexpected exception received. " + e);
- }
-
- // test: grant privilege to role with the error privilege hierarchy
- args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p",
- "consumergroup=cg1->host=h1->action=create", "-conf",
- confPath.getAbsolutePath(), "-t", "kafka" };
- sentryShell = new SentryShellGeneric();
- try {
- sentryShell.executeShell(args);
- fail("Exception should be thrown for the error privilege format, invalid key value.");
- } catch (IllegalArgumentException e) {
- // expected exception
- } catch (Exception e) {
- fail ("Unexpected exception received. " + e);
- }
-
- // clear the test data
- client.dropRole(requestorName, TEST_ROLE_NAME_1, KAFKA);
- }
- });
- }
-
- @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, KAFKA);
- // test: the conf is required argument
- String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-t", "kafka" };
- SentryShellGeneric sentryShell = new SentryShellGeneric();
- validateMissingParameterMsg(sentryShell, args,
- SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + strOptionConf);
-
- // test: -r is required when create role
- args = new String[] { "-cr", "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
- sentryShell = new SentryShellGeneric();
- 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(), "-t", "kafka" };
- sentryShell = new SentryShellGeneric();
- 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(), "-t", "kafka" };
- sentryShell = new SentryShellGeneric();
- 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(), "-t", "kafka" };
- sentryShell = new SentryShellGeneric();
- 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(), "-t", "kafka" };
- sentryShell = new SentryShellGeneric();
- 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(), "-t", "kafka" };
- sentryShell = new SentryShellGeneric();
- 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(), "-t", "kafka" };
- sentryShell = new SentryShellGeneric();
- 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(), "-t", "kafka" };
- sentryShell = new SentryShellGeneric();
- validateMissingParameterMsg(sentryShell, args,
- SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_PRIVILEGE);
-
- // test: action is required in privilege
- args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-p", "host=*->topic=t1", "-t", "kafka" };
- sentryShell = new SentryShellGeneric();
- try {
- getShellResultWithOSRedirect(sentryShell, args, false);
- fail("Expected IllegalArgumentException");
- } catch (IllegalArgumentException e) {
- assert(("Kafka privilege must end with a valid action.\n" + KafkaPrivilegeValidator.KafkaPrivilegeHelpMsg).equals(e.getCause().getMessage()));
- } catch (Exception e) {
- fail ("Unexpected exception received. " + e);
- }
-
- // test: -r is required when revoke privilege from role
- args = new String[] { "-rpr", "-p", "host=h1", "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
- sentryShell = new SentryShellGeneric();
- 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(), "-t", "kafka" };
- sentryShell = new SentryShellGeneric();
- 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(), "-t", "kafka" };
- sentryShell = new SentryShellGeneric();
- 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, KAFKA);
- }
- });
- }
-
- // redirect the System.out to ByteArrayOutputStream, then execute the command and parse the result.
- private Set<String> getShellResultWithOSRedirect(SentryShellGeneric sentryShell,
- String[] args, boolean expectedExecuteResult) throws Exception {
- PrintStream oldOut = System.out;
- ByteArrayOutputStream outContent = new ByteArrayOutputStream();
- System.setOut(new PrintStream(outContent));
- assertEquals(expectedExecuteResult, 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(SentryShellGeneric sentryShell, String[] args,
- String expectedErrorMsg) throws Exception {
- Set<String> errorMsgs = getShellResultWithOSRedirect(sentryShell, args, false);
- assertTrue("Expected error message: " + expectedErrorMsg, errorMsgs.contains(expectedErrorMsg));
- }
-
- private void validateMissingParameterMsgsContains(SentryShellGeneric 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);
- }
-}
[2/9] sentry git commit: SENTRY-2207 Refactor out Sentry CLI from
sentry-provider-db into own module. Steve Moist,
reviewed by Colm O hEigeartaigh.
Posted by co...@apache.org.
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellIndexer.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellIndexer.java b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellIndexer.java
new file mode 100644
index 0000000..f31d7b7
--- /dev/null
+++ b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellIndexer.java
@@ -0,0 +1,525 @@
+/**
+ * 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.SentryUserException;
+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.service.thrift.ServiceConstants;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+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 static junit.framework.Assert.assertEquals;
+import static org.apache.sentry.provider.common.AuthorizationComponent.HBASE_INDEXER;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+public class TestSentryShellIndexer extends SentryGenericServiceIntegrationBase {
+ 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 = "";
+ 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();
+ 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() };
+ SentryShellIndexer.main(args);
+ // test: create role with --create_role
+ args = new String[] { "--create_role", "-r", TEST_ROLE_NAME_2, "-conf",
+ confPath.getAbsolutePath() };
+ SentryShellIndexer.main(args);
+
+ // validate the result, list roles with -lr
+ args = new String[] { "-lr", "-conf", confPath.getAbsolutePath() };
+ SentryShellIndexer sentryShell = new SentryShellIndexer();
+ 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 SentryShellIndexer();
+ 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() };
+ SentryShellIndexer.main(args);
+ // test: drop role with --drop_role
+ args = new String[] { "--drop_role", "-r", TEST_ROLE_NAME_2, "-conf",
+ confPath.getAbsolutePath() };
+ SentryShellIndexer.main(args);
+
+ // validate the result
+ Set<TSentryRole> roles = client.listAllRoles(requestorName, HBASE_INDEXER);
+ assertEquals("Incorrect number of roles", 0, roles.size());
+ }
+ });
+ }
+
+ @Test
+ public void testAddDeleteRoleForGroup() throws Exception {
+ runTestAsSubject(new TestOperation() {
+ @Override
+ public void runTestAsSubject() throws Exception {
+ // Group names are case sensitive - mixed case names should work
+ String TEST_GROUP_1 = "testGroup1";
+ String TEST_GROUP_2 = "testGroup2";
+ String TEST_GROUP_3 = "testGroup3";
+
+ // create the role for test
+ client.createRole(requestorName, TEST_ROLE_NAME_1, HBASE_INDEXER);
+ client.createRole(requestorName, TEST_ROLE_NAME_2, HBASE_INDEXER);
+ // test: add role to group with -arg
+ String[] args = { "-arg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_1, "-conf",
+ confPath.getAbsolutePath() };
+ SentryShellIndexer.main(args);
+ // test: add role to multiple groups
+ args = new String[] { "-arg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_2 + "," + TEST_GROUP_3,
+ "-conf",
+ confPath.getAbsolutePath() };
+ SentryShellIndexer.main(args);
+ // test: add role to group with --add_role_group
+ args = new String[] { "--add_role_group", "-r", TEST_ROLE_NAME_2, "-g", TEST_GROUP_1,
+ "-conf",
+ confPath.getAbsolutePath() };
+ SentryShellIndexer.main(args);
+
+ // validate the result list roles with -lr and -g
+ args = new String[] { "-lr", "-g", TEST_GROUP_1, "-conf", confPath.getAbsolutePath() };
+ SentryShellIndexer sentryShell = new SentryShellIndexer();
+ 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", TEST_GROUP_2, "-conf",
+ confPath.getAbsolutePath() };
+ sentryShell = new SentryShellIndexer();
+ roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+ validateRoleNames(roleNames, TEST_ROLE_NAME_1);
+
+ args = new String[] { "--list_role", "-g", TEST_GROUP_3, "-conf",
+ confPath.getAbsolutePath() };
+ sentryShell = new SentryShellIndexer();
+ roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+ validateRoleNames(roleNames, TEST_ROLE_NAME_1);
+
+ // test: delete role from group with -drg
+ args = new String[] { "-drg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_1, "-conf",
+ confPath.getAbsolutePath() };
+ SentryShellIndexer.main(args);
+ // test: delete role to multiple groups
+ args = new String[] { "-drg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_2 + "," + TEST_GROUP_3,
+ "-conf",
+ confPath.getAbsolutePath() };
+ SentryShellIndexer.main(args);
+ // test: delete role from group with --delete_role_group
+ args = new String[] { "--delete_role_group", "-r", TEST_ROLE_NAME_2, "-g", TEST_GROUP_1,
+ "-conf", confPath.getAbsolutePath() };
+ SentryShellIndexer.main(args);
+
+ // validate the result
+ Set<TSentryRole> roles = client.listRolesByGroupName(requestorName, TEST_GROUP_1, HBASE_INDEXER);
+ assertEquals("Incorrect number of roles", 0, roles.size());
+ roles = client.listRolesByGroupName(requestorName, TEST_GROUP_2, HBASE_INDEXER);
+ assertEquals("Incorrect number of roles", 0, roles.size());
+ roles = client.listRolesByGroupName(requestorName, TEST_GROUP_3, HBASE_INDEXER);
+ assertEquals("Incorrect number of roles", 0, roles.size());
+ // clear the test data
+ client.dropRole(requestorName, TEST_ROLE_NAME_1, HBASE_INDEXER);
+ client.dropRole(requestorName, TEST_ROLE_NAME_2, HBASE_INDEXER);
+ }
+ });
+ }
+
+ @Test
+ public void testCaseSensitiveGroupName() throws Exception {
+ runTestAsSubject(new TestOperation() {
+ @Override
+ public void runTestAsSubject() throws Exception {
+
+ // create the role for test
+ client.createRole(requestorName, TEST_ROLE_NAME_1, HBASE_INDEXER);
+ // add role to a group (lower case)
+ String[] args = { "-arg", "-r", TEST_ROLE_NAME_1, "-g", "group1", "-conf",
+ confPath.getAbsolutePath() };
+ SentryShellIndexer.main(args);
+
+ // validate the roles when group name is same case as above
+ args = new String[] { "-lr", "-g", "group1", "-conf", confPath.getAbsolutePath() };
+ SentryShellIndexer sentryShell = new SentryShellIndexer();
+ Set<String> roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+ validateRoleNames(roleNames, TEST_ROLE_NAME_1);
+
+ // roles should be empty when group name is different case than above
+ args = new String[] { "-lr", "-g", "GROUP1", "-conf", confPath.getAbsolutePath() };
+ roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+ validateRoleNames(roleNames);
+ }
+ });
+ }
+
+ public static String grant(boolean shortOption) {
+ return shortOption ? "-gpr" : "--grant_privilege_role";
+ }
+
+ public static String revoke(boolean shortOption) {
+ return shortOption ? "-rpr" : "--revoke_privilege_role";
+ }
+
+ public static String list(boolean shortOption) {
+ return shortOption ? "-lp" : "--list_privilege";
+ }
+
+ private void assertGrantRevokePrivilege(final boolean shortOption) throws Exception {
+ runTestAsSubject(new TestOperation() {
+ @Override
+ public void runTestAsSubject() throws Exception {
+ // create the role for test
+ client.createRole(requestorName, TEST_ROLE_NAME_1, HBASE_INDEXER);
+ client.createRole(requestorName, TEST_ROLE_NAME_2, HBASE_INDEXER);
+
+ String [] privs = {
+ "Indexer=*->action=*",
+ "Indexer=indexer1->action=read",
+ "Indexer=indexer2->action=write"
+ };
+ for (int i = 0; i < privs.length; ++i) {
+ // test: grant privilege to role
+ String [] args = new String [] { grant(shortOption), "-r", TEST_ROLE_NAME_1, "-p",
+ privs[ i ],
+ "-conf", confPath.getAbsolutePath() };
+ SentryShellIndexer.main(args);
+ }
+
+ // test the list privilege
+ String [] args = new String[] { list(shortOption), "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() };
+ SentryShellIndexer sentryShell = new SentryShellIndexer();
+ Set<String> privilegeStrs = getShellResultWithOSRedirect(sentryShell, args, true);
+ assertEquals("Incorrect number of privileges", privs.length, privilegeStrs.size());
+ for (int i = 0; i < privs.length; ++i) {
+ assertTrue("Expected privilege: " + privs[ i ], privilegeStrs.contains(privs[ i ]));
+ }
+
+ for (int i = 0; i < privs.length; ++i) {
+ args = new String[] { revoke(shortOption), "-r", TEST_ROLE_NAME_1, "-p",
+ privs[ i ], "-conf",
+ confPath.getAbsolutePath() };
+ SentryShellIndexer.main(args);
+ Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(requestorName,
+ TEST_ROLE_NAME_1, HBASE_INDEXER, service);
+ assertEquals("Incorrect number of privileges", privs.length - (i + 1), privileges.size());
+ }
+
+ // clear the test data
+ client.dropRole(requestorName, TEST_ROLE_NAME_1, HBASE_INDEXER);
+ client.dropRole(requestorName, TEST_ROLE_NAME_2, HBASE_INDEXER);
+ }
+ });
+ }
+
+
+ @Test
+ public void testGrantRevokePrivilegeWithShortOption() throws Exception {
+ assertGrantRevokePrivilege(true);
+ }
+
+ @Test
+ public void testGrantRevokePrivilegeWithLongOption() throws Exception {
+ assertGrantRevokePrivilege(false);
+ }
+
+ @Test
+ public void testNegativeCaseWithInvalidArgument() throws Exception {
+ runTestAsSubject(new TestOperation() {
+ @Override
+ public void runTestAsSubject() throws Exception {
+ client.createRole(requestorName, TEST_ROLE_NAME_1, HBASE_INDEXER);
+ // test: create duplicate role with -cr
+ String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() };
+ SentryShellIndexer sentryShell = new SentryShellIndexer();
+ try {
+ sentryShell.executeShell(args);
+ fail("Exception should be thrown for creating duplicate role");
+ } catch (SentryUserException e) {
+ // expected exception
+ }
+
+ // test: drop non-exist role with -dr
+ args = new String[] { "-dr", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath() };
+ sentryShell = new SentryShellIndexer();
+ 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 SentryShellIndexer();
+ 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 SentryShellIndexer();
+ 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 SentryShellIndexer();
+ 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 SentryShellIndexer();
+ try {
+ sentryShell.executeShell(args);
+ fail("Exception should be thrown for the error privilege format, invalid key value.");
+ } catch (IllegalArgumentException e) {
+ // expected exception
+ }
+
+ // clear the test data
+ client.dropRole(requestorName, TEST_ROLE_NAME_1, HBASE_INDEXER);
+ }
+ });
+ }
+
+ @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, HBASE_INDEXER);
+ // test: the conf is required argument
+ String[] args = { "-cr", "-r", TEST_ROLE_NAME_1 };
+ SentryShellIndexer sentryShell = new SentryShellIndexer();
+ 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 SentryShellIndexer();
+ 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 SentryShellIndexer();
+ 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 SentryShellIndexer();
+ 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 SentryShellIndexer();
+ 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 SentryShellIndexer();
+ 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 SentryShellIndexer();
+ 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", "indexer=Indexer1", "-conf", confPath.getAbsolutePath() };
+ sentryShell = new SentryShellIndexer();
+ 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 SentryShellIndexer();
+ validateMissingParameterMsg(sentryShell, args,
+ SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_PRIVILEGE);
+
+ // test: action is required in privilege
+ args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-p", "indexer=Indexer1" };
+ sentryShell = new SentryShellIndexer();
+ try {
+ getShellResultWithOSRedirect(sentryShell, args, false);
+ fail("Expected IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ assert("Privilege is invalid: action required but not specified.".equals(e.getMessage()));
+ }
+
+ // test: -r is required when revoke privilege from role
+ args = new String[] { "-rpr", "-p", "indexer=Indexer1", "-conf", confPath.getAbsolutePath() };
+ sentryShell = new SentryShellIndexer();
+ 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 SentryShellIndexer();
+ 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 SentryShellIndexer();
+ 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, HBASE_INDEXER);
+ }
+ });
+ }
+
+ // redirect the System.out to ByteArrayOutputStream, then execute the command and parse the result.
+ private Set<String> getShellResultWithOSRedirect(SentryShellIndexer sentryShell,
+ String[] args, boolean expectedExecuteResult) throws Exception {
+ PrintStream oldOut = System.out;
+ ByteArrayOutputStream outContent = new ByteArrayOutputStream();
+ System.setOut(new PrintStream(outContent));
+ assertEquals(expectedExecuteResult, sentryShell.executeShell(args));
+ String outContentStr = outContent.toString();
+ Set<String> resultSet = outContentStr.length() > 0 ? Sets.<String>newHashSet(outContentStr.split("\n")) : Sets.<String>newHashSet();
+ 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(SentryShellIndexer sentryShell, String[] args,
+ String expectedErrorMsg) throws Exception {
+ Set<String> errorMsgs = getShellResultWithOSRedirect(sentryShell, args, false);
+ assertTrue("Expected error message: " + expectedErrorMsg, errorMsgs.contains(expectedErrorMsg));
+ }
+
+ private void validateMissingParameterMsgsContains(SentryShellIndexer 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);
+ }
+}
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellKafka.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellKafka.java b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellKafka.java
new file mode 100644
index 0000000..3b06d90
--- /dev/null
+++ b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellKafka.java
@@ -0,0 +1,549 @@
+/**
+ * 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.SentryUserException;
+import org.apache.sentry.core.model.kafka.validator.KafkaPrivilegeValidator;
+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.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import static org.junit.Assert.*;
+
+public class TestSentryShellKafka extends SentryGenericServiceIntegrationBase {
+ private File confDir;
+ private File confPath;
+ private static String TEST_ROLE_NAME_1 = "testRole1";
+ private static String TEST_ROLE_NAME_2 = "testRole2";
+ private static String KAFKA = "kafka";
+ private String requestorName = "";
+ private String service = "kafka";
+
+ @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();//.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);
+ }
+
+ @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(), "-t", "kafka" };
+ SentryShellGeneric.main(args);
+ // test: create role with --create_role
+ args = new String[] { "--create_role", "-r", TEST_ROLE_NAME_2, "-conf",
+ confPath.getAbsolutePath(), "-t", "kafka" };
+ SentryShellGeneric.main(args);
+
+ // validate the result, list roles with -lr
+ args = new String[] { "-lr", "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
+ SentryShellGeneric sentryShell = new SentryShellGeneric();
+ 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(), "-t", "kafka" };
+ sentryShell = new SentryShellGeneric();
+ 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(), "-t", "kafka" };
+ SentryShellGeneric.main(args);
+ // test: drop role with --drop_role
+ args = new String[] { "--drop_role", "-r", TEST_ROLE_NAME_2, "-conf",
+ confPath.getAbsolutePath(), "-t", "kafka" };
+ SentryShellGeneric.main(args);
+
+ // validate the result
+ Set<TSentryRole> roles = client.listAllRoles(requestorName, KAFKA);
+ assertEquals("Incorrect number of roles", 0, roles.size());
+ }
+ });
+ }
+
+ @Test
+ public void testAddDeleteRoleForGroup() throws Exception {
+ runTestAsSubject(new TestOperation() {
+ @Override
+ public void runTestAsSubject() throws Exception {
+ // Group names are case sensitive - mixed case names should work
+ String TEST_GROUP_1 = "testGroup1";
+ String TEST_GROUP_2 = "testGroup2";
+ String TEST_GROUP_3 = "testGroup3";
+
+ // create the role for test
+ client.createRole(requestorName, TEST_ROLE_NAME_1, KAFKA);
+ client.createRole(requestorName, TEST_ROLE_NAME_2, KAFKA);
+ // test: add role to group with -arg
+ String[] args = { "-arg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_1, "-conf",
+ confPath.getAbsolutePath(), "-t", "kafka" };
+ SentryShellGeneric.main(args);
+ // test: add role to multiple groups
+ args = new String[] { "-arg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_2 + "," + TEST_GROUP_3,
+ "-conf",
+ confPath.getAbsolutePath(), "-t", "kafka" };
+ SentryShellGeneric.main(args);
+ // test: add role to group with --add_role_group
+ args = new String[] { "--add_role_group", "-r", TEST_ROLE_NAME_2, "-g", TEST_GROUP_1,
+ "-conf",
+ confPath.getAbsolutePath(), "-t", "kafka" };
+ SentryShellGeneric.main(args);
+
+ // validate the result list roles with -lr and -g
+ args = new String[] { "-lr", "-g", TEST_GROUP_1, "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
+ SentryShellGeneric sentryShell = new SentryShellGeneric();
+ 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", TEST_GROUP_2, "-conf",
+ confPath.getAbsolutePath(), "-t", "kafka" };
+ sentryShell = new SentryShellGeneric();
+ roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+ validateRoleNames(roleNames, TEST_ROLE_NAME_1);
+
+ args = new String[] { "--list_role", "-g", TEST_GROUP_3, "-conf",
+ confPath.getAbsolutePath(), "-t", "kafka" };
+ sentryShell = new SentryShellGeneric();
+ 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(), "-t", "kafka" };
+ sentryShell = new SentryShellGeneric();
+ 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", TEST_GROUP_1, "-conf",
+ confPath.getAbsolutePath(), "-t", "kafka" };
+ SentryShellGeneric.main(args);
+ // test: delete role to multiple groups
+ args = new String[] { "-drg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_2 + "," + TEST_GROUP_3,
+ "-conf",
+ confPath.getAbsolutePath(), "-t", "kafka" };
+ SentryShellGeneric.main(args);
+ // test: delete role from group with --delete_role_group
+ args = new String[] { "--delete_role_group", "-r", TEST_ROLE_NAME_2, "-g", TEST_GROUP_1,
+ "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
+ SentryShellGeneric.main(args);
+
+ // validate the result
+ Set<TSentryRole> roles = client.listRolesByGroupName(requestorName, TEST_GROUP_1, KAFKA);
+ assertEquals("Incorrect number of roles", 0, roles.size());
+ roles = client.listRolesByGroupName(requestorName, TEST_GROUP_2, KAFKA);
+ assertEquals("Incorrect number of roles", 0, roles.size());
+ roles = client.listRolesByGroupName(requestorName, TEST_GROUP_3, KAFKA);
+ assertEquals("Incorrect number of roles", 0, roles.size());
+ // clear the test data
+ client.dropRole(requestorName, TEST_ROLE_NAME_1, KAFKA);
+ client.dropRole(requestorName, TEST_ROLE_NAME_2, KAFKA);
+ }
+ });
+ }
+
+ @Test
+ public void testCaseSensitiveGroupName() throws Exception {
+ runTestAsSubject(new TestOperation() {
+ @Override
+ public void runTestAsSubject() throws Exception {
+
+ // create the role for test
+ client.createRole(requestorName, TEST_ROLE_NAME_1, KAFKA);
+ // add role to a group (lower case)
+ String[] args = {"-arg", "-r", TEST_ROLE_NAME_1, "-g", "group1", "-conf",
+ confPath.getAbsolutePath(), "-t", "kafka"};
+ SentryShellGeneric.main(args);
+
+ // validate the roles when group name is same case as above
+ args = new String[]{"-lr", "-g", "group1", "-conf", confPath.getAbsolutePath(), "-t", "kafka"};
+ SentryShellGeneric sentryShell = new SentryShellGeneric();
+ Set<String> roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+ validateRoleNames(roleNames, TEST_ROLE_NAME_1);
+
+ // roles should be empty when group name is different case than above
+ args = new String[]{"-lr", "-g", "GROUP1", "-conf", confPath.getAbsolutePath(), "-t", "kafka"};
+ roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+ validateRoleNames(roleNames);
+ }
+ });
+ }
+
+ public static String grant(boolean shortOption) {
+ return shortOption ? "-gpr" : "--grant_privilege_role";
+ }
+
+ public static String revoke(boolean shortOption) {
+ return shortOption ? "-rpr" : "--revoke_privilege_role";
+ }
+
+ public static String list(boolean shortOption) {
+ return shortOption ? "-lp" : "--list_privilege";
+ }
+
+ private void assertGrantRevokePrivilege(final boolean shortOption) throws Exception {
+ runTestAsSubject(new TestOperation() {
+ @Override
+ public void runTestAsSubject() throws Exception {
+ // create the role for test
+ client.createRole(requestorName, TEST_ROLE_NAME_1, KAFKA);
+ client.createRole(requestorName, TEST_ROLE_NAME_2, KAFKA);
+
+ String [] privs = {
+ "HOST=*->CLUSTER=kafka-cluster->action=read",
+ "HOST=h1->TOPIC=t1->action=write",
+ "HOST=*->CONSUMERGROUP=cg1->action=read",
+ "CLUSTER=kafka-cluster->action=write",
+ "CONSUMERGROUP=cg2->action=write"
+ };
+ for (int i = 0; i < privs.length; ++i) {
+ // test: grant privilege to role
+ String [] args = new String [] { grant(shortOption), "-r", TEST_ROLE_NAME_1, "-p",
+ privs[ i ],
+ "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
+ SentryShellGeneric.main(args);
+ }
+
+ // test the list privilege
+ String [] args = new String[] { list(shortOption), "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
+ SentryShellGeneric sentryShell = new SentryShellGeneric();
+ Set<String> privilegeStrs = getShellResultWithOSRedirect(sentryShell, args, true);
+
+ assertEquals("Incorrect number of privileges", privs.length, privilegeStrs.size());
+ for (int i = 0; i < privs.length; ++i) {
+ assertTrue("Expected privilege: " + privs[i] + " in " + Arrays.toString(privilegeStrs.toArray()), privilegeStrs.contains(privs[i].startsWith("HOST=") ? privs[i] : "HOST=*->" + privs[i]));
+ }
+
+ for (int i = 0; i < privs.length; ++i) {
+ args = new String[] { revoke(shortOption), "-r", TEST_ROLE_NAME_1, "-p",
+ privs[ i ], "-conf",
+ confPath.getAbsolutePath(), "-t", "kafka" };
+ SentryShellGeneric.main(args);
+ Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(requestorName,
+ TEST_ROLE_NAME_1, KAFKA, service);
+ assertEquals("Incorrect number of privileges. Received privileges: " + Arrays.toString(privileges.toArray()), privs.length - (i + 1), privileges.size());
+ }
+
+ // clear the test data
+ client.dropRole(requestorName, TEST_ROLE_NAME_1, KAFKA);
+ client.dropRole(requestorName, TEST_ROLE_NAME_2, KAFKA);
+ }
+ });
+ }
+
+
+ @Test
+ public void testGrantRevokePrivilegeWithShortOption() throws Exception {
+ assertGrantRevokePrivilege(true);
+ }
+
+ @Test
+ public void testGrantRevokePrivilegeWithLongOption() throws Exception {
+ assertGrantRevokePrivilege(false);
+ }
+
+
+ @Test
+ public void testNegativeCaseWithInvalidArgument() throws Exception {
+ runTestAsSubject(new TestOperation() {
+ @Override
+ public void runTestAsSubject() throws Exception {
+ client.createRole(requestorName, TEST_ROLE_NAME_1, KAFKA);
+ // test: create duplicate role with -cr
+ String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
+ SentryShellGeneric sentryShell = new SentryShellGeneric();
+ try {
+ sentryShell.executeShell(args);
+ fail("Exception should be thrown for creating duplicate role");
+ } catch (SentryUserException e) {
+ // expected exception
+ } catch (Exception e) {
+ fail ("Unexpected exception received. " + e);
+ }
+
+ // test: drop non-exist role with -dr
+ args = new String[] { "-dr", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
+ sentryShell = new SentryShellGeneric();
+ try {
+ sentryShell.executeShell(args);
+ fail("Exception should be thrown for dropping non-exist role");
+ } catch (SentryUserException e) {
+ // excepted exception
+ } catch (Exception e) {
+ fail ("Unexpected exception received. " + e);
+ }
+
+ // test: add non-exist role to group with -arg
+ args = new String[] { "-arg", "-r", TEST_ROLE_NAME_2, "-g", "testGroup1", "-conf",
+ confPath.getAbsolutePath(), "-t", "kafka" };
+ sentryShell = new SentryShellGeneric();
+ try {
+ sentryShell.executeShell(args);
+ fail("Exception should be thrown for granting non-exist role to group");
+ } catch (SentryUserException e) {
+ // excepted exception
+ } catch (Exception e) {
+ fail ("Unexpected exception received. " + e);
+ }
+
+ // test: drop group from non-exist role with -drg
+ args = new String[] { "-drg", "-r", TEST_ROLE_NAME_2, "-g", "testGroup1", "-conf",
+ confPath.getAbsolutePath(), "-t", "kafka" };
+ sentryShell = new SentryShellGeneric();
+ try {
+ sentryShell.executeShell(args);
+ fail("Exception should be thrown for drop group from non-exist role");
+ } catch (SentryUserException e) {
+ // excepted exception
+ } catch (Exception e) {
+ fail ("Unexpected exception received. " + e);
+ }
+
+ // test: grant privilege to role with the error privilege format
+ args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p", "serverserver1->action=all",
+ "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
+ sentryShell = new SentryShellGeneric();
+ try {
+ sentryShell.executeShell(args);
+ fail("Exception should be thrown for the error privilege format, invalid key value.");
+ } catch (IllegalArgumentException e) {
+ // excepted exception
+ } catch (Exception e) {
+ fail ("Unexpected exception received. " + e);
+ }
+
+ // test: grant privilege to role with the error privilege hierarchy
+ args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p",
+ "consumergroup=cg1->host=h1->action=create", "-conf",
+ confPath.getAbsolutePath(), "-t", "kafka" };
+ sentryShell = new SentryShellGeneric();
+ try {
+ sentryShell.executeShell(args);
+ fail("Exception should be thrown for the error privilege format, invalid key value.");
+ } catch (IllegalArgumentException e) {
+ // expected exception
+ } catch (Exception e) {
+ fail ("Unexpected exception received. " + e);
+ }
+
+ // clear the test data
+ client.dropRole(requestorName, TEST_ROLE_NAME_1, KAFKA);
+ }
+ });
+ }
+
+ @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, KAFKA);
+ // test: the conf is required argument
+ String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-t", "kafka" };
+ SentryShellGeneric sentryShell = new SentryShellGeneric();
+ validateMissingParameterMsg(sentryShell, args,
+ SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + strOptionConf);
+
+ // test: -r is required when create role
+ args = new String[] { "-cr", "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
+ sentryShell = new SentryShellGeneric();
+ 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(), "-t", "kafka" };
+ sentryShell = new SentryShellGeneric();
+ 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(), "-t", "kafka" };
+ sentryShell = new SentryShellGeneric();
+ 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(), "-t", "kafka" };
+ sentryShell = new SentryShellGeneric();
+ 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(), "-t", "kafka" };
+ sentryShell = new SentryShellGeneric();
+ 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(), "-t", "kafka" };
+ sentryShell = new SentryShellGeneric();
+ 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(), "-t", "kafka" };
+ sentryShell = new SentryShellGeneric();
+ 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(), "-t", "kafka" };
+ sentryShell = new SentryShellGeneric();
+ validateMissingParameterMsg(sentryShell, args,
+ SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_PRIVILEGE);
+
+ // test: action is required in privilege
+ args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-p", "host=*->topic=t1", "-t", "kafka" };
+ sentryShell = new SentryShellGeneric();
+ try {
+ getShellResultWithOSRedirect(sentryShell, args, false);
+ fail("Expected IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ assert(("Kafka privilege must end with a valid action.\n" + KafkaPrivilegeValidator.KafkaPrivilegeHelpMsg).equals(e.getCause().getMessage()));
+ } catch (Exception e) {
+ fail ("Unexpected exception received. " + e);
+ }
+
+ // test: -r is required when revoke privilege from role
+ args = new String[] { "-rpr", "-p", "host=h1", "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
+ sentryShell = new SentryShellGeneric();
+ 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(), "-t", "kafka" };
+ sentryShell = new SentryShellGeneric();
+ 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(), "-t", "kafka" };
+ sentryShell = new SentryShellGeneric();
+ 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, KAFKA);
+ }
+ });
+ }
+
+ // redirect the System.out to ByteArrayOutputStream, then execute the command and parse the result.
+ private Set<String> getShellResultWithOSRedirect(SentryShellGeneric sentryShell,
+ String[] args, boolean expectedExecuteResult) throws Exception {
+ PrintStream oldOut = System.out;
+ ByteArrayOutputStream outContent = new ByteArrayOutputStream();
+ System.setOut(new PrintStream(outContent));
+ assertEquals(expectedExecuteResult, 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(SentryShellGeneric sentryShell, String[] args,
+ String expectedErrorMsg) throws Exception {
+ Set<String> errorMsgs = getShellResultWithOSRedirect(sentryShell, args, false);
+ assertTrue("Expected error message: " + expectedErrorMsg, errorMsgs.contains(expectedErrorMsg));
+ }
+
+ private void validateMissingParameterMsgsContains(SentryShellGeneric 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);
+ }
+}
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellSolr.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellSolr.java b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellSolr.java
new file mode 100644
index 0000000..b770727
--- /dev/null
+++ b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellSolr.java
@@ -0,0 +1,533 @@
+/**
+ * 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.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.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.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestSentryShellSolr extends SentryGenericServiceIntegrationBase {
+ 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 = "";
+ 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);
+ }
+
+ @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(), "-t", "solr" };
+ SentryShellGeneric.main(args);
+ // test: create role with --create_role
+ args = new String[] { "--create_role", "-r", TEST_ROLE_NAME_2, "-conf",
+ confPath.getAbsolutePath(), "-t", "solr" };
+ SentryShellGeneric.main(args);
+
+ // validate the result, list roles with -lr
+ args = new String[] { "-lr", "-conf", confPath.getAbsolutePath(), "-t", "solr" };
+ SentryShellGeneric sentryShell = new SentryShellGeneric();
+ 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(), "-t", "solr" };
+ sentryShell = new SentryShellGeneric();
+ 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(), "-t", "solr" };
+ SentryShellGeneric.main(args);
+ // test: drop role with --drop_role
+ args = new String[] { "--drop_role", "-r", TEST_ROLE_NAME_2, "-conf",
+ confPath.getAbsolutePath(), "-t", "solr" };
+ SentryShellGeneric.main(args);
+
+ // validate the result
+ Set<TSentryRole> roles = client.listAllRoles(requestorName, SOLR);
+ assertEquals("Incorrect number of roles", 0, roles.size());
+ }
+ });
+ }
+
+ @Test
+ public void testAddDeleteRoleForGroup() throws Exception {
+ runTestAsSubject(new TestOperation() {
+ @Override
+ public void runTestAsSubject() throws Exception {
+ // Group names are case sensitive - mixed case names should work
+ String TEST_GROUP_1 = "testGroup1";
+ String TEST_GROUP_2 = "testGroup2";
+ String TEST_GROUP_3 = "testGroup3";
+
+ // create the role for test
+ client.createRole(requestorName, TEST_ROLE_NAME_1, SOLR);
+ client.createRole(requestorName, TEST_ROLE_NAME_2, SOLR);
+ // test: add role to group with -arg
+ String[] args = { "-arg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_1, "-conf",
+ confPath.getAbsolutePath(), "-t", "solr" };
+ SentryShellGeneric.main(args);
+ // test: add role to multiple groups
+ args = new String[] { "-arg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_2 + "," + TEST_GROUP_3,
+ "-conf",
+ confPath.getAbsolutePath(), "-t", "solr" };
+ SentryShellGeneric.main(args);
+ // test: add role to group with --add_role_group
+ args = new String[] { "--add_role_group", "-r", TEST_ROLE_NAME_2, "-g", TEST_GROUP_1,
+ "-conf",
+ confPath.getAbsolutePath(), "-t", "solr" };
+ SentryShellGeneric.main(args);
+
+ // validate the result list roles with -lr and -g
+ args = new String[] { "-lr", "-g", TEST_GROUP_1, "-conf", confPath.getAbsolutePath(), "-t", "solr" };
+ SentryShellGeneric sentryShell = new SentryShellGeneric();
+ 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", TEST_GROUP_2, "-conf",
+ confPath.getAbsolutePath(), "-t", "solr" };
+ sentryShell = new SentryShellGeneric();
+ roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+ validateRoleNames(roleNames, TEST_ROLE_NAME_1);
+
+ args = new String[] { "--list_role", "-g", TEST_GROUP_3, "-conf",
+ confPath.getAbsolutePath(), "-t", "solr" };
+ sentryShell = new SentryShellGeneric();
+ 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(), "-t", "solr" };
+ sentryShell = new SentryShellGeneric();
+ 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", TEST_GROUP_1, "-conf",
+ confPath.getAbsolutePath(), "-t", "solr" };
+ SentryShellGeneric.main(args);
+ // test: delete role to multiple groups
+ args = new String[] { "-drg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_2 + "," + TEST_GROUP_3,
+ "-conf",
+ confPath.getAbsolutePath(), "-t", "solr" };
+ SentryShellGeneric.main(args);
+ // test: delete role from group with --delete_role_group
+ args = new String[] { "--delete_role_group", "-r", TEST_ROLE_NAME_2, "-g", TEST_GROUP_1,
+ "-conf", confPath.getAbsolutePath(), "-t", "solr" };
+ SentryShellGeneric.main(args);
+
+ // validate the result
+ Set<TSentryRole> roles = client.listRolesByGroupName(requestorName, TEST_GROUP_1, SOLR);
+ assertEquals("Incorrect number of roles", 0, roles.size());
+ roles = client.listRolesByGroupName(requestorName, TEST_GROUP_2, SOLR);
+ assertEquals("Incorrect number of roles", 0, roles.size());
+ roles = client.listRolesByGroupName(requestorName, TEST_GROUP_3, SOLR);
+ assertEquals("Incorrect number of roles", 0, roles.size());
+ // clear the test data
+ client.dropRole(requestorName, TEST_ROLE_NAME_1, SOLR);
+ client.dropRole(requestorName, TEST_ROLE_NAME_2, SOLR);
+ }
+ });
+ }
+
+ @Test
+ public void testCaseSensitiveGroupName() throws Exception {
+ runTestAsSubject(new TestOperation() {
+ @Override
+ public void runTestAsSubject() throws Exception {
+
+ // create the role for test
+ client.createRole(requestorName, TEST_ROLE_NAME_1, SOLR);
+ // add role to a group (lower case)
+ String[] args = { "-arg", "-r", TEST_ROLE_NAME_1, "-g", "group1", "-conf",
+ confPath.getAbsolutePath(), "-t", "solr" };
+ SentryShellGeneric.main(args);
+
+ // validate the roles when group name is same case as above
+ args = new String[] { "-lr", "-g", "group1", "-conf", confPath.getAbsolutePath(), "-t", "solr" };
+ SentryShellGeneric sentryShell = new SentryShellGeneric();
+ Set<String> roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+ validateRoleNames(roleNames, TEST_ROLE_NAME_1);
+
+ // roles should be empty when group name is different case than above
+ args = new String[] { "-lr", "-g", "GROUP1", "-conf", confPath.getAbsolutePath(), "-t", "solr" };
+ roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+ validateRoleNames(roleNames);
+ }
+ });
+ }
+
+ public static String grant(boolean shortOption) {
+ return shortOption ? "-gpr" : "--grant_privilege_role";
+ }
+
+ public static String revoke(boolean shortOption) {
+ return shortOption ? "-rpr" : "--revoke_privilege_role";
+ }
+
+ public static String list(boolean shortOption) {
+ return shortOption ? "-lp" : "--list_privilege";
+ }
+
+ private void assertGrantRevokePrivilege(final boolean shortOption) throws Exception {
+ runTestAsSubject(new TestOperation() {
+ @Override
+ public void runTestAsSubject() throws Exception {
+ // create the role for test
+ client.createRole(requestorName, TEST_ROLE_NAME_1, SOLR);
+ client.createRole(requestorName, TEST_ROLE_NAME_2, SOLR);
+
+ String [] privs = {
+ "Collection=*->action=*",
+ "Collection=collection2->action=update",
+ "Collection=collection3->action=query",
+ };
+ for (int i = 0; i < privs.length; ++i) {
+ // test: grant privilege to role
+ String [] args = new String [] { grant(shortOption), "-r", TEST_ROLE_NAME_1, "-p",
+ privs[ i ],
+ "-conf", confPath.getAbsolutePath(), "-t", "solr" };
+ SentryShellGeneric.main(args);
+ }
+
+ // test the list privilege
+ String [] args = new String[] { list(shortOption), "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "solr" };
+ SentryShellGeneric sentryShell = new SentryShellGeneric();
+ Set<String> privilegeStrs = getShellResultWithOSRedirect(sentryShell, args, true);
+ assertEquals("Incorrect number of privileges", privs.length, privilegeStrs.size());
+ for (int i = 0; i < privs.length; ++i) {
+ assertTrue("Expected privilege: " + privs[ i ], privilegeStrs.contains(privs[ i ]));
+ }
+
+ for (int i = 0; i < privs.length; ++i) {
+ args = new String[] { revoke(shortOption), "-r", TEST_ROLE_NAME_1, "-p",
+ privs[ i ], "-conf",
+ confPath.getAbsolutePath(), "-t", "solr" };
+ SentryShellGeneric.main(args);
+ Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(requestorName,
+ TEST_ROLE_NAME_1, SOLR, service);
+ assertEquals("Incorrect number of privileges", privs.length - (i + 1), privileges.size());
+ }
+
+ // clear the test data
+ client.dropRole(requestorName, TEST_ROLE_NAME_1, SOLR);
+ client.dropRole(requestorName, TEST_ROLE_NAME_2, SOLR);
+ }
+ });
+ }
+
+
+ @Test
+ public void testGrantRevokePrivilegeWithShortOption() throws Exception {
+ assertGrantRevokePrivilege(true);
+ }
+
+ @Test
+ public void testGrantRevokePrivilegeWithLongOption() throws Exception {
+ assertGrantRevokePrivilege(false);
+ }
+
+
+ @Test
+ public void testNegativeCaseWithInvalidArgument() throws Exception {
+ runTestAsSubject(new TestOperation() {
+ @Override
+ public void runTestAsSubject() throws Exception {
+ client.createRole(requestorName, TEST_ROLE_NAME_1, SOLR);
+ // test: create duplicate role with -cr
+ String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "solr" };
+ SentryShellGeneric sentryShell = new SentryShellGeneric();
+ try {
+ sentryShell.executeShell(args);
+ fail("Exception should be thrown for creating duplicate role");
+ } catch (SentryUserException e) {
+ // expected exception
+ }
+
+ // test: drop non-exist role with -dr
+ args = new String[] { "-dr", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath(), "-t", "solr" };
+ sentryShell = new SentryShellGeneric();
+ 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(), "-t", "solr" };
+ sentryShell = new SentryShellGeneric();
+ 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(), "-t", "solr" };
+ sentryShell = new SentryShellGeneric();
+ 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(), "-t", "solr" };
+ sentryShell = new SentryShellGeneric();
+ 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(), "-t", "solr" };
+ sentryShell = new SentryShellGeneric();
+ try {
+ sentryShell.executeShell(args);
+ fail("Exception should be thrown for the error privilege format, invalid key value.");
+ } catch (IllegalArgumentException e) {
+ // expected exception
+ }
+
+ // clear the test data
+ client.dropRole(requestorName, TEST_ROLE_NAME_1, SOLR);
+ }
+ });
+ }
+
+ @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, SOLR);
+ // test: the conf is required argument
+ String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-t", "solr" };
+ SentryShellGeneric sentryShell = new SentryShellGeneric();
+ validateMissingParameterMsg(sentryShell, args,
+ SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + strOptionConf);
+
+ // test: -r is required when create role
+ args = new String[] { "-cr", "-conf", confPath.getAbsolutePath(), "-t", "solr" };
+ sentryShell = new SentryShellGeneric();
+ 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(), "-t", "solr" };
+ sentryShell = new SentryShellGeneric();
+ 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(), "-t", "solr" };
+ sentryShell = new SentryShellGeneric();
+ 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(), "-t", "solr" };
+ sentryShell = new SentryShellGeneric();
+ 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(), "-t", "solr" };
+ sentryShell = new SentryShellGeneric();
+ 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(), "-t", "solr" };
+ sentryShell = new SentryShellGeneric();
+ 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(), "-t", "solr" };
+ sentryShell = new SentryShellGeneric();
+ 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(), "-t", "solr" };
+ sentryShell = new SentryShellGeneric();
+ validateMissingParameterMsg(sentryShell, args,
+ SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_PRIVILEGE);
+
+ // test: action is required in privilege
+ args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-p", "collection=collection1", "-t", "solr" };
+ sentryShell = new SentryShellGeneric();
+ try {
+ getShellResultWithOSRedirect(sentryShell, args, false);
+ fail("Expected IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ assertEquals("Privilege is invalid: action required but not specified.", e.getMessage());
+ }
+
+ // test: -r is required when revoke privilege from role
+ args = new String[] { "-rpr", "-p", "server=server1", "-conf", confPath.getAbsolutePath(), "-t", "solr" };
+ sentryShell = new SentryShellGeneric();
+ 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(), "-t", "solr" };
+ sentryShell = new SentryShellGeneric();
+ 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 SentryShellGeneric();
+ 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, SOLR);
+ }
+ });
+ }
+
+ // redirect the System.out to ByteArrayOutputStream, then execute the command and parse the result.
+ private Set<String> getShellResultWithOSRedirect(SentryShellGeneric sentryShell,
+ String[] args, boolean expectedExecuteResult) throws Exception {
+ PrintStream oldOut = System.out;
+ ByteArrayOutputStream outContent = new ByteArrayOutputStream();
+ System.setOut(new PrintStream(outContent));
+ assertEquals(expectedExecuteResult, 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(SentryShellGeneric sentryShell, String[] args,
+ String expectedErrorMsg) throws Exception {
+ Set<String> errorMsgs = getShellResultWithOSRedirect(sentryShell, args, false);
+ assertTrue("Expected error message: " + expectedErrorMsg, errorMsgs.contains(expectedErrorMsg));
+ }
+
+ private void validateMissingParameterMsgsContains(SentryShellGeneric 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);
+ }
+}
[6/9] sentry git commit: SENTRY-2207 Refactor out Sentry CLI from
sentry-provider-db into own module. Steve Moist,
reviewed by Colm O hEigeartaigh.
Posted by co...@apache.org.
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryShellSolr.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryShellSolr.java b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryShellSolr.java
deleted file mode 100644
index 0f4bb62..0000000
--- a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryShellSolr.java
+++ /dev/null
@@ -1,534 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.sentry.provider.db.generic.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.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.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.provider.db.tools.SentryShellCommon;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-public class TestSentryShellSolr extends SentryGenericServiceIntegrationBase {
- 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 = "";
- 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);
- }
-
- @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(), "-t", "solr" };
- SentryShellGeneric.main(args);
- // test: create role with --create_role
- args = new String[] { "--create_role", "-r", TEST_ROLE_NAME_2, "-conf",
- confPath.getAbsolutePath(), "-t", "solr" };
- SentryShellGeneric.main(args);
-
- // validate the result, list roles with -lr
- args = new String[] { "-lr", "-conf", confPath.getAbsolutePath(), "-t", "solr" };
- SentryShellGeneric sentryShell = new SentryShellGeneric();
- 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(), "-t", "solr" };
- sentryShell = new SentryShellGeneric();
- 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(), "-t", "solr" };
- SentryShellGeneric.main(args);
- // test: drop role with --drop_role
- args = new String[] { "--drop_role", "-r", TEST_ROLE_NAME_2, "-conf",
- confPath.getAbsolutePath(), "-t", "solr" };
- SentryShellGeneric.main(args);
-
- // validate the result
- Set<TSentryRole> roles = client.listAllRoles(requestorName, SOLR);
- assertEquals("Incorrect number of roles", 0, roles.size());
- }
- });
- }
-
- @Test
- public void testAddDeleteRoleForGroup() throws Exception {
- runTestAsSubject(new TestOperation() {
- @Override
- public void runTestAsSubject() throws Exception {
- // Group names are case sensitive - mixed case names should work
- String TEST_GROUP_1 = "testGroup1";
- String TEST_GROUP_2 = "testGroup2";
- String TEST_GROUP_3 = "testGroup3";
-
- // create the role for test
- client.createRole(requestorName, TEST_ROLE_NAME_1, SOLR);
- client.createRole(requestorName, TEST_ROLE_NAME_2, SOLR);
- // test: add role to group with -arg
- String[] args = { "-arg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_1, "-conf",
- confPath.getAbsolutePath(), "-t", "solr" };
- SentryShellGeneric.main(args);
- // test: add role to multiple groups
- args = new String[] { "-arg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_2 + "," + TEST_GROUP_3,
- "-conf",
- confPath.getAbsolutePath(), "-t", "solr" };
- SentryShellGeneric.main(args);
- // test: add role to group with --add_role_group
- args = new String[] { "--add_role_group", "-r", TEST_ROLE_NAME_2, "-g", TEST_GROUP_1,
- "-conf",
- confPath.getAbsolutePath(), "-t", "solr" };
- SentryShellGeneric.main(args);
-
- // validate the result list roles with -lr and -g
- args = new String[] { "-lr", "-g", TEST_GROUP_1, "-conf", confPath.getAbsolutePath(), "-t", "solr" };
- SentryShellGeneric sentryShell = new SentryShellGeneric();
- 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", TEST_GROUP_2, "-conf",
- confPath.getAbsolutePath(), "-t", "solr" };
- sentryShell = new SentryShellGeneric();
- roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
- validateRoleNames(roleNames, TEST_ROLE_NAME_1);
-
- args = new String[] { "--list_role", "-g", TEST_GROUP_3, "-conf",
- confPath.getAbsolutePath(), "-t", "solr" };
- sentryShell = new SentryShellGeneric();
- 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(), "-t", "solr" };
- sentryShell = new SentryShellGeneric();
- 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", TEST_GROUP_1, "-conf",
- confPath.getAbsolutePath(), "-t", "solr" };
- SentryShellGeneric.main(args);
- // test: delete role to multiple groups
- args = new String[] { "-drg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_2 + "," + TEST_GROUP_3,
- "-conf",
- confPath.getAbsolutePath(), "-t", "solr" };
- SentryShellGeneric.main(args);
- // test: delete role from group with --delete_role_group
- args = new String[] { "--delete_role_group", "-r", TEST_ROLE_NAME_2, "-g", TEST_GROUP_1,
- "-conf", confPath.getAbsolutePath(), "-t", "solr" };
- SentryShellGeneric.main(args);
-
- // validate the result
- Set<TSentryRole> roles = client.listRolesByGroupName(requestorName, TEST_GROUP_1, SOLR);
- assertEquals("Incorrect number of roles", 0, roles.size());
- roles = client.listRolesByGroupName(requestorName, TEST_GROUP_2, SOLR);
- assertEquals("Incorrect number of roles", 0, roles.size());
- roles = client.listRolesByGroupName(requestorName, TEST_GROUP_3, SOLR);
- assertEquals("Incorrect number of roles", 0, roles.size());
- // clear the test data
- client.dropRole(requestorName, TEST_ROLE_NAME_1, SOLR);
- client.dropRole(requestorName, TEST_ROLE_NAME_2, SOLR);
- }
- });
- }
-
- @Test
- public void testCaseSensitiveGroupName() throws Exception {
- runTestAsSubject(new TestOperation() {
- @Override
- public void runTestAsSubject() throws Exception {
-
- // create the role for test
- client.createRole(requestorName, TEST_ROLE_NAME_1, SOLR);
- // add role to a group (lower case)
- String[] args = { "-arg", "-r", TEST_ROLE_NAME_1, "-g", "group1", "-conf",
- confPath.getAbsolutePath(), "-t", "solr" };
- SentryShellGeneric.main(args);
-
- // validate the roles when group name is same case as above
- args = new String[] { "-lr", "-g", "group1", "-conf", confPath.getAbsolutePath(), "-t", "solr" };
- SentryShellGeneric sentryShell = new SentryShellGeneric();
- Set<String> roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
- validateRoleNames(roleNames, TEST_ROLE_NAME_1);
-
- // roles should be empty when group name is different case than above
- args = new String[] { "-lr", "-g", "GROUP1", "-conf", confPath.getAbsolutePath(), "-t", "solr" };
- roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
- validateRoleNames(roleNames);
- }
- });
- }
-
- public static String grant(boolean shortOption) {
- return shortOption ? "-gpr" : "--grant_privilege_role";
- }
-
- public static String revoke(boolean shortOption) {
- return shortOption ? "-rpr" : "--revoke_privilege_role";
- }
-
- public static String list(boolean shortOption) {
- return shortOption ? "-lp" : "--list_privilege";
- }
-
- private void assertGrantRevokePrivilege(final boolean shortOption) throws Exception {
- runTestAsSubject(new TestOperation() {
- @Override
- public void runTestAsSubject() throws Exception {
- // create the role for test
- client.createRole(requestorName, TEST_ROLE_NAME_1, SOLR);
- client.createRole(requestorName, TEST_ROLE_NAME_2, SOLR);
-
- String [] privs = {
- "Collection=*->action=*",
- "Collection=collection2->action=update",
- "Collection=collection3->action=query",
- };
- for (int i = 0; i < privs.length; ++i) {
- // test: grant privilege to role
- String [] args = new String [] { grant(shortOption), "-r", TEST_ROLE_NAME_1, "-p",
- privs[ i ],
- "-conf", confPath.getAbsolutePath(), "-t", "solr" };
- SentryShellGeneric.main(args);
- }
-
- // test the list privilege
- String [] args = new String[] { list(shortOption), "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "solr" };
- SentryShellGeneric sentryShell = new SentryShellGeneric();
- Set<String> privilegeStrs = getShellResultWithOSRedirect(sentryShell, args, true);
- assertEquals("Incorrect number of privileges", privs.length, privilegeStrs.size());
- for (int i = 0; i < privs.length; ++i) {
- assertTrue("Expected privilege: " + privs[ i ], privilegeStrs.contains(privs[ i ]));
- }
-
- for (int i = 0; i < privs.length; ++i) {
- args = new String[] { revoke(shortOption), "-r", TEST_ROLE_NAME_1, "-p",
- privs[ i ], "-conf",
- confPath.getAbsolutePath(), "-t", "solr" };
- SentryShellGeneric.main(args);
- Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(requestorName,
- TEST_ROLE_NAME_1, SOLR, service);
- assertEquals("Incorrect number of privileges", privs.length - (i + 1), privileges.size());
- }
-
- // clear the test data
- client.dropRole(requestorName, TEST_ROLE_NAME_1, SOLR);
- client.dropRole(requestorName, TEST_ROLE_NAME_2, SOLR);
- }
- });
- }
-
-
- @Test
- public void testGrantRevokePrivilegeWithShortOption() throws Exception {
- assertGrantRevokePrivilege(true);
- }
-
- @Test
- public void testGrantRevokePrivilegeWithLongOption() throws Exception {
- assertGrantRevokePrivilege(false);
- }
-
-
- @Test
- public void testNegativeCaseWithInvalidArgument() throws Exception {
- runTestAsSubject(new TestOperation() {
- @Override
- public void runTestAsSubject() throws Exception {
- client.createRole(requestorName, TEST_ROLE_NAME_1, SOLR);
- // test: create duplicate role with -cr
- String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "solr" };
- SentryShellGeneric sentryShell = new SentryShellGeneric();
- try {
- sentryShell.executeShell(args);
- fail("Exception should be thrown for creating duplicate role");
- } catch (SentryUserException e) {
- // expected exception
- }
-
- // test: drop non-exist role with -dr
- args = new String[] { "-dr", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath(), "-t", "solr" };
- sentryShell = new SentryShellGeneric();
- 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(), "-t", "solr" };
- sentryShell = new SentryShellGeneric();
- 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(), "-t", "solr" };
- sentryShell = new SentryShellGeneric();
- 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(), "-t", "solr" };
- sentryShell = new SentryShellGeneric();
- 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(), "-t", "solr" };
- sentryShell = new SentryShellGeneric();
- try {
- sentryShell.executeShell(args);
- fail("Exception should be thrown for the error privilege format, invalid key value.");
- } catch (IllegalArgumentException e) {
- // expected exception
- }
-
- // clear the test data
- client.dropRole(requestorName, TEST_ROLE_NAME_1, SOLR);
- }
- });
- }
-
- @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, SOLR);
- // test: the conf is required argument
- String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-t", "solr" };
- SentryShellGeneric sentryShell = new SentryShellGeneric();
- validateMissingParameterMsg(sentryShell, args,
- SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + strOptionConf);
-
- // test: -r is required when create role
- args = new String[] { "-cr", "-conf", confPath.getAbsolutePath(), "-t", "solr" };
- sentryShell = new SentryShellGeneric();
- 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(), "-t", "solr" };
- sentryShell = new SentryShellGeneric();
- 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(), "-t", "solr" };
- sentryShell = new SentryShellGeneric();
- 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(), "-t", "solr" };
- sentryShell = new SentryShellGeneric();
- 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(), "-t", "solr" };
- sentryShell = new SentryShellGeneric();
- 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(), "-t", "solr" };
- sentryShell = new SentryShellGeneric();
- 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(), "-t", "solr" };
- sentryShell = new SentryShellGeneric();
- 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(), "-t", "solr" };
- sentryShell = new SentryShellGeneric();
- validateMissingParameterMsg(sentryShell, args,
- SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_PRIVILEGE);
-
- // test: action is required in privilege
- args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-p", "collection=collection1", "-t", "solr" };
- sentryShell = new SentryShellGeneric();
- try {
- getShellResultWithOSRedirect(sentryShell, args, false);
- fail("Expected IllegalArgumentException");
- } catch (IllegalArgumentException e) {
- assertEquals("Privilege is invalid: action required but not specified.", e.getMessage());
- }
-
- // test: -r is required when revoke privilege from role
- args = new String[] { "-rpr", "-p", "server=server1", "-conf", confPath.getAbsolutePath(), "-t", "solr" };
- sentryShell = new SentryShellGeneric();
- 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(), "-t", "solr" };
- sentryShell = new SentryShellGeneric();
- 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 SentryShellGeneric();
- 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, SOLR);
- }
- });
- }
-
- // redirect the System.out to ByteArrayOutputStream, then execute the command and parse the result.
- private Set<String> getShellResultWithOSRedirect(SentryShellGeneric sentryShell,
- String[] args, boolean expectedExecuteResult) throws Exception {
- PrintStream oldOut = System.out;
- ByteArrayOutputStream outContent = new ByteArrayOutputStream();
- System.setOut(new PrintStream(outContent));
- assertEquals(expectedExecuteResult, 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(SentryShellGeneric sentryShell, String[] args,
- String expectedErrorMsg) throws Exception {
- Set<String> errorMsgs = getShellResultWithOSRedirect(sentryShell, args, false);
- assertTrue("Expected error message: " + expectedErrorMsg, errorMsgs.contains(expectedErrorMsg));
- }
-
- private void validateMissingParameterMsgsContains(SentryShellGeneric 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);
- }
-}
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryShellSqoop.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryShellSqoop.java b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryShellSqoop.java
deleted file mode 100644
index cdba442..0000000
--- a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryShellSqoop.java
+++ /dev/null
@@ -1,532 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.sentry.provider.db.generic.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.SentryUserException;
-import org.apache.sentry.provider.common.AuthorizationComponent;
-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.tools.SentryShellCommon;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.PrintStream;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-
-import static org.junit.Assert.*;
-
-public class TestSentryShellSqoop extends SentryGenericServiceIntegrationBase {
- 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 = "";
- private String service = "sqoopServer1";
-
- @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();//.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);
- }
-
- @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(), "-t", "sqoop" };
- SentryShellGeneric.main(args);
- // test: create role with --create_role
- args = new String[] { "--create_role", "-r", TEST_ROLE_NAME_2, "-conf",
- confPath.getAbsolutePath(), "-t", "sqoop" };
- SentryShellGeneric.main(args);
-
- // validate the result, list roles with -lr
- args = new String[] { "-lr", "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
- SentryShellGeneric sentryShell = new SentryShellGeneric();
- 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(), "-t", "sqoop" };
- sentryShell = new SentryShellGeneric();
- 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(), "-t", "sqoop" };
- SentryShellGeneric.main(args);
- // test: drop role with --drop_role
- args = new String[] { "--drop_role", "-r", TEST_ROLE_NAME_2, "-conf",
- confPath.getAbsolutePath(), "-t", "sqoop" };
- SentryShellGeneric.main(args);
-
- // validate the result
- Set<TSentryRole> roles = client.listAllRoles(requestorName, AuthorizationComponent.SQOOP);
- assertEquals("Incorrect number of roles", 0, roles.size());
- }
- });
- }
-
- @Test
- public void testAddDeleteRoleForGroup() throws Exception {
- runTestAsSubject(new TestOperation() {
- @Override
- public void runTestAsSubject() throws Exception {
- // Group names are case sensitive - mixed case names should work
- String TEST_GROUP_1 = "testGroup1";
- String TEST_GROUP_2 = "testGroup2";
- String TEST_GROUP_3 = "testGroup3";
-
- // create the role for test
- client.createRole(requestorName, TEST_ROLE_NAME_1, AuthorizationComponent.SQOOP);
- client.createRole(requestorName, TEST_ROLE_NAME_2, AuthorizationComponent.SQOOP);
- // test: add role to group with -arg
- String[] args = { "-arg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_1, "-conf",
- confPath.getAbsolutePath(), "-t", "sqoop" };
- SentryShellGeneric.main(args);
- // test: add role to multiple groups
- args = new String[] { "-arg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_2 + "," + TEST_GROUP_3,
- "-conf",
- confPath.getAbsolutePath(), "-t", "sqoop" };
- SentryShellGeneric.main(args);
- // test: add role to group with --add_role_group
- args = new String[] { "--add_role_group", "-r", TEST_ROLE_NAME_2, "-g", TEST_GROUP_1,
- "-conf",
- confPath.getAbsolutePath(), "-t", "sqoop" };
- SentryShellGeneric.main(args);
-
- // validate the result list roles with -lr and -g
- args = new String[] { "-lr", "-g", TEST_GROUP_1, "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
- SentryShellGeneric sentryShell = new SentryShellGeneric();
- 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", TEST_GROUP_2, "-conf",
- confPath.getAbsolutePath(), "-t", "sqoop" };
- sentryShell = new SentryShellGeneric();
- roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
- validateRoleNames(roleNames, TEST_ROLE_NAME_1);
-
- args = new String[] { "--list_role", "-g", TEST_GROUP_3, "-conf",
- confPath.getAbsolutePath(), "-t", "sqoop" };
- sentryShell = new SentryShellGeneric();
- 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(), "-t", "sqoop" };
- sentryShell = new SentryShellGeneric();
- 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", TEST_GROUP_1, "-conf",
- confPath.getAbsolutePath(), "-t", "sqoop" };
- SentryShellGeneric.main(args);
- // test: delete role to multiple groups
- args = new String[] { "-drg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_2 + "," + TEST_GROUP_3,
- "-conf",
- confPath.getAbsolutePath(), "-t", "sqoop" };
- SentryShellGeneric.main(args);
- // test: delete role from group with --delete_role_group
- args = new String[] { "--delete_role_group", "-r", TEST_ROLE_NAME_2, "-g", TEST_GROUP_1,
- "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
- SentryShellGeneric.main(args);
-
- // validate the result
- Set<TSentryRole> roles = client.listRolesByGroupName(requestorName, TEST_GROUP_1, AuthorizationComponent.SQOOP);
- assertEquals("Incorrect number of roles", 0, roles.size());
- roles = client.listRolesByGroupName(requestorName, TEST_GROUP_2, AuthorizationComponent.SQOOP);
- assertEquals("Incorrect number of roles", 0, roles.size());
- roles = client.listRolesByGroupName(requestorName, TEST_GROUP_3, AuthorizationComponent.SQOOP);
- assertEquals("Incorrect number of roles", 0, roles.size());
- // clear the test data
- client.dropRole(requestorName, TEST_ROLE_NAME_1, AuthorizationComponent.SQOOP);
- client.dropRole(requestorName, TEST_ROLE_NAME_2, AuthorizationComponent.SQOOP);
- }
- });
- }
-
- @Test
- public void testCaseSensitiveGroupName() throws Exception {
- runTestAsSubject(new TestOperation() {
- @Override
- public void runTestAsSubject() throws Exception {
-
- // create the role for test
- client.createRole(requestorName, TEST_ROLE_NAME_1, AuthorizationComponent.SQOOP);
- // add role to a group (lower case)
- String[] args = {"-arg", "-r", TEST_ROLE_NAME_1, "-g", "group1", "-conf",
- confPath.getAbsolutePath(), "-t", "sqoop"};
- SentryShellGeneric.main(args);
-
- // validate the roles when group name is same case as above
- args = new String[]{"-lr", "-g", "group1", "-conf", confPath.getAbsolutePath(), "-t", "sqoop"};
- SentryShellGeneric sentryShell = new SentryShellGeneric();
- Set<String> roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
- validateRoleNames(roleNames, TEST_ROLE_NAME_1);
-
- // roles should be empty when group name is different case than above
- args = new String[]{"-lr", "-g", "GROUP1", "-conf", confPath.getAbsolutePath(), "-t", "sqoop"};
- roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
- validateRoleNames(roleNames);
- }
- });
- }
-
- public static String grant(boolean shortOption) {
- return shortOption ? "-gpr" : "--grant_privilege_role";
- }
-
- public static String revoke(boolean shortOption) {
- return shortOption ? "-rpr" : "--revoke_privilege_role";
- }
-
- public static String list(boolean shortOption) {
- return shortOption ? "-lp" : "--list_privilege";
- }
-
- private void assertGrantRevokePrivilege(final boolean shortOption) throws Exception {
- runTestAsSubject(new TestOperation() {
- @Override
- public void runTestAsSubject() throws Exception {
- // create the role for test
- client.createRole(requestorName, TEST_ROLE_NAME_1, AuthorizationComponent.SQOOP);
- client.createRole(requestorName, TEST_ROLE_NAME_2, AuthorizationComponent.SQOOP);
-
- String [] privs = {
- "SERVER=sqoopserver1->CONNECTOR=c1->action=read",
- "SERVER=sqoopserver1->JOB=j1->action=write",
- "SERVER=sqoopserver1->LINK=l1->action=read",
- };
- for (int i = 0; i < privs.length; ++i) {
- // test: grant privilege to role
- String [] args = new String [] { grant(shortOption), "-r", TEST_ROLE_NAME_1, "-p",
- privs[ i ],
- "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
- SentryShellGeneric.main(args);
- }
-
- // test the list privilege
- String [] args = new String[] { list(shortOption), "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
- SentryShellGeneric sentryShell = new SentryShellGeneric();
- Set<String> privilegeStrs = getShellResultWithOSRedirect(sentryShell, args, true);
-
- assertEquals("Incorrect number of privileges", privs.length, privilegeStrs.size());
- for (int i = 0; i < privs.length; ++i) {
- assertTrue("Expected privilege: " + privs[i] + " in " + Arrays.toString(privilegeStrs.toArray()), privilegeStrs.contains(privs[i]));
- }
-
- for (int i = 0; i < privs.length; ++i) {
- args = new String[] { revoke(shortOption), "-r", TEST_ROLE_NAME_1, "-p",
- privs[ i ], "-conf",
- confPath.getAbsolutePath(), "-t", "sqoop" };
- SentryShellGeneric.main(args);
- Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(requestorName,
- TEST_ROLE_NAME_1, AuthorizationComponent.SQOOP, service);
- assertEquals("Incorrect number of privileges. Received privileges: " + Arrays.toString(privileges.toArray()), privs.length - (i + 1), privileges.size());
- }
-
- // clear the test data
- client.dropRole(requestorName, TEST_ROLE_NAME_1, AuthorizationComponent.SQOOP);
- client.dropRole(requestorName, TEST_ROLE_NAME_2, AuthorizationComponent.SQOOP);
- }
- });
- }
-
-
- @Test
- public void testGrantRevokePrivilegeWithShortOption() throws Exception {
- assertGrantRevokePrivilege(true);
- }
-
- @Test
- public void testGrantRevokePrivilegeWithLongOption() throws Exception {
- assertGrantRevokePrivilege(false);
- }
-
- @Test
- public void testNegativeCaseWithInvalidArgument() throws Exception {
- runTestAsSubject(new TestOperation() {
- @Override
- public void runTestAsSubject() throws Exception {
- client.createRole(requestorName, TEST_ROLE_NAME_1, AuthorizationComponent.SQOOP);
- // test: create duplicate role with -cr
- String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
- SentryShellGeneric sentryShell = new SentryShellGeneric();
- try {
- sentryShell.executeShell(args);
- fail("Exception should be thrown for creating duplicate role");
- } catch (SentryUserException e) {
- // expected exception
- } catch (Exception e) {
- fail ("Unexpected exception received. " + e);
- }
-
- // test: drop non-exist role with -dr
- args = new String[] { "-dr", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
- sentryShell = new SentryShellGeneric();
- try {
- sentryShell.executeShell(args);
- fail("Exception should be thrown for dropping non-exist role");
- } catch (SentryUserException e) {
- // excepted exception
- } catch (Exception e) {
- fail ("Unexpected exception received. " + e);
- }
-
- // test: add non-exist role to group with -arg
- args = new String[] { "-arg", "-r", TEST_ROLE_NAME_2, "-g", "testGroup1", "-conf",
- confPath.getAbsolutePath(), "-t", "sqoop" };
- sentryShell = new SentryShellGeneric();
- try {
- sentryShell.executeShell(args);
- fail("Exception should be thrown for granting non-exist role to group");
- } catch (SentryUserException e) {
- // excepted exception
- } catch (Exception e) {
- fail ("Unexpected exception received. " + e);
- }
-
- // test: drop group from non-exist role with -drg
- args = new String[] { "-drg", "-r", TEST_ROLE_NAME_2, "-g", "testGroup1", "-conf",
- confPath.getAbsolutePath(), "-t", "sqoop" };
- sentryShell = new SentryShellGeneric();
- try {
- sentryShell.executeShell(args);
- fail("Exception should be thrown for drop group from non-exist role");
- } catch (SentryUserException e) {
- // excepted exception
- } catch (Exception e) {
- fail ("Unexpected exception received. " + e);
- }
-
- // test: grant privilege to role with the error privilege format
- args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p", "serverserver1->action=all",
- "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
- sentryShell = new SentryShellGeneric();
- try {
- sentryShell.executeShell(args);
- fail("Exception should be thrown for the error privilege format, invalid key value.");
- } catch (IllegalArgumentException e) {
- // excepted exception
- } catch (Exception e) {
- fail ("Unexpected exception received. " + e);
- }
-
- // clear the test data
- client.dropRole(requestorName, TEST_ROLE_NAME_1, AuthorizationComponent.SQOOP);
- }
- });
- }
-
- @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, AuthorizationComponent.SQOOP);
- // test: the conf is required argument
- String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-t", "sqoop" };
- SentryShellGeneric sentryShell = new SentryShellGeneric();
- validateMissingParameterMsg(sentryShell, args,
- SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + strOptionConf);
-
- // test: -r is required when create role
- args = new String[] { "-cr", "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
- sentryShell = new SentryShellGeneric();
- 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(), "-t", "sqoop" };
- sentryShell = new SentryShellGeneric();
- 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(), "-t", "sqoop" };
- sentryShell = new SentryShellGeneric();
- 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(), "-t", "sqoop" };
- sentryShell = new SentryShellGeneric();
- 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(), "-t", "sqoop" };
- sentryShell = new SentryShellGeneric();
- 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(), "-t", "sqoop" };
- sentryShell = new SentryShellGeneric();
- 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(), "-t", "sqoop" };
- sentryShell = new SentryShellGeneric();
- 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(), "-t", "sqoop" };
- sentryShell = new SentryShellGeneric();
- validateMissingParameterMsg(sentryShell, args,
- SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_PRIVILEGE);
-
- // test: action is required in privilege
- args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-p", "Server=sqoopServer1->Connector", "-t", "sqoop" };
- sentryShell = new SentryShellGeneric();
- try {
- getShellResultWithOSRedirect(sentryShell, args, false);
- fail("Expected IllegalArgumentException");
- } catch (IllegalArgumentException e) {
- // expected
- } catch (Exception e) {
- fail ("Unexpected exception received. " + e);
- }
-
- // test: -r is required when revoke privilege from role
- args = new String[] { "-rpr", "-p", "Server=sqoopServer1->Connector->action=*", "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
- sentryShell = new SentryShellGeneric();
- 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(), "-t", "sqoop" };
- sentryShell = new SentryShellGeneric();
- 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(), "-t", "sqoop" };
- sentryShell = new SentryShellGeneric();
- 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, AuthorizationComponent.SQOOP);
- }
- });
- }
-
- // redirect the System.out to ByteArrayOutputStream, then execute the command and parse the result.
- private Set<String> getShellResultWithOSRedirect(SentryShellGeneric sentryShell,
- String[] args, boolean expectedExecuteResult) throws Exception {
- PrintStream oldOut = System.out;
- ByteArrayOutputStream outContent = new ByteArrayOutputStream();
- System.setOut(new PrintStream(outContent));
- assertEquals(expectedExecuteResult, 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(SentryShellGeneric sentryShell, String[] args,
- String expectedErrorMsg) throws Exception {
- Set<String> errorMsgs = getShellResultWithOSRedirect(sentryShell, args, false);
- assertTrue("Expected error message: " + expectedErrorMsg, errorMsgs.contains(expectedErrorMsg));
- }
-
- private void validateMissingParameterMsgsContains(SentryShellGeneric 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);
- }
-}
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/tools/TestSentrySchemaTool.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/tools/TestSentrySchemaTool.java b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/tools/TestSentrySchemaTool.java
deleted file mode 100644
index 68abf27..0000000
--- a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/tools/TestSentrySchemaTool.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/**
- * 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.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";
-
- @Before
- public void defaultSetup() throws Exception {
- 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("./src/main/resources", sentryConf,
- "derby");
- }
-
- private void nonDefaultsetup() throws Exception {
- 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("./src/main/resources", sentryConf,
- "derby");
- }
-
- @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-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/tools/TestSentryShellHive.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/tools/TestSentryShellHive.java b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/tools/TestSentryShellHive.java
deleted file mode 100644
index de8f043..0000000
--- a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/tools/TestSentryShellHive.java
+++ /dev/null
@@ -1,613 +0,0 @@
-/**
- * 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.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);
- }
-}
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/test/resources/indexer_case.ini
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/test/resources/indexer_case.ini b/sentry-provider/sentry-provider-db/src/test/resources/indexer_case.ini
deleted file mode 100644
index f1afe1f..0000000
--- a/sentry-provider/sentry-provider-db/src/test/resources/indexer_case.ini
+++ /dev/null
@@ -1,26 +0,0 @@
-# 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.
-
-[groups]
-groupa = RoLe1
-groupb = rOlE1
-groupc = ROLE2
-
-[roles]
-RoLe1 = indexer=*
-rOlE1 = indexer=*
-ROLE2 = indexer=*
[8/9] sentry git commit: SENTRY-2207 Refactor out Sentry CLI from
sentry-provider-db into own module. Steve Moist,
reviewed by Colm O hEigeartaigh.
Posted by co...@apache.org.
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/SentrySchemaHelper.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/SentrySchemaHelper.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/SentrySchemaHelper.java
deleted file mode 100644
index cf1c725..0000000
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/SentrySchemaHelper.java
+++ /dev/null
@@ -1,315 +0,0 @@
-/**
- * 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.tools;
-
-import java.util.IllegalFormatException;
-
-public final class SentrySchemaHelper {
- public static final String DB_DERBY = "derby";
- public static final String DB_MYSQL = "mysql";
- public static final String DB_POSTGRACE = "postgres";
- public static final String DB_ORACLE = "oracle";
- public static final String DB_DB2 = "db2";
-
- public interface NestedScriptParser {
-
- public enum CommandType {
- PARTIAL_STATEMENT,
- TERMINATED_STATEMENT,
- COMMENT
- }
-
- String DEFAUTL_DELIMITER = ";";
- /***
- * Find the type of given command
- * @param dbCommand
- * @return
- */
- boolean isPartialCommand(String dbCommand) throws IllegalArgumentException;
-
- /** Parse the DB specific nesting format and extract the inner script name if any
- * @param dbCommand command from parent script
- * @return
- * @throws IllegalFormatException
- */
- String getScriptName(String dbCommand) throws IllegalArgumentException;
-
- /***
- * Find if the given command is a nested script execution
- * @param dbCommand
- * @return
- */
- boolean isNestedScript(String dbCommand);
-
- /***
- * Find if the given command is should be passed to DB
- * @param dbCommand
- * @return
- */
- boolean isNonExecCommand(String dbCommand);
-
- /***
- * Get the SQL statement delimiter
- * @return
- */
- String getDelimiter();
-
- /***
- * Clear any client specific tags
- * @return
- */
- String cleanseCommand(String dbCommand);
-
- /***
- * Does the DB required table/column names quoted
- * @return
- */
- boolean needsQuotedIdentifier();
-
- /***
- * Set DB specific options if any
- * @param dbOps
- */
- void setDbOpts(String dbOps);
- }
-
-
- /***
- * Base implemenation of NestedScriptParser
- * abstractCommandParser.
- *
- */
- private static abstract class AbstractCommandParser implements NestedScriptParser {
- private String dbOpts = null;
-
- @Override
- public boolean isPartialCommand(String dbCommand) throws IllegalArgumentException{
- if (dbCommand == null || dbCommand.isEmpty()) {
- throw new IllegalArgumentException("invalid command line " + dbCommand);
- }
- String trimmedDbCommand = dbCommand.trim();
- return !(trimmedDbCommand.endsWith(getDelimiter()) || isNonExecCommand(trimmedDbCommand));
- }
-
- @Override
- public boolean isNonExecCommand(String dbCommand) {
- return dbCommand.startsWith("--") || dbCommand.startsWith("#");
- }
-
- @Override
- public String getDelimiter() {
- return DEFAUTL_DELIMITER;
- }
-
- @Override
- public String cleanseCommand(String dbCommand) {
- // strip off the delimiter
- if (dbCommand.endsWith(getDelimiter())) {
- dbCommand = dbCommand.substring(0,
- dbCommand.length() - getDelimiter().length());
- }
- return dbCommand;
- }
-
- @Override
- public boolean needsQuotedIdentifier() {
- return false;
- }
-
- @Override
- public void setDbOpts(String dbOpts) {
- this.dbOpts = dbOpts;
- }
-
- protected String getDbOpts() {
- return dbOpts;
- }
- }
-
-
- // Derby commandline parser
- public static class DerbyCommandParser extends AbstractCommandParser {
- private static final String DERBY_NESTING_TOKEN = "RUN";
-
- @Override
- public String getScriptName(String dbCommand) throws IllegalArgumentException {
-
- if (!isNestedScript(dbCommand)) {
- throw new IllegalArgumentException("Not a script format " + dbCommand);
- }
- String[] tokens = dbCommand.split(" ");
- if (tokens.length != 2) {
- throw new IllegalArgumentException("Couldn't parse line " + dbCommand);
- }
- return tokens[1].replace(";", "").replaceAll("'", "");
- }
-
- @Override
- public boolean isNestedScript(String dbCommand) {
- // Derby script format is RUN '<file>'
- return dbCommand.startsWith(DERBY_NESTING_TOKEN);
- }
- }
-
-
- // MySQL parser
- public static class MySqlCommandParser extends AbstractCommandParser {
- private static final String MYSQL_NESTING_TOKEN = "SOURCE";
- private static final String DELIMITER_TOKEN = "DELIMITER";
- private String delimiter = DEFAUTL_DELIMITER;
-
- @Override
- public boolean isPartialCommand(String dbCommand) throws IllegalArgumentException{
- boolean isPartial = super.isPartialCommand(dbCommand);
- // if this is a delimiter directive, reset our delimiter
- if (dbCommand.startsWith(DELIMITER_TOKEN)) {
- String[] tokens = dbCommand.split(" ");
- if (tokens.length != 2) {
- throw new IllegalArgumentException("Couldn't parse line " + dbCommand);
- }
- delimiter = tokens[1];
- }
- return isPartial;
- }
-
- @Override
- public String getScriptName(String dbCommand) throws IllegalArgumentException {
- String[] tokens = dbCommand.split(" ");
- if (tokens.length != 2) {
- throw new IllegalArgumentException("Couldn't parse line " + dbCommand);
- }
- // remove ending ';'
- return tokens[1].replace(";", "");
- }
-
- @Override
- public boolean isNestedScript(String dbCommand) {
- return dbCommand.startsWith(MYSQL_NESTING_TOKEN);
- }
-
- @Override
- public String getDelimiter() {
- return delimiter;
- }
-
- @Override
- public boolean isNonExecCommand(String dbCommand) {
- return super.isNonExecCommand(dbCommand) ||
- dbCommand.startsWith("/*") && dbCommand.endsWith("*/") ||
- dbCommand.startsWith(DELIMITER_TOKEN);
- }
-
- @Override
- public String cleanseCommand(String dbCommand) {
- return super.cleanseCommand(dbCommand).replaceAll("/\\*.*?\\*/[^;]", "");
- }
-
- }
-
- // Postgres specific parser
- public static class PostgresCommandParser extends AbstractCommandParser {
- public static final String POSTGRES_STRING_COMMAND_FILTER = "SET standard_conforming_strings";
- public static final String POSTGRES_STRING_CLIENT_ENCODING = "SET client_encoding";
- public static final String POSTGRES_SKIP_STANDARD_STRING = "postgres.filter.81";
- private static final String POSTGRES_NESTING_TOKEN = "\\i";
-
- @Override
- public String getScriptName(String dbCommand) throws IllegalArgumentException {
- String[] tokens = dbCommand.split(" ");
- if (tokens.length != 2) {
- throw new IllegalArgumentException("Couldn't parse line " + dbCommand);
- }
- // remove ending ';'
- return tokens[1].replace(";", "");
- }
-
- @Override
- public boolean isNestedScript(String dbCommand) {
- return dbCommand.startsWith(POSTGRES_NESTING_TOKEN);
- }
-
- @Override
- public boolean needsQuotedIdentifier() {
- return true;
- }
-
- @Override
- public boolean isNonExecCommand(String dbCommand) {
- // Skip "standard_conforming_strings" command which is not supported in older postgres
- if (POSTGRES_SKIP_STANDARD_STRING.equalsIgnoreCase(getDbOpts())
- && (dbCommand.startsWith(POSTGRES_STRING_COMMAND_FILTER) || dbCommand.startsWith(POSTGRES_STRING_CLIENT_ENCODING))) {
- return true;
- }
- return super.isNonExecCommand(dbCommand);
- }
- }
-
- //Oracle specific parser
- public static class OracleCommandParser extends AbstractCommandParser {
- private static final String ORACLE_NESTING_TOKEN = "@";
- @Override
- public String getScriptName(String dbCommand) throws IllegalArgumentException {
- if (!isNestedScript(dbCommand)) {
- throw new IllegalArgumentException("Not a nested script format " + dbCommand);
- }
- // remove ending ';' and starting '@'
- return dbCommand.replace(";", "").replace(ORACLE_NESTING_TOKEN, "");
- }
-
- @Override
- public boolean isNestedScript(String dbCommand) {
- return dbCommand.startsWith(ORACLE_NESTING_TOKEN);
- }
- }
-
- // DB2 commandline parser
- public static class DB2CommandParser extends AbstractCommandParser {
-
- @Override
- public String getScriptName(String dbCommand) throws IllegalArgumentException {
- //DB2 does not support nesting script
- throw new IllegalArgumentException("DB2 does not support nesting script " + dbCommand);
- }
-
- @Override
- public boolean isNestedScript(String dbCommand) {
- //DB2 does not support nesting script
- return false;
- }
- }
-
- public static NestedScriptParser getDbCommandParser(String dbName) {
- if (dbName.equalsIgnoreCase(DB_DERBY)) {
- return new DerbyCommandParser();
- } else if (dbName.equalsIgnoreCase(DB_MYSQL)) {
- return new MySqlCommandParser();
- } else if (dbName.equalsIgnoreCase(DB_POSTGRACE)) {
- return new PostgresCommandParser();
- } else if (dbName.equalsIgnoreCase(DB_ORACLE)) {
- return new OracleCommandParser();
- } else if (dbName.equalsIgnoreCase(DB_DB2)) {
- return new DB2CommandParser();
- } else {
- throw new IllegalArgumentException("Unknown dbType " + dbName);
- }
- }
-
- private SentrySchemaHelper() {
- // Make constructor private to avoid instantiation
- }
-}
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/SentrySchemaTool.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/SentrySchemaTool.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/SentrySchemaTool.java
deleted file mode 100644
index d75e24b..0000000
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/SentrySchemaTool.java
+++ /dev/null
@@ -1,595 +0,0 @@
-/**
- * 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.tools;
-
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.PrintStream;
-import java.net.MalformedURLException;
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.ArrayList;
-import java.util.IllegalFormatException;
-import java.util.List;
-
-import org.apache.commons.cli.CommandLine;
-import org.apache.commons.cli.CommandLineParser;
-import org.apache.commons.cli.GnuParser;
-import org.apache.commons.cli.HelpFormatter;
-import org.apache.commons.cli.Option;
-import org.apache.commons.cli.OptionBuilder;
-import org.apache.commons.cli.OptionGroup;
-import org.apache.commons.cli.Options;
-import org.apache.commons.cli.ParseException;
-import org.apache.commons.io.output.NullOutputStream;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hive.beeline.BeeLine;
-import org.apache.sentry.Command;
-import org.apache.sentry.core.common.exception.SentryUserException;
-import org.apache.sentry.core.common.exception.SentrySiteConfigurationException;
-import org.apache.sentry.provider.db.service.persistent.SentryStoreSchemaInfo;
-import org.apache.sentry.provider.db.tools.SentrySchemaHelper.NestedScriptParser;
-import org.apache.sentry.service.thrift.SentryService;
-import org.apache.sentry.service.thrift.ServiceConstants;
-
-public class SentrySchemaTool {
- private static final String SENTRY_SCRIP_DIR = File.separatorChar + "scripts"
- + File.separatorChar + "sentrystore" + File.separatorChar + "upgrade";
- private String userName = null;
- private String passWord = null;
- private String connectionURL = null;
- private String driver = null;
- private boolean dryRun = false;
- private String dbOpts = null;
- private boolean verbose = false;
- private final Configuration sentryConf;
- private final String dbType;
- private final SentryStoreSchemaInfo sentryStoreSchemaInfo;
-
- public SentrySchemaTool(Configuration sentryConf, String dbType)
- throws SentryUserException, IOException {
- this(System.getenv("SENTRY_HOME") + SENTRY_SCRIP_DIR, sentryConf, dbType);
- }
-
- public SentrySchemaTool(String sentryScripPath, Configuration sentryConf,
- String dbType) throws SentryUserException, IOException {
- if (sentryScripPath == null || sentryScripPath.isEmpty()) {
- throw new SentryUserException("No Sentry script dir provided");
- }
- this.sentryConf = sentryConf;
- this.dbType = dbType;
- this.sentryStoreSchemaInfo = new SentryStoreSchemaInfo(sentryScripPath,
- dbType);
- userName = sentryConf.get(ServiceConstants.ServerConfig.SENTRY_STORE_JDBC_USER,
- ServiceConstants.ServerConfig.SENTRY_STORE_JDBC_USER_DEFAULT);
- //Password will be read from Credential provider specified using property
- // CREDENTIAL_PROVIDER_PATH("hadoop.security.credential.provider.path" in sentry-site.xml
- // it falls back to reading directly from sentry-site.xml
- char[] passTmp = sentryConf.getPassword(ServiceConstants.ServerConfig.SENTRY_STORE_JDBC_PASS);
- if(passTmp != null) {
- passWord = new String(passTmp);
- } else {
- throw new SentrySiteConfigurationException("Error reading " + ServiceConstants.ServerConfig.SENTRY_STORE_JDBC_PASS);
- }
-
- try {
- connectionURL = getValidConfVar(ServiceConstants.ServerConfig.SENTRY_STORE_JDBC_URL);
- if(dbType.equalsIgnoreCase(SentrySchemaHelper.DB_DERBY)) {
- driver = sentryConf.get(ServiceConstants.ServerConfig.SENTRY_STORE_JDBC_DRIVER,
- ServiceConstants.ServerConfig.SENTRY_STORE_JDBC_DRIVER_DEFAULT);
- } else {
- driver = getValidConfVar(ServiceConstants.ServerConfig.SENTRY_STORE_JDBC_DRIVER);
- }
- // load required JDBC driver
- Class.forName(driver);
- } catch (IOException e) {
- throw new SentryUserException("Missing property: " + e.getMessage());
- } catch (ClassNotFoundException e) {
- throw new SentryUserException("Failed to load driver", e);
- }
- }
-
- public Configuration getConfiguration() {
- return sentryConf;
- }
-
- public void setUserName(String userName) {
- this.userName = userName;
- }
-
- public void setPassWord(String passWord) {
- this.passWord = passWord;
- }
-
- public void setDryRun(boolean dryRun) {
- this.dryRun = dryRun;
- }
-
- public void setVerbose(boolean verbose) {
- this.verbose = verbose;
- }
-
- public String getDbOpts() {
- return dbOpts;
- }
-
- public void setDbOpts(String dbOpts) {
- this.dbOpts = dbOpts;
- }
-
- private static void printAndExit(Options cmdLineOptions) {
- HelpFormatter formatter = new HelpFormatter();
- formatter.printHelp("schemaTool", cmdLineOptions);
- System.exit(1);
- }
-
- /***
- * Print Hive version and schema version
- * @throws SentryUserException
- */
- public void showInfo() throws SentryUserException {
- Connection sentryStoreConn = getConnectionToMetastore(true);
- System.out.println("Sentry distribution version:\t "
- + SentryStoreSchemaInfo.getSentryVersion());
- System.out.println("SentryStore schema version:\t "
- + getMetaStoreSchemaVersion(sentryStoreConn));
- }
-
- // read schema version from sentry store
- private String getMetaStoreSchemaVersion(Connection sentryStoreConn)
- throws SentryUserException {
- String versionQuery;
- if (SentrySchemaHelper.getDbCommandParser(dbType).needsQuotedIdentifier()) {
- versionQuery = "select t.\"SCHEMA_VERSION\" from \"SENTRY_VERSION\" t";
- } else {
- versionQuery = "select t.SCHEMA_VERSION from SENTRY_VERSION t";
- }
- try (Statement stmt = sentryStoreConn.createStatement();
- ResultSet res = stmt.executeQuery(versionQuery)) {
- if (!res.next()) {
- throw new SentryUserException("Didn't find version data in sentry store");
- }
- String currentSchemaVersion = res.getString(1);
- sentryStoreConn.close();
- return currentSchemaVersion;
- } catch (SQLException e) {
- throw new SentryUserException("Failed to get schema version.", e);
- }
- }
-
- // test the connection sentry store using the config property
- private void testConnectionToMetastore() throws SentryUserException {
- try (Connection conn = getConnectionToMetastore(true)) {
- conn.close();
- } catch (SQLException e) {
- throw new SentryUserException("Failed to close sentry store connection", e);
- }
- }
-
- /***
- * get JDBC connection to sentry store db
- *
- * @param printInfo print connection parameters
- * @return
- * @throws SentryUserException
- */
- private Connection getConnectionToMetastore(boolean printInfo)
- throws SentryUserException {
- if (printInfo) {
- System.out.println("Sentry store connection URL:\t " + connectionURL);
- System.out.println("Sentry store Connection Driver :\t " + driver);
- System.out.println("Sentry store connection User:\t " + userName);
- }
- if (userName == null || userName.isEmpty()) {
- throw new SentryUserException("UserName empty ");
- }
- try {
- // Connect using the JDBC URL and user/pass from conf
- return DriverManager.getConnection(connectionURL, userName, passWord);
- } catch (SQLException e) {
- throw new SentryUserException("Failed to make connection to Sentry store.", e);
- }
- }
-
- /**
- * check if the current schema version in sentry store matches the Hive version
- * @throws SentryUserException
- */
- public void verifySchemaVersion() throws SentryUserException {
- // don't check version if its a dry run
- if (dryRun) {
- return;
- }
- String newSchemaVersion =
- getMetaStoreSchemaVersion(getConnectionToMetastore(false));
- // verify that the new version is added to schema
- if (!sentryStoreSchemaInfo.getSentrySchemaVersion().equalsIgnoreCase(
- newSchemaVersion)) {
- throw new SentryUserException("Found unexpected schema version "
- + newSchemaVersion);
- }
- }
-
- /**
- * Perform sentry store schema upgrade. extract the current schema version from sentry store
- * @throws SentryUserException
- */
- public void doUpgrade() throws SentryUserException {
- String fromVersion = getMetaStoreSchemaVersion(getConnectionToMetastore(false));
- if (fromVersion == null || fromVersion.isEmpty()) {
- throw new SentryUserException(
- "Schema version not stored in the sentry store. "
- +
- "Metastore schema is too old or corrupt. Try specifying the version manually");
- }
- doUpgrade(fromVersion);
- }
-
- /**
- * Perform sentry store schema upgrade
- *
- * @param fromSchemaVer
- * Existing version of the sentry store. If null, then read from the sentry store
- * @throws SentryUserException
- */
- public void doUpgrade(String fromSchemaVer) throws SentryUserException {
- if (sentryStoreSchemaInfo.getSentrySchemaVersion().equals(fromSchemaVer)) {
- System.out.println("No schema upgrade required from version " + fromSchemaVer);
- return;
- }
- // Find the list of scripts to execute for this upgrade
- List<String> upgradeScripts =
- sentryStoreSchemaInfo.getUpgradeScripts(fromSchemaVer);
- testConnectionToMetastore();
- System.out.println("Starting upgrade sentry store schema from version " +
- fromSchemaVer + " to "
- + sentryStoreSchemaInfo.getSentrySchemaVersion());
- String scriptDir = sentryStoreSchemaInfo.getSentryStoreScriptDir();
- try {
- for (String scriptFile : upgradeScripts) {
- System.out.println("Upgrade script " + scriptFile);
- if (!dryRun) {
- runBeeLine(scriptDir, scriptFile);
- System.out.println("Completed " + scriptFile);
- }
- }
- } catch (IOException eIO) {
- throw new SentryUserException(
- "Upgrade FAILED! Metastore state would be inconsistent !!", eIO);
- }
-
- // Revalidated the new version after upgrade
- verifySchemaVersion();
- }
-
- /**
- * Initialize the sentry store schema to current version
- *
- * @throws SentryUserException
- */
- public void doInit() throws SentryUserException {
- doInit(sentryStoreSchemaInfo.getSentrySchemaVersion());
-
- // Revalidated the new version after upgrade
- verifySchemaVersion();
- }
-
- /**
- * Initialize the sentry store schema
- *
- * @param toVersion
- * If null then current hive version is used
- * @throws SentryUserException
- */
- public void doInit(String toVersion) throws SentryUserException {
- testConnectionToMetastore();
- System.out.println("Starting sentry store schema initialization to " + toVersion);
-
- String initScriptDir = sentryStoreSchemaInfo.getSentryStoreScriptDir();
- String initScriptFile = sentryStoreSchemaInfo.generateInitFileName(toVersion);
-
- try {
- System.out.println("Initialization script " + initScriptFile);
- if (!dryRun) {
- runBeeLine(initScriptDir, initScriptFile);
- System.out.println("Initialization script completed");
- }
- } catch (IOException e) {
- throw new SentryUserException("Schema initialization FAILED!"
- + " Metastore state would be inconsistent !!", e);
- }
- }
-
- // Flatten the nested upgrade script into a buffer
- public static String buildCommand(NestedScriptParser dbCommandParser,
- String scriptDir, String scriptFile) throws IllegalFormatException, IOException {
-
- BufferedReader bfReader =
- new BufferedReader(new FileReader(scriptDir + File.separatorChar + scriptFile));
- String currLine;
- StringBuilder sb = new StringBuilder();
- String currentCommand = null;
- while ((currLine = bfReader.readLine()) != null) {
- currLine = currLine.trim();
- if (currLine.isEmpty()) {
- continue; // skip empty lines
- }
-
- if (currentCommand == null) {
- currentCommand = currLine;
- } else {
- currentCommand = currentCommand + " " + currLine;
- }
- if (dbCommandParser.isPartialCommand(currLine)) {
- // if its a partial line, continue collecting the pieces
- continue;
- }
-
- // if this is a valid executable command then add it to the buffer
- if (!dbCommandParser.isNonExecCommand(currentCommand)) {
- currentCommand = dbCommandParser.cleanseCommand(currentCommand);
-
- if (dbCommandParser.isNestedScript(currentCommand)) {
- // if this is a nested sql script then flatten it
- String currScript = dbCommandParser.getScriptName(currentCommand);
- sb.append(buildCommand(dbCommandParser, scriptDir, currScript));
- } else {
- // Now we have a complete statement, process it
- // write the line to buffer
- sb.append(currentCommand);
- sb.append(System.getProperty("line.separator"));
- }
- }
- currentCommand = null;
- }
- bfReader.close();
- return sb.toString();
- }
-
- // run beeline on the given sentry store scrip, flatten the nested scripts into single file
- private void runBeeLine(String scriptDir, String scriptFile) throws IOException {
- NestedScriptParser dbCommandParser =
- SentrySchemaHelper.getDbCommandParser(dbType);
- dbCommandParser.setDbOpts(getDbOpts());
- // expand the nested script
- String sqlCommands = buildCommand(dbCommandParser, scriptDir, scriptFile);
- File tmpFile = File.createTempFile("schematool", ".sql");
- tmpFile.deleteOnExit();
-
- // write out the buffer into a file. Add beeline commands for autocommit and close
- try (FileWriter fstream = new FileWriter(tmpFile.getPath());
- BufferedWriter out = new BufferedWriter(fstream)) {
-
- out.write("!set Silent " + verbose + System.getProperty("line.separator"));
- out.write("!autocommit on" + System.getProperty("line.separator"));
- out.write("!set Isolation TRANSACTION_READ_COMMITTED"
- + System.getProperty("line.separator"));
- out.write("!set AllowMultiLineCommand false"
- + System.getProperty("line.separator"));
- out.write(sqlCommands);
- out.write("!closeall" + System.getProperty("line.separator"));
- out.close();
- }
- runBeeLine(tmpFile.getPath());
- }
-
- // Generate the beeline args per hive conf and execute the given script
- public void runBeeLine(String sqlScriptFile) throws IOException {
- List<String> argList = new ArrayList<String>();
- argList.add("-u");
- argList.add(connectionURL);
- argList.add("-d");
- argList
- .add(driver);
- argList.add("-n");
- argList.add(userName);
- argList.add("-p");
- argList.add(passWord);
- argList.add("-f");
- argList.add(sqlScriptFile);
-
- BeeLine beeLine = new BeeLine();
- if (!verbose) {
- beeLine.setOutputStream(new PrintStream(new NullOutputStream()));
- // beeLine.getOpts().setSilent(true);
- }
- // beeLine.getOpts().setAllowMultiLineCommand(false);
- // beeLine.getOpts().setIsolation("TRANSACTION_READ_COMMITTED");
- int status = beeLine.begin(argList.toArray(new String[0]), null);
- if (status != 0) {
- throw new IOException("Schema script failed, errorcode " + status);
- }
- }
-
- private String getValidConfVar(String confVar) throws IOException {
- String confVarKey = confVar;
- String confVarValue = sentryConf.get(confVarKey);
- if (confVarValue == null || confVarValue.isEmpty()) {
- throw new IOException("Empty " + confVar);
- }
- return confVarValue;
- }
-
- // Create the required command line options
- @SuppressWarnings("static-access")
- private static void initOptions(Options cmdLineOptions) {
- Option help = new Option("help", "print this message");
- Option upgradeOpt = new Option("upgradeSchema", "Schema upgrade");
- Option upgradeFromOpt = OptionBuilder.withArgName("upgradeFrom").hasArg().
- withDescription("Schema upgrade from a version").
- create("upgradeSchemaFrom");
- Option initOpt = new Option("initSchema", "Schema initialization");
- Option initToOpt = OptionBuilder.withArgName("initTo").hasArg().
- withDescription("Schema initialization to a version").
- create("initSchemaTo");
- Option infoOpt = new Option("info", "Show config and schema details");
-
- OptionGroup optGroup = new OptionGroup();
- optGroup.addOption(upgradeOpt).addOption(initOpt).
- addOption(help).addOption(upgradeFromOpt).
- addOption(initToOpt).addOption(infoOpt);
- optGroup.setRequired(true);
-
- Option userNameOpt = OptionBuilder.withArgName("user")
- .hasArg()
- .withDescription("Override config file user name")
- .create("userName");
- Option passwdOpt = OptionBuilder.withArgName("password")
- .hasArg()
- .withDescription("Override config file password")
- .create("passWord");
- Option dbTypeOpt = OptionBuilder.withArgName("databaseType")
- .hasArg().withDescription("Metastore database type [" +
- SentrySchemaHelper.DB_DERBY + "," +
- SentrySchemaHelper.DB_MYSQL + "," +
- SentrySchemaHelper.DB_ORACLE + "," +
- SentrySchemaHelper.DB_POSTGRACE + "," +
- SentrySchemaHelper.DB_DB2 + "]")
- .create("dbType");
- Option dbOpts = OptionBuilder.withArgName("databaseOpts")
- .hasArgs().withDescription("Backend DB specific options")
- .create("dbOpts");
-
- Option dryRunOpt = new Option("dryRun", "list SQL scripts (no execute)");
- Option verboseOpt = new Option("verbose", "only print SQL statements");
-
- Option configOpt = OptionBuilder.withArgName("confName").hasArgs()
- .withDescription("Sentry Service configuration file").isRequired(true)
- .create(ServiceConstants.ServiceArgs.CONFIG_FILE_LONG);
-
- cmdLineOptions.addOption(help);
- cmdLineOptions.addOption(dryRunOpt);
- cmdLineOptions.addOption(userNameOpt);
- cmdLineOptions.addOption(passwdOpt);
- cmdLineOptions.addOption(dbTypeOpt);
- cmdLineOptions.addOption(verboseOpt);
- cmdLineOptions.addOption(dbOpts);
- cmdLineOptions.addOption(configOpt);
- cmdLineOptions.addOptionGroup(optGroup);
- }
-
- public static class CommandImpl implements Command {
- @Override
- public void run(String[] args) throws Exception {
- CommandLineParser parser = new GnuParser();
- CommandLine line = null;
- String dbType = null;
- String schemaVer = null;
- Options cmdLineOptions = new Options();
- String configFileName = null;
-
- // Argument handling
- initOptions(cmdLineOptions);
- try {
- line = parser.parse(cmdLineOptions, args);
- } catch (ParseException e) {
- System.err.println("SentrySchemaTool:Parsing failed. Reason: "
- + e.getLocalizedMessage());
- printAndExit(cmdLineOptions);
- }
-
- if (line.hasOption("help")) {
- HelpFormatter formatter = new HelpFormatter();
- formatter.printHelp("schemaTool", cmdLineOptions);
- return;
- }
-
- if (line.hasOption("dbType")) {
- dbType = line.getOptionValue("dbType");
- if (!dbType.equalsIgnoreCase(SentrySchemaHelper.DB_DERBY)
- && !dbType.equalsIgnoreCase(SentrySchemaHelper.DB_MYSQL)
- && !dbType.equalsIgnoreCase(SentrySchemaHelper.DB_POSTGRACE)
- && !dbType.equalsIgnoreCase(SentrySchemaHelper.DB_ORACLE)
- && !dbType.equalsIgnoreCase(SentrySchemaHelper.DB_DB2)) {
- System.err.println("Unsupported dbType " + dbType);
- printAndExit(cmdLineOptions);
- }
- } else {
- System.err.println("no dbType supplied");
- printAndExit(cmdLineOptions);
- }
- if (line.hasOption(ServiceConstants.ServiceArgs.CONFIG_FILE_LONG)) {
- configFileName = line
- .getOptionValue(ServiceConstants.ServiceArgs.CONFIG_FILE_LONG);
- } else {
- System.err.println("no config file specified");
- printAndExit(cmdLineOptions);
- }
- try {
- SentrySchemaTool schemaTool = new SentrySchemaTool(
- SentryService.loadConfig(configFileName), dbType);
-
- if (line.hasOption("userName")) {
- schemaTool.setUserName(line.getOptionValue("userName"));
- }
- if (line.hasOption("passWord")) {
- schemaTool.setPassWord(line.getOptionValue("passWord"));
- }
- if (line.hasOption("dryRun")) {
- schemaTool.setDryRun(true);
- }
- if (line.hasOption("verbose")) {
- schemaTool.setVerbose(true);
- }
- if (line.hasOption("dbOpts")) {
- schemaTool.setDbOpts(line.getOptionValue("dbOpts"));
- }
-
- if (line.hasOption("info")) {
- schemaTool.showInfo();
- } else if (line.hasOption("upgradeSchema")) {
- schemaTool.doUpgrade();
- } else if (line.hasOption("upgradeSchemaFrom")) {
- schemaVer = line.getOptionValue("upgradeSchemaFrom");
- schemaTool.doUpgrade(schemaVer);
- } else if (line.hasOption("initSchema")) {
- schemaTool.doInit();
- } else if (line.hasOption("initSchemaTo")) {
- schemaVer = line.getOptionValue("initSchemaTo");
- schemaTool.doInit(schemaVer);
- } else {
- System.err.println("no valid option supplied");
- printAndExit(cmdLineOptions);
- }
- } catch (SentryUserException e) {
- System.err.println(e);
- if (line.hasOption("verbose")) {
- e.printStackTrace();
- }
- System.err.println("*** Sentry schemaTool failed ***");
- System.exit(1);
- } catch (MalformedURLException e) {
- System.err.println(e);
- if (line.hasOption("verbose")) {
- e.printStackTrace();
- }
- System.err.println("*** Sentry schemaTool failed ***");
- System.exit(1);
- }
- System.out.println("Sentry schemaTool completed");
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/SentryShellCommon.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/SentryShellCommon.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/SentryShellCommon.java
deleted file mode 100644
index c8b2eef..0000000
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/SentryShellCommon.java
+++ /dev/null
@@ -1,284 +0,0 @@
-/**
- * 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.tools;
-
-import com.google.common.annotations.VisibleForTesting;
-
-import org.apache.commons.cli.CommandLine;
-import org.apache.commons.cli.GnuParser;
-import org.apache.commons.cli.HelpFormatter;
-import org.apache.commons.cli.Option;
-import org.apache.commons.cli.OptionGroup;
-import org.apache.commons.cli.Options;
-import org.apache.commons.cli.ParseException;
-import org.apache.commons.cli.Parser;
-import org.apache.commons.lang.StringUtils;
-
-/**
- * SentryShellCommon provides the function for parsing the argument.
- * For hive model and generic model, child class should be implemented as a sentry admin tool.
- */
-abstract public class SentryShellCommon {
-
- public enum TYPE { kafka, hive, solr, sqoop };
-
- public static final String OPTION_DESC_HELP = "Shell usage";
- public static final String OPTION_DESC_CONF = "sentry-site file path";
- public static final String OPTION_DESC_ROLE_NAME = "Role name";
- public static final String OPTION_DESC_GROUP_NAME = "Group name";
- public static final String OPTION_DESC_PRIVILEGE = "Privilege string";
- public final static String OPTION_DESC_SERVICE = "Name of the service being managed";
- public static final String PREFIX_MESSAGE_MISSING_OPTION = "Missing required option: ";
-
- public static final String GROUP_SPLIT_CHAR = ",";
-
- protected String roleName;
- protected String serviceName;
- protected String groupName;
- protected String privilegeStr;
- protected String confPath;
- // flag for the command
- protected boolean isCreateRole;
- protected boolean isDropRole;
- protected boolean isAddRoleGroup;
- protected boolean isDeleteRoleGroup;
- protected boolean isGrantPrivilegeRole;
- protected boolean isRevokePrivilegeRole;
- protected boolean isListRole;
- protected boolean isListPrivilege;
- protected boolean isListGroup;
- protected boolean isPrintHelp;
- // flag for the parameter check
- protected boolean roleNameRequired;
- protected boolean groupNameRequired;
- protected boolean privilegeStrRequired;
- protected TYPE type;
-
- /**
- * parse arguments
- *
- * <pre>
- * -conf,--sentry_conf <filepath> sentry config file path
- * -cr,--create_role -r <rolename> create role
- * -dr,--drop_role -r <rolename> drop role
- * -arg,--add_role_group -r <rolename> -g <groupname> add role to group
- * -drg,--delete_role_group -r <rolename> -g <groupname> delete role from group
- * -gpr,--grant_privilege_role -r <rolename> -p <privilege> grant privilege to role
- * -rpr,--revoke_privilege_role -r <rolename> -p <privilege> revoke privilege from role
- * -lr,--list_role -g <groupname> list roles for group
- * -lp,--list_privilege -r <rolename> list privilege for role
- * -lg,--list_group list all groups associated with all roles
- * -t,--type <typename> the shell for hive model or generic model
- * </pre>
- *
- * @param args
- */
- protected boolean parseArgs(String[] args) {
- Options simpleShellOptions = new Options();
-
- setupOptions(simpleShellOptions);
-
-
-
- // help option
- Option helpOpt = new Option("h", "help", false, OPTION_DESC_HELP);
- helpOpt.setRequired(false);
- simpleShellOptions.addOption(helpOpt);
-
- // this Options is parsed first for help option
- Options helpOptions = new Options();
- helpOptions.addOption(helpOpt);
-
- try {
- Parser parser = new GnuParser();
-
- // parse help option first
- CommandLine cmd = parser.parse(helpOptions, args, true);
- for (Option opt : cmd.getOptions()) {
- if (opt.getOpt().equals("h")) {
- // get the help option, print the usage and exit
- usage(simpleShellOptions);
- return false;
- }
- }
-
- // without help option
- cmd = parser.parse(simpleShellOptions, args);
-
- parseOptions(cmd);
- } catch (ParseException pe) {
- System.out.println(pe.getMessage());
- usage(simpleShellOptions);
- return false;
- }
- return true;
- }
-
- protected void setupOptions(Options simpleShellOptions) {
- OptionGroup simpleShellOptGroup = getMainOptions();
- simpleShellOptions.addOptionGroup(simpleShellOptGroup);
-
- Option sOpt = new Option("s", "service", true, OPTION_DESC_SERVICE);
- sOpt.setRequired(false);
- simpleShellOptions.addOption(sOpt);
-
- // optional args
- Option pOpt = new Option("p", "privilege", true, OPTION_DESC_PRIVILEGE);
- pOpt.setRequired(false);
- simpleShellOptions.addOption(pOpt);
-
- Option gOpt = new Option("g", "groupname", true, OPTION_DESC_GROUP_NAME);
- gOpt.setRequired(false);
- simpleShellOptions.addOption(gOpt);
-
- Option rOpt = new Option("r", "rolename", true, OPTION_DESC_ROLE_NAME);
- rOpt.setRequired(false);
- simpleShellOptions.addOption(rOpt);
-
- // this argument should also be parsed in the bin/sentryShell
- Option tOpt = new Option("t", "type", true, "[hive|solr|sqoop|.....]");
- tOpt.setRequired(false);
- simpleShellOptions.addOption(tOpt);
-
- // file path of sentry-site
- Option sentrySitePathOpt = new Option("conf", "sentry_conf", true, OPTION_DESC_CONF);
- sentrySitePathOpt.setRequired(true);
- simpleShellOptions.addOption(sentrySitePathOpt);
- }
-
- protected OptionGroup getMainOptions() {
- OptionGroup simpleShellOptGroup = new OptionGroup();
- Option crOpt = new Option("cr", "create_role", false, "Create role");
- crOpt.setRequired(false);
-
- Option drOpt = new Option("dr", "drop_role", false, "Drop role");
- drOpt.setRequired(false);
-
- Option argOpt = new Option("arg", "add_role_group", false, "Add role to group");
- argOpt.setRequired(false);
-
- Option drgOpt = new Option("drg", "delete_role_group", false, "Delete role from group");
- drgOpt.setRequired(false);
-
- Option gprOpt = new Option("gpr", "grant_privilege_role", false, "Grant privilege to role");
- gprOpt.setRequired(false);
-
- Option rprOpt = new Option("rpr", "revoke_privilege_role", false, "Revoke privilege from role");
- rprOpt.setRequired(false);
-
- Option lrOpt = new Option("lr", "list_role", false, "List role");
- lrOpt.setRequired(false);
-
- Option lpOpt = new Option("lp", "list_privilege", false, "List privilege");
- lpOpt.setRequired(false);
-
- Option lgOpt = new Option("lg", "list_group", false, "List groups");
- lgOpt.setRequired(false);
-
-
- // required args group
- simpleShellOptGroup.addOption(crOpt);
- simpleShellOptGroup.addOption(drOpt);
- simpleShellOptGroup.addOption(argOpt);
- simpleShellOptGroup.addOption(drgOpt);
- simpleShellOptGroup.addOption(gprOpt);
- simpleShellOptGroup.addOption(rprOpt);
- simpleShellOptGroup.addOption(lrOpt);
- simpleShellOptGroup.addOption(lpOpt);
- simpleShellOptGroup.addOption(lgOpt);
- simpleShellOptGroup.setRequired(true);
- return simpleShellOptGroup;
- }
-
- protected void parseOptions(CommandLine cmd) throws ParseException {
- for (Option opt : cmd.getOptions()) {
- if (opt.getOpt().equals("p")) {
- privilegeStr = opt.getValue();
- } else if (opt.getOpt().equals("g")) {
- groupName = opt.getValue();
- } else if (opt.getOpt().equals("r")) {
- roleName = opt.getValue();
- } else if (opt.getOpt().equals("s")) {
- serviceName = opt.getValue();
- } else if (opt.getOpt().equals("cr")) {
- isCreateRole = true;
- roleNameRequired = true;
- } else if (opt.getOpt().equals("dr")) {
- isDropRole = true;
- roleNameRequired = true;
- } else if (opt.getOpt().equals("arg")) {
- isAddRoleGroup = true;
- roleNameRequired = true;
- groupNameRequired = true;
- } else if (opt.getOpt().equals("drg")) {
- isDeleteRoleGroup = true;
- roleNameRequired = true;
- groupNameRequired = true;
- } else if (opt.getOpt().equals("gpr")) {
- isGrantPrivilegeRole = true;
- roleNameRequired = true;
- privilegeStrRequired = true;
- } else if (opt.getOpt().equals("rpr")) {
- isRevokePrivilegeRole = true;
- roleNameRequired = true;
- privilegeStrRequired = true;
- } else if (opt.getOpt().equals("lr")) {
- isListRole = true;
- } else if (opt.getOpt().equals("lp")) {
- isListPrivilege = true;
- roleNameRequired = true;
- } else if (opt.getOpt().equals("lg")) {
- isListGroup = true;
- } else if (opt.getOpt().equals("conf")) {
- confPath = opt.getValue();
- } else if (opt.getOpt().equals("t")) {
- type = TYPE.valueOf(opt.getValue());
- }
- }
- checkRequiredParameter(roleNameRequired, roleName, OPTION_DESC_ROLE_NAME);
- checkRequiredParameter(groupNameRequired, groupName, OPTION_DESC_GROUP_NAME);
- checkRequiredParameter(privilegeStrRequired, privilegeStr, OPTION_DESC_PRIVILEGE);
- }
-
- protected void checkRequiredParameter(boolean isRequired, String paramValue, String paramName) throws ParseException {
- if (isRequired && StringUtils.isEmpty(paramValue)) {
- throw new ParseException(PREFIX_MESSAGE_MISSING_OPTION + paramName);
- }
- }
-
- // print usage
- private void usage(Options sentryOptions) {
- HelpFormatter formatter = new HelpFormatter();
- formatter.printHelp("sentryShell", sentryOptions);
- }
-
- // hive model and generic model should implement this method
- public abstract void run() throws Exception;
-
- @VisibleForTesting
- public boolean executeShell(String[] args) throws Exception {
- boolean result = true;
- if (parseArgs(args)) {
- run();
- } else {
- result = false;
- }
- return result;
- }
-}
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/SentryShellHive.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/SentryShellHive.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/SentryShellHive.java
deleted file mode 100644
index 785e27d..0000000
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/SentryShellHive.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/**
- * 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.tools;
-
-import java.util.List;
-import java.util.Set;
-
-import org.apache.commons.lang.StringUtils;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.security.UserGroupInformation;
-import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
-import org.apache.sentry.provider.db.tools.command.hive.*;
-import org.apache.sentry.service.thrift.SentryServiceClientFactory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.Sets;
-
-/**
- * SentryShellHive is an admin tool, and responsible for the management of repository.
- * The following function are supported:
- * create role, drop role, add group to role, delete group from role, grant privilege to role,
- * revoke privilege from role, list roles for group, list privilege for role.
- */
-public class SentryShellHive extends SentryShellCommon {
-
- private static final Logger LOGGER = LoggerFactory.getLogger(SentryShellHive.class);
-
- public void run() throws Exception {
-
- try(SentryPolicyServiceClient client =
- SentryServiceClientFactory.create(getSentryConf())) {
- UserGroupInformation ugi = UserGroupInformation.getLoginUser();
- String requestorName = ugi.getShortUserName();
- ShellCommand command = new HiveShellCommand(client);
-
- // check the requestor name
- if (StringUtils.isEmpty(requestorName)) {
- // The exception message will be recorded in the log file.
- throw new Exception("The requestor name is empty.");
- }
-
- if (isCreateRole) {
- command.createRole(requestorName, roleName);
- } else if (isDropRole) {
- command.dropRole(requestorName, roleName);
- } else if (isAddRoleGroup) {
- Set<String> groups = Sets.newHashSet(groupName.split(SentryShellCommon.GROUP_SPLIT_CHAR));
- command.grantRoleToGroups(requestorName, roleName, groups);
- } else if (isDeleteRoleGroup) {
- Set<String> groups = Sets.newHashSet(groupName.split(SentryShellCommon.GROUP_SPLIT_CHAR));
- command.revokeRoleFromGroups(requestorName, roleName, groups);
- } else if (isGrantPrivilegeRole) {
- command.grantPrivilegeToRole(requestorName, roleName, privilegeStr);
- } else if (isRevokePrivilegeRole) {
- command.revokePrivilegeFromRole(requestorName, roleName, privilegeStr);
- } else if (isListRole) {
- List<String> roles = command.listRoles(requestorName, groupName);
- for (String role : roles) {
- System.out.println(role);
- }
- } else if (isListPrivilege) {
- List<String> privileges = command.listPrivileges(requestorName, roleName);
- for (String privilege : privileges) {
- System.out.println(privilege);
- }
- } else if (isListGroup) {
- List<String> groups = command.listGroupRoles(requestorName);
- for (String group : groups) {
- System.out.println(group);
- }
- }
- }
- }
-
- private Configuration getSentryConf() {
- Configuration conf = new Configuration();
- conf.addResource(new Path(confPath), true);
- return conf;
- }
-
- public static void main(String[] args) throws Exception {
- SentryShellHive sentryShell = new SentryShellHive();
- try {
- sentryShell.executeShell(args);
- } catch (Exception e) {
- LOGGER.error(e.getMessage(), e);
- Throwable current = e;
- // find the first printable message;
- while (current != null && current.getMessage() == null) {
- current = current.getCause();
- }
-
- if (current != null) {
- System.out.println("The operation failed." +
- (current.getMessage() == null ? "" : " Message: " + current.getMessage()));
- }
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/ShellCommand.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/ShellCommand.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/ShellCommand.java
deleted file mode 100644
index eeb3a23..0000000
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/ShellCommand.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/**
- * 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.tools;
-
-import java.util.List;
-import java.util.Set;
-
-import org.apache.sentry.core.common.exception.SentryUserException;
-
-/**
- * The interface for all admin commands, eg, CreateRoleCmd. It is independent of the underlying mechanism (i.e. Generic or Hive)
- */
-public interface ShellCommand {
-
- void createRole(String requestorName, String roleName) throws SentryUserException;
-
- void dropRole(String requestorName, String roleName) throws SentryUserException;
-
- void grantPrivilegeToRole(String requestorName, String roleName, String privilege) throws SentryUserException;
-
- void grantRoleToGroups(String requestorName, String roleName, Set<String> groups) throws SentryUserException;
-
- void revokePrivilegeFromRole(String requestorName, String roleName, String privilege) throws SentryUserException;
-
- void revokeRoleFromGroups(String requestorName, String roleName, Set<String> groups) throws SentryUserException;
-
- List<String> listRoles(String requestorName, String group) throws SentryUserException;
-
- List<String> listPrivileges(String requestorName, String roleName) throws SentryUserException;
-
- List<String> listGroupRoles(String requestorName) throws SentryUserException;
-}
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/command/hive/CommandUtil.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/command/hive/CommandUtil.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/command/hive/CommandUtil.java
deleted file mode 100644
index 3f0b5fa..0000000
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/command/hive/CommandUtil.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/**
- * 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.tools.command.hive;
-
-import org.apache.commons.lang.StringUtils;
-import org.apache.sentry.provider.db.service.thrift.TSentryPrivilege;
-import org.apache.sentry.service.thrift.ServiceConstants;
-
-public final class CommandUtil {
-
- public static final String SPLIT_CHAR = ",";
-
- private CommandUtil() {
- // Make constructor private to avoid instantiation
- }
-
- // check the privilege value for the specific privilege scope
- // eg, for the table scope, server and database can't be empty
- public static void validatePrivilegeHierarchy(TSentryPrivilege tSentryPrivilege) throws IllegalArgumentException {
- String serverName = tSentryPrivilege.getServerName();
- String dbName = tSentryPrivilege.getDbName();
- String tableName = tSentryPrivilege.getTableName();
- String columnName = tSentryPrivilege.getColumnName();
- String uri = tSentryPrivilege.getURI();
- if (ServiceConstants.PrivilegeScope.SERVER.toString().equals(tSentryPrivilege.getPrivilegeScope())) {
- if (StringUtils.isEmpty(serverName)) {
- throw new IllegalArgumentException("The hierarchy of privilege is not correct.");
- }
- } else if (ServiceConstants.PrivilegeScope.URI.toString().equals(tSentryPrivilege.getPrivilegeScope())) {
- if (StringUtils.isEmpty(serverName) || StringUtils.isEmpty(uri)) {
- throw new IllegalArgumentException("The hierarchy of privilege is not correct.");
- }
- } else if (ServiceConstants.PrivilegeScope.DATABASE.toString().equals(tSentryPrivilege.getPrivilegeScope())) {
- if (StringUtils.isEmpty(serverName) || StringUtils.isEmpty(dbName)) {
- throw new IllegalArgumentException("The hierarchy of privilege is not correct.");
- }
- } else if (ServiceConstants.PrivilegeScope.TABLE.toString().equals(tSentryPrivilege.getPrivilegeScope())) {
- if (StringUtils.isEmpty(serverName) || StringUtils.isEmpty(dbName)
- || StringUtils.isEmpty(tableName)) {
- throw new IllegalArgumentException("The hierarchy of privilege is not correct.");
- }
- } else if (ServiceConstants.PrivilegeScope.COLUMN.toString().equals(tSentryPrivilege.getPrivilegeScope())
- && (StringUtils.isEmpty(serverName) || StringUtils.isEmpty(dbName)
- || StringUtils.isEmpty(tableName) || StringUtils.isEmpty(columnName))) {
- throw new IllegalArgumentException("The hierarchy of privilege is not correct.");
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/command/hive/HiveShellCommand.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/command/hive/HiveShellCommand.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/command/hive/HiveShellCommand.java
deleted file mode 100644
index 3abba52..0000000
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/command/hive/HiveShellCommand.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/**
- * 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.tools.command.hive;
-
-import java.util.ArrayList;
-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 org.apache.commons.lang.StringUtils;
-import org.apache.sentry.core.common.exception.SentryUserException;
-import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
-import org.apache.sentry.provider.db.service.thrift.TSentryGroup;
-import org.apache.sentry.provider.db.service.thrift.TSentryPrivilege;
-import org.apache.sentry.provider.db.service.thrift.TSentryRole;
-import org.apache.sentry.provider.db.tools.ShellCommand;
-import org.apache.sentry.service.thrift.SentryServiceUtil;
-
-/**
- * The ShellCommand implementation for Hive.
- */
-public class HiveShellCommand implements ShellCommand {
-
- private final SentryPolicyServiceClient client;
-
- public HiveShellCommand(SentryPolicyServiceClient client) {
- this.client = client;
- }
-
- public void createRole(String requestorName, String roleName) throws SentryUserException {
- client.createRole(requestorName, roleName);
- }
-
- public void dropRole(String requestorName, String roleName) throws SentryUserException {
- client.dropRole(requestorName, roleName);
- }
-
- public void grantPrivilegeToRole(String requestorName, String roleName, String privilege) throws SentryUserException {
- TSentryPrivilege tSentryPrivilege = SentryServiceUtil.convertToTSentryPrivilege(privilege);
- CommandUtil.validatePrivilegeHierarchy(tSentryPrivilege);
- client.grantPrivilege(requestorName, roleName, tSentryPrivilege);
- }
-
- public void grantRoleToGroups(String requestorName, String roleName, Set<String> groups) throws SentryUserException {
- client.grantRoleToGroups(requestorName, roleName, groups);
- }
-
- public void revokePrivilegeFromRole(String requestorName, String roleName, String privilege) throws SentryUserException {
- TSentryPrivilege tSentryPrivilege = SentryServiceUtil.convertToTSentryPrivilege(privilege);
- CommandUtil.validatePrivilegeHierarchy(tSentryPrivilege);
- client.revokePrivilege(requestorName, roleName, tSentryPrivilege);
- }
-
- public void revokeRoleFromGroups(String requestorName, String roleName, Set<String> groups) throws SentryUserException {
- client.revokeRoleFromGroups(requestorName, roleName, groups);
- }
-
- public List<String> listRoles(String requestorName, String group) throws SentryUserException {
- Set<TSentryRole> roles;
- if (StringUtils.isEmpty(group)) {
- roles = client.listAllRoles(requestorName);
- } else {
- roles = client.listRolesByGroupName(requestorName, group);
- }
-
- List<String> result = new ArrayList<>();
- if (roles != null) {
- for (TSentryRole role : roles) {
- result.add(role.getRoleName());
- }
- }
-
- return result;
- }
-
- public List<String> listPrivileges(String requestorName, String roleName) throws SentryUserException {
- Set<TSentryPrivilege> privileges = client
- .listAllPrivilegesByRoleName(requestorName, roleName);
-
- List<String> result = new ArrayList<>();
- if (privileges != null) {
- for (TSentryPrivilege privilege : privileges) {
- String privilegeStr = SentryServiceUtil.convertTSentryPrivilegeToStr(privilege);
- result.add(privilegeStr);
- }
- }
- return result;
- }
-
- public List<String> listGroupRoles(String requestorName) throws SentryUserException {
- Set<TSentryRole> roles = client.listAllRoles(requestorName);
- if (roles == null || roles.isEmpty()) {
- return Collections.emptyList();
- }
-
- // Set of all group names
- Set<String> groupNames = new HashSet<>();
-
- // Map group to set of roles
- Map<String, Set<String>> groupInfo = new HashMap<>();
-
- // Get all group names
- for (TSentryRole role: roles) {
- for (TSentryGroup group : role.getGroups()) {
- String groupName = group.getGroupName();
- groupNames.add(groupName);
- Set<String> groupRoles = groupInfo.get(groupName);
- if (groupRoles != null) {
- // Add a new or existing role
- groupRoles.add(role.getRoleName());
- continue;
- }
- // Never seen this group before
- groupRoles = new HashSet<>();
- groupRoles.add(role.getRoleName());
- groupInfo.put(groupName, groupRoles);
- }
- }
-
- List<String> groups = new ArrayList<>(groupNames);
-
- // Produce printable result as
- // group1 = role1, role2, ...
- // group2 = ...
- List<String> result = new LinkedList<>();
- for (String groupName: groups) {
- result.add(groupName + " = " + StringUtils.join(groupInfo.get(groupName), ", "));
- }
-
- return result;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestPermissionsMigrationToolSolr.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestPermissionsMigrationToolSolr.java b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestPermissionsMigrationToolSolr.java
deleted file mode 100644
index 69c067f..0000000
--- a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestPermissionsMigrationToolSolr.java
+++ /dev/null
@@ -1,362 +0,0 @@
- /**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.sentry.provider.db.generic.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.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);
- }
- }
- }
- }
-}
[5/9] sentry git commit: SENTRY-2207 Refactor out Sentry CLI from
sentry-provider-db into own module. Steve Moist,
reviewed by Colm O hEigeartaigh.
Posted by co...@apache.org.
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/test/resources/indexer_config_import_tool.ini
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/test/resources/indexer_config_import_tool.ini b/sentry-provider/sentry-provider-db/src/test/resources/indexer_config_import_tool.ini
deleted file mode 100644
index c1bfe4b..0000000
--- a/sentry-provider/sentry-provider-db/src/test/resources/indexer_config_import_tool.ini
+++ /dev/null
@@ -1,29 +0,0 @@
-# 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.
-
-[groups]
-corporal = corporal_role
-sergeant = corporal_role, sergeant_role
-general = corporal_role, sergeant_role, general_role
-commander_in_chief = corporal_role, sergeant_role, general_role, commander_in_chief_role
-
-[roles]
-corporal_role = indexer=info->action=read, \
- indexer=info->action=write
-sergeant_role = indexer=info->action=write
-general_role = indexer=info->action=*
-commander_in_chief_role = indexer=*
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/test/resources/indexer_invalid.ini
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/test/resources/indexer_invalid.ini b/sentry-provider/sentry-provider-db/src/test/resources/indexer_invalid.ini
deleted file mode 100644
index 03083a7..0000000
--- a/sentry-provider/sentry-provider-db/src/test/resources/indexer_invalid.ini
+++ /dev/null
@@ -1,21 +0,0 @@
-# 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.
-
-[groups]
-
-[roles]
-
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/test/resources/solr_case.ini
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/test/resources/solr_case.ini b/sentry-provider/sentry-provider-db/src/test/resources/solr_case.ini
deleted file mode 100644
index fbbebfc..0000000
--- a/sentry-provider/sentry-provider-db/src/test/resources/solr_case.ini
+++ /dev/null
@@ -1,26 +0,0 @@
-# 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.
-
-[groups]
-groupa = RoLe1
-groupb = rOlE1
-groupc = ROLE2
-
-[roles]
-RoLe1 = collection=*
-rOlE1 = collection=*
-ROLE2 = collection=*
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/test/resources/solr_config_import_tool.ini
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/test/resources/solr_config_import_tool.ini b/sentry-provider/sentry-provider-db/src/test/resources/solr_config_import_tool.ini
deleted file mode 100644
index da7df4c..0000000
--- a/sentry-provider/sentry-provider-db/src/test/resources/solr_config_import_tool.ini
+++ /dev/null
@@ -1,29 +0,0 @@
-# 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.
-
-[groups]
-corporal = corporal_role
-sergeant = corporal_role, sergeant_role
-general = corporal_role, sergeant_role, general_role
-commander_in_chief = corporal_role, sergeant_role, general_role, commander_in_chief_role
-
-[roles]
-corporal_role = collection=info->action=query, \
- collection=info->action=update
-sergeant_role = collection=info->action=update
-general_role = collection=info->action=*
-commander_in_chief_role = collection=*
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/test/resources/solr_invalid.ini
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/test/resources/solr_invalid.ini b/sentry-provider/sentry-provider-db/src/test/resources/solr_invalid.ini
deleted file mode 100644
index 03083a7..0000000
--- a/sentry-provider/sentry-provider-db/src/test/resources/solr_invalid.ini
+++ /dev/null
@@ -1,21 +0,0 @@
-# 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.
-
-[groups]
-
-[roles]
-
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/pom.xml
----------------------------------------------------------------------
diff --git a/sentry-tools/pom.xml b/sentry-tools/pom.xml
index 4d8fc89..b882c6f 100644
--- a/sentry-tools/pom.xml
+++ b/sentry-tools/pom.xml
@@ -26,6 +26,7 @@ limitations under the License.
<modelVersion>4.0.0</modelVersion>
<artifactId>sentry-tools</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
<dependencies>
<dependency>
@@ -33,27 +34,56 @@ limitations under the License.
<artifactId>sentry-binding-hive</artifactId>
</dependency>
<dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-log4j12</artifactId>
+ <groupId>org.apache.sentry</groupId>
+ <artifactId>sentry-provider-db</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.sentry</groupId>
+ <artifactId>sentry-provider-db</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
</dependency>
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
</dependency>
<dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ </dependency>
+ <dependency>
<groupId>com.budhash.cliche</groupId>
<artifactId>cliche-shell</artifactId>
<version>0.9.3</version>
</dependency>
<dependency>
- <groupId>org.apache.sentry</groupId>
- <artifactId>sentry-provider-db</artifactId>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.hadoop</groupId>
+ <artifactId>hadoop-minikdc</artifactId>
+ <scope>test</scope>
</dependency>
</dependencies>
<build>
- <sourceDirectory>${basedir}/src/main/java</sourceDirectory>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <reuseForks>false</reuseForks>
+ </configuration>
+ </plugin>
+ </plugins>
+ <testResources>
+ <testResource>
+ <directory>src/test/resources</directory>
+ </testResource>
+ </testResources>
</build>
-
-
</project>
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/main/java/org/apache/sentry/SentryMain.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/SentryMain.java b/sentry-tools/src/main/java/org/apache/sentry/SentryMain.java
index e92155c..495d4cd 100644
--- a/sentry-tools/src/main/java/org/apache/sentry/SentryMain.java
+++ b/sentry-tools/src/main/java/org/apache/sentry/SentryMain.java
@@ -24,7 +24,7 @@ import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;
import org.apache.log4j.PropertyConfigurator;
import org.apache.sentry.binding.hive.authz.SentryConfigTool;
-import org.apache.sentry.provider.db.tools.SentrySchemaTool;
+import org.apache.sentry.cli.tools.SentrySchemaTool;
import org.apache.sentry.service.thrift.SentryService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/PermissionsMigrationToolCommon.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/PermissionsMigrationToolCommon.java b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/PermissionsMigrationToolCommon.java
new file mode 100644
index 0000000..8b5130c
--- /dev/null
+++ b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/PermissionsMigrationToolCommon.java
@@ -0,0 +1,349 @@
+/**
+ * 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.util.Collection;
+import java.util.Collections;
+import java.util.Optional;
+import java.util.Set;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.GnuParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.apache.commons.cli.Parser;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.sentry.core.common.ActiveRoleSet;
+import org.apache.sentry.core.common.utils.PolicyFileConstants;
+import org.apache.sentry.core.common.utils.PolicyFiles;
+import org.apache.sentry.core.common.utils.Version;
+import org.apache.sentry.policy.common.PrivilegeUtils;
+import org.apache.sentry.provider.common.ProviderBackendContext;
+import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClient;
+import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClientFactory;
+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.SimpleFileProviderBackend;
+import org.apache.shiro.config.Ini;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.Sets;
+import com.google.common.collect.Table;
+
+/**
+ * This class provides basic framework required to migrate permissions between different Sentry
+ * versions. Individual components (e.g. SOLR, KAFKA) needs to override the this class
+ * to provide component specific migration functionality.
+ */
+public abstract class PermissionsMigrationToolCommon {
+ private static final Logger LOGGER = LoggerFactory.getLogger(PermissionsMigrationToolCommon.class);
+ public static final String SOLR_SERVICE_NAME = "sentry.service.client.solr.service.name";
+
+ private Version sourceVersion;
+ private Optional<String> confPath = Optional.empty();
+ private Optional<String> policyFile = Optional.empty();
+ private Optional<String> outputFile = Optional.empty();
+ private boolean dryRun = false;
+
+ /**
+ * @return version of Sentry for which the privileges need to be migrated.
+ */
+ public final Version getSourceVersion() {
+ return sourceVersion;
+ }
+
+ /**
+ * This method returns the name of the component for the migration purpose.
+ * @param conf The Sentry configuration
+ * @return the name of the component
+ */
+ protected abstract String getComponent(Configuration conf);
+
+
+ /**
+ * This method returns the name of the service name for the migration purpose.
+ *
+ * @param conf The Sentry configuration
+ * @return the name of the service
+ */
+ protected abstract String getServiceName(Configuration conf);
+
+ /**
+ * Migrate the privileges specified via <code>privileges</code>.
+ *
+ * @param privileges A collection of privileges to be migrated.
+ * @return A collection of migrated privileges
+ * An empty collection if migration is not necessary for the specified privileges.
+ */
+ protected abstract Collection<String> transformPrivileges (Collection<String> privileges);
+
+ /**
+ * parse arguments
+ * <pre>
+ * -s,--source Sentry source version
+ * -c,--sentry_conf <filepath> sentry config file path
+ * -p --policy_file <filepath> sentry (source) policy file path
+ * -o --output <filepath> sentry (target) policy file path
+ * -d --dry_run provides the output the migration for inspection without
+ * making any configuration changes.
+ * -h,--help print usage
+ * </pre>
+ * @param args
+ */
+ protected boolean parseArgs(String [] args) {
+ Options options = new Options();
+
+ Option sourceVersionOpt = new Option("s", "source", true, "Source Sentry version");
+ sourceVersionOpt.setRequired(true);
+ options.addOption(sourceVersionOpt);
+
+ Option sentryConfPathOpt = new Option("c", "sentry_conf", true,
+ "sentry-site.xml file path (only required in case of Sentry service)");
+ sentryConfPathOpt.setRequired(false);
+ options.addOption(sentryConfPathOpt);
+
+ Option sentryPolicyFileOpt = new Option("p", "policy_file", true,
+ "sentry (source) policy file path (only in case of file based Sentry configuration)");
+ sentryPolicyFileOpt.setRequired(false);
+ options.addOption(sentryPolicyFileOpt);
+
+ Option sentryOutputFileOpt = new Option("o", "output", true,
+ "sentry (target) policy file path (only in case of file based Sentry configuration)");
+ sentryOutputFileOpt.setRequired(false);
+ options.addOption(sentryOutputFileOpt);
+
+ Option dryRunOpt = new Option("d", "dry_run", false,
+ "provides the output the migration for inspection without making actual configuration changes");
+ dryRunOpt.setRequired(false);
+ options.addOption(dryRunOpt);
+
+ // help option
+ Option helpOpt = new Option("h", "help", false, "Shell usage");
+ helpOpt.setRequired(false);
+ options.addOption(helpOpt);
+
+ // this Option is parsed first for help option
+ Options helpOptions = new Options();
+ helpOptions.addOption(helpOpt);
+
+ try {
+ Parser parser = new GnuParser();
+
+ // parse help option first
+ CommandLine cmd = parser.parse(helpOptions, args, true);
+ for (Option opt : cmd.getOptions()) {
+ if (opt.getOpt().equals("h")) {
+ // get the help option, print the usage and exit
+ usage(options);
+ return false;
+ }
+ }
+
+ // without help option
+ cmd = parser.parse(options, args);
+
+ String sourceVersionStr = null;
+
+ for (Option opt : cmd.getOptions()) {
+ if (opt.getOpt().equals("s")) {
+ sourceVersionStr = opt.getValue();
+ } else if (opt.getOpt().equals("c")) {
+ confPath = Optional.of(opt.getValue());
+ } else if (opt.getOpt().equals("p")) {
+ policyFile = Optional.of(opt.getValue());
+ } else if (opt.getOpt().equals("o")) {
+ outputFile = Optional.of(opt.getValue());
+ } else if (opt.getOpt().equals("d")) {
+ dryRun = true;
+ }
+ }
+
+ sourceVersion = Version.parse(sourceVersionStr);
+
+ if (!(confPath.isPresent() || policyFile.isPresent())) {
+ System.out.println("Please select either file-based Sentry configuration (-p and -o flags)"
+ + " or Sentry service (-c flag) for migration.");
+ usage(options);
+ return false;
+ }
+
+ if (confPath.isPresent() && (policyFile.isPresent() || outputFile.isPresent())) {
+ System.out.println("In order to migrate service based Sentry configuration,"
+ + " do not specify either -p or -o parameters");
+ usage(options);
+ return false;
+ }
+
+ if (!confPath.isPresent() && (policyFile.isPresent() ^ outputFile.isPresent())) {
+ System.out.println("In order to migrate file based Sentry configuration,"
+ + " please make sure to specify both -p and -o parameters.");
+ usage(options);
+ return false;
+ }
+
+ } catch (ParseException | java.text.ParseException pe) {
+ System.out.println(pe.getMessage());
+ usage(options);
+ return false;
+ }
+ return true;
+ }
+
+ // print usage
+ private void usage(Options sentryOptions) {
+ HelpFormatter formatter = new HelpFormatter();
+ formatter.printHelp("sentryMigrationTool", sentryOptions);
+ }
+
+ public void run() throws Exception {
+ if (policyFile.isPresent()) {
+ migratePolicyFile();
+ } else {
+ migrateSentryServiceConfig();
+ }
+ }
+
+ private void migrateSentryServiceConfig() throws Exception {
+ Configuration conf = getSentryConf();
+ String component = getComponent(conf);
+ String serviceName = getServiceName(conf);
+ GenericPrivilegeConverter converter = new GenericPrivilegeConverter(component, serviceName, false);
+
+ // instantiate a client for sentry service. This sets the ugi, so must
+ // be done before getting the ugi below.
+ try(SentryGenericServiceClient client =
+ SentryGenericServiceClientFactory.create(getSentryConf())) {
+ UserGroupInformation ugi = UserGroupInformation.getLoginUser();
+ String requestorName = ugi.getShortUserName();
+
+ for (TSentryRole r : client.listAllRoles(requestorName, component)) {
+ for (TSentryPrivilege p : client.listAllPrivilegesByRoleName(requestorName,
+ r.getRoleName(), component, serviceName)) {
+
+ String privilegeStr = converter.toString(p);
+ Collection<String> privileges = Collections.singleton(privilegeStr);
+ Collection<String> migrated = transformPrivileges(privileges);
+ if (!migrated.isEmpty()) {
+ LOGGER.info("{} For role {} migrating privileges from {} to {}", getDryRunMessage(), r.getRoleName(),
+ privileges, migrated);
+
+ /*
+ * Note that it is not possible to provide transactional (all-or-nothing) behavior for these configuration
+ * changes since the Sentry client/server protocol does not support. e.g. under certain failure conditions
+ * like crash of Sentry server or network disconnect between client/server, it is possible that the migration
+ * can not complete but can also not be rolled back. Hence this migration tool relies on the fact that privilege
+ * grant/revoke operations are idempotent and hence re-execution of the migration tool will fix any inconsistency
+ * due to such failures.
+ **/
+ boolean originalPermPresent = false;
+ for (String perm : migrated) {
+ if (perm.equalsIgnoreCase(privilegeStr)) {
+ originalPermPresent = true;
+ continue;
+ }
+ TSentryPrivilege x = converter.fromString(perm);
+ LOGGER.info("{} GRANT permission {}", getDryRunMessage(), perm);
+ if (!dryRun) {
+ client.grantPrivilege(requestorName, r.getRoleName(), component, x);
+ }
+ }
+
+ // Revoke old permission (only if not part of migrated permissions)
+ if (!originalPermPresent) {
+ LOGGER.info("{} REVOKE permission {}", getDryRunMessage(), privilegeStr);
+ if (!dryRun) {
+ client.revokePrivilege(requestorName, r.getRoleName(), component, p);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private void migratePolicyFile () throws Exception {
+ Configuration conf = getSentryConf();
+ Path sourceFile = new Path (policyFile.get());
+ SimpleFileProviderBackend policyFileBackend = new SimpleFileProviderBackend(conf, sourceFile);
+ ProviderBackendContext ctx = new ProviderBackendContext();
+ policyFileBackend.initialize(ctx);
+
+ Set<String> roles = Sets.newHashSet();
+ Table<String, String, Set<String>> groupRolePrivilegeTable =
+ policyFileBackend.getGroupRolePrivilegeTable();
+
+ Ini output = PolicyFiles.loadFromPath(sourceFile.getFileSystem(conf), sourceFile);
+ Ini.Section rolesSection = output.get(PolicyFileConstants.ROLES);
+
+ for (String groupName : groupRolePrivilegeTable.rowKeySet()) {
+ for (String roleName : policyFileBackend.getRoles(Collections.singleton(groupName), ActiveRoleSet.ALL)) {
+ if (!roles.contains(roleName)) {
+ // Do the actual migration
+ Set<String> privileges = groupRolePrivilegeTable.get(groupName, roleName);
+ Collection<String> migrated = transformPrivileges(privileges);
+
+ if (!migrated.isEmpty()) {
+ LOGGER.info("{} For role {} migrating privileges from {} to {}", getDryRunMessage(),
+ roleName, privileges, migrated);
+ if (!dryRun) {
+ rolesSection.put(roleName, PrivilegeUtils.fromPrivilegeStrings(migrated));
+ }
+ }
+
+ roles.add(roleName);
+ }
+ }
+ }
+
+ if (!dryRun) {
+ Path targetFile = new Path (outputFile.get());
+ PolicyFiles.writeToPath(output, targetFile.getFileSystem(conf), targetFile);
+ LOGGER.info("Successfully saved migrated Sentry policy file at {}", outputFile.get());
+ }
+ }
+
+ private String getDryRunMessage() {
+ return dryRun ? "[Dry Run]" : "";
+ }
+
+ private Configuration getSentryConf() {
+ Configuration conf = new Configuration();
+ if (confPath.isPresent()) {
+ conf.addResource(new Path(confPath.get()), true);
+ }
+ return conf;
+ }
+
+ @VisibleForTesting
+ public boolean executeConfigTool(String [] args) throws Exception {
+ boolean result = true;
+ if (parseArgs(args)) {
+ run();
+ } else {
+ result = false;
+ }
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/PermissionsMigrationToolSolr.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/PermissionsMigrationToolSolr.java b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/PermissionsMigrationToolSolr.java
new file mode 100644
index 0000000..c24ae93
--- /dev/null
+++ b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/PermissionsMigrationToolSolr.java
@@ -0,0 +1,109 @@
+/**
+ * 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.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.sentry.core.common.utils.SentryConstants;
+import org.apache.sentry.core.model.solr.validator.SolrPrivilegeValidator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This class provides SOLR specific functionality required for migrating Sentry privileges.
+ */
+public class PermissionsMigrationToolSolr extends PermissionsMigrationToolCommon {
+ private static final Logger LOGGER = LoggerFactory.getLogger(PermissionsMigrationToolSolr.class);
+
+
+ @Override
+ protected String getComponent(Configuration conf) {
+ return "SOLR";
+ }
+
+ @Override
+ protected String getServiceName(Configuration conf) {
+ return conf.get(SOLR_SERVICE_NAME, "service1");
+ }
+
+ @Override
+ protected Collection<String> transformPrivileges(Collection<String> privileges) {
+ List<String> result = new ArrayList<>();
+ boolean migrated = false;
+
+ if (getSourceVersion().major == 1) { // Migrate only Sentry 1.x permissions
+ for (String p : privileges) {
+ SolrPrivilegeValidator v = new SolrPrivilegeValidator();
+ v.validate(p, false);
+
+ if ("collection".equalsIgnoreCase(v.getEntityType()) && "admin".equalsIgnoreCase(v.getEntityName())) {
+ result.add(getPermissionStr("admin", "collections", v.getActionName()));
+ result.add(getPermissionStr("admin", "cores", v.getActionName()));
+ migrated = true;
+ } else if ("collection".equalsIgnoreCase(v.getEntityType()) && "*".equals(v.getEntityName())) {
+ result.add(getPermissionStr("admin", "collections", v.getActionName()));
+ result.add(getPermissionStr("admin", "cores", v.getActionName()));
+ result.add(p);
+ migrated = true;
+ } else {
+ result.add(p);
+ }
+ }
+ }
+
+ return migrated ? result : Collections.emptyList();
+ }
+
+ private String getPermissionStr (String entityType, String entityName, String action) {
+ StringBuilder builder = new StringBuilder();
+ builder.append(entityType);
+ builder.append(SentryConstants.KV_SEPARATOR);
+ builder.append(entityName);
+ if (action != null) {
+ builder.append(SentryConstants.AUTHORIZABLE_SEPARATOR);
+ builder.append(SentryConstants.PRIVILEGE_NAME);
+ builder.append(SentryConstants.KV_SEPARATOR);
+ builder.append(action);
+ }
+ return builder.toString();
+ }
+
+ public static void main(String[] args) throws Exception {
+ PermissionsMigrationToolSolr solrTool = new PermissionsMigrationToolSolr();
+ try {
+ solrTool.executeConfigTool(args);
+ } catch (Exception e) {
+ LOGGER.error(e.getMessage(), e);
+ Throwable current = e;
+ // find the first printable message;
+ while (current != null && current.getMessage() == null) {
+ current = current.getCause();
+ }
+ String error = "";
+ if (current != null && current.getMessage() != null) {
+ error = "Message: " + current.getMessage();
+ }
+ System.out.println("The operation failed. " + error);
+ System.exit(1);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryConfigToolCommon.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryConfigToolCommon.java b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryConfigToolCommon.java
new file mode 100644
index 0000000..2d4f973
--- /dev/null
+++ b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryConfigToolCommon.java
@@ -0,0 +1,152 @@
+/**
+ * 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.annotations.VisibleForTesting;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.GnuParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.apache.commons.cli.Parser;
+
+abstract public class SentryConfigToolCommon {
+ private String policyFile;
+ private boolean validate;
+ private boolean importPolicy;
+ private boolean checkCompat;
+ private String confPath;
+
+ /**
+ * parse arguments
+ * <pre>
+ * -conf,--sentry_conf <filepath> sentry config file path
+ * -p,--policy_ini <arg> policy file path
+ * -v,--validate validate policy file
+ * -c,--checkcompat check compatibility with service
+ * -i,--import import policy file
+ * -h,--help print usage
+ * </pre>
+ * @param args
+ */
+ protected boolean parseArgs(String [] args) {
+ Options options = new Options();
+
+ Option globalPolicyPath = new Option("p", "policy_ini", true,
+ "Policy file path");
+ globalPolicyPath.setRequired(true);
+ options.addOption(globalPolicyPath);
+
+ Option validateOpt = new Option("v", "validate", false,
+ "Validate policy file");
+ validateOpt.setRequired(false);
+ options.addOption(validateOpt);
+
+ Option checkCompatOpt = new Option("c","checkcompat",false,
+ "Check compatibility with Sentry Service");
+ checkCompatOpt.setRequired(false);
+ options.addOption(checkCompatOpt);
+
+ Option importOpt = new Option("i", "import", false,
+ "Import policy file");
+ importOpt.setRequired(false);
+ options.addOption(importOpt);
+
+ // file path of sentry-site
+ Option sentrySitePathOpt = new Option("conf", "sentry_conf", true, "sentry-site file path");
+ sentrySitePathOpt.setRequired(true);
+ options.addOption(sentrySitePathOpt);
+
+ // help option
+ Option helpOpt = new Option("h", "help", false, "Shell usage");
+ helpOpt.setRequired(false);
+ options.addOption(helpOpt);
+
+ // this Options is parsed first for help option
+ Options helpOptions = new Options();
+ helpOptions.addOption(helpOpt);
+
+ try {
+ Parser parser = new GnuParser();
+
+ // parse help option first
+ CommandLine cmd = parser.parse(helpOptions, args, true);
+ for (Option opt : cmd.getOptions()) {
+ if (opt.getOpt().equals("h")) {
+ // get the help option, print the usage and exit
+ usage(options);
+ return false;
+ }
+ }
+
+ // without help option
+ cmd = parser.parse(options, args);
+
+ for (Option opt : cmd.getOptions()) {
+ if (opt.getOpt().equals("p")) {
+ policyFile = opt.getValue();
+ } else if (opt.getOpt().equals("v")) {
+ validate = true;
+ } else if (opt.getOpt().equals("i")) {
+ importPolicy = true;
+ } else if (opt.getOpt().equals("c")) {
+ checkCompat = true;
+ } else if (opt.getOpt().equals("conf")) {
+ confPath = opt.getValue();
+ }
+ }
+
+ if (!validate && !importPolicy) {
+ throw new IllegalArgumentException("No action specified; at least one of action or import must be specified");
+ }
+ } catch (ParseException pe) {
+ System.out.println(pe.getMessage());
+ usage(options);
+ return false;
+ }
+ return true;
+ }
+
+ // print usage
+ private void usage(Options sentryOptions) {
+ HelpFormatter formatter = new HelpFormatter();
+ formatter.printHelp("sentryConfigTool", sentryOptions);
+ }
+
+ public abstract void run() throws Exception;
+
+ @VisibleForTesting
+ public boolean executeConfigTool(String [] args) throws Exception {
+ boolean result = true;
+ if (parseArgs(args)) {
+ run();
+ } else {
+ result = false;
+ }
+ return result;
+ }
+
+ public String getPolicyFile() { return policyFile; }
+ public boolean getValidate() { return validate; }
+ public boolean getImportPolicy() { return importPolicy; }
+ public boolean getCheckCompat() { return checkCompat; }
+ public String getConfPath() { return confPath; }
+}
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryConfigToolIndexer.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryConfigToolIndexer.java b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryConfigToolIndexer.java
new file mode 100644
index 0000000..712d9ed
--- /dev/null
+++ b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryConfigToolIndexer.java
@@ -0,0 +1,341 @@
+/**
+ * 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.Lists;
+import com.google.common.collect.Sets;
+import com.google.common.collect.Table;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.sentry.core.common.Action;
+import org.apache.sentry.core.common.exception.SentryConfigurationException;
+import org.apache.sentry.core.common.utils.KeyValue;
+import org.apache.sentry.core.model.indexer.IndexerPrivilegeModel;
+import org.apache.sentry.provider.common.ProviderBackend;
+import org.apache.sentry.provider.common.ProviderBackendContext;
+import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClient;
+import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClientFactory;
+import org.apache.sentry.provider.db.generic.tools.GenericPrivilegeConverter;
+import org.apache.sentry.provider.file.SimpleFileProviderBackend;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import static org.apache.sentry.core.common.utils.SentryConstants.AUTHORIZABLE_SPLITTER;
+import static org.apache.sentry.provider.common.AuthorizationComponent.HBASE_INDEXER;
+import static org.apache.sentry.service.thrift.ServiceConstants.ClientConfig.SERVICE_NAME;
+
+/**
+ * SentryConfigToolIndexer is an administrative tool used to parse a HBase Indexer policy file
+ * and add the role, group mappings, and privileges therein to the Sentry service.
+ */
+public class SentryConfigToolIndexer {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(SentryConfigToolIndexer.class);
+
+ private String policyFile;
+ private boolean validate;
+ private boolean importPolicy;
+ private boolean checkCompat;
+ private String confPath;
+
+ private String serviceName;
+
+
+
+ public String getPolicyFile() { return policyFile; }
+
+ public boolean getValidate() { return validate; }
+ public boolean getImportPolicy() { return importPolicy; }
+ public boolean getCheckCompat() { return checkCompat; }
+ public String getConfPath() { return confPath; }
+ public String getServiceName() {
+ return serviceName;
+ }
+
+ /**
+ * Adds command line options for the tool to the passed Options object. Used to extend existing options.
+ * @param options
+ */
+ public void setupOptions(Options options) {
+ Option globalPolicyPath = new Option("f", "policy_ini", true,
+ "Policy file path");
+ globalPolicyPath.setRequired(false);
+ options.addOption(globalPolicyPath);
+
+ Option validateOpt = new Option("v", "validate", false,
+ "Validate policy file");
+ validateOpt.setRequired(false);
+ options.addOption(validateOpt);
+
+ Option checkCompatOpt = new Option("c","checkcompat",false,
+ "Check compatibility with Sentry Service");
+ checkCompatOpt.setRequired(false);
+ options.addOption(checkCompatOpt);
+
+ Option importOpt = new Option("i", "import", false,
+ "Import policy file");
+ importOpt.setRequired(false);
+ options.addOption(importOpt);
+
+ }
+
+ /**
+ * Parses and processes the arguments from the given command line object.
+ * @param cmd
+ */
+ public void parseOptions(CommandLine cmd) {
+ boolean isToolActive = false;
+ for (Option opt : cmd.getOptions()) {
+ if (opt.getOpt().equals("mgr")) {
+ isToolActive = true;
+ }
+ }
+ if (!isToolActive) {
+ return;
+ }
+ for (Option opt : cmd.getOptions()) {
+ if (opt.getOpt().equals("f")) {
+ policyFile = opt.getValue();
+ } else if (opt.getOpt().equals("v")) {
+ validate = true;
+ } else if (opt.getOpt().equals("i")) {
+ importPolicy = true;
+ } else if (opt.getOpt().equals("c")) {
+ checkCompat = true;
+ } else if (opt.getOpt().equals("conf")) {
+ confPath = opt.getValue();
+ } else if (opt.getOpt().equals("s")) {
+ serviceName = opt.getValue();
+ }
+ }
+ if (policyFile == null) {
+ throw new IllegalArgumentException("Missing required option: f");
+ }
+ if (!validate && !importPolicy) {
+ throw new IllegalArgumentException("No action specified; at least one of action or import must be specified");
+ }
+ }
+
+
+ /**
+ * Processes the necessary command based on the arguments parsed earlier.
+ * @throws Exception
+ */
+ public void run() throws Exception {
+ String component = HBASE_INDEXER;
+ Configuration conf = getSentryConf();
+
+ String service = conf.get(SERVICE_NAME, getServiceName());
+
+ if (service == null) {
+ throw new IllegalArgumentException("Service was not defined. Please, use -s command option, or sentry.provider.backend.generic.service-name configuration entry.");
+ }
+
+ LOGGER.info(String.format("Context: component=%s, service=%s", component, service));
+ // instantiate a solr client for sentry service. This sets the ugi, so must
+ // be done before getting the ugi below.
+ try(SentryGenericServiceClient client =
+ SentryGenericServiceClientFactory.create(conf)) {
+ UserGroupInformation ugi = UserGroupInformation.getLoginUser();
+ String requestorName = ugi.getShortUserName();
+
+ convertINIToSentryServiceCmds(component, service, requestorName, conf, client,
+ getPolicyFile(), getValidate(), getImportPolicy(), getCheckCompat());
+ }
+ }
+
+ private Configuration getSentryConf() {
+ Configuration conf = new Configuration();
+ conf.addResource(new Path(getConfPath()), true);
+ return conf;
+ }
+
+ private void convertINIToSentryServiceCmds(String component,
+ String service, String requestorName,
+ Configuration conf, SentryGenericServiceClient client,
+ String policyFile, boolean validate, boolean importPolicy,
+ boolean checkCompat) throws Exception {
+
+ //instantiate a file providerBackend for parsing
+ LOGGER.info("Reading policy file at: " + policyFile);
+ SimpleFileProviderBackend policyFileBackend =
+ new SimpleFileProviderBackend(conf, policyFile);
+ ProviderBackendContext context = new ProviderBackendContext();
+ context.setValidators(IndexerPrivilegeModel.getInstance().getPrivilegeValidators());
+ policyFileBackend.initialize(context);
+ if (validate) {
+ validatePolicy(policyFileBackend);
+ }
+
+ if (checkCompat) {
+ checkCompat(policyFileBackend);
+ }
+
+ //import the relations about group,role and privilege into the DB store
+ Set<String> roles = Sets.newHashSet();
+ Table<String, String, Set<String>> groupRolePrivilegeTable =
+ policyFileBackend.getGroupRolePrivilegeTable();
+ GenericPrivilegeConverter converter = new GenericPrivilegeConverter(component, service, false);
+
+ for (String groupName : groupRolePrivilegeTable.rowKeySet()) {
+ for (String roleName : groupRolePrivilegeTable.columnKeySet()) {
+ if (!roles.contains(roleName)) {
+ LOGGER.info(dryRunMessage(importPolicy) + "Creating role: " + roleName.toLowerCase(Locale.US));
+ if (importPolicy) {
+ client.createRoleIfNotExist(requestorName, roleName, component);
+ }
+ roles.add(roleName);
+ }
+
+ Set<String> privileges = groupRolePrivilegeTable.get(groupName, roleName);
+ if (privileges == null) {
+ continue;
+ }
+ LOGGER.info(dryRunMessage(importPolicy) + "Adding role: " + roleName.toLowerCase(Locale.US) + " to group: " + groupName);
+ if (importPolicy) {
+ client.grantRoleToGroups(requestorName, roleName, component, Sets.newHashSet(groupName));
+ }
+
+ for (String permission : privileges) {
+ String action = null;
+
+ for (String authorizable : AUTHORIZABLE_SPLITTER.
+ trimResults().split(permission)) {
+ KeyValue kv = new KeyValue(authorizable);
+ String key = kv.getKey();
+ String value = kv.getValue();
+ if ("action".equalsIgnoreCase(key)) {
+ action = value;
+ }
+ }
+
+ // Service doesn't support not specifying action
+ if (action == null) {
+ permission += "->action=" + Action.ALL;
+ }
+ LOGGER.info(dryRunMessage(importPolicy) + "Adding permission: " + permission + " to role: " + roleName.toLowerCase(Locale.US));
+ if (importPolicy) {
+ client.grantPrivilege(requestorName, roleName, component, converter.fromString(permission));
+ }
+ }
+ }
+ }
+ }
+
+ private void validatePolicy(ProviderBackend backend) throws Exception {
+ try {
+ backend.validatePolicy(true);
+ } catch (SentryConfigurationException e) {
+ printConfigErrorsWarnings(e);
+ throw e;
+ }
+ }
+
+ private void printConfigErrorsWarnings(SentryConfigurationException configException) {
+ System.out.println(" *** Found configuration problems *** ");
+ for (String errMsg : configException.getConfigErrors()) {
+ System.out.println("ERROR: " + errMsg);
+ }
+ for (String warnMsg : configException.getConfigWarnings()) {
+ System.out.println("Warning: " + warnMsg);
+ }
+ }
+
+ private void checkCompat(SimpleFileProviderBackend backend) throws Exception {
+ Map<String, Set<String>> rolesCaseMapping = new HashMap<String, Set<String>>();
+ Table<String, String, Set<String>> groupRolePrivilegeTable =
+ backend.getGroupRolePrivilegeTable();
+
+ for (String roleName : groupRolePrivilegeTable.columnKeySet()) {
+ String roleNameLower = roleName.toLowerCase(Locale.US);
+ if (!roleName.equals(roleNameLower)) {
+ if (!rolesCaseMapping.containsKey(roleNameLower)) {
+ rolesCaseMapping.put(roleNameLower, Sets.newHashSet(roleName));
+ } else {
+ rolesCaseMapping.get(roleNameLower).add(roleName);
+ }
+ }
+ }
+
+ List<String> errors = new LinkedList<String>();
+ StringBuilder warningString = new StringBuilder();
+ if (!rolesCaseMapping.isEmpty()) {
+ warningString.append("The following roles names will be lower cased when added to the Sentry Service.\n");
+ warningString.append("This will cause document-level security to fail to match the role tokens.\n");
+ warningString.append("Role names: ");
+ }
+ boolean firstWarning = true;
+
+ for (Map.Entry<String, Set<String>> entry : rolesCaseMapping.entrySet()) {
+ Set<String> caseMapping = entry.getValue();
+ if (caseMapping.size() > 1) {
+ StringBuilder errorString = new StringBuilder();
+ errorString.append("The following (cased) roles map to the same role in the sentry service: ");
+ boolean first = true;
+ for (String casedRole : caseMapping) {
+ errorString.append(first ? "" : ", ");
+ errorString.append(casedRole);
+ first = false;
+ }
+ errorString.append(". Role in service: ").append(entry.getKey());
+ errors.add(errorString.toString());
+ }
+
+ for (String casedRole : caseMapping) {
+ warningString.append(firstWarning? "" : ", ");
+ warningString.append(casedRole);
+ firstWarning = false;
+ }
+ }
+
+ for (String error : errors) {
+ System.out.println("ERROR: " + error);
+ }
+ System.out.println("\n");
+
+ System.out.println("Warning: " + warningString.toString());
+ if (errors.size() > 0) {
+ SentryConfigurationException ex =
+ new SentryConfigurationException("Compatibility check failure");
+ ex.setConfigErrors(errors);
+ ex.setConfigWarnings(Lists.<String>asList(warningString.toString(), new String[0]));
+ throw ex;
+ }
+ }
+
+ private String dryRunMessage(boolean importPolicy) {
+ if (importPolicy) {
+ return "";
+ } else {
+ return "[Dry Run] ";
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryConfigToolSolr.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryConfigToolSolr.java b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryConfigToolSolr.java
new file mode 100644
index 0000000..dfa981d
--- /dev/null
+++ b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryConfigToolSolr.java
@@ -0,0 +1,265 @@
+/**
+ * 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.Lists;
+import com.google.common.collect.Sets;
+import com.google.common.collect.Table;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.sentry.core.common.Action;
+import org.apache.sentry.core.common.exception.SentryConfigurationException;
+import org.apache.sentry.core.common.utils.KeyValue;
+import org.apache.sentry.core.common.utils.SentryConstants;
+import org.apache.sentry.core.model.solr.SolrPrivilegeModel;
+import org.apache.sentry.provider.common.ProviderBackend;
+import org.apache.sentry.provider.common.ProviderBackendContext;
+import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClient;
+import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClientFactory;
+import org.apache.sentry.provider.db.generic.tools.GenericPrivilegeConverter;
+import org.apache.sentry.provider.file.SimpleFileProviderBackend;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * SentryConfigToolSolr is an administrative tool used to parse a Solr policy file
+ * and add the role, group mappings, and privileges therein to the Sentry service.
+ */
+public class SentryConfigToolSolr extends SentryConfigToolCommon {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(SentryConfigToolSolr.class);
+ public static final String SOLR_SERVICE_NAME = "sentry.service.client.solr.service.name";
+
+ @Override
+ public void run() throws Exception {
+ String component = "SOLR";
+ Configuration conf = getSentryConf();
+
+ String service = conf.get(SOLR_SERVICE_NAME, "service1");
+ // instantiate a solr client for sentry service. This sets the ugi, so must
+ // be done before getting the ugi below.
+ try(SentryGenericServiceClient client =
+ SentryGenericServiceClientFactory.create(conf)) {
+ UserGroupInformation ugi = UserGroupInformation.getLoginUser();
+ String requestorName = ugi.getShortUserName();
+
+ convertINIToSentryServiceCmds(component, service, requestorName, conf, client,
+ getPolicyFile(), getValidate(), getImportPolicy(), getCheckCompat());
+ }
+ }
+
+ private Configuration getSentryConf() {
+ Configuration conf = new Configuration();
+ conf.addResource(new Path(getConfPath()), true);
+ return conf;
+ }
+
+ /**
+ * Convert policy file to solrctl commands -- based on SENTRY-480
+ */
+ private void convertINIToSentryServiceCmds(String component,
+ String service, String requestorName,
+ Configuration conf, SentryGenericServiceClient client,
+ String policyFile, boolean validate, boolean importPolicy,
+ boolean checkCompat) throws Exception {
+
+ //instantiate a file providerBackend for parsing
+ LOGGER.info("Reading policy file at: " + policyFile);
+ SimpleFileProviderBackend policyFileBackend =
+ new SimpleFileProviderBackend(conf, policyFile);
+ ProviderBackendContext context = new ProviderBackendContext();
+ context.setValidators(SolrPrivilegeModel.getInstance().getPrivilegeValidators());
+ policyFileBackend.initialize(context);
+ if (validate) {
+ validatePolicy(policyFileBackend);
+ }
+
+ if (checkCompat) {
+ checkCompat(policyFileBackend);
+ }
+
+ //import the relations about group,role and privilege into the DB store
+ Set<String> roles = Sets.newHashSet();
+ Table<String, String, Set<String>> groupRolePrivilegeTable =
+ policyFileBackend.getGroupRolePrivilegeTable();
+ GenericPrivilegeConverter converter = new GenericPrivilegeConverter(component, service, false);
+
+ for (String groupName : groupRolePrivilegeTable.rowKeySet()) {
+ for (String roleName : groupRolePrivilegeTable.columnKeySet()) {
+ if (!roles.contains(roleName)) {
+ LOGGER.info(dryRunMessage(importPolicy) + "Creating role: " + roleName.toLowerCase(Locale.US));
+ if (importPolicy) {
+ client.createRoleIfNotExist(requestorName, roleName, component);
+ }
+ roles.add(roleName);
+ }
+
+ Set<String> privileges = groupRolePrivilegeTable.get(groupName, roleName);
+ if (privileges == null) {
+ continue;
+ }
+ LOGGER.info(dryRunMessage(importPolicy) + "Adding role: " + roleName.toLowerCase(Locale.US) + " to group: " + groupName);
+ if (importPolicy) {
+ client.grantRoleToGroups(requestorName, roleName, component, Sets.newHashSet(groupName));
+ }
+
+ for (String permission : privileges) {
+ String action = null;
+
+ for (String authorizable : SentryConstants.AUTHORIZABLE_SPLITTER.
+ trimResults().split(permission)) {
+ KeyValue kv = new KeyValue(authorizable);
+ String key = kv.getKey();
+ String value = kv.getValue();
+ if ("action".equalsIgnoreCase(key)) {
+ action = value;
+ }
+ }
+
+ // Service doesn't support not specifying action
+ if (action == null) {
+ permission += "->action=" + Action.ALL;
+ }
+ LOGGER.info(dryRunMessage(importPolicy) + "Adding permission: " + permission + " to role: " + roleName.toLowerCase(Locale.US));
+ if (importPolicy) {
+ client.grantPrivilege(requestorName, roleName, component, converter.fromString(permission));
+ }
+ }
+ }
+ }
+ }
+
+ private void validatePolicy(ProviderBackend backend) throws Exception {
+ try {
+ backend.validatePolicy(true);
+ } catch (SentryConfigurationException e) {
+ printConfigErrorsWarnings(e);
+ throw e;
+ }
+ }
+
+ private void printConfigErrorsWarnings(SentryConfigurationException configException) {
+ System.out.println(" *** Found configuration problems *** ");
+ for (String errMsg : configException.getConfigErrors()) {
+ System.out.println("ERROR: " + errMsg);
+ }
+ for (String warnMsg : configException.getConfigWarnings()) {
+ System.out.println("Warning: " + warnMsg);
+ }
+ }
+
+ private void checkCompat(SimpleFileProviderBackend backend) throws Exception {
+ Map<String, Set<String>> rolesCaseMapping = new HashMap<String, Set<String>>();
+ Table<String, String, Set<String>> groupRolePrivilegeTable =
+ backend.getGroupRolePrivilegeTable();
+
+ for (String roleName : groupRolePrivilegeTable.columnKeySet()) {
+ String roleNameLower = roleName.toLowerCase(Locale.US);
+ if (!roleName.equals(roleNameLower)) {
+ if (!rolesCaseMapping.containsKey(roleNameLower)) {
+ rolesCaseMapping.put(roleNameLower, Sets.newHashSet(roleName));
+ } else {
+ rolesCaseMapping.get(roleNameLower).add(roleName);
+ }
+ }
+ }
+
+ List<String> errors = new LinkedList<String>();
+ StringBuilder warningString = new StringBuilder();
+ if (!rolesCaseMapping.isEmpty()) {
+ warningString.append("The following roles names will be lower cased when added to the Sentry Service.\n");
+ warningString.append("This will cause document-level security to fail to match the role tokens.\n");
+ warningString.append("Role names: ");
+ }
+ boolean firstWarning = true;
+
+ for (Map.Entry<String, Set<String>> entry : rolesCaseMapping.entrySet()) {
+ Set<String> caseMapping = entry.getValue();
+ if (caseMapping.size() > 1) {
+ StringBuilder errorString = new StringBuilder();
+ errorString.append("The following (cased) roles map to the same role in the sentry service: ");
+ boolean first = true;
+ for (String casedRole : caseMapping) {
+ errorString.append(first ? "" : ", ");
+ errorString.append(casedRole);
+ first = false;
+ }
+ errorString.append(". Role in service: ").append(entry.getKey());
+ errors.add(errorString.toString());
+ }
+
+ for (String casedRole : caseMapping) {
+ warningString.append(firstWarning? "" : ", ");
+ warningString.append(casedRole);
+ firstWarning = false;
+ }
+ }
+
+ for (String error : errors) {
+ System.out.println("ERROR: " + error);
+ }
+ System.out.println("\n");
+
+ System.out.println("Warning: " + warningString.toString());
+ if (errors.size() > 0) {
+ SentryConfigurationException ex =
+ new SentryConfigurationException("Compatibility check failure");
+ ex.setConfigErrors(errors);
+ ex.setConfigWarnings(Lists.<String>asList(warningString.toString(), new String[0]));
+ throw ex;
+ }
+ }
+
+ private String dryRunMessage(boolean importPolicy) {
+ if (importPolicy) {
+ return "";
+ } else {
+ return "[Dry Run] ";
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ SentryConfigToolSolr solrTool = new SentryConfigToolSolr();
+ try {
+ solrTool.executeConfigTool(args);
+ } catch (Exception e) {
+ LOGGER.error(e.getMessage(), e);
+ Throwable current = e;
+ // find the first printable message;
+ while (current != null && current.getMessage() == null) {
+ current = current.getCause();
+ }
+ String error = "";
+ if (current != null && current.getMessage() != null) {
+ error = "Message: " + current.getMessage();
+ }
+ System.out.println("The operation failed. " + error);
+ System.exit(1);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentrySchemaHelper.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentrySchemaHelper.java b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentrySchemaHelper.java
new file mode 100644
index 0000000..3723fd9
--- /dev/null
+++ b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentrySchemaHelper.java
@@ -0,0 +1,315 @@
+/**
+ * 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.util.IllegalFormatException;
+
+public final class SentrySchemaHelper {
+ public static final String DB_DERBY = "derby";
+ public static final String DB_MYSQL = "mysql";
+ public static final String DB_POSTGRACE = "postgres";
+ public static final String DB_ORACLE = "oracle";
+ public static final String DB_DB2 = "db2";
+
+ public interface NestedScriptParser {
+
+ public enum CommandType {
+ PARTIAL_STATEMENT,
+ TERMINATED_STATEMENT,
+ COMMENT
+ }
+
+ String DEFAUTL_DELIMITER = ";";
+ /***
+ * Find the type of given command
+ * @param dbCommand
+ * @return
+ */
+ boolean isPartialCommand(String dbCommand) throws IllegalArgumentException;
+
+ /** Parse the DB specific nesting format and extract the inner script name if any
+ * @param dbCommand command from parent script
+ * @return
+ * @throws IllegalFormatException
+ */
+ String getScriptName(String dbCommand) throws IllegalArgumentException;
+
+ /***
+ * Find if the given command is a nested script execution
+ * @param dbCommand
+ * @return
+ */
+ boolean isNestedScript(String dbCommand);
+
+ /***
+ * Find if the given command is should be passed to DB
+ * @param dbCommand
+ * @return
+ */
+ boolean isNonExecCommand(String dbCommand);
+
+ /***
+ * Get the SQL statement delimiter
+ * @return
+ */
+ String getDelimiter();
+
+ /***
+ * Clear any client specific tags
+ * @return
+ */
+ String cleanseCommand(String dbCommand);
+
+ /***
+ * Does the DB required table/column names quoted
+ * @return
+ */
+ boolean needsQuotedIdentifier();
+
+ /***
+ * Set DB specific options if any
+ * @param dbOps
+ */
+ void setDbOpts(String dbOps);
+ }
+
+
+ /***
+ * Base implemenation of NestedScriptParser
+ * abstractCommandParser.
+ *
+ */
+ private static abstract class AbstractCommandParser implements NestedScriptParser {
+ private String dbOpts = null;
+
+ @Override
+ public boolean isPartialCommand(String dbCommand) throws IllegalArgumentException{
+ if (dbCommand == null || dbCommand.isEmpty()) {
+ throw new IllegalArgumentException("invalid command line " + dbCommand);
+ }
+ String trimmedDbCommand = dbCommand.trim();
+ return !(trimmedDbCommand.endsWith(getDelimiter()) || isNonExecCommand(trimmedDbCommand));
+ }
+
+ @Override
+ public boolean isNonExecCommand(String dbCommand) {
+ return dbCommand.startsWith("--") || dbCommand.startsWith("#");
+ }
+
+ @Override
+ public String getDelimiter() {
+ return DEFAUTL_DELIMITER;
+ }
+
+ @Override
+ public String cleanseCommand(String dbCommand) {
+ // strip off the delimiter
+ if (dbCommand.endsWith(getDelimiter())) {
+ dbCommand = dbCommand.substring(0,
+ dbCommand.length() - getDelimiter().length());
+ }
+ return dbCommand;
+ }
+
+ @Override
+ public boolean needsQuotedIdentifier() {
+ return false;
+ }
+
+ @Override
+ public void setDbOpts(String dbOpts) {
+ this.dbOpts = dbOpts;
+ }
+
+ protected String getDbOpts() {
+ return dbOpts;
+ }
+ }
+
+
+ // Derby commandline parser
+ public static class DerbyCommandParser extends AbstractCommandParser {
+ private static final String DERBY_NESTING_TOKEN = "RUN";
+
+ @Override
+ public String getScriptName(String dbCommand) throws IllegalArgumentException {
+
+ if (!isNestedScript(dbCommand)) {
+ throw new IllegalArgumentException("Not a script format " + dbCommand);
+ }
+ String[] tokens = dbCommand.split(" ");
+ if (tokens.length != 2) {
+ throw new IllegalArgumentException("Couldn't parse line " + dbCommand);
+ }
+ return tokens[1].replace(";", "").replaceAll("'", "");
+ }
+
+ @Override
+ public boolean isNestedScript(String dbCommand) {
+ // Derby script format is RUN '<file>'
+ return dbCommand.startsWith(DERBY_NESTING_TOKEN);
+ }
+ }
+
+
+ // MySQL parser
+ public static class MySqlCommandParser extends AbstractCommandParser {
+ private static final String MYSQL_NESTING_TOKEN = "SOURCE";
+ private static final String DELIMITER_TOKEN = "DELIMITER";
+ private String delimiter = DEFAUTL_DELIMITER;
+
+ @Override
+ public boolean isPartialCommand(String dbCommand) throws IllegalArgumentException{
+ boolean isPartial = super.isPartialCommand(dbCommand);
+ // if this is a delimiter directive, reset our delimiter
+ if (dbCommand.startsWith(DELIMITER_TOKEN)) {
+ String[] tokens = dbCommand.split(" ");
+ if (tokens.length != 2) {
+ throw new IllegalArgumentException("Couldn't parse line " + dbCommand);
+ }
+ delimiter = tokens[1];
+ }
+ return isPartial;
+ }
+
+ @Override
+ public String getScriptName(String dbCommand) throws IllegalArgumentException {
+ String[] tokens = dbCommand.split(" ");
+ if (tokens.length != 2) {
+ throw new IllegalArgumentException("Couldn't parse line " + dbCommand);
+ }
+ // remove ending ';'
+ return tokens[1].replace(";", "");
+ }
+
+ @Override
+ public boolean isNestedScript(String dbCommand) {
+ return dbCommand.startsWith(MYSQL_NESTING_TOKEN);
+ }
+
+ @Override
+ public String getDelimiter() {
+ return delimiter;
+ }
+
+ @Override
+ public boolean isNonExecCommand(String dbCommand) {
+ return super.isNonExecCommand(dbCommand) ||
+ dbCommand.startsWith("/*") && dbCommand.endsWith("*/") ||
+ dbCommand.startsWith(DELIMITER_TOKEN);
+ }
+
+ @Override
+ public String cleanseCommand(String dbCommand) {
+ return super.cleanseCommand(dbCommand).replaceAll("/\\*.*?\\*/[^;]", "");
+ }
+
+ }
+
+ // Postgres specific parser
+ public static class PostgresCommandParser extends AbstractCommandParser {
+ public static final String POSTGRES_STRING_COMMAND_FILTER = "SET standard_conforming_strings";
+ public static final String POSTGRES_STRING_CLIENT_ENCODING = "SET client_encoding";
+ public static final String POSTGRES_SKIP_STANDARD_STRING = "postgres.filter.81";
+ private static final String POSTGRES_NESTING_TOKEN = "\\i";
+
+ @Override
+ public String getScriptName(String dbCommand) throws IllegalArgumentException {
+ String[] tokens = dbCommand.split(" ");
+ if (tokens.length != 2) {
+ throw new IllegalArgumentException("Couldn't parse line " + dbCommand);
+ }
+ // remove ending ';'
+ return tokens[1].replace(";", "");
+ }
+
+ @Override
+ public boolean isNestedScript(String dbCommand) {
+ return dbCommand.startsWith(POSTGRES_NESTING_TOKEN);
+ }
+
+ @Override
+ public boolean needsQuotedIdentifier() {
+ return true;
+ }
+
+ @Override
+ public boolean isNonExecCommand(String dbCommand) {
+ // Skip "standard_conforming_strings" command which is not supported in older postgres
+ if (POSTGRES_SKIP_STANDARD_STRING.equalsIgnoreCase(getDbOpts())
+ && (dbCommand.startsWith(POSTGRES_STRING_COMMAND_FILTER) || dbCommand.startsWith(POSTGRES_STRING_CLIENT_ENCODING))) {
+ return true;
+ }
+ return super.isNonExecCommand(dbCommand);
+ }
+ }
+
+ //Oracle specific parser
+ public static class OracleCommandParser extends AbstractCommandParser {
+ private static final String ORACLE_NESTING_TOKEN = "@";
+ @Override
+ public String getScriptName(String dbCommand) throws IllegalArgumentException {
+ if (!isNestedScript(dbCommand)) {
+ throw new IllegalArgumentException("Not a nested script format " + dbCommand);
+ }
+ // remove ending ';' and starting '@'
+ return dbCommand.replace(";", "").replace(ORACLE_NESTING_TOKEN, "");
+ }
+
+ @Override
+ public boolean isNestedScript(String dbCommand) {
+ return dbCommand.startsWith(ORACLE_NESTING_TOKEN);
+ }
+ }
+
+ // DB2 commandline parser
+ public static class DB2CommandParser extends AbstractCommandParser {
+
+ @Override
+ public String getScriptName(String dbCommand) throws IllegalArgumentException {
+ //DB2 does not support nesting script
+ throw new IllegalArgumentException("DB2 does not support nesting script " + dbCommand);
+ }
+
+ @Override
+ public boolean isNestedScript(String dbCommand) {
+ //DB2 does not support nesting script
+ return false;
+ }
+ }
+
+ public static NestedScriptParser getDbCommandParser(String dbName) {
+ if (dbName.equalsIgnoreCase(DB_DERBY)) {
+ return new DerbyCommandParser();
+ } else if (dbName.equalsIgnoreCase(DB_MYSQL)) {
+ return new MySqlCommandParser();
+ } else if (dbName.equalsIgnoreCase(DB_POSTGRACE)) {
+ return new PostgresCommandParser();
+ } else if (dbName.equalsIgnoreCase(DB_ORACLE)) {
+ return new OracleCommandParser();
+ } else if (dbName.equalsIgnoreCase(DB_DB2)) {
+ return new DB2CommandParser();
+ } else {
+ throw new IllegalArgumentException("Unknown dbType " + dbName);
+ }
+ }
+
+ private SentrySchemaHelper() {
+ // Make constructor private to avoid instantiation
+ }
+}