http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryShellKafka.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryShellKafka.java b/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryShellKafka.java new file mode 100644 index 0000000..7db5426 --- /dev/null +++ b/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryShellKafka.java @@ -0,0 +1,542 @@ +/** + * 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.apache.shiro.config.ConfigurationException; +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 = "kafka1"; + + @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() }; + SentryShellKafka.main(args); + // test: create role with --create_role + args = new String[] { "--create_role", "-r", TEST_ROLE_NAME_2, "-conf", + confPath.getAbsolutePath() }; + SentryShellKafka.main(args); + + // validate the result, list roles with -lr + args = new String[] { "-lr", "-conf", confPath.getAbsolutePath() }; + SentryShellKafka sentryShell = new SentryShellKafka(); + 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 SentryShellKafka(); + 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() }; + SentryShellKafka.main(args); + // test: drop role with --drop_role + args = new String[] { "--drop_role", "-r", TEST_ROLE_NAME_2, "-conf", + confPath.getAbsolutePath() }; + SentryShellKafka.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() }; + SentryShellKafka.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() }; + SentryShellKafka.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() }; + SentryShellKafka.main(args); + + // validate the result list roles with -lr and -g + args = new String[] { "-lr", "-g", TEST_GROUP_1, "-conf", confPath.getAbsolutePath() }; + SentryShellKafka sentryShell = new SentryShellKafka(); + 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 SentryShellKafka(); + 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 SentryShellKafka(); + 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() }; + SentryShellKafka.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() }; + SentryShellKafka.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() }; + SentryShellKafka.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()}; + SentryShellKafka.main(args); + + // validate the roles when group name is same case as above + args = new String[]{"-lr", "-g", "group1", "-conf", confPath.getAbsolutePath()}; + SentryShellKafka sentryShell = new SentryShellKafka(); + 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, 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() }; + SentryShellKafka.main(args); + } + + // test the list privilege + String [] args = new String[] { list(shortOption), "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() }; + SentryShellKafka sentryShell = new SentryShellKafka(); + 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() }; + SentryShellKafka.main(args); + Set<TSentryPrivilege> privileges = client.listPrivilegesByRoleName(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() }; + SentryShellKafka sentryShell = new SentryShellKafka(); + 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() }; + sentryShell = new SentryShellKafka(); + 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() }; + sentryShell = new SentryShellKafka(); + 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() }; + sentryShell = new SentryShellKafka(); + 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() }; + sentryShell = new SentryShellKafka(); + 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() }; + sentryShell = new SentryShellKafka(); + try { + sentryShell.executeShell(args); + fail("Exception should be thrown for the error privilege format, invalid key value."); + } catch (ConfigurationException 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 }; + SentryShellKafka sentryShell = new SentryShellKafka(); + 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 SentryShellKafka(); + 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 SentryShellKafka(); + 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 SentryShellKafka(); + 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 SentryShellKafka(); + 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 SentryShellKafka(); + 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 SentryShellKafka(); + 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 SentryShellKafka(); + 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 SentryShellKafka(); + 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" }; + sentryShell = new SentryShellKafka(); + try { + getShellResultWithOSRedirect(sentryShell, args, false); + fail("Expected IllegalArgumentException"); + } catch (ConfigurationException e) { + assert(("Kafka privilege must end with a valid action.\n" + KafkaPrivilegeValidator.KafkaPrivilegeHelpMsg).equals(e.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() }; + sentryShell = new SentryShellKafka(); + 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 SentryShellKafka(); + 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 SentryShellKafka(); + 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(SentryShellKafka 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(SentryShellKafka 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(SentryShellKafka 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/e72e6eac/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryShellSolr.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryShellSolr.java b/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryShellSolr.java new file mode 100644 index 0000000..d4e26e8 --- /dev/null +++ b/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryShellSolr.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.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() }; + SentryShellSolr.main(args); + // test: create role with --create_role + args = new String[] { "--create_role", "-r", TEST_ROLE_NAME_2, "-conf", + confPath.getAbsolutePath() }; + SentryShellSolr.main(args); + + // validate the result, list roles with -lr + args = new String[] { "-lr", "-conf", confPath.getAbsolutePath() }; + SentryShellSolr sentryShell = new SentryShellSolr(); + 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 SentryShellSolr(); + 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() }; + SentryShellSolr.main(args); + // test: drop role with --drop_role + args = new String[] { "--drop_role", "-r", TEST_ROLE_NAME_2, "-conf", + confPath.getAbsolutePath() }; + SentryShellSolr.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() }; + SentryShellSolr.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() }; + SentryShellSolr.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() }; + SentryShellSolr.main(args); + + // validate the result list roles with -lr and -g + args = new String[] { "-lr", "-g", TEST_GROUP_1, "-conf", confPath.getAbsolutePath() }; + SentryShellSolr sentryShell = new SentryShellSolr(); + 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 SentryShellSolr(); + 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 SentryShellSolr(); + 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() }; + SentryShellSolr.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() }; + SentryShellSolr.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() }; + SentryShellSolr.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() }; + SentryShellSolr.main(args); + + // validate the roles when group name is same case as above + args = new String[] { "-lr", "-g", "group1", "-conf", confPath.getAbsolutePath() }; + SentryShellSolr sentryShell = new SentryShellSolr(); + 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, 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() }; + SentryShellSolr.main(args); + } + + // test the list privilege + String [] args = new String[] { list(shortOption), "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() }; + SentryShellSolr sentryShell = new SentryShellSolr(); + 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() }; + SentryShellSolr.main(args); + Set<TSentryPrivilege> privileges = client.listPrivilegesByRoleName(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() }; + SentryShellSolr sentryShell = new SentryShellSolr(); + 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 SentryShellSolr(); + 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 SentryShellSolr(); + 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 SentryShellSolr(); + 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 SentryShellSolr(); + 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 SentryShellSolr(); + 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 }; + SentryShellSolr sentryShell = new SentryShellSolr(); + 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 SentryShellSolr(); + 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 SentryShellSolr(); + 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 SentryShellSolr(); + 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 SentryShellSolr(); + 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 SentryShellSolr(); + 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 SentryShellSolr(); + 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 SentryShellSolr(); + 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 SentryShellSolr(); + 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" }; + sentryShell = new SentryShellSolr(); + 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", "server=server1", "-conf", confPath.getAbsolutePath() }; + sentryShell = new SentryShellSolr(); + 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 SentryShellSolr(); + 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 SentryShellSolr(); + 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(SentryShellSolr 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(SentryShellSolr 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(SentryShellSolr 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/e72e6eac/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/log/appender/TestRollingFileWithoutDeleteAppender.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/log/appender/TestRollingFileWithoutDeleteAppender.java b/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/log/appender/TestRollingFileWithoutDeleteAppender.java new file mode 100644 index 0000000..50785fd --- /dev/null +++ b/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/log/appender/TestRollingFileWithoutDeleteAppender.java @@ -0,0 +1,103 @@ +/** + * 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.log.appender; + +import java.io.File; + +import org.apache.commons.io.FileUtils; +import org.apache.log4j.Logger; +import org.apache.log4j.PatternLayout; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.google.common.io.Files; + +public class TestRollingFileWithoutDeleteAppender { + private Logger sentryLogger = Logger.getRootLogger(); + private File dataDir; + + @Before + public void init() { + dataDir = Files.createTempDir(); + } + + @Test + public void testRollOver() throws Throwable { + if (dataDir == null) { + Assert.fail("Excepted temp folder for audit log is created."); + } + RollingFileWithoutDeleteAppender appender = new RollingFileWithoutDeleteAppender( + new PatternLayout("%m%n"), dataDir.getPath() + "/auditLog.log"); + appender.setMaximumFileSize(100); + sentryLogger.addAppender(appender); + // Write exactly 10 bytes with each log + for (int i = 0; i < 99; i++) { + if (i < 10) { + sentryLogger.debug("Hello---" + i); + } else if (i < 100) { + sentryLogger.debug("Hello--" + i); + } + } + + if (dataDir != null) { + File[] files = dataDir.listFiles(); + if (files != null) { + Assert.assertEquals(files.length, 10); + } else { + Assert.fail("Excepted 10 log files."); + } + } else { + Assert.fail("Excepted 10 log files."); + } + + } + + /*** + * Generate log enough to cause a single rollover. Verify the file name format + * @throws Throwable + */ + @Test + public void testFileNamePattern() throws Throwable { + if (dataDir == null) { + Assert.fail("Excepted temp folder for audit log is created."); + } + RollingFileWithoutDeleteAppender appender = new RollingFileWithoutDeleteAppender( + new PatternLayout("%m%n"), dataDir.getPath() + "/auditLog.log"); + appender.setMaximumFileSize(10); + sentryLogger.addAppender(appender); + sentryLogger.debug("123456789012345"); + File[] files = dataDir.listFiles(); + if (files != null) { + Assert.assertEquals(files.length, 2); + Assert.assertTrue(files[0].getName().contains("auditLog.log.")); + Assert.assertTrue(files[1].getName().contains("auditLog.log.")); + } else { + Assert.fail("Excepted 2 log files."); + } + } + + @After + public void destroy() { + if (dataDir != null) { + FileUtils.deleteQuietly(dataDir); + } + } +} http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/log/entity/TestDbAuditMetadataLogEntity.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/log/entity/TestDbAuditMetadataLogEntity.java b/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/log/entity/TestDbAuditMetadataLogEntity.java new file mode 100644 index 0000000..3d15b4f --- /dev/null +++ b/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/log/entity/TestDbAuditMetadataLogEntity.java @@ -0,0 +1,67 @@ +/** + * 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.log.entity; + +import org.apache.sentry.provider.db.log.util.Constants; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.node.ContainerNode; +import org.junit.Assert; +import org.junit.Test; + +public class TestDbAuditMetadataLogEntity { + + @Test + public void testToJsonFormatLog() throws Throwable { + DBAuditMetadataLogEntity amle = new DBAuditMetadataLogEntity("serviceName", "userName", + "impersonator", "ipAddress", "operation", "eventTime", "operationText", "allowed", + "objectType", "component", "databaseName", "tableName", "columnName", "resourcePath"); + String jsonAuditLog = amle.toJsonFormatLog(); + ContainerNode rootNode = AuditMetadataLogEntity.parse(jsonAuditLog); + assertEntryEquals(rootNode, Constants.LOG_FIELD_SERVICE_NAME, "serviceName"); + assertEntryEquals(rootNode, Constants.LOG_FIELD_USER_NAME, "userName"); + assertEntryEquals(rootNode, Constants.LOG_FIELD_IMPERSONATOR, + "impersonator"); + assertEntryEquals(rootNode, Constants.LOG_FIELD_IP_ADDRESS, "ipAddress"); + assertEntryEquals(rootNode, Constants.LOG_FIELD_OPERATION, "operation"); + assertEntryEquals(rootNode, Constants.LOG_FIELD_EVENT_TIME, "eventTime"); + assertEntryEquals(rootNode, Constants.LOG_FIELD_OPERATION_TEXT, + "operationText"); + assertEntryEquals(rootNode, Constants.LOG_FIELD_ALLOWED, "allowed"); + assertEntryEquals(rootNode, Constants.LOG_FIELD_DATABASE_NAME, + "databaseName"); + assertEntryEquals(rootNode, Constants.LOG_FIELD_TABLE_NAME, "tableName"); + assertEntryEquals(rootNode, Constants.LOG_FIELD_COLUMN_NAME, "columnName"); + assertEntryEquals(rootNode, Constants.LOG_FIELD_RESOURCE_PATH, + "resourcePath"); + assertEntryEquals(rootNode, Constants.LOG_FIELD_OBJECT_TYPE, "objectType"); + } + + void assertEntryEquals(ContainerNode rootNode, String key, String value) { + JsonNode node = assertNodeContains(rootNode, key); + Assert.assertEquals(value, node.getTextValue()); + } + + private JsonNode assertNodeContains(ContainerNode rootNode, String key) { + JsonNode node = rootNode.get(key); + if (node == null) { + Assert.fail("No entry of name \"" + key + "\" found in " + rootNode.toString()); + } + return node; + } +} http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/log/entity/TestGMAuditMetadataLogEntity.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/log/entity/TestGMAuditMetadataLogEntity.java b/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/log/entity/TestGMAuditMetadataLogEntity.java new file mode 100644 index 0000000..62b46f6 --- /dev/null +++ b/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/log/entity/TestGMAuditMetadataLogEntity.java @@ -0,0 +1,72 @@ +/** + * 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.log.entity; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.sentry.provider.db.log.util.Constants; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.node.ContainerNode; +import org.junit.Assert; +import org.junit.Test; + +public class TestGMAuditMetadataLogEntity { + @Test + public void testToJsonFormatLog() throws Throwable { + + Map<String, String> privilegesMap = new HashMap<String, String>(); + privilegesMap.put("resourceType1", "resourceName1"); + privilegesMap.put("resourceType2", "resourceName2"); + privilegesMap.put("resourceType3", "resourceName3"); + privilegesMap.put("resourceType4", "resourceName4"); + GMAuditMetadataLogEntity gmamle = new GMAuditMetadataLogEntity("serviceName", "userName", + "impersonator", "ipAddress", "operation", "eventTime", "operationText", "allowed", + "objectType", "component", privilegesMap); + String jsonAuditLog = gmamle.toJsonFormatLog(); + ContainerNode rootNode = AuditMetadataLogEntity.parse(jsonAuditLog); + assertEntryEquals(rootNode, Constants.LOG_FIELD_SERVICE_NAME, "serviceName"); + assertEntryEquals(rootNode, Constants.LOG_FIELD_USER_NAME, "userName"); + assertEntryEquals(rootNode, Constants.LOG_FIELD_IMPERSONATOR, "impersonator"); + assertEntryEquals(rootNode, Constants.LOG_FIELD_IP_ADDRESS, "ipAddress"); + assertEntryEquals(rootNode, Constants.LOG_FIELD_OPERATION, "operation"); + assertEntryEquals(rootNode, Constants.LOG_FIELD_EVENT_TIME, "eventTime"); + assertEntryEquals(rootNode, Constants.LOG_FIELD_OPERATION_TEXT, "operationText"); + assertEntryEquals(rootNode, Constants.LOG_FIELD_ALLOWED, "allowed"); + assertEntryEquals(rootNode, Constants.LOG_FIELD_OBJECT_TYPE, "objectType"); + assertEntryEquals(rootNode, Constants.LOG_FIELD_COMPONENT, "component"); + assertEntryEquals(rootNode, "resourceType1", "resourceName1"); + assertEntryEquals(rootNode, "resourceType2", "resourceName2"); + assertEntryEquals(rootNode, "resourceType3", "resourceName3"); + assertEntryEquals(rootNode, "resourceType4", "resourceName4"); + } + + void assertEntryEquals(ContainerNode rootNode, String key, String value) { + JsonNode node = assertNodeContains(rootNode, key); + Assert.assertEquals(value, node.getTextValue()); + } + + private JsonNode assertNodeContains(ContainerNode rootNode, String key) { + JsonNode node = rootNode.get(key); + if (node == null) { + Assert.fail("No entry of name \"" + key + "\" found in " + rootNode.toString()); + } + return node; + } +} http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/log/entity/TestJsonLogEntityFactory.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/log/entity/TestJsonLogEntityFactory.java b/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/log/entity/TestJsonLogEntityFactory.java new file mode 100644 index 0000000..bf206ea --- /dev/null +++ b/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/log/entity/TestJsonLogEntityFactory.java @@ -0,0 +1,272 @@ +/** + * 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.log.entity; + +import static org.junit.Assert.assertEquals; + +import java.util.LinkedHashSet; +import java.util.Set; + +import org.apache.hadoop.conf.Configuration; +import org.apache.sentry.core.model.db.AccessConstants; +import org.apache.sentry.provider.db.log.util.Constants; +import org.apache.sentry.provider.db.service.thrift.TAlterSentryRoleAddGroupsRequest; +import org.apache.sentry.provider.db.service.thrift.TAlterSentryRoleAddGroupsResponse; +import org.apache.sentry.provider.db.service.thrift.TAlterSentryRoleDeleteGroupsRequest; +import org.apache.sentry.provider.db.service.thrift.TAlterSentryRoleDeleteGroupsResponse; +import org.apache.sentry.provider.db.service.thrift.TAlterSentryRoleGrantPrivilegeRequest; +import org.apache.sentry.provider.db.service.thrift.TAlterSentryRoleGrantPrivilegeResponse; +import org.apache.sentry.provider.db.service.thrift.TAlterSentryRoleRevokePrivilegeRequest; +import org.apache.sentry.provider.db.service.thrift.TAlterSentryRoleRevokePrivilegeResponse; +import org.apache.sentry.provider.db.service.thrift.TCreateSentryRoleRequest; +import org.apache.sentry.provider.db.service.thrift.TCreateSentryRoleResponse; +import org.apache.sentry.provider.db.service.thrift.TDropSentryRoleRequest; +import org.apache.sentry.provider.db.service.thrift.TDropSentryRoleResponse; +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.ThriftUtil; +import org.apache.sentry.service.thrift.ServiceConstants.PrivilegeScope; +import org.apache.sentry.service.thrift.ServiceConstants.ServerConfig; +import org.apache.sentry.service.thrift.Status; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.google.common.collect.Sets; + +public class TestJsonLogEntityFactory { + + private static Configuration conf; + + private static String TEST_IP = "localhost/127.0.0.1"; + private static String TEST_IMPERSONATOR = "impersonator"; + private static String TEST_ROLE_NAME = "testRole"; + private static String TEST_USER_NAME = "requestUser"; + private static String TEST_DATABASE_NAME = "testDB"; + private static String TEST_TABLE_NAME = "testTable"; + private static String TEST_GROUP = "testGroup"; + + @BeforeClass + public static void init() { + conf = new Configuration(); + conf.set(ServerConfig.SENTRY_SERVICE_NAME, + ServerConfig.SENTRY_SERVICE_NAME_DEFAULT); + ThriftUtil.setIpAddress(TEST_IP); + ThriftUtil.setImpersonator(TEST_IMPERSONATOR); + } + + @Test + public void testCreateRole() { + TCreateSentryRoleRequest request = new TCreateSentryRoleRequest(); + TCreateSentryRoleResponse response = new TCreateSentryRoleResponse(); + request.setRequestorUserName(TEST_USER_NAME); + request.setRoleName(TEST_ROLE_NAME); + response.setStatus(Status.OK()); + DBAuditMetadataLogEntity amle = (DBAuditMetadataLogEntity) JsonLogEntityFactory + .getInstance().createJsonLogEntity(request, response, conf); + assertCommon(amle, Constants.TRUE, Constants.OPERATION_CREATE_ROLE, + "CREATE ROLE testRole", null, null, null, Constants.OBJECT_TYPE_ROLE); + + response.setStatus(Status.InvalidInput("", null)); + amle = (DBAuditMetadataLogEntity) JsonLogEntityFactory.getInstance() + .createJsonLogEntity(request, response, conf); + assertCommon(amle, Constants.FALSE, Constants.OPERATION_CREATE_ROLE, + "CREATE ROLE testRole", null, null, null, Constants.OBJECT_TYPE_ROLE); + } + + @Test + public void testDropRole() { + TDropSentryRoleRequest request = new TDropSentryRoleRequest(); + TDropSentryRoleResponse response = new TDropSentryRoleResponse(); + request.setRequestorUserName(TEST_USER_NAME); + request.setRoleName(TEST_ROLE_NAME); + response.setStatus(Status.OK()); + DBAuditMetadataLogEntity amle = (DBAuditMetadataLogEntity) JsonLogEntityFactory + .getInstance().createJsonLogEntity(request, response, conf); + assertCommon(amle, Constants.TRUE, Constants.OPERATION_DROP_ROLE, + "DROP ROLE testRole", null, null, null, Constants.OBJECT_TYPE_ROLE); + + response.setStatus(Status.InvalidInput("", null)); + amle = (DBAuditMetadataLogEntity) JsonLogEntityFactory.getInstance() + .createJsonLogEntity(request, response, conf); + assertCommon(amle, Constants.FALSE, Constants.OPERATION_DROP_ROLE, + "DROP ROLE testRole", null, null, null, Constants.OBJECT_TYPE_ROLE); + } + + @Test + public void testGrantRole() { + TAlterSentryRoleGrantPrivilegeRequest request = new TAlterSentryRoleGrantPrivilegeRequest(); + request.setRequestorUserName(TEST_USER_NAME); + request.setRoleName(TEST_ROLE_NAME); + + TAlterSentryRoleGrantPrivilegeResponse response = new TAlterSentryRoleGrantPrivilegeResponse(); + + TSentryPrivilege privilege = getPrivilege(AccessConstants.ALL, + PrivilegeScope.DATABASE.name(), TEST_DATABASE_NAME, null, null, null); + Set<TSentryPrivilege> privileges = Sets.newHashSet(); + privileges.add(privilege); + request.setPrivileges(privileges); + response.setStatus(Status.OK()); + DBAuditMetadataLogEntity amle = new DBAuditMetadataLogEntity(); + Set<JsonLogEntity> amles = JsonLogEntityFactory + .getInstance().createJsonLogEntitys(request, response, conf); + assertEquals(amles.size(), 1); + amle = (DBAuditMetadataLogEntity) amles.iterator().next(); + + assertCommon(amle, Constants.TRUE, Constants.OPERATION_GRANT_PRIVILEGE, + "GRANT ALL ON DATABASE testDB TO ROLE testRole", TEST_DATABASE_NAME, + null, null, Constants.OBJECT_TYPE_PRINCIPAL); + + privilege = getPrivilege(AccessConstants.ALL, PrivilegeScope.TABLE.name(), + null, TEST_TABLE_NAME, null, null); + privileges = Sets.newHashSet(); + privileges.add(privilege); + request.setPrivileges(privileges); + response.setStatus(Status.InvalidInput("", null)); + amles = JsonLogEntityFactory.getInstance() + .createJsonLogEntitys(request, response, conf); + assertEquals(amles.size(), 1); + amle = (DBAuditMetadataLogEntity) amles.iterator().next(); + + assertCommon(amle, Constants.FALSE, Constants.OPERATION_GRANT_PRIVILEGE, + "GRANT ALL ON TABLE testTable TO ROLE testRole", null, TEST_TABLE_NAME, + null, Constants.OBJECT_TYPE_PRINCIPAL); + } + + @Test + public void testRevokeRole() { + TAlterSentryRoleRevokePrivilegeRequest request = new TAlterSentryRoleRevokePrivilegeRequest(); + TAlterSentryRoleRevokePrivilegeResponse response = new TAlterSentryRoleRevokePrivilegeResponse(); + request.setRequestorUserName(TEST_USER_NAME); + request.setRoleName(TEST_ROLE_NAME); + + TSentryPrivilege privilege = getPrivilege(AccessConstants.ALL, + PrivilegeScope.DATABASE.name(), TEST_DATABASE_NAME, null, null, null); + Set<TSentryPrivilege> privileges = Sets.newHashSet(); + privileges.add(privilege); + request.setPrivileges(privileges); + response.setStatus(Status.OK()); + DBAuditMetadataLogEntity amle = new DBAuditMetadataLogEntity(); + Set<JsonLogEntity> amles = JsonLogEntityFactory + .getInstance().createJsonLogEntitys(request, response, conf); + assertEquals(amles.size(), 1); + amle = (DBAuditMetadataLogEntity) amles.iterator().next(); + + assertCommon(amle, Constants.TRUE, Constants.OPERATION_REVOKE_PRIVILEGE, + "REVOKE ALL ON DATABASE testDB FROM ROLE testRole", TEST_DATABASE_NAME, + null, null, Constants.OBJECT_TYPE_PRINCIPAL); + + privilege = getPrivilege(AccessConstants.ALL, PrivilegeScope.TABLE.name(), + null, TEST_TABLE_NAME, null, null); + privileges = Sets.newHashSet(); + privileges.add(privilege); + request.setPrivileges(privileges); + response.setStatus(Status.InvalidInput("", null)); + amles = JsonLogEntityFactory.getInstance() + .createJsonLogEntitys(request, response, conf); + assertEquals(amles.size(), 1); + amle = (DBAuditMetadataLogEntity) amles.iterator().next(); + + assertCommon(amle, Constants.FALSE, Constants.OPERATION_REVOKE_PRIVILEGE, + "REVOKE ALL ON TABLE testTable FROM ROLE testRole", null, + TEST_TABLE_NAME, null, Constants.OBJECT_TYPE_PRINCIPAL); + } + + @Test + public void testAddRole() { + TAlterSentryRoleAddGroupsRequest request = new TAlterSentryRoleAddGroupsRequest(); + TAlterSentryRoleAddGroupsResponse response = new TAlterSentryRoleAddGroupsResponse(); + request.setRequestorUserName(TEST_USER_NAME); + request.setRoleName(TEST_ROLE_NAME); + request.setGroups(getGroups()); + response.setStatus(Status.OK()); + DBAuditMetadataLogEntity amle = (DBAuditMetadataLogEntity) JsonLogEntityFactory + .getInstance().createJsonLogEntity(request, response, conf); + assertCommon(amle, Constants.TRUE, Constants.OPERATION_ADD_ROLE, + "GRANT ROLE testRole TO GROUP testGroup", null, null, null, + Constants.OBJECT_TYPE_ROLE); + + response.setStatus(Status.InvalidInput("", null)); + amle = (DBAuditMetadataLogEntity) JsonLogEntityFactory.getInstance() + .createJsonLogEntity(request, response, conf); + assertCommon(amle, Constants.FALSE, Constants.OPERATION_ADD_ROLE, + "GRANT ROLE testRole TO GROUP testGroup", null, null, null, + Constants.OBJECT_TYPE_ROLE); + } + + @Test + public void testDeleteRole() { + TAlterSentryRoleDeleteGroupsRequest request = new TAlterSentryRoleDeleteGroupsRequest(); + TAlterSentryRoleDeleteGroupsResponse response = new TAlterSentryRoleDeleteGroupsResponse(); + request.setRequestorUserName(TEST_USER_NAME); + request.setRoleName(TEST_ROLE_NAME); + request.setGroups(getGroups()); + response.setStatus(Status.OK()); + DBAuditMetadataLogEntity amle = (DBAuditMetadataLogEntity) JsonLogEntityFactory + .getInstance().createJsonLogEntity(request, response, conf); + assertCommon(amle, Constants.TRUE, Constants.OPERATION_DELETE_ROLE, + "REVOKE ROLE testRole FROM GROUP testGroup", null, null, null, + Constants.OBJECT_TYPE_ROLE); + + response.setStatus(Status.InvalidInput("", null)); + amle = (DBAuditMetadataLogEntity) JsonLogEntityFactory.getInstance() + .createJsonLogEntity(request, response, conf); + assertCommon(amle, Constants.FALSE, Constants.OPERATION_DELETE_ROLE, + "REVOKE ROLE testRole FROM GROUP testGroup", null, null, null, + Constants.OBJECT_TYPE_ROLE); + } + + private void assertCommon(DBAuditMetadataLogEntity amle, + String allowedExcepted, String operationExcepted, + String operationTextExcepted, String databaseNameExcepted, + String tableNameExcepted, String resourcePathExcepted, + String objectTypeExcepted) { + assertEquals(ServerConfig.SENTRY_SERVICE_NAME_DEFAULT, + amle.getServiceName()); + assertEquals(TEST_IP, amle.getIpAddress()); + assertEquals(TEST_USER_NAME, amle.getUserName()); + assertEquals(TEST_IMPERSONATOR, amle.getImpersonator()); + assertEquals(allowedExcepted, amle.getAllowed()); + assertEquals(operationExcepted, amle.getOperation()); + assertEquals(operationTextExcepted, amle.getOperationText()); + assertEquals(tableNameExcepted, amle.getTableName()); + assertEquals(databaseNameExcepted, amle.getDatabaseName()); + assertEquals(resourcePathExcepted, amle.getResourcePath()); + assertEquals(objectTypeExcepted, amle.getObjectType()); + } + + private TSentryPrivilege getPrivilege(String action, String privilegeScope, + String dbName, String tableName, String serverName, String URI) { + TSentryPrivilege privilege = new TSentryPrivilege(); + privilege.setAction(action); + privilege.setPrivilegeScope(privilegeScope); + privilege.setDbName(dbName); + privilege.setTableName(tableName); + privilege.setServerName(serverName); + privilege.setURI(URI); + return privilege; + } + + private Set<TSentryGroup> getGroups() { + Set<TSentryGroup> groups = new LinkedHashSet<TSentryGroup>(); + TSentryGroup group = new TSentryGroup(); + group.setGroupName(TEST_GROUP); + groups.add(group); + return groups; + } +} http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/log/entity/TestJsonLogEntityFactoryGM.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/log/entity/TestJsonLogEntityFactoryGM.java b/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/log/entity/TestJsonLogEntityFactoryGM.java new file mode 100644 index 0000000..dfae5ab --- /dev/null +++ b/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/log/entity/TestJsonLogEntityFactoryGM.java @@ -0,0 +1,259 @@ +/** + * 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.log.entity; + +import static org.junit.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.hadoop.conf.Configuration; +import org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleAddGroupsRequest; +import org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleAddGroupsResponse; +import org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleDeleteGroupsRequest; +import org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleDeleteGroupsResponse; +import org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleGrantPrivilegeRequest; +import org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleGrantPrivilegeResponse; +import org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleRevokePrivilegeRequest; +import org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleRevokePrivilegeResponse; +import org.apache.sentry.provider.db.generic.service.thrift.TAuthorizable; +import org.apache.sentry.provider.db.generic.service.thrift.TCreateSentryRoleRequest; +import org.apache.sentry.provider.db.generic.service.thrift.TCreateSentryRoleResponse; +import org.apache.sentry.provider.db.generic.service.thrift.TDropSentryRoleRequest; +import org.apache.sentry.provider.db.generic.service.thrift.TDropSentryRoleResponse; +import org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege; +import org.apache.sentry.provider.db.log.util.Constants; +import org.apache.sentry.provider.db.service.thrift.ThriftUtil; +import org.apache.sentry.service.thrift.ServiceConstants.ServerConfig; +import org.apache.sentry.service.thrift.Status; +import org.junit.BeforeClass; +import org.junit.Test; + +public class TestJsonLogEntityFactoryGM { + + private static Configuration conf; + private static String TEST_IP = "localhost/127.0.0.1"; + private static String TEST_IMPERSONATOR = "impersonator"; + private static String TEST_ROLE_NAME = "testRole"; + private static String TEST_USER_NAME = "requestUser"; + private static String TEST_GROUP = "testGroup"; + private static String TEST_ACTION = "action"; + private static String TEST_COMPONENT = "component"; + private static Map<String, String> TEST_PRIVILEGES_MAP = new HashMap<String, String>(); + + @BeforeClass + public static void init() { + conf = new Configuration(); + conf.set(ServerConfig.SENTRY_SERVICE_NAME, ServerConfig.SENTRY_SERVICE_NAME_DEFAULT); + ThriftUtil.setIpAddress(TEST_IP); + ThriftUtil.setImpersonator(TEST_IMPERSONATOR); + TEST_PRIVILEGES_MAP.put("resourceType1", "resourceName1"); + TEST_PRIVILEGES_MAP.put("resourceType2", "resourceName2"); + TEST_PRIVILEGES_MAP.put("resourceType3", "resourceName3"); + } + + @Test + public void testCreateRole() { + TCreateSentryRoleRequest request = new TCreateSentryRoleRequest(); + TCreateSentryRoleResponse response = new TCreateSentryRoleResponse(); + request.setRequestorUserName(TEST_USER_NAME); + request.setRoleName(TEST_ROLE_NAME); + response.setStatus(Status.OK()); + GMAuditMetadataLogEntity amle = (GMAuditMetadataLogEntity) JsonLogEntityFactory.getInstance() + .createJsonLogEntity(request, response, conf); + assertCommon(amle, Constants.TRUE, Constants.OPERATION_CREATE_ROLE, "CREATE ROLE testRole", + Constants.OBJECT_TYPE_ROLE, new HashMap<String, String>()); + + response.setStatus(Status.InvalidInput("", null)); + amle = (GMAuditMetadataLogEntity) JsonLogEntityFactory.getInstance().createJsonLogEntity( + request, response, conf); + assertCommon(amle, Constants.FALSE, Constants.OPERATION_CREATE_ROLE, "CREATE ROLE testRole", + Constants.OBJECT_TYPE_ROLE, new HashMap<String, String>()); + } + + @Test + public void testDropRole() { + TDropSentryRoleRequest request = new TDropSentryRoleRequest(); + TDropSentryRoleResponse response = new TDropSentryRoleResponse(); + request.setRequestorUserName(TEST_USER_NAME); + request.setRoleName(TEST_ROLE_NAME); + response.setStatus(Status.OK()); + GMAuditMetadataLogEntity amle = (GMAuditMetadataLogEntity) JsonLogEntityFactory + .getInstance().createJsonLogEntity(request, response, conf); + assertCommon(amle, Constants.TRUE, Constants.OPERATION_DROP_ROLE, "DROP ROLE testRole", + Constants.OBJECT_TYPE_ROLE, new HashMap<String, String>()); + + response.setStatus(Status.InvalidInput("", null)); + amle = (GMAuditMetadataLogEntity) JsonLogEntityFactory.getInstance().createJsonLogEntity( + request, response, conf); + assertCommon(amle, Constants.FALSE, Constants.OPERATION_DROP_ROLE, "DROP ROLE testRole", + Constants.OBJECT_TYPE_ROLE, new HashMap<String, String>()); + } + + @Test + public void testGrantRole() { + TAlterSentryRoleGrantPrivilegeRequest request = new TAlterSentryRoleGrantPrivilegeRequest(); + request.setRequestorUserName(TEST_USER_NAME); + request.setRoleName(TEST_ROLE_NAME); + + TAlterSentryRoleGrantPrivilegeResponse response = new TAlterSentryRoleGrantPrivilegeResponse(); + + TSentryPrivilege privilege = getPrivilege(); + request.setPrivilege(privilege); + response.setStatus(Status.OK()); + GMAuditMetadataLogEntity amle = (GMAuditMetadataLogEntity) JsonLogEntityFactory.getInstance() + .createJsonLogEntity( + request, response, conf); + assertCommon( + amle, + Constants.TRUE, + Constants.OPERATION_GRANT_PRIVILEGE, + "GRANT ACTION ON resourceType1 resourceName1 resourceType2 resourceName2 resourceType3 resourceName3 TO ROLE testRole", + Constants.OBJECT_TYPE_PRINCIPAL, TEST_PRIVILEGES_MAP); + + response.setStatus(Status.InvalidInput("", null)); + amle = (GMAuditMetadataLogEntity) JsonLogEntityFactory.getInstance().createJsonLogEntity( + request, response, conf); + assertCommon( + amle, + Constants.FALSE, + Constants.OPERATION_GRANT_PRIVILEGE, + "GRANT ACTION ON resourceType1 resourceName1 resourceType2 resourceName2 resourceType3 resourceName3 TO ROLE testRole", + Constants.OBJECT_TYPE_PRINCIPAL, TEST_PRIVILEGES_MAP); + } + + @Test + public void testRevokeRole() { + TAlterSentryRoleRevokePrivilegeRequest request = new TAlterSentryRoleRevokePrivilegeRequest(); + TAlterSentryRoleRevokePrivilegeResponse response = new TAlterSentryRoleRevokePrivilegeResponse(); + request.setRequestorUserName(TEST_USER_NAME); + request.setRoleName(TEST_ROLE_NAME); + + TSentryPrivilege privilege = getPrivilege(); + request.setPrivilege(privilege); + response.setStatus(Status.OK()); + GMAuditMetadataLogEntity amle = (GMAuditMetadataLogEntity) JsonLogEntityFactory.getInstance() + .createJsonLogEntity(request, response, conf); + assertCommon( + amle, + Constants.TRUE, + Constants.OPERATION_REVOKE_PRIVILEGE, + "REVOKE ACTION ON resourceType1 resourceName1 resourceType2 resourceName2 resourceType3 resourceName3 FROM ROLE testRole", + Constants.OBJECT_TYPE_PRINCIPAL, TEST_PRIVILEGES_MAP); + + response.setStatus(Status.InvalidInput("", null)); + amle = (GMAuditMetadataLogEntity) JsonLogEntityFactory.getInstance().createJsonLogEntity( + request, response, conf); + + assertCommon( + amle, + Constants.FALSE, + Constants.OPERATION_REVOKE_PRIVILEGE, + "REVOKE ACTION ON resourceType1 resourceName1 resourceType2 resourceName2 resourceType3 resourceName3 FROM ROLE testRole", + Constants.OBJECT_TYPE_PRINCIPAL, TEST_PRIVILEGES_MAP); + } + + @Test + public void testAddRole() { + TAlterSentryRoleAddGroupsRequest request = new TAlterSentryRoleAddGroupsRequest(); + TAlterSentryRoleAddGroupsResponse response = new TAlterSentryRoleAddGroupsResponse(); + request.setRequestorUserName(TEST_USER_NAME); + request.setRoleName(TEST_ROLE_NAME); + request.setGroups(getGroups()); + response.setStatus(Status.OK()); + GMAuditMetadataLogEntity amle = (GMAuditMetadataLogEntity) JsonLogEntityFactory.getInstance() + .createJsonLogEntity(request, response, conf); + assertCommon(amle, Constants.TRUE, Constants.OPERATION_ADD_ROLE, + "GRANT ROLE testRole TO GROUP testGroup", Constants.OBJECT_TYPE_ROLE, + new HashMap<String, String>()); + + response.setStatus(Status.InvalidInput("", null)); + amle = (GMAuditMetadataLogEntity) JsonLogEntityFactory.getInstance().createJsonLogEntity( + request, response, conf); + assertCommon(amle, Constants.FALSE, Constants.OPERATION_ADD_ROLE, + "GRANT ROLE testRole TO GROUP testGroup", Constants.OBJECT_TYPE_ROLE, + new HashMap<String, String>()); + } + + @Test + public void testDeleteRole() { + TAlterSentryRoleDeleteGroupsRequest request = new TAlterSentryRoleDeleteGroupsRequest(); + TAlterSentryRoleDeleteGroupsResponse response = new TAlterSentryRoleDeleteGroupsResponse(); + request.setRequestorUserName(TEST_USER_NAME); + request.setRoleName(TEST_ROLE_NAME); + request.setGroups(getGroups()); + response.setStatus(Status.OK()); + GMAuditMetadataLogEntity amle = (GMAuditMetadataLogEntity) JsonLogEntityFactory + .getInstance().createJsonLogEntity(request, response, conf); + assertCommon(amle, Constants.TRUE, Constants.OPERATION_DELETE_ROLE, + "REVOKE ROLE testRole FROM GROUP testGroup", Constants.OBJECT_TYPE_ROLE, + new HashMap<String, String>()); + + response.setStatus(Status.InvalidInput("", null)); + amle = (GMAuditMetadataLogEntity) JsonLogEntityFactory.getInstance().createJsonLogEntity( + request, response, conf); + assertCommon(amle, Constants.FALSE, Constants.OPERATION_DELETE_ROLE, + "REVOKE ROLE testRole FROM GROUP testGroup", Constants.OBJECT_TYPE_ROLE, + new HashMap<String, String>()); + } + + private void assertCommon(GMAuditMetadataLogEntity amle, String allowedExcepted, + String operationExcepted, String operationTextExcepted, String objectTypeExcepted, + Map<String, String> privilegesExcepted) { + assertEquals(ServerConfig.SENTRY_SERVICE_NAME_DEFAULT, amle.getServiceName()); + assertEquals(TEST_IP, amle.getIpAddress()); + assertEquals(TEST_USER_NAME, amle.getUserName()); + assertEquals(TEST_IMPERSONATOR, amle.getImpersonator()); + assertEquals(allowedExcepted, amle.getAllowed()); + assertEquals(operationExcepted, amle.getOperation()); + assertEquals(operationTextExcepted, amle.getOperationText()); + assertEquals(objectTypeExcepted, amle.getObjectType()); + assertPrivilegesMap(privilegesExcepted, amle.getPrivilegesMap()); + } + + private void assertPrivilegesMap(Map<String, String> privilegesExcepted, + Map<String, String> privilegesActual) { + assertEquals(privilegesExcepted.size(), privilegesActual.size()); + for (Map.Entry<String, String> privilege : privilegesExcepted.entrySet()) { + assertEquals(privilege.getValue(), privilegesActual.get(privilege.getKey())); + } + } + + private TSentryPrivilege getPrivilege() { + TSentryPrivilege privilege = new TSentryPrivilege(); + privilege.setAction(TEST_ACTION); + privilege.setComponent(TEST_COMPONENT); + List<TAuthorizable> authorizables = new ArrayList<TAuthorizable>(); + authorizables.add(new TAuthorizable("resourceType1", "resourceName1")); + authorizables.add(new TAuthorizable("resourceType2", "resourceName2")); + authorizables.add(new TAuthorizable("resourceType3", "resourceName3")); + privilege.setAuthorizables(authorizables); + return privilege; + } + + private Set<String> getGroups() { + Set<String> groups = new HashSet<String>(); + groups.add(TEST_GROUP); + return groups; + } +}
