http://git-wip-us.apache.org/repos/asf/sentry/blob/bfb354f2/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbPrivilegeCleanupOnDrop.java ---------------------------------------------------------------------- diff --git a/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbPrivilegeCleanupOnDrop.java b/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbPrivilegeCleanupOnDrop.java new file mode 100644 index 0000000..767bcbe --- /dev/null +++ b/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbPrivilegeCleanupOnDrop.java @@ -0,0 +1,354 @@ +/** + * 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.hamcrest.Matchers.is; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.FileOutputStream; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.List; + +import org.apache.sentry.tests.e2e.hive.AbstractTestWithStaticConfiguration; +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.google.common.collect.Lists; +import com.google.common.io.Resources; + +public class TestDbPrivilegeCleanupOnDrop extends + AbstractTestWithStaticConfiguration { + + private final static int SHOW_GRANT_TABLE_POSITION = 2; + private final static int SHOW_GRANT_DB_POSITION = 1; + + private final String SINGLE_TYPE_DATA_FILE_NAME = "kv1.dat"; + + private final static String tableName1 = "tb_1"; + private final static String tableName2 = "tb_2"; + private final static String tableName3 = "tb_3"; + private final static String tableName4 = "tb_4"; + private final static String renameTag = "_new"; + + @BeforeClass + public static void setupTestStaticConfiguration() throws Exception { + useSentryService = true; + if (!setMetastoreListener) { + setMetastoreListener = true; + } + AbstractTestWithStaticConfiguration.setupTestStaticConfiguration(); + } + + @Override + @Before + public void setup() throws Exception { + super.setupAdmin(); + super.setup(); + // context = createContext(); + File dataFile = new File(dataDir, SINGLE_TYPE_DATA_FILE_NAME); + FileOutputStream to = new FileOutputStream(dataFile); + Resources.copy(Resources.getResource(SINGLE_TYPE_DATA_FILE_NAME), to); + to.close(); + } + + @After + public void tearDown() throws Exception { + if (context != null) { + context.close(); + } + } + + /** + * drop table and verify that the no privileges are referring to it drop db + * and verify that the no privileges are referring to it drop db cascade + * verify that the no privileges are referring to db and tables under it + * + * @throws Exception + */ + @Test + public void testDropObjects() throws Exception { + Connection connection = context.createConnection(ADMIN1); + Statement statement = context.createStatement(connection); + + setupRoles(statement); // create required roles + setupDbObjects(statement); // create test DBs and Tables + setupPrivileges(statement); // setup privileges for USER1 + dropDbObjects(statement); // drop objects + verifyPrivilegesDropped(statement); // verify privileges are removed + + statement.close(); + connection.close(); + } + + /** + * Return the remaining rows of the current resultSet + * Cautiously it will modify the cursor position of the resultSet + * + */ + private void assertRemainingRows(ResultSet resultSet, int expected) throws SQLException{ + int count = 0; + while(resultSet.next()) { + count++; + } + assertThat(count, is(expected)); + } + + /** + * drop table and verify that the no privileges are referring to it drop db + * and verify that the no privileges are referring to it drop db cascade + * verify that the no privileges are referring to db and tables under it + * + * @throws Exception + */ + @Test + public void testReCreateObjects() throws Exception { + Connection connection = context.createConnection(ADMIN1); + Statement statement = context.createStatement(connection); + setupRoles(statement); // create required roles + setupDbObjects(statement); // create test DBs and Tables + setupPrivileges(statement); // setup privileges for USER1 + dropDbObjects(statement); // drop DB and tables + + setupDbObjects(statement); // recreate same DBs and tables + verifyPrivilegesDropped(statement); // verify the stale privileges removed + } + + /** + * rename table and verify that the no privileges are referring to it old table + * verify that the same privileges are created for the new table name + * + * @throws Exception + */ + @Test + public void testRenameTables() throws Exception { + Connection connection = context.createConnection(ADMIN1); + Statement statement = context.createStatement(connection); + + setupRoles(statement); // create required roles + setupDbObjects(statement); // create test DBs and Tables + setupPrivileges(statement); // setup privileges for USER1 + + // verify privileges on the created tables + statement.execute("USE " + DB2); + verifyTablePrivilegeExist(statement, + Lists.newArrayList("select_tbl1", "insert_tbl1", "all_tbl1"), + tableName1); + verifyTablePrivilegeExist(statement, Lists.newArrayList("all_tbl2"), + tableName2); + + renameTables(statement); // alter tables to rename + + // verify privileges removed for old tables + verifyTablePrivilegesDropped(statement); + + // verify privileges created for new tables + statement.execute("USE " + DB2); + verifyTablePrivilegeExist(statement, + Lists.newArrayList("select_tbl1", "insert_tbl1", "all_tbl1"), + tableName1 + renameTag); + verifyTablePrivilegeExist(statement, Lists.newArrayList("all_tbl2"), + tableName2 + renameTag); + + statement.close(); + connection.close(); + } + + /** + * After we drop/rename table, we will drop/rename all privileges(ALL,SELECT,INSERT,ALTER,DROP...) + * from this role + * + * @throws Exception + */ + @Test + public void testDropAndRenameWithMultiAction() throws Exception { + Connection connection = context.createConnection(ADMIN1); + Statement statement = context.createStatement(connection); + statement.execute("CREATE ROLE user_role"); + statement.execute("GRANT ROLE user_role TO GROUP " + USERGROUP1); + + statement.execute("CREATE DATABASE " + DB1); + statement.execute("USE " + DB1); + statement.execute("CREATE TABLE t1 (c1 string)"); + + // Grant SELECT/INSERT/DROP/ALTER to TABLE t1 + statement.execute("GRANT SELECT ON TABLE t1 TO ROLE user_role"); + statement.execute("GRANT INSERT ON TABLE t1 TO ROLE user_role"); + statement.execute("GRANT ALTER ON TABLE t1 TO ROLE user_role"); + statement.execute("GRANT DROP ON TABLE t1 TO ROLE user_role"); + // For rename, grant CREATE to DB1 + statement.execute("GRANT CREATE ON DATABASE " + DB1 + " TO ROLE user_role"); + + // After rename table t1 to t2, user_role will have no permission to drop t1 + connection = context.createConnection(USER1_1); + statement = context.createStatement(connection); + statement.execute("USE " + DB1); + statement.execute("ALTER TABLE t1 RENAME TO t2"); + context.assertSentrySemanticException(statement, "drop table t1", semanticException); + + // After rename table t1 to t2, user_role should have permission to drop t2 + statement.execute("drop table t2"); + ResultSet resultSet = statement.executeQuery("SHOW GRANT ROLE user_role"); + // user_role will revoke all privilege from table t2, only remain CREATE on db_1 + assertRemainingRows(resultSet, 1); + + statement.close(); + connection.close(); + } + + // Create test roles + private void setupRoles(Statement statement) throws Exception { + statement.execute("CREATE ROLE all_db1"); + statement.execute("CREATE ROLE read_db1"); + statement.execute("CREATE ROLE select_tbl1"); + statement.execute("CREATE ROLE insert_tbl1"); + statement.execute("CREATE ROLE all_tbl1"); + statement.execute("CREATE ROLE all_tbl2"); + statement.execute("CREATE ROLE all_prod"); + + statement.execute("GRANT ROLE all_db1, read_db1, select_tbl1, insert_tbl1," + + " all_tbl1, all_tbl2, all_prod to GROUP " + USERGROUP1); + + statement.execute("DROP DATABASE IF EXISTS " + DB1 + " CASCADE"); + statement.execute("DROP DATABASE IF EXISTS " + DB2 + " CASCADE"); + } + + // create test DBs and Tables + private void setupDbObjects(Statement statement) throws Exception { + statement.execute("CREATE DATABASE " + DB1); + statement.execute("CREATE DATABASE " + DB2); + statement.execute("create table " + DB2 + "." + tableName1 + + " (under_col int comment 'the under column', value string)"); + statement.execute("create table " + DB2 + "." + tableName2 + + " (under_col int comment 'the under column', value string)"); + statement.execute("create table " + DB1 + "." + tableName3 + + " (under_col int comment 'the under column', value string)"); + statement.execute("create table " + DB1 + "." + tableName4 + + " (under_col int comment 'the under column', value string)"); + } + + // Create privileges on DB and Tables + private void setupPrivileges(Statement statement) throws Exception { + statement.execute("GRANT ALL ON DATABASE " + DB1 + " TO ROLE all_db1"); + statement.execute("GRANT SELECT ON DATABASE " + DB1 + + " TO ROLE read_db1"); + statement.execute("GRANT ALL ON DATABASE " + DB2 + " TO ROLE all_prod"); + statement.execute("USE " + DB2); + statement.execute("GRANT SELECT ON TABLE " + tableName1 + + " TO ROLE select_tbl1"); + statement.execute("GRANT INSERT ON TABLE " + tableName1 + + " TO ROLE insert_tbl1"); + statement.execute("GRANT ALL ON TABLE " + tableName1 + " TO ROLE all_tbl1"); + statement.execute("GRANT ALL ON TABLE " + tableName2 + " TO ROLE all_tbl2"); + } + + // Drop test DBs and Tables + private void dropDbObjects(Statement statement) throws Exception { + statement.execute("DROP TABLE " + DB2 + "." + tableName1); + statement.execute("DROP TABLE " + DB2 + "." + tableName2); + statement.execute("DROP DATABASE " + DB2); + statement.execute("DROP DATABASE " + DB1 + " CASCADE"); + } + + // rename tables + private void renameTables(Statement statement) throws Exception { + statement.execute("USE " + DB2); + statement.execute("ALTER TABLE " + tableName1 + " RENAME TO " + tableName1 + + renameTag); + statement.execute("ALTER TABLE " + tableName2 + " RENAME TO " + tableName2 + + renameTag); + statement.execute("USE " + DB1); + statement.execute("ALTER TABLE " + tableName3 + " RENAME TO " + tableName3 + + renameTag); + statement.execute("ALTER TABLE " + tableName4 + " RENAME TO " + tableName4 + + renameTag); + } + + // verify all the test privileges are dropped as we drop the objects + private void verifyPrivilegesDropped(Statement statement) + throws Exception { + verifyDbPrivilegesDropped(statement); + verifyTablePrivilegesDropped(statement); + } + + // verify all the test privileges are dropped as we drop the objects + private void verifyTablePrivilegesDropped(Statement statement) + throws Exception { + List<String> roles = getRoles(statement); + verifyPrivilegeDropped(statement, roles, tableName1, + SHOW_GRANT_TABLE_POSITION); + verifyPrivilegeDropped(statement, roles, tableName2, + SHOW_GRANT_TABLE_POSITION); + verifyPrivilegeDropped(statement, roles, tableName3, + SHOW_GRANT_TABLE_POSITION); + verifyPrivilegeDropped(statement, roles, tableName4, + SHOW_GRANT_TABLE_POSITION); + + } + + // verify all the test privileges are dropped as we drop the objects + private void verifyDbPrivilegesDropped(Statement statement) throws Exception { + List<String> roles = getRoles(statement); + verifyPrivilegeDropped(statement, roles, DB2, SHOW_GRANT_DB_POSITION); + verifyPrivilegeDropped(statement, roles, DB1, SHOW_GRANT_DB_POSITION); + + } + + // verify given table/DB has no longer permissions + private void verifyPrivilegeDropped(Statement statement, List<String> roles, + String objectName, int resultPos) throws Exception { + for (String roleName : roles) { + ResultSet resultSet = statement.executeQuery("SHOW GRANT ROLE " + + roleName); + while (resultSet.next()) { + String returned = resultSet.getString(resultPos); + assertFalse("value " + objectName + " shouldn't be detected, but actually " + returned + " is found from resultSet", + objectName.equalsIgnoreCase(returned)); + } + resultSet.close(); + } + } + + // verify given table is part of the role + private void verifyTablePrivilegeExist(Statement statement, + List<String> roles, String tableName) throws Exception { + for (String roleName : roles) { + ResultSet resultSet = statement.executeQuery("SHOW GRANT ROLE " + + roleName + " ON TABLE " + tableName); + assertTrue(resultSet.next()); + resultSet.close(); + } + } + + private List<String> getRoles(Statement statement) throws Exception { + ArrayList<String> roleList = Lists.newArrayList(); + ResultSet resultSet = statement.executeQuery("SHOW ROLES "); + while (resultSet.next()) { + roleList.add(resultSet.getString(1)); + } + return roleList; + } +}
http://git-wip-us.apache.org/repos/asf/sentry/blob/bfb354f2/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbPrivilegesAtColumnScope.java ---------------------------------------------------------------------- diff --git a/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbPrivilegesAtColumnScope.java b/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbPrivilegesAtColumnScope.java new file mode 100644 index 0000000..659c61f --- /dev/null +++ b/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbPrivilegesAtColumnScope.java @@ -0,0 +1,38 @@ +/* + * 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 org.apache.sentry.tests.e2e.hive.TestPrivilegesAtColumnScope; +import org.junit.Before; +import org.junit.BeforeClass; + +public class TestDbPrivilegesAtColumnScope extends TestPrivilegesAtColumnScope { + @Override + @Before + public void setup() throws Exception { + setupAdmin(); + super.setup(); + } + + @BeforeClass + public static void setupTestStaticConfiguration() throws Exception { + useSentryService = true; + TestPrivilegesAtColumnScope.setupTestStaticConfiguration(); + } + +} http://git-wip-us.apache.org/repos/asf/sentry/blob/bfb354f2/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbPrivilegesAtDatabaseScope.java ---------------------------------------------------------------------- diff --git a/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbPrivilegesAtDatabaseScope.java b/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbPrivilegesAtDatabaseScope.java new file mode 100644 index 0000000..883bedd --- /dev/null +++ b/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbPrivilegesAtDatabaseScope.java @@ -0,0 +1,46 @@ +/* + * 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 org.apache.sentry.tests.e2e.hive.AbstractTestWithStaticConfiguration; +import org.apache.sentry.tests.e2e.hive.TestPrivilegesAtDatabaseScope; +import org.junit.Before; +import org.junit.BeforeClass; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TestDbPrivilegesAtDatabaseScope extends + TestPrivilegesAtDatabaseScope { + private static final Logger LOGGER = LoggerFactory. + getLogger(TestDbPrivilegesAtDatabaseScope.class); + + @Override + @Before + public void setup() throws Exception { + LOGGER.info("TestDbPrivilegesAtDatabaseScope setup"); + super.setupAdmin(); + super.setup(); + } + @BeforeClass + public static void setupTestStaticConfiguration() throws Exception { + LOGGER.info("TestDbPrivilegesAtDatabaseScope setupTestStaticConfiguration"); + useSentryService = true; + AbstractTestWithStaticConfiguration.setupTestStaticConfiguration(); + } + +} http://git-wip-us.apache.org/repos/asf/sentry/blob/bfb354f2/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbPrivilegesAtFunctionScope.java ---------------------------------------------------------------------- diff --git a/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbPrivilegesAtFunctionScope.java b/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbPrivilegesAtFunctionScope.java new file mode 100644 index 0000000..cebad98 --- /dev/null +++ b/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbPrivilegesAtFunctionScope.java @@ -0,0 +1,39 @@ +/* + * 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 org.apache.sentry.tests.e2e.hive.AbstractTestWithStaticConfiguration; +import org.apache.sentry.tests.e2e.hive.TestPrivilegesAtFunctionScope; +import org.junit.Before; +import org.junit.BeforeClass; + +public class TestDbPrivilegesAtFunctionScope extends + TestPrivilegesAtFunctionScope { + @Override + @Before + public void setup() throws Exception { + super.setupAdmin(); + super.setup(); + } + @BeforeClass + public static void setupTestStaticConfiguration() throws Exception { + useSentryService = true; + AbstractTestWithStaticConfiguration.setupTestStaticConfiguration(); + + } + +} http://git-wip-us.apache.org/repos/asf/sentry/blob/bfb354f2/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbPrivilegesAtTableScope.java ---------------------------------------------------------------------- diff --git a/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbPrivilegesAtTableScope.java b/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbPrivilegesAtTableScope.java new file mode 100644 index 0000000..a4f07df --- /dev/null +++ b/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbPrivilegesAtTableScope.java @@ -0,0 +1,39 @@ +/* + * 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 org.apache.sentry.tests.e2e.hive.AbstractTestWithStaticConfiguration; +import org.apache.sentry.tests.e2e.hive.TestPrivilegesAtTableScope; +import org.junit.Before; +import org.junit.BeforeClass; + +public class TestDbPrivilegesAtTableScope extends TestPrivilegesAtTableScope { + @Override + @Before + public void setup() throws Exception { + super.setupAdmin(); + super.setup(); + prepareDBDataForTest(); + } + @BeforeClass + public static void setupTestStaticConfiguration() throws Exception { + useSentryService = true; + AbstractTestWithStaticConfiguration.setupTestStaticConfiguration(); + } + +} http://git-wip-us.apache.org/repos/asf/sentry/blob/bfb354f2/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbRuntimeMetadataRetrieval.java ---------------------------------------------------------------------- diff --git a/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbRuntimeMetadataRetrieval.java b/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbRuntimeMetadataRetrieval.java new file mode 100644 index 0000000..8d98179 --- /dev/null +++ b/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbRuntimeMetadataRetrieval.java @@ -0,0 +1,46 @@ +/* + * 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 org.apache.sentry.tests.e2e.hive.AbstractTestWithStaticConfiguration; +import org.apache.sentry.tests.e2e.hive.TestRuntimeMetadataRetrieval; +import org.junit.Before; +import org.junit.BeforeClass; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TestDbRuntimeMetadataRetrieval extends + TestRuntimeMetadataRetrieval { + private static final Logger LOGGER = LoggerFactory. + getLogger(TestDbRuntimeMetadataRetrieval.class); + + @Override + @Before + public void setup() throws Exception { + LOGGER.info("TestDbRuntimeMetadataRetrieval setup"); + super.setupAdmin(); + super.setup(); + } + @BeforeClass + public static void setupTestStaticConfiguration() throws Exception { + LOGGER.info("TestDbRuntimeMetadataRetrieval setupTestStaticConfiguration"); + useSentryService = true; + AbstractTestWithStaticConfiguration.setupTestStaticConfiguration(); + + } + +} http://git-wip-us.apache.org/repos/asf/sentry/blob/bfb354f2/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbSandboxOps.java ---------------------------------------------------------------------- diff --git a/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbSandboxOps.java b/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbSandboxOps.java new file mode 100644 index 0000000..fa429e7 --- /dev/null +++ b/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbSandboxOps.java @@ -0,0 +1,49 @@ +/* + * 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 org.apache.sentry.tests.e2e.hive.AbstractTestWithStaticConfiguration; +import org.apache.sentry.tests.e2e.hive.TestSandboxOps; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; + +public class TestDbSandboxOps extends TestSandboxOps { + @Override + @Before + public void setup() throws Exception { + super.setupAdmin(); + super.setup(); + } + + @BeforeClass + public static void setupTestStaticConfiguration() throws Exception { + useSentryService = true; + AbstractTestWithStaticConfiguration.setupTestStaticConfiguration(); + + } + + @Ignore + @Test + public void testPerDbPolicyOnDFS() throws Exception { + // TODO : Looks like the test in the base class is specifically meant for + // File based providers... Since it is assuming that multiple policy files + // in DFS would be handled by the provider.. + } + +} http://git-wip-us.apache.org/repos/asf/sentry/blob/bfb354f2/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbSentryOnFailureHookLoading.java ---------------------------------------------------------------------- diff --git a/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbSentryOnFailureHookLoading.java b/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbSentryOnFailureHookLoading.java new file mode 100644 index 0000000..8cb04f7 --- /dev/null +++ b/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbSentryOnFailureHookLoading.java @@ -0,0 +1,271 @@ +/* + * 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 java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.junit.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.After; +import org.junit.Assume; +import org.junit.BeforeClass; +import org.junit.Test; + +public class TestDbSentryOnFailureHookLoading extends AbstractTestWithDbProvider { + + + @BeforeClass + public static void setup() throws Exception { + properties = new HashMap<String, String>(); + properties.put(HiveAuthzConf.AuthzConfVars.AUTHZ_ONFAILURE_HOOKS.getVar(), + DummySentryOnFailureHook.class.getName()); + createContext(); + 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()))); + } + } + + @After + public void clearDB() throws Exception { + Connection connection; + Statement statement; + connection = context.createConnection(ADMIN1); + statement = context.createStatement(connection); + ResultSet resultSet; + resultSet = statement.executeQuery("SHOW roles"); + List<String> roles = new ArrayList<String>(); + while ( resultSet.next()) { + roles.add(resultSet.getString(1)); + } + for(String role:roles) { + statement.execute("DROP Role " + role); + } + + statement.close(); + connection.close(); + if (context != null) { + context.close(); + } + } + + /* Admin creates database DB_2 + * user1 tries to drop DB_2, but it has permissions for DB_1. + */ + @Test + public void testOnFailureHookLoading() throws Exception { + + // setup db objects needed by the test + Connection connection = context.createConnection(ADMIN1); + Statement statement = context.createStatement(connection); + try { + statement.execute("DROP ROLE admin_role"); + } catch (Exception ex) { + //It is ok if admin_role already exists + } + 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 DATABASE DB_2"); + statement.execute("CREATE TABLE db_2.tab1(a int )"); + + statement.execute("CREATE ROLE all_db1"); + statement.execute("GRANT ALL ON DATABASE DB_1 TO ROLE all_db1"); + statement.execute("GRANT ROLE all_db1 TO GROUP " + USERGROUP1); + + statement.execute("CREATE ROLE lock_db2_tab1"); + statement.execute("GRANT ROLE lock_db2_tab1 TO GROUP " + USERGROUP1); + + statement.execute("USE db_2"); + statement.execute("GRANT LOCK ON TABLE tab1 TO ROLE lock_db2_tab1");// To give user1 privilege to do USE db_2 + statement.close(); + connection.close(); + + // test execution + connection = context.createConnection(USER1_1); + statement = context.createStatement(connection); + + // Failure hook for create table when table doesnt exist + verifyFailureHook(statement, "CREATE TABLE DB_2.TAB2(id INT)", HiveOperation.CREATETABLE, "db_2", null, false); + + // Failure hook for create table when table exist + verifyFailureHook(statement, "CREATE TABLE DB_2.TAB1(id INT)", HiveOperation.CREATETABLE, "db_2", null, false); + + // Failure hook for select * from table when table exist + verifyFailureHook(statement, "select * from db_2.tab1", HiveOperation.QUERY, + null, null, false); + + //Denied alter table invokes failure hook + statement.execute("USE DB_2"); + verifyFailureHook(statement, "ALTER TABLE tab1 CHANGE id id1 INT", HiveOperation.ALTERTABLE_RENAMECOL, + "db_2", null, false); + + statement.close(); + connection.close(); + + //test cleanup + connection = context.createConnection(ADMIN1); + statement = context.createStatement(connection); + statement.execute("DROP DATABASE DB_1 CASCADE"); + statement.execute("DROP DATABASE DB_2 CASCADE"); + statement.close(); + connection.close(); + context.close(); + } + + /* + * Admin creates database DB_2 user1 tries to drop DB_2, but it has + * permissions for DB_1. + */ + @Test + public void testOnFailureHookForAuthDDL() 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 TABLE DB_1.tab1(a int )"); + statement.execute("CREATE ROLE all_db1"); + statement.execute("GRANT ALL ON DATABASE DB_1 TO ROLE all_db1"); + statement.execute("GRANT ROLE all_db1 TO GROUP " + USERGROUP1); + 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, "CREATE ROLE fooTest", + HiveOperation.CREATEROLE, null, null, true); + + verifyFailureHook(statement, "DROP ROLE fooTest", + HiveOperation.DROPROLE, null, null, true); + + verifyFailureHook(statement, + "GRANT ALL ON SERVER server1 TO ROLE admin_role", + HiveOperation.GRANT_PRIVILEGE, null, null, true); + + verifyFailureHook(statement, + "REVOKE ALL ON SERVER server1 FROM ROLE admin_role", + HiveOperation.REVOKE_PRIVILEGE, null, null, true); + + verifyFailureHook(statement, "GRANT ROLE all_db1 TO GROUP " + USERGROUP1, + HiveOperation.GRANT_ROLE, null, null, true); + + verifyFailureHook(statement, + "REVOKE ROLE all_db1 FROM GROUP " + USERGROUP1, + HiveOperation.REVOKE_ROLE, null, null, true); + + verifyFailureHook(statement, "SHOW ROLES", + HiveOperation.SHOW_ROLES, null, null, true); + + verifyFailureHook(statement, "SHOW ROLE GRANT group group1", + HiveOperation.SHOW_ROLE_GRANT, null, null, true); + + verifyFailureHook(statement, "SHOW GRANT role role1", + HiveOperation.SHOW_GRANT, null, null, true); + + //Should pass as user1_1 is granted role all_db1 + statement.execute("SHOW GRANT role all_db1"); + + //Grant privilege on table doesnt expose db and table objects + verifyFailureHook(statement, + "GRANT ALL ON TABLE db_1.tab1 TO ROLE admin_role", + HiveOperation.GRANT_PRIVILEGE, null, null, true); + + //Revoke privilege on table doesnt expose db and table objects + verifyFailureHook(statement, + "REVOKE ALL ON TABLE db_1.tab1 FROM ROLE admin_role", + HiveOperation.REVOKE_PRIVILEGE, null, null, true); + + //Grant privilege on database doesnt expose db and table objects + verifyFailureHook(statement, + "GRANT ALL ON Database db_1 TO ROLE admin_role", + HiveOperation.GRANT_PRIVILEGE, null, null, true); + + //Revoke privilege on database doesnt expose db and table objects + verifyFailureHook(statement, + "REVOKE ALL ON Database db_1 FROM ROLE admin_role", + HiveOperation.REVOKE_PRIVILEGE, null, null, true); + + statement.close(); + 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 + Assert.assertFalse(DummySentryOnFailureHook.invoked); + try { + statement.execute(sqlStr); + Assert.fail("Expected SQL exception for " + sqlStr); + } catch (SQLException e) { + Assert.assertTrue("FailureHook is not ran : " + e.getMessage(), 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())); + } + } +} http://git-wip-us.apache.org/repos/asf/sentry/blob/bfb354f2/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbUriPermissions.java ---------------------------------------------------------------------- diff --git a/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbUriPermissions.java b/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbUriPermissions.java new file mode 100644 index 0000000..1a90e06 --- /dev/null +++ b/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbUriPermissions.java @@ -0,0 +1,45 @@ +/* + * 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 org.apache.sentry.tests.e2e.hive.AbstractTestWithStaticConfiguration; +import org.apache.sentry.tests.e2e.hive.TestUriPermissions; +import org.junit.Before; +import org.junit.BeforeClass; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TestDbUriPermissions extends TestUriPermissions { + private static final Logger LOGGER = LoggerFactory. + getLogger(TestDbUriPermissions.class); + + @Override + @Before + public void setup() throws Exception { + LOGGER.info("TestDbUriPermissions setup"); + super.setupAdmin(); + super.setup(); + } + @BeforeClass + public static void setupTestStaticConfiguration() throws Exception { + LOGGER.info("TestDbUriPermissions setupTestStaticConfiguration"); + useSentryService = true; + AbstractTestWithStaticConfiguration.setupTestStaticConfiguration(); + + } +} http://git-wip-us.apache.org/repos/asf/sentry/blob/bfb354f2/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestPrivilegeWithGrantOption.java ---------------------------------------------------------------------- diff --git a/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestPrivilegeWithGrantOption.java b/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestPrivilegeWithGrantOption.java new file mode 100644 index 0000000..65ece8f --- /dev/null +++ b/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestPrivilegeWithGrantOption.java @@ -0,0 +1,269 @@ +/* + * 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 java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import org.junit.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.AbstractTestWithStaticConfiguration; +import org.apache.sentry.tests.e2e.hive.DummySentryOnFailureHook; +import org.apache.sentry.tests.e2e.hive.hiveserver.HiveServerFactory; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +public class TestPrivilegeWithGrantOption extends AbstractTestWithStaticConfiguration { + + private static boolean isInternalServer = false; + private static int SHOW_GRANT_ROLE_DB_POSITION = 1; + private static int SHOW_GRANT_ROLE_TABLE_POSITION = 2; + private static int SHOW_GRANT_ROLE_WITH_GRANT_POSITION = 8; + + @BeforeClass + public static void setupTestStaticConfiguration() throws Exception { + useSentryService = true; + String hiveServer2Type = System + .getProperty(HiveServerFactory.HIVESERVER2_TYPE); + if ((hiveServer2Type == null) + || HiveServerFactory.isInternalServer(HiveServerFactory.HiveServer2Type + .valueOf(hiveServer2Type.trim()))) { + System.setProperty( + HiveAuthzConf.AuthzConfVars.AUTHZ_ONFAILURE_HOOKS.getVar(), + DummySentryOnFailureHook.class.getName()); + isInternalServer = true; + } + AbstractTestWithStaticConfiguration.setupTestStaticConfiguration(); + } + + @Override + @Before + public void setup() throws Exception { + DummySentryOnFailureHook.invoked = false; + super.setupAdmin(); + super.setup(); + } + + /* + * 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("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)"); + runSQLWithError(statement, "GRANT ALL ON DATABASE db_1 TO ROLE group2_role", + HiveOperation.GRANT_PRIVILEGE, null, null, true); + runSQLWithError(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); + runSQLWithError(statement, "REVOKE ALL ON Database db_1 FROM ROLE admin_role", + HiveOperation.REVOKE_PRIVILEGE, null, null, true); + runSQLWithError(statement, "REVOKE ALL ON Database db_1 FROM ROLE group2_role", + HiveOperation.REVOKE_PRIVILEGE, null, null, true); + runSQLWithError(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"); + runSQLWithError(statement, "REVOKE ALL ON Database db_1 FROM ROLE group1_role", + HiveOperation.REVOKE_PRIVILEGE, null, null, true); + + connection.close(); + context.close(); + } + + /** + * Test privileges with grant on parent objects are sufficient for operation + * on child objects + * @throws Exception + */ + @Test + public void testImpliedPrivilegesWithGrant() throws Exception { + // setup db objects needed by the test + Connection connection = context.createConnection(ADMIN1); + Statement statement = context.createStatement(connection); + + statement.execute("DROP DATABASE IF EXISTS db_1 CASCADE"); + statement.execute("CREATE DATABASE db_1"); + + statement.execute("CREATE ROLE role1"); + statement + .execute("GRANT ALL ON DATABASE db_1 TO ROLE role1 WITH GRANT OPTION"); + statement.execute("GRANT ROLE role1 TO GROUP " + USERGROUP1); + + statement.execute("CREATE ROLE role2"); + statement.execute("GRANT ROLE role2 TO GROUP " + USERGROUP2); + + statement.execute("CREATE ROLE role3_1"); + statement.execute("GRANT ROLE role3_1 TO GROUP " + USERGROUP3); + + statement.execute("CREATE ROLE role3_2"); + statement.execute("GRANT ROLE role3_2 TO GROUP " + USERGROUP3); + connection.close(); + + connection = context.createConnection(USER1_1); + statement = context.createStatement(connection); + + statement.execute("USE db_1"); + statement.execute("CREATE TABLE foo (id int)"); + // user1 with grant option of ALL on DB should be able grant ALL on TABLE + statement.execute("GRANT ALL ON TABLE foo TO ROLE role2"); + // user1 with grant option of ALL on DB should be able grant SELECT on DB + statement.execute("GRANT SELECT ON DATABASE db_1 TO ROLE role3_1"); + // user1 with grant option of ALL on DB should be able grant INSERT on TABLE + statement.execute("GRANT INSERT ON TABLE foo TO ROLE role3_2"); + connection.close(); + + connection = context.createConnection(USER2_1); + statement = context.createStatement(connection); + statement.execute("USE db_1"); + runSQLWithError(statement, "GRANT ALL ON TABLE foo TO ROLE role3_2", + HiveOperation.GRANT_PRIVILEGE, null, null, true); + connection.close(); + + connection = context.createConnection(ADMIN1); + statement = context.createStatement(connection); + statement.execute("use db_1"); + verifySingleGrantWithGrantOption(statement, + "SHOW GRANT ROLE role2 ON TABLE foo", SHOW_GRANT_ROLE_TABLE_POSITION, + "foo"); + verifySingleGrantWithGrantOption(statement, + "SHOW GRANT ROLE role3_1 ON DATABASE db_1", + SHOW_GRANT_ROLE_DB_POSITION, "db_1"); + verifySingleGrantWithGrantOption(statement, + "SHOW GRANT ROLE role3_2 ON TABLE foo", SHOW_GRANT_ROLE_TABLE_POSITION, + "foo"); + + // test 'with grant option' status + verifySingleGrantWithGrantOption(statement, "show grant role role1", + SHOW_GRANT_ROLE_WITH_GRANT_POSITION, "true"); + verifySingleGrantWithGrantOption(statement, + "SHOW GRANT ROLE role1 ON DATABASE db_1", + SHOW_GRANT_ROLE_WITH_GRANT_POSITION, "true"); + verifySingleGrantWithGrantOption(statement, + "SHOW GRANT ROLE role1 ON TABLE foo", + SHOW_GRANT_ROLE_WITH_GRANT_POSITION, "true"); + verifySingleGrantWithGrantOption(statement, "show grant role role2", + SHOW_GRANT_ROLE_WITH_GRANT_POSITION, "false"); + verifySingleGrantWithGrantOption(statement, + "SHOW GRANT ROLE role2 ON TABLE foo", + SHOW_GRANT_ROLE_WITH_GRANT_POSITION, "false"); + statement.close(); + connection.close(); + } + + // run the given statement and verify that failure hook is invoked as expected + private void runSQLWithError(Statement statement, String sqlStr, + HiveOperation expectedOp, String dbName, String tableName, + boolean checkSentryAccessDeniedException) throws Exception { + // negative test case: non admin user can't create role + Assert.assertFalse(DummySentryOnFailureHook.invoked); + try { + statement.execute(sqlStr); + Assert.fail("Expected SQL exception for " + sqlStr); + } catch (SQLException e) { + verifyFailureHook(expectedOp, dbName, tableName, checkSentryAccessDeniedException); + } finally { + DummySentryOnFailureHook.invoked = false; + } + + } + + // run the given statement and verify that failure hook is invoked as expected + private void verifyFailureHook(HiveOperation expectedOp, + String dbName, String tableName, boolean checkSentryAccessDeniedException) + throws Exception { + if (!isInternalServer) { + return; + } + + Assert.assertTrue(DummySentryOnFailureHook.invoked); + 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())); + } + } + + // verify the expected object name at specific position in the SHOW GRANT result + private void verifySingleGrantWithGrantOption(Statement statetment, + String statementSql, int dbObjectPosition, String dbObjectName) + throws Exception { + ResultSet res = statetment.executeQuery(statementSql); + Assert.assertTrue(res.next()); + Assert.assertEquals(dbObjectName, res.getString(dbObjectPosition)); + res.close(); + } + +} http://git-wip-us.apache.org/repos/asf/sentry/blob/bfb354f2/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestPrivilegeWithHAGrantOption.java ---------------------------------------------------------------------- diff --git a/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestPrivilegeWithHAGrantOption.java b/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestPrivilegeWithHAGrantOption.java new file mode 100644 index 0000000..d837a85 --- /dev/null +++ b/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestPrivilegeWithHAGrantOption.java @@ -0,0 +1,161 @@ +/* + * 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 java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.HashMap; + +import org.junit.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.BeforeClass; +import org.junit.Test; + +public class TestPrivilegeWithHAGrantOption extends AbstractTestWithDbProvider { + + @BeforeClass + public static void setup() throws Exception { + haEnabled = true; + properties = new HashMap<String, String>(); + properties.put(HiveAuthzConf.AuthzConfVars.AUTHZ_ONFAILURE_HOOKS.getVar(), + DummySentryOnFailureHook.class.getName()); + createContext(); + 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"); + shutdownAllSentryService(); + startSentryService(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"); + shutdownAllSentryService(); + startSentryService(1); + 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); + shutdownAllSentryService(); + startSentryService(1); + 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); + shutdownAllSentryService(); + startSentryService(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); + shutdownAllSentryService(); + startSentryService(1); + 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 + Assert.assertFalse(DummySentryOnFailureHook.invoked); + try { + statement.execute(sqlStr); + Assert.fail("Expected SQL exception for " + sqlStr); + } catch (SQLException e) { + Assert.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())); + } + } +} http://git-wip-us.apache.org/repos/asf/sentry/blob/bfb354f2/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/ha/TestHaEnd2End.java ---------------------------------------------------------------------- diff --git a/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/ha/TestHaEnd2End.java b/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/ha/TestHaEnd2End.java new file mode 100644 index 0000000..6ad70cf --- /dev/null +++ b/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/ha/TestHaEnd2End.java @@ -0,0 +1,171 @@ +/** + * 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.ha; + +import java.io.File; +import java.io.FileOutputStream; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.Statement; + +import org.apache.sentry.provider.db.SentryAccessDeniedException; +import org.apache.sentry.provider.file.PolicyFile; +import org.apache.sentry.service.thrift.HAClientInvocationHandler; +import org.apache.sentry.tests.e2e.hive.AbstractTestWithStaticConfiguration; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.google.common.io.Resources; + +/** + * End2End tests with Sentry service HA enabled. + */ +public class TestHaEnd2End extends AbstractTestWithStaticConfiguration { + + private final String SINGLE_TYPE_DATA_FILE_NAME = "kv1.dat"; + private File dataFile; + + @BeforeClass + public static void setupTestStaticConfiguration() throws Exception { + useSentryService = true; + enableSentryHA = true; + AbstractTestWithStaticConfiguration.setupTestStaticConfiguration(); + } + + @Override + @Before + public void setup() throws Exception { + super.setupAdmin(); + super.setup(); + dataFile = new File(dataDir, SINGLE_TYPE_DATA_FILE_NAME); + FileOutputStream to = new FileOutputStream(dataFile); + Resources.copy(Resources.getResource(SINGLE_TYPE_DATA_FILE_NAME), to); + to.close(); + PolicyFile.setAdminOnServer1(ADMINGROUP); + } + + /** + * Basic test with two Sentry service running. + * @throws Exception + */ + @Test + public void testBasic() throws Exception { + Connection connection = context.createConnection(ADMIN1); + Statement statement = context.createStatement(connection); + statement.execute("CREATE TABLE t1 (c1 string)"); + statement.execute("CREATE ROLE user_role"); + statement.execute("GRANT SELECT ON TABLE t1 TO ROLE user_role"); + statement.execute("GRANT ROLE user_role TO GROUP " + USERGROUP1); + statement.close(); + connection.close(); + connection = context.createConnection(USER1_1); + statement = context.createStatement(connection); + context.assertSentryException(statement, "CREATE ROLE r2", + SentryAccessDeniedException.class.getSimpleName()); + // test default of ALL + statement.execute("SELECT * FROM t1"); + // test a specific role + statement.execute("SET ROLE user_role"); + statement.execute("SELECT * FROM t1"); + + // test ALL + statement.execute("SET ROLE ALL"); + statement.execute("SELECT * FROM t1"); + statement.close(); + connection.close(); + + // cleanup + connection = context.createConnection(ADMIN1); + statement = context.createStatement(connection); + statement.execute("DROP ROLE user_role"); + statement.close(); + connection.close(); + } + + /** + * Test service failover. Run Sentry operations with shutting down one or more + * of the services. + * @throws Exception + */ + @Test + public void testFailover() throws Exception { + String roleName1 = "test_role_1"; + String roleName2 = "test_role_2"; + String roleName3 = "test_role_3"; + + dropDb(ADMIN1, DB1); + createDb(ADMIN1, DB1); + createTable(ADMIN1, DB1, dataFile, TBL1); + + Connection adminCon = context.createConnection(ADMIN1); + Statement adminStmt = context.createStatement(adminCon); + // access the new databases + adminStmt.execute("use " + DB1); + + // stop server1 and verify sentry continues to work + getSentrySrv().stop(0); + adminStmt.execute("CREATE ROLE " + roleName1); + verifyRoleExists(adminStmt, roleName1); + + // restart server1 and stop server2 + getSentrySrv().start(0); + getSentrySrv().stop(1); + adminStmt.execute("CREATE ROLE " + roleName2); + verifyRoleExists(adminStmt, roleName2); + + // stop both servers and verify it fails + getSentrySrv().stop(0); + getSentrySrv().stop(1); + context.assertAuthzExecHookException(adminStmt, "CREATE ROLE " + roleName3, + HAClientInvocationHandler.SENTRY_HA_ERROR_MESSAGE); + + getSentrySrv().start(0); + getSentrySrv().start(1); + adminStmt.execute("CREATE ROLE " + roleName3); + verifyRoleExists(adminStmt, roleName3); + + // cleanup + + dropDb(ADMIN1, DB1); + adminStmt.execute("DROP ROLE " + roleName1); + adminStmt.execute("DROP ROLE " + roleName2); + adminStmt.execute("DROP ROLE " + roleName3); + adminStmt.close(); + adminCon.close(); + + } + + private void verifyRoleExists(Statement statement, String roleName) + throws Exception { + ResultSet resultSet = null; + try { + resultSet = statement.executeQuery("SHOW ROLES "); + while (resultSet.next()) { + if (roleName.equalsIgnoreCase(resultSet.getString(1))) { + return; + } + } + throw new Exception("Role " + roleName + " does not exist"); + } finally { + if (resultSet != null) { + resultSet.close(); + } + } + } +}
