Repository: incubator-sentry Updated Branches: refs/heads/master 46c506d96 -> 7b17cef73
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/7b17cef7/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/persistent/TestSentryStore.java ---------------------------------------------------------------------- diff --git a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/persistent/TestSentryStore.java b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/persistent/TestSentryStore.java index 7e1ae58..985a73d 100644 --- a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/persistent/TestSentryStore.java +++ b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/persistent/TestSentryStore.java @@ -19,6 +19,7 @@ package org.apache.sentry.provider.db.service.persistent; import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; import static junit.framework.Assert.fail; @@ -32,13 +33,16 @@ import org.apache.commons.io.FileUtils; import org.apache.hadoop.conf.Configuration; import org.apache.sentry.core.model.db.AccessConstants; import org.apache.sentry.provider.db.SentryAlreadyExistsException; +import org.apache.sentry.provider.db.SentryGrantDeniedException; import org.apache.sentry.provider.db.SentryNoSuchObjectException; import org.apache.sentry.provider.db.service.model.MSentryPrivilege; import org.apache.sentry.provider.db.service.model.MSentryRole; import org.apache.sentry.provider.db.service.thrift.TSentryActiveRoleSet; import org.apache.sentry.provider.db.service.thrift.TSentryAuthorizable; +import org.apache.sentry.provider.db.service.thrift.TSentryGrantOption; import org.apache.sentry.provider.db.service.thrift.TSentryGroup; import org.apache.sentry.provider.db.service.thrift.TSentryPrivilege; +import org.apache.sentry.provider.file.PolicyFile; import org.apache.sentry.service.thrift.ServiceConstants.ServerConfig; import org.junit.After; import org.junit.Before; @@ -52,6 +56,9 @@ public class TestSentryStore { private File dataDir; private SentryStore sentryStore; + private String[] adminGroups = {"adminGroup1"}; + private PolicyFile policyFile; + private File policyFilePath; @Before public void setup() throws Exception { @@ -60,7 +67,18 @@ public class TestSentryStore { conf.set(ServerConfig.SENTRY_VERIFY_SCHEM_VERSION, "false"); conf.set(ServerConfig.SENTRY_STORE_JDBC_URL, "jdbc:derby:;databaseName=" + dataDir.getPath() + ";create=true"); + conf.setStrings(ServerConfig.ADMIN_GROUPS, adminGroups); + conf.set(ServerConfig.SENTRY_STORE_GROUP_MAPPING, + ServerConfig.SENTRY_STORE_LOCAL_GROUP_MAPPING); + policyFilePath = new File(dataDir, "local_policy_file.ini"); + conf.set(ServerConfig.SENTRY_STORE_GROUP_MAPPING_RESOURCE, + policyFilePath.getPath()); + policyFile = new PolicyFile(); sentryStore = new SentryStore(conf); + + String adminUser = "g1"; + addGroupsToUser(adminUser, adminGroups); + writePolicyFile(); } @After @@ -104,13 +122,13 @@ public class TestSentryStore { sentryStore.createSentryRole(roleName, grantor); TSentryPrivilege tSentryPrivilege = new TSentryPrivilege("URI", "server1", "ALL"); tSentryPrivilege.setURI(uri); + tSentryPrivilege.setGrantorPrincipal(grantor); sentryStore.alterSentryRoleGrantPrivilege(roleName, tSentryPrivilege); TSentryAuthorizable tSentryAuthorizable = new TSentryAuthorizable(); tSentryAuthorizable.setUri(uri); tSentryAuthorizable.setServer("server1"); - Set<TSentryPrivilege> privileges = sentryStore.getTSentryPrivileges(new HashSet<String>(Arrays.asList(roleName)), tSentryAuthorizable); @@ -148,6 +166,7 @@ public class TestSentryStore { long seqId = sentryStore.createSentryRole(roleName, grantor).getSequenceId(); TSentryPrivilege sentryPrivilege = new TSentryPrivilege("Database", "server1", "all"); sentryPrivilege.setDbName("db1"); + sentryPrivilege.setGrantorPrincipal(grantor); assertEquals(seqId + 1, sentryStore.alterSentryRoleGrantPrivilege(roleName, sentryPrivilege).getSequenceId()); } @Test @@ -220,6 +239,334 @@ public class TestSentryStore { assertEquals(db, mPrivilege.getDbName()); assertEquals(table, mPrivilege.getTableName()); assertEquals(AccessConstants.INSERT, mPrivilege.getAction()); + assertFalse(mPrivilege.getGrantOption()); + } + + @Test + public void testGrantRevokePrivilegeWithGrantOption() throws Exception { + String roleName = "test-grantOption-table"; + String grantor = "g1"; + String server = "server1"; + String db = "db1"; + String table = "tbl1"; + TSentryGrantOption grantOption = TSentryGrantOption.TRUE; + long seqId = sentryStore.createSentryRole(roleName, grantor).getSequenceId(); + TSentryPrivilege privilege = new TSentryPrivilege(); + privilege.setPrivilegeScope("TABLE"); + privilege.setServerName(server); + privilege.setDbName(db); + privilege.setTableName(table); + privilege.setAction(AccessConstants.ALL); + privilege.setGrantorPrincipal(grantor); + privilege.setCreateTime(System.currentTimeMillis()); + privilege.setGrantOption(grantOption); + assertEquals(seqId + 1, sentryStore.alterSentryRoleGrantPrivilege(roleName, privilege) + .getSequenceId()); + MSentryRole role = sentryStore.getMSentryRoleByName(roleName); + Set<MSentryPrivilege> privileges = role.getPrivileges(); + assertEquals(privileges.toString(), 1, privileges.size()); + assertEquals(Boolean.valueOf(privilege.getGrantOption().toString()), Iterables.get(privileges, 0).getGrantOption()); + assertEquals(seqId + 2, sentryStore.alterSentryRoleRevokePrivilege(roleName, privilege) + .getSequenceId()); + role = sentryStore.getMSentryRoleByName(roleName); + privileges = role.getPrivileges(); + assertEquals(0, privileges.size()); + + roleName = "test-grantOption-db"; + sentryStore.createSentryRole(roleName, grantor); + privilege = new TSentryPrivilege(); + privilege.setPrivilegeScope("DATABASE"); + privilege.setServerName(server); + privilege.setDbName(db); + privilege.setAction(AccessConstants.ALL); + privilege.setGrantorPrincipal(grantor); + privilege.setGrantOption(TSentryGrantOption.TRUE); + privilege.setCreateTime(System.currentTimeMillis()); + privilege.setGrantOption(grantOption); + sentryStore.alterSentryRoleGrantPrivilege(roleName, privilege); + role = sentryStore.getMSentryRoleByName(roleName); + privileges = role.getPrivileges(); + assertEquals(privileges.toString(), 1, privileges.size()); + + privilege.setAction(AccessConstants.SELECT); + privilege.setGrantOption(TSentryGrantOption.UNSET); + sentryStore.alterSentryRoleRevokePrivilege(roleName, privilege); + // after having ALL and revoking SELECT, we should have INSERT + role = sentryStore.getMSentryRoleByName(roleName); + privileges = role.getPrivileges(); + assertEquals(privileges.toString(), 1, privileges.size()); + MSentryPrivilege mPrivilege = Iterables.get(privileges, 0); + assertEquals(server, mPrivilege.getServerName()); + assertEquals(db, mPrivilege.getDbName()); + assertEquals(AccessConstants.INSERT, mPrivilege.getAction()); + } + + @Test + public void testGrantCheckWithGrantOption() throws Exception { + // 1. set local group mapping + // user0->group0->role0 + // user1->group1->role1 + // user2->group2->role2 + // user3->group3->role3 + // user4->group4->role4 + String grantor = "g1"; + String[] users = {"user0","user1","user2","user3","user4"}; + String[] roles = {"role0","role1","role2","role3","role4"}; + String[] groups = {"group0","group1","group2","group3","group4"}; + for (int i = 0; i < users.length; i++) { + addGroupsToUser(users[i], groups[i]); + sentryStore.createSentryRole(roles[i], grantor); + Set<TSentryGroup> tGroups = Sets.newHashSet(); + TSentryGroup tGroup = new TSentryGroup(groups[i]); + tGroups.add(tGroup); + sentryStore.alterSentryRoleAddGroups(grantor, roles[i], tGroups); + } + writePolicyFile(); + + // 2. g1 grant all on database db1 to role0 with grant option + String server = "server1"; + String db = "db1"; + String table = "tbl1"; + String roleName = roles[0]; + grantor = "g1"; + TSentryPrivilege privilege1 = new TSentryPrivilege(); + privilege1.setPrivilegeScope("DATABASE"); + privilege1.setServerName(server); + privilege1.setDbName(db); + privilege1.setAction(AccessConstants.ALL); + privilege1.setGrantorPrincipal(grantor); + privilege1.setCreateTime(System.currentTimeMillis()); + privilege1.setGrantOption(TSentryGrantOption.TRUE); + sentryStore.alterSentryRoleGrantPrivilege(roleName, privilege1); + MSentryRole role = sentryStore.getMSentryRoleByName(roleName); + Set<MSentryPrivilege> privileges = role.getPrivileges(); + assertEquals(privileges.toString(), 1, privileges.size()); + + // 3. user0 grant select on database db1 to role1, with grant option + roleName = roles[1]; + grantor = users[0]; + TSentryPrivilege privilege2 = new TSentryPrivilege(); + privilege2.setPrivilegeScope("DATABASE"); + privilege2.setServerName(server); + privilege2.setDbName(db); + privilege2.setAction(AccessConstants.SELECT); + privilege2.setGrantorPrincipal(grantor); + privilege2.setCreateTime(System.currentTimeMillis()); + privilege2.setGrantOption(TSentryGrantOption.TRUE); + sentryStore.alterSentryRoleGrantPrivilege(roleName, privilege2); + + // 4. user0 grant all on table tb1 to role2, no grant option + roleName = roles[2]; + grantor = users[0]; + TSentryPrivilege privilege3 = new TSentryPrivilege(); + privilege3.setPrivilegeScope("TABLE"); + privilege3.setServerName(server); + privilege3.setDbName(db); + privilege3.setTableName(table); + privilege3.setAction(AccessConstants.ALL); + privilege3.setGrantorPrincipal(grantor); + privilege3.setCreateTime(System.currentTimeMillis()); + privilege3.setGrantOption(TSentryGrantOption.FALSE); + sentryStore.alterSentryRoleGrantPrivilege(roleName, privilege3); + + // 5. user1 has role1, no insert privilege, + // grant insert to role3, will throw no grant exception + roleName = roles[3]; + grantor = users[1]; + TSentryPrivilege privilege4 = new TSentryPrivilege(); + privilege4.setPrivilegeScope("DATABASE"); + privilege4.setServerName(server); + privilege4.setDbName(db); + privilege4.setAction(AccessConstants.INSERT); + privilege4.setGrantorPrincipal(grantor); + privilege4.setCreateTime(System.currentTimeMillis()); + privilege4.setGrantOption(TSentryGrantOption.FALSE); + boolean isGrantOptionException = false; + try { + sentryStore.alterSentryRoleGrantPrivilege(roleName, privilege4); + } catch (SentryGrantDeniedException e) { + isGrantOptionException = true; + System.err.println(e.getMessage()); + } + assertTrue(isGrantOptionException); + + // 6. user2 has role2, no grant option, + // grant insert to role4, will throw no grant exception + roleName = roles[4]; + grantor = users[2]; + TSentryPrivilege privilege5 = new TSentryPrivilege(); + privilege5.setPrivilegeScope("TABLE"); + privilege5.setServerName(server); + privilege5.setDbName(db); + privilege5.setTableName(table); + privilege5.setAction(AccessConstants.INSERT); + privilege5.setGrantorPrincipal(grantor); + privilege5.setCreateTime(System.currentTimeMillis()); + privilege5.setGrantOption(TSentryGrantOption.FALSE); + isGrantOptionException = false; + try { + sentryStore.alterSentryRoleGrantPrivilege(roleName, privilege5); + } catch (SentryGrantDeniedException e) { + isGrantOptionException = true; + System.err.println(e.getMessage()); + } + assertTrue(isGrantOptionException); + } + + @Test + public void testRevokeCheckWithGrantOption() throws Exception { + // 1. set local group mapping + // user0->group0->role0 + // user1->group1->role1 + // user2->group2->role2 + String grantor = "g1"; + String[] users = {"user0","user1","user2"}; + String[] roles = {"role0","role1","role2"}; + String[] groups = {"group0","group1","group2"}; + for (int i = 0; i < users.length; i++) { + addGroupsToUser(users[i], groups[i]); + sentryStore.createSentryRole(roles[i], grantor); + Set<TSentryGroup> tGroups = Sets.newHashSet(); + TSentryGroup tGroup = new TSentryGroup(groups[i]); + tGroups.add(tGroup); + sentryStore.alterSentryRoleAddGroups(grantor, roles[i], tGroups); + } + writePolicyFile(); + + // 2. g1 grant select on database db1 to role0, with grant option + String server = "server1"; + String db = "db1"; + String table = "tbl1"; + String roleName = roles[0]; + grantor = "g1"; + TSentryPrivilege privilege1 = new TSentryPrivilege(); + privilege1.setPrivilegeScope("DATABASE"); + privilege1.setServerName(server); + privilege1.setDbName(db); + privilege1.setAction(AccessConstants.SELECT); + privilege1.setGrantorPrincipal(grantor); + privilege1.setCreateTime(System.currentTimeMillis()); + privilege1.setGrantOption(TSentryGrantOption.TRUE); + sentryStore.alterSentryRoleGrantPrivilege(roleName, privilege1); + MSentryRole role = sentryStore.getMSentryRoleByName(roleName); + Set<MSentryPrivilege> privileges = role.getPrivileges(); + assertEquals(privileges.toString(), 1, privileges.size()); + + // 3. g1 grant all on table tb1 to role1, no grant option + roleName = roles[1]; + grantor = "g1"; + TSentryPrivilege privilege2 = new TSentryPrivilege(); + privilege2.setPrivilegeScope("TABLE"); + privilege2.setServerName(server); + privilege2.setDbName(db); + privilege2.setTableName(table); + privilege2.setAction(AccessConstants.ALL); + privilege2.setGrantorPrincipal(grantor); + privilege2.setCreateTime(System.currentTimeMillis()); + privilege2.setGrantOption(TSentryGrantOption.FALSE); + sentryStore.alterSentryRoleGrantPrivilege(roleName, privilege2); + + // 4. g1 grant select on table tb1 to role2, no grant option + roleName = roles[2]; + grantor = "g1"; + TSentryPrivilege privilege3 = new TSentryPrivilege(); + privilege3.setPrivilegeScope("TABLE"); + privilege3.setServerName(server); + privilege3.setDbName(db); + privilege3.setTableName(table); + privilege3.setAction(AccessConstants.SELECT); + privilege3.setGrantorPrincipal(grantor); + privilege3.setCreateTime(System.currentTimeMillis()); + privilege3.setGrantOption(TSentryGrantOption.FALSE); + sentryStore.alterSentryRoleGrantPrivilege(roleName, privilege3); + + // 5. user1 has role1, no grant option, + // revoke from role2 will throw no grant exception + roleName = roles[2]; + grantor = users[1]; + privilege3.setGrantorPrincipal(grantor); + boolean isGrantOptionException = false; + try { + sentryStore.alterSentryRoleRevokePrivilege(roleName, privilege3); + } catch (SentryGrantDeniedException e) { + isGrantOptionException = true; + System.err.println(e.getMessage()); + } + assertTrue(isGrantOptionException); + + // 6. user0 has role0, only have select, + // revoke all from role1 will throw no grant exception + roleName = roles[1]; + grantor = users[0]; + privilege2.setGrantorPrincipal(grantor); + try { + sentryStore.alterSentryRoleRevokePrivilege(roleName, privilege2); + } catch (SentryGrantDeniedException e) { + isGrantOptionException = true; + System.err.println(e.getMessage()); + } + assertTrue(isGrantOptionException); + + // 7. user0 has role0, has select and grant option, + // revoke select from role2 + roleName = roles[2]; + grantor = users[0]; + privilege3.setGrantorPrincipal(grantor); + sentryStore.alterSentryRoleRevokePrivilege(roleName, privilege3); + role = sentryStore.getMSentryRoleByName(roleName); + privileges = role.getPrivileges(); + assertEquals(0, privileges.size()); + } + + @Test + public void testRevokeAllGrantOption() throws Exception { + // 1. set local group mapping + // user0->group0->role0 + String grantor = "g1"; + String[] users = {"user0"}; + String[] roles = {"role0"}; + String[] groups = {"group0"}; + for (int i = 0; i < users.length; i++) { + addGroupsToUser(users[i], groups[i]); + sentryStore.createSentryRole(roles[i], grantor); + Set<TSentryGroup> tGroups = Sets.newHashSet(); + TSentryGroup tGroup = new TSentryGroup(groups[i]); + tGroups.add(tGroup); + sentryStore.alterSentryRoleAddGroups(grantor, roles[i], tGroups); + } + writePolicyFile(); + + // 2. g1 grant select on table tb1 to role0, with grant option + String server = "server1"; + String db = "db1"; + String table = "tbl1"; + String roleName = roles[0]; + grantor = "g1"; + TSentryPrivilege privilege = new TSentryPrivilege(); + privilege.setPrivilegeScope("TABLE"); + privilege.setServerName(server); + privilege.setDbName(db); + privilege.setTableName(table); + privilege.setAction(AccessConstants.SELECT); + privilege.setGrantorPrincipal(grantor); + privilege.setCreateTime(System.currentTimeMillis()); + privilege.setGrantOption(TSentryGrantOption.TRUE); + sentryStore.alterSentryRoleGrantPrivilege(roleName, privilege); + + // 3. g1 grant select on table tb1 to role0, no grant option + roleName = roles[0]; + grantor = "g1"; + privilege.setGrantOption(TSentryGrantOption.FALSE); + sentryStore.alterSentryRoleGrantPrivilege(roleName, privilege); + + // 4. g1 revoke all privilege from role0 + roleName = roles[0]; + grantor = "g1"; + privilege.setGrantOption(TSentryGrantOption.UNSET); + sentryStore.alterSentryRoleRevokePrivilege(roleName, privilege); + MSentryRole role = sentryStore.getMSentryRoleByName(roleName); + Set<MSentryPrivilege> privileges = role.getPrivileges(); + assertEquals(privileges.toString(), 0, privileges.size()); } @Test @@ -519,4 +866,12 @@ public class TestSentryStore { } } } + + protected void addGroupsToUser(String user, String... groupNames) { + policyFile.addGroupsToUser(user, groupNames); + } + + protected void writePolicyFile() throws Exception { + policyFile.write(policyFilePath); + } } http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/7b17cef7/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/thrift/TestSentryServiceIntegration.java ---------------------------------------------------------------------- diff --git a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/thrift/TestSentryServiceIntegration.java b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/thrift/TestSentryServiceIntegration.java index e2f0a8d..5244094 100644 --- a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/thrift/TestSentryServiceIntegration.java +++ b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/thrift/TestSentryServiceIntegration.java @@ -24,7 +24,6 @@ import static org.junit.Assert.assertTrue; import java.util.Set; import org.apache.sentry.core.model.db.AccessConstants; -import org.apache.sentry.provider.db.service.persistent.SentryStore; import org.apache.sentry.service.thrift.SentryServiceIntegrationBase; import org.junit.Test; @@ -235,4 +234,57 @@ public class TestSentryServiceIntegration extends SentryServiceIntegrationBase { client.grantTablePrivilege(requestorUserName, roleName, "server", "db1", "table1", "ALL"); assertEquals(1, client.listAllPrivilegesByRoleName(requestorUserName, roleName).size()); } + + @Test + public void testGrantRevokeWithGrantOption() throws Exception { + // Grant a privilege with Grant Option + String requestorUserName = ADMIN_USER; + Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP); + setLocalGroupMapping(requestorUserName, requestorUserGroupNames); + writePolicyFile(); + String roleName = "admin_r1"; + boolean grantOption = true; + boolean withoutGrantOption = false; + + client.dropRoleIfExists(requestorUserName, roleName); + client.createRole(requestorUserName, roleName); + + client.grantTablePrivilege(requestorUserName, roleName, "server", "db1", "table1", "ALL", grantOption); + assertEquals(1, client.listAllPrivilegesByRoleName(requestorUserName, roleName).size()); + + // Try to revoke the privilege without grantOption and can't revoke the privilege. + client.revokeTablePrivilege(requestorUserName, roleName, "server", "db1", "table1", "ALL", withoutGrantOption); + assertEquals(1, client.listAllPrivilegesByRoleName(requestorUserName, roleName).size()); + + // Try to revoke the privilege with grantOption, the privilege will be revoked. + client.revokeTablePrivilege(requestorUserName, roleName, "server", "db1", "table1", "ALL", grantOption); + assertEquals(0, client.listAllPrivilegesByRoleName(requestorUserName, roleName).size()); + + } + + @Test + public void testGrantTwoPrivilegeDiffInGrantOption() throws Exception { + // Grant a privilege with 'Grant Option'. + String requestorUserName = ADMIN_USER; + Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP); + setLocalGroupMapping(requestorUserName, requestorUserGroupNames); + writePolicyFile(); + String roleName = "admin_r1"; + boolean grantOption = true; + boolean withoutGrantOption = false; + + client.dropRoleIfExists(requestorUserName, roleName); + client.createRole(requestorUserName, roleName); + + client.grantTablePrivilege(requestorUserName, roleName, "server", "db1", "table1", "ALL", grantOption); + assertEquals(1, client.listAllPrivilegesByRoleName(requestorUserName, roleName).size()); + + // Grant a privilege without 'Grant Option'. + client.grantTablePrivilege(requestorUserName, roleName, "server", "db1", "table1", "ALL", withoutGrantOption); + assertEquals(2, client.listAllPrivilegesByRoleName(requestorUserName, roleName).size()); + + // Use 'grantOption = null', the two privileges will be revoked. + client.revokeTablePrivilege(requestorUserName, roleName, "server", "db1", "table1", "ALL", null); + assertEquals(0, client.listAllPrivilegesByRoleName(requestorUserName, roleName).size()); + } } http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/7b17cef7/sentry-provider/sentry-provider-file/pom.xml ---------------------------------------------------------------------- diff --git a/sentry-provider/sentry-provider-file/pom.xml b/sentry-provider/sentry-provider-file/pom.xml index b9a718c..84cdf3f 100644 --- a/sentry-provider/sentry-provider-file/pom.xml +++ b/sentry-provider/sentry-provider-file/pom.xml @@ -29,10 +29,6 @@ limitations under the License. <dependencies> <dependency> - <groupId>commons-lang</groupId> - <artifactId>commons-lang</artifactId> - </dependency> - <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-common</artifactId> <scope>provided</scope> http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/7b17cef7/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestPrivilegeWithGrantOption.java ---------------------------------------------------------------------- diff --git a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestPrivilegeWithGrantOption.java b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestPrivilegeWithGrantOption.java new file mode 100644 index 0000000..7cd667e --- /dev/null +++ b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestPrivilegeWithGrantOption.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.tests.e2e.dbprovider; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.HashMap; +import java.util.Map; + +import junit.framework.Assert; + +import org.apache.hadoop.hive.ql.plan.HiveOperation; +import org.apache.sentry.binding.hive.conf.HiveAuthzConf; +import org.apache.sentry.provider.db.SentryAccessDeniedException; +import org.apache.sentry.tests.e2e.hive.DummySentryOnFailureHook; +import org.apache.sentry.tests.e2e.hive.hiveserver.HiveServerFactory; +import org.junit.Assume; +import org.junit.Before; +import org.junit.Test; + +public class TestPrivilegeWithGrantOption extends AbstractTestWithDbProvider { + + Map<String, String > testProperties; + + @Before + public void setup() throws Exception { + testProperties = new HashMap<String, String>(); + testProperties.put(HiveAuthzConf.AuthzConfVars.AUTHZ_ONFAILURE_HOOKS.getVar(), + DummySentryOnFailureHook.class.getName()); + createContext(testProperties); + DummySentryOnFailureHook.invoked = false; + + // Do not run these tests if run with external HiveServer2 + // This test checks for a static member, which will not + // be set if HiveServer2 and the test run in different JVMs + String hiveServer2Type = System + .getProperty(HiveServerFactory.HIVESERVER2_TYPE); + if(hiveServer2Type != null) { + Assume.assumeTrue(HiveServerFactory.isInternalServer( + HiveServerFactory.HiveServer2Type.valueOf(hiveServer2Type.trim()))); + } + } + + /* + * Admin grant DB_1 user1 without grant option, grant user3 with grant option, + * user1 tries to grant it to user2, but failed. + * user3 can grant it to user2. + * user1 tries to revoke, but failed. + * user3 tries to revoke user2, user3 and user1, user3 revoke user1 will failed. + * permissions for DB_1. + */ + @Test + public void testOnGrantPrivilege() throws Exception { + + // setup db objects needed by the test + Connection connection = context.createConnection(ADMIN1); + Statement statement = context.createStatement(connection); + statement.execute("CREATE ROLE admin_role"); + statement.execute("GRANT ALL ON SERVER " + + HiveServerFactory.DEFAULT_AUTHZ_SERVER_NAME + " TO ROLE admin_role"); + statement.execute("GRANT ROLE admin_role TO GROUP " + ADMINGROUP); + statement.execute("DROP DATABASE IF EXISTS db_1 CASCADE"); + statement.execute("DROP DATABASE IF EXISTS db_2 CASCADE"); + statement.execute("CREATE DATABASE db_1"); + statement.execute("CREATE ROLE group1_role"); + statement.execute("GRANT ALL ON DATABASE db_1 TO ROLE group1_role"); + statement.execute("GRANT ROLE group1_role TO GROUP " + USERGROUP1); + statement.execute("CREATE ROLE group3_grant_role"); + statement.execute("GRANT ALL ON DATABASE db_1 TO ROLE group3_grant_role WITH GRANT OPTION"); + statement.execute("GRANT ROLE group3_grant_role TO GROUP " + USERGROUP3); + statement.execute("CREATE ROLE group2_role"); + statement.execute("GRANT ROLE group2_role TO GROUP " + USERGROUP2); + + connection.close(); + + connection = context.createConnection(USER1_1); + statement = context.createStatement(connection); + + statement.execute("USE db_1"); + statement.execute("CREATE TABLE foo (id int)"); + verifyFailureHook(statement,"GRANT ALL ON DATABASE db_1 TO ROLE group2_role",HiveOperation.GRANT_PRIVILEGE,null,null,true); + verifyFailureHook(statement,"GRANT ALL ON DATABASE db_1 TO ROLE group2_role WITH GRANT OPTION",HiveOperation.GRANT_PRIVILEGE,null,null,true); + connection.close(); + + connection = context.createConnection(USER3_1); + statement = context.createStatement(connection); + statement.execute("GRANT ALL ON DATABASE db_1 TO ROLE group2_role"); + connection.close(); + + connection = context.createConnection(USER1_1); + statement = context.createStatement(connection); + verifyFailureHook(statement,"REVOKE ALL ON Database db_1 FROM ROLE admin_role",HiveOperation.REVOKE_PRIVILEGE,null,null,true); + verifyFailureHook(statement,"REVOKE ALL ON Database db_1 FROM ROLE group2_role",HiveOperation.REVOKE_PRIVILEGE,null,null,true); + verifyFailureHook(statement,"REVOKE ALL ON Database db_1 FROM ROLE group3_grant_role",HiveOperation.REVOKE_PRIVILEGE,null,null,true); + connection.close(); + + connection = context.createConnection(USER3_1); + statement = context.createStatement(connection); + statement.execute("REVOKE ALL ON Database db_1 FROM ROLE group2_role"); + statement.execute("REVOKE ALL ON Database db_1 FROM ROLE group3_grant_role"); + verifyFailureHook(statement,"REVOKE ALL ON Database db_1 FROM ROLE group1_role",HiveOperation.REVOKE_PRIVILEGE,null,null,true); + + connection.close(); + context.close(); + } + + // run the given statement and verify that failure hook is invoked as expected + private void verifyFailureHook(Statement statement, String sqlStr, HiveOperation expectedOp, + String dbName, String tableName, boolean checkSentryAccessDeniedException) throws Exception { + // negative test case: non admin user can't create role + assertFalse(DummySentryOnFailureHook.invoked); + try { + statement.execute(sqlStr); + Assert.fail("Expected SQL exception for " + sqlStr); + } catch (SQLException e) { + assertTrue(DummySentryOnFailureHook.invoked); + } finally { + DummySentryOnFailureHook.invoked = false; + } + if (expectedOp != null) { + Assert.assertNotNull("Hive op is null for op: " + expectedOp, DummySentryOnFailureHook.hiveOp); + Assert.assertTrue(expectedOp.equals(DummySentryOnFailureHook.hiveOp)); + } + if (checkSentryAccessDeniedException) { + Assert.assertTrue("Expected SentryDeniedException for op: " + expectedOp, + DummySentryOnFailureHook.exception.getCause() instanceof SentryAccessDeniedException); + } + if(tableName != null) { + Assert.assertNotNull("Table object is null for op: " + expectedOp, DummySentryOnFailureHook.table); + Assert.assertTrue(tableName.equalsIgnoreCase(DummySentryOnFailureHook.table.getName())); + } + if(dbName != null) { + Assert.assertNotNull("Database object is null for op: " + expectedOp, DummySentryOnFailureHook.db); + Assert.assertTrue(dbName.equalsIgnoreCase(DummySentryOnFailureHook.db.getName())); + } + } +}
