You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sentry.apache.org by sh...@apache.org on 2013/09/21 01:38:57 UTC
[8/9] SENTRY-16: Move sentry-tests to sentry-tests-hive package
(Gregory Chanan via Shreepadma Venugopalan)
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/aef404c6/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestEndToEnd.java
----------------------------------------------------------------------
diff --git a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestEndToEnd.java b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestEndToEnd.java
new file mode 100644
index 0000000..8a32e5f
--- /dev/null
+++ b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestEndToEnd.java
@@ -0,0 +1,143 @@
+/*
+ * 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.hive;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.sql.Connection;
+import java.sql.Statement;
+
+import org.apache.sentry.provider.file.PolicyFile;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.io.Resources;
+
+public class TestEndToEnd extends AbstractTestWithStaticLocalFS {
+ private Context context;
+ private final String SINGLE_TYPE_DATA_FILE_NAME = "kv1.dat";
+ private File dataFile;
+ private PolicyFile policyFile;
+
+
+ @Before
+ public void setup() throws Exception {
+ context = createContext();
+ 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 = PolicyFile.createAdminOnServer1(ADMIN1);
+
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (context != null) {
+ context.close();
+ }
+ }
+
+ /**
+ * Steps:
+ * 1. admin create a new experimental database
+ * 2. admin create a new production database, create table, load data
+ * 3. admin create new user group, and add user into it
+ * 4. admin grant privilege all@'experimental database' to group
+ * 5. user create table, load data in experimental DB
+ * 6. user create view based on table in experimental DB
+ * 7. admin create table (same name) in production DB
+ * 8. admin grant read@productionDB.table to group
+ * admin grant select@productionDB.table to group
+ * 9. user load data from experimental table to production table
+ */
+ @Test
+ public void testEndToEnd1() throws Exception {
+ policyFile.write(context.getPolicyFile());
+
+ String dbName1 = "db_1";
+ String dbName2 = "productionDB";
+ String tableName1 = "tb_1";
+ String tableName2 = "tb_2";
+ String viewName1 = "view_1";
+ Connection connection = context.createConnection("admin1", "foo");
+ Statement statement = context.createStatement(connection);
+ // 1
+ statement.execute("DROP DATABASE IF EXISTS " + dbName1 + " CASCADE");
+ statement.execute("CREATE DATABASE " + dbName1);
+ // 2
+ statement.execute("DROP DATABASE IF EXISTS " + dbName2 + " CASCADE");
+ statement.execute("CREATE DATABASE " + dbName2);
+ statement.execute("USE " + dbName2);
+ statement.execute("DROP TABLE IF EXISTS " + dbName2 + "." + tableName2);
+ statement.execute("create table " + dbName2 + "." + tableName2
+ + " (under_col int comment 'the under column', value string)");
+ statement.execute("load data local inpath '" + dataFile.getPath()
+ + "' into table " + tableName2);
+ statement.close();
+ connection.close();
+
+ // 3
+ policyFile.addGroupsToUser("user1", "group1");
+
+ // 4
+ policyFile
+ .addRolesToGroup("group1", "all_db1", "data_uri", "select_tb1", "insert_tb1")
+ .addPermissionsToRole("all_db1", "server=server1->db=db_1")
+ .addPermissionsToRole("select_tb1", "server=server1->db=productionDB->table=tb_1->action=select")
+ .addPermissionsToRole("insert_tb2", "server=server1->db=productionDB->table=tb_2->action=insert")
+ .addPermissionsToRole("insert_tb1", "server=server1->db=productionDB->table=tb_2->action=insert")
+ .addPermissionsToRole("data_uri", "server=server1->uri=file://" + dataDir.getPath());
+ policyFile.write(context.getPolicyFile());
+
+ // 5
+ connection = context.createConnection("user1", "foo");
+ statement = context.createStatement(connection);
+ statement.execute("USE " + dbName1);
+ statement.execute("DROP TABLE IF EXISTS " + dbName1 + "." + tableName1);
+ statement.execute("create table " + dbName1 + "." + tableName1
+ + " (under_col int comment 'the under column', value string)");
+ statement.execute("load data local inpath '" + dataFile.getPath()
+ + "' into table " + tableName1);
+ // 6
+ statement.execute("CREATE VIEW " + viewName1 + " (value) AS SELECT value from " + tableName1 + " LIMIT 10");
+ statement.close();
+ connection.close();
+
+ // 7
+ connection = context.createConnection("admin1", "foo");
+ statement = context.createStatement(connection);
+ statement.execute("USE " + dbName2);
+ statement.execute("DROP TABLE IF EXISTS " + dbName1 + "." + tableName1);
+ statement.execute("create table " + dbName1 + "." + tableName1
+ + " (under_col int comment 'the under column', value string)");
+ statement.close();
+ connection.close();
+
+ // 9
+ connection = context.createConnection("user1", "foo");
+ statement = context.createStatement(connection);
+ statement.execute("USE " + dbName2);
+ statement.execute("INSERT OVERWRITE TABLE " +
+ dbName2 + "." + tableName2 + " SELECT * FROM " + dbName1
+ + "." + tableName1);
+ statement.close();
+ connection.close();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/aef404c6/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestExportImportPrivileges.java
----------------------------------------------------------------------
diff --git a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestExportImportPrivileges.java b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestExportImportPrivileges.java
new file mode 100644
index 0000000..c2403f8
--- /dev/null
+++ b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestExportImportPrivileges.java
@@ -0,0 +1,154 @@
+/*
+ * 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.hive;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.sql.Connection;
+import java.sql.Statement;
+
+import org.apache.hadoop.hive.conf.HiveConf;
+import org.apache.sentry.provider.file.PolicyFile;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.io.Resources;
+
+public class TestExportImportPrivileges extends AbstractTestWithStaticDFS {
+ private File dataFile;
+ private PolicyFile policyFile;
+
+ @Before
+ public void setup() throws Exception {
+ context = createContext();
+ 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 = PolicyFile.createAdminOnServer1(ADMIN1);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (context != null) {
+ context.close();
+ }
+ }
+
+ @Test
+ public void testInsertToDirPrivileges() throws Exception {
+ Connection connection = null;
+ Statement statement = null;
+ String dumpDir = context.getDFSUri().toString() + "/hive_data_dump";
+
+ policyFile
+ .addRolesToGroup("user_group1", "db1_read", "db1_write", "data_dump")
+ .addRolesToGroup("user_group2", "db1_read", "db1_write")
+ .addPermissionsToRole("db1_write", "server=server1->db=" + DB1 + "->table=" + TBL1 + "->action=INSERT")
+ .addPermissionsToRole("db1_read", "server=server1->db=" + DB1 + "->table=" + TBL1 + "->action=SELECT")
+ .addPermissionsToRole("data_dump", "server=server1->URI=" + dumpDir)
+ .addGroupsToUser("user1", "user_group1")
+ .addGroupsToUser("user2", "user_group2");
+ policyFile.write(context.getPolicyFile());
+
+ dropDb(ADMIN1, DB1);
+ createDb(ADMIN1, DB1);
+ createTable(ADMIN1, DB1, dataFile, TBL1);
+
+ // Negative test, user2 doesn't have access to write to dir
+ connection = context.createConnection(USER2, "password");
+ statement = context.createStatement(connection);
+ statement.execute("use " + DB1);
+ context.assertAuthzException(statement, "INSERT OVERWRITE DIRECTORY '" + dumpDir + "' SELECT * FROM " + TBL1);
+ statement.close();
+ connection.close();
+
+ // Negative test, user2 doesn't have access to dir that's similar to scratch dir
+ String scratchDumpDir = context.getProperty(HiveConf.ConfVars.SCRATCHDIR.varname) + "_foo" + "/bar";
+ connection = context.createConnection(USER2, "password");
+ statement = context.createStatement(connection);
+ statement.execute("use " + DB1);
+ context.assertAuthzException(statement, "INSERT OVERWRITE DIRECTORY '" + scratchDumpDir + "' SELECT * FROM " + TBL1);
+ statement.close();
+ connection.close();
+
+ // positive test, user1 has access to write to dir
+ connection = context.createConnection(USER1, "password");
+ statement = context.createStatement(connection);
+ statement.execute("use " + DB1);
+ assertTrue(statement.executeQuery("SELECT * FROM " + TBL1).next());
+ statement.execute("INSERT OVERWRITE DIRECTORY '" + dumpDir + "' SELECT * FROM " + TBL1);
+ }
+
+ @Test
+ public void testExportImportPrivileges() throws Exception {
+ Connection connection = null;
+ Statement statement = null;
+ String exportDir = context.getDFSUri().toString() + "/hive_export1";
+
+ policyFile
+ .addRolesToGroup("user_group1", "tab1_read", "tab1_write", "db1_all", "data_read", "data_export")
+ .addRolesToGroup("user_group2", "tab1_write", "tab1_read")
+ .addPermissionsToRole("tab1_write", "server=server1->db=" + DB1 + "->table=" + TBL1 + "->action=INSERT")
+ .addPermissionsToRole("tab1_read", "server=server1->db=" + DB1 + "->table=" + TBL1 + "->action=SELECT")
+ .addPermissionsToRole("db1_all", "server=server1->db=" + DB1)
+ .addPermissionsToRole("data_read", "server=server1->URI=file://" + dataFile.getPath())
+ .addPermissionsToRole("data_export", "server=server1->URI=" + exportDir)
+ .addGroupsToUser("user1", "user_group1")
+ .addGroupsToUser("user2", "user_group2");
+ policyFile.write(context.getPolicyFile());
+
+ dropDb(ADMIN1, DB1);
+ createDb(ADMIN1, DB1);
+ createTable(ADMIN1, DB1, dataFile, TBL1);
+
+ // Negative test, user2 doesn't have access to the file being loaded
+ connection = context.createConnection(USER2, "password");
+ statement = context.createStatement(connection);
+ statement.execute("use " + DB1);
+ context.assertAuthzException(statement, "EXPORT TABLE " + TBL1 + " TO '" + exportDir + "'");
+ statement.close();
+ connection.close();
+
+ // Positive test, user1 have access to the target directory
+ connection = context.createConnection(USER1, "password");
+ statement = context.createStatement(connection);
+ statement.execute("use " + DB1);
+ statement.execute("EXPORT TABLE " + TBL1 + " TO '" + exportDir + "'");
+ statement.close();
+ connection.close();
+
+ // Negative test, user2 doesn't have access to the directory loading from
+ connection = context.createConnection(USER2, "password");
+ statement = context.createStatement(connection);
+ statement.execute("use " + DB1);
+ context.assertAuthzException(statement, "IMPORT TABLE " + TBL2 + " FROM '" + exportDir + "'");
+ statement.close();
+ connection.close();
+
+ // Positive test, user1 have access to the target directory
+ connection = context.createConnection(USER1, "password");
+ statement = context.createStatement(connection);
+ statement.execute("use " + DB1);
+ statement.execute("IMPORT TABLE " + TBL2 + " FROM '" + exportDir + "'");
+ statement.close();
+ connection.close();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/aef404c6/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestMetadataObjectRetrieval.java
----------------------------------------------------------------------
diff --git a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestMetadataObjectRetrieval.java b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestMetadataObjectRetrieval.java
new file mode 100644
index 0000000..a16db9b
--- /dev/null
+++ b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestMetadataObjectRetrieval.java
@@ -0,0 +1,453 @@
+/*
+ * 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.hive;
+
+import static org.junit.Assert.assertEquals;
+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.Statement;
+
+import org.apache.sentry.provider.file.PolicyFile;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.io.Resources;
+
+public class TestMetadataObjectRetrieval extends
+AbstractTestWithStaticLocalFS {
+ private PolicyFile policyFile;
+ private File dataFile;
+
+ @Before
+ public void setup() throws Exception {
+ policyFile = PolicyFile.createAdminOnServer1(ADMIN1);
+ context = createContext();
+ 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();
+ }
+ }
+
+ /**
+ * Method called to run positive tests:
+ * describe table
+ * describe table column
+ * show columns from table
+ * show create table table
+ * show tblproperties table
+ *
+ * The table is assumed to have two colums under_col int and value string.
+ */
+ private void positiveDescribeShowTests(String user, String db, String table) throws Exception {
+ Connection connection = context.createConnection(user, "password");
+ Statement statement = context.createStatement(connection);
+ statement.execute("USE " + db);
+ ResultSet rs = statement.executeQuery("DESCRIBE " + table);
+ assertTrue(rs.next());
+
+ assertTrue("describe table fail", rs.getString(1).trim().equals("under_col"));
+ assertTrue("describe table fail", rs.getString(2).trim().equals("int"));
+ assertTrue(rs.next());
+ assertTrue("describe table fail", rs.getString(1).trim().equals("value"));
+ assertTrue("describe table fail", rs.getString(2).trim().equals("string"));
+
+ rs = statement.executeQuery("DESCRIBE " + table + " under_col");
+ assertTrue(rs.next());
+ assertTrue("describe table fail", rs.getString(1).trim().equals("under_col"));
+ assertTrue("describe table fail", rs.getString(2).trim().equals("int"));
+
+ rs = statement.executeQuery("DESCRIBE " + table + " value");
+ assertTrue(rs.next());
+ assertTrue("describe table fail", rs.getString(1).trim().equals("value"));
+ assertTrue("describe table fail", rs.getString(2).trim().equals("string"));
+
+ rs = statement.executeQuery("SHOW COLUMNS FROM " + table);
+ assertTrue(rs.next());
+ assertTrue("show columns from fail", rs.getString(1).trim().equals("under_col"));
+ assertTrue(rs.next());
+ assertTrue("show columns from fail", rs.getString(1).trim().equals("value"));
+
+ rs = statement.executeQuery("SHOW CREATE TABLE " + table);
+ assertTrue("SHOW CREATE TABLE fail", rs.next());
+
+ rs = statement.executeQuery("SHOW TBLPROPERTIES " + table);
+ assertTrue("SHOW TBLPROPERTIES fail", rs.next());
+
+ statement.close();
+ connection.close();
+ }
+ /**
+ * Method called to run negative tests:
+ * describe table
+ * describe table column
+ * show columns from table
+ * show create table table
+ * show tblproperties table
+ *
+ * The table is assumed to have two columns under_col int and value string.
+ */
+ private void negativeDescribeShowTests(String user, String db, String table) throws Exception {
+ Connection connection = context.createConnection(user, "password");
+ Statement statement = context.createStatement(connection);
+ statement.execute("USE " + db);
+ context.assertAuthzException(statement, "DESCRIBE " + table);
+ context.assertAuthzException(statement, "DESCRIBE " + table + " under_col");
+ context.assertAuthzException(statement, "DESCRIBE " + table + " value");
+ context.assertAuthzException(statement, "SHOW COLUMNS FROM " + table);
+ context.assertAuthzException(statement, "SHOW CREATE TABLE " + table);
+ context.assertAuthzException(statement, "SHOW TBLPROPERTIES " + table);
+ statement.close();
+ connection.close();
+ }
+
+
+ /**
+ * Tests to ensure a user with all on server,
+ * insert|select on table can view metadata while
+ * a user with all on a different table cannot
+ * view the metadata.
+
+ * Test both positive and negative of:
+ * describe table
+ * describe table column
+ * show columns from table
+ * show create table table
+ * show tblproperties table
+ *
+ * Positive tests are run with:
+ * all@server
+ * select@table
+ * insert@table
+ * Negative tests are run three times:
+ * none
+ * insert@different table
+ */
+ @Test
+ public void testAllOnServerSelectInsertNegativeNoneAllOnDifferentTable()
+ throws Exception {
+ policyFile
+ .addPermissionsToRole(GROUP1_ROLE, "server=server1->db=" + DB1 + "->table=" + TBL2)
+ .addRolesToGroup(GROUP1, GROUP1_ROLE)
+ .addGroupsToUser(USER1, GROUP1)
+ .write(context.getPolicyFile());
+ dropDb(ADMIN1, DB1);
+ createDb(ADMIN1, DB1);
+ createTable(ADMIN1, DB1, dataFile, TBL1);
+ positiveDescribeShowTests(ADMIN1, DB1, TBL1);
+ negativeDescribeShowTests(USER1, DB1, TBL1);
+ policyFile
+ .addPermissionsToRole(GROUP1_ROLE, SELECT_DB1_TBL1)
+ .write(context.getPolicyFile());
+ positiveDescribeShowTests(USER1, DB1, TBL1);
+ policyFile.removePermissionsFromRole(GROUP1_ROLE, SELECT_DB1_TBL1);
+ policyFile
+ .addPermissionsToRole(GROUP1_ROLE, INSERT_DB1_TBL1)
+ .write(context.getPolicyFile());
+ positiveDescribeShowTests(USER1, DB1, TBL1);
+ }
+
+ /**
+ * Tests to ensure that a user is able to view metadata
+ * with all on db
+ *
+ * Test positive:
+ * describe table
+ * describe table column
+ * show columns from table
+ * show create table table
+ * show tblproperties table
+ *
+ * Positive tests are run twice:
+ * all@server
+ * all@db
+ */
+ @Test
+ public void testAllOnServerAndAllOnDb() throws Exception {
+ policyFile
+ .addPermissionsToRole(GROUP1_ROLE, "server=server1->db=" + DB1)
+ .addRolesToGroup(GROUP1, GROUP1_ROLE)
+ .addGroupsToUser(USER1, GROUP1)
+ .write(context.getPolicyFile());
+ dropDb(ADMIN1, DB1);
+ createDb(ADMIN1, DB1);
+ createTable(ADMIN1, DB1, dataFile, TBL1);
+ positiveDescribeShowTests(ADMIN1, DB1, TBL1);
+ positiveDescribeShowTests(USER1, DB1, TBL1);
+ }
+
+ /**
+ * Test to ensure that all on view do not result in
+ * metadata privileges on the underlying table
+ *
+ * Test both positive and negative of:
+ * describe table
+ * describe table column
+ * show columns from table
+ * show create table table
+ * show tblproperties table
+ *
+ * Positive tests are run with all@server
+ * Negative tests are run three times:
+ * none
+ * all@view
+ */
+ @Test
+ public void testAllOnServerNegativeAllOnView() throws Exception {
+ policyFile
+ .addPermissionsToRole(GROUP1_ROLE, "server=server1->db=" + DB1 + "->table=" + VIEW1)
+ .addRolesToGroup(GROUP1, GROUP1_ROLE)
+ .addGroupsToUser(USER1, GROUP1)
+ .write(context.getPolicyFile());
+ dropDb(ADMIN1, DB1);
+ createDb(ADMIN1, DB1);
+ createTable(ADMIN1, DB1, dataFile, TBL1);
+ Connection connection = context.createConnection(ADMIN1, "password");
+ Statement statement = context.createStatement(connection);
+ statement.execute("USE " + DB1);
+ statement.execute("DROP VIEW IF EXISTS " + VIEW1);
+ statement.execute("CREATE VIEW " + VIEW1 + " (value) AS SELECT value from " + TBL1 + " LIMIT 10");
+ positiveDescribeShowTests(ADMIN1, DB1, TBL1);
+ statement.close();
+ connection.close();
+ negativeDescribeShowTests(USER1, DB1, TBL1);
+ }
+
+ /**
+ * Tests to ensure that a user is able to view metadata
+ * with all on table
+ *
+ * Test positive:
+ * describe table
+ * describe table column
+ * show columns from table
+ * show create table table
+ * show tblproperties table
+ *
+ * Positive tests are run twice:
+ * all@server
+ * all@table
+ */
+ @Test
+ public void testAllOnServerAndAllOnTable() throws Exception {
+ policyFile
+ .addPermissionsToRole(GROUP1_ROLE, "server=server1->db=" + DB1 + "->table=" + TBL1)
+ .addRolesToGroup(GROUP1, GROUP1_ROLE)
+ .addGroupsToUser(USER1, GROUP1)
+ .write(context.getPolicyFile());
+ dropDb(ADMIN1, DB1);
+ createDb(ADMIN1, DB1);
+ createTable(ADMIN1, DB1, dataFile, TBL1);
+ positiveDescribeShowTests(ADMIN1, DB1, TBL1);
+ positiveDescribeShowTests(USER1, DB1, TBL1);
+ }
+
+
+ /**
+ * Tests that admin and all@db can describe database
+ * and describe database extended. Also tests that a user
+ * with no privileges on a db cannot describe database.
+ */
+ @Test
+ public void testDescribeDatabasesWithAllOnServerAndAllOnDb()
+ throws Exception {
+ policyFile
+ .addPermissionsToRole(GROUP1_ROLE, "server=server1->db=" + DB1)
+ .addRolesToGroup(GROUP1, GROUP1_ROLE)
+ .addGroupsToUser(USER1, GROUP1)
+ .write(context.getPolicyFile());
+ dropDb(ADMIN1, DB1, DB2);
+ createDb(ADMIN1, DB1, DB2);
+ createTable(ADMIN1, DB1, dataFile, TBL1);
+
+ Connection connection = context.createConnection(ADMIN1, "password");
+ Statement statement = context.createStatement(connection);
+ assertTrue(statement.executeQuery("DESCRIBE DATABASE " + DB1).next());
+ assertTrue(statement.executeQuery("DESCRIBE DATABASE EXTENDED " + DB1).next());
+ statement.close();
+ connection.close();
+
+ connection = context.createConnection(USER1, "password");
+ statement = context.createStatement(connection);
+ assertTrue(statement.executeQuery("DESCRIBE DATABASE " + DB1).next());
+ assertTrue(statement.executeQuery("DESCRIBE DATABASE EXTENDED " + DB1).next());
+ context.assertAuthzException(statement, "DESCRIBE DATABASE " + DB2);
+ context.assertAuthzException(statement, "DESCRIBE DATABASE EXTENDED " + DB2);
+ policyFile.addPermissionsToRole(GROUP1_ROLE, INSERT_DB2_TBL1)
+ .write(context.getPolicyFile());
+ context.assertAuthzException(statement, "DESCRIBE DATABASE " + DB2);
+ context.assertAuthzException(statement, "DESCRIBE DATABASE EXTENDED " + DB2);
+ statement.close();
+ connection.close();
+ }
+
+ /**
+ * Tests that a user without db level privileges cannot describe default
+ */
+ @Test
+ public void testDescribeDefaultDatabase() throws Exception {
+ policyFile
+ .addPermissionsToRole(GROUP1_ROLE, "server=server1->db=default->table=" + TBL1 + "->action=select",
+ "server=server1->db=" + DB1 + "->table=" + TBL1 + "->action=select")
+ .addRolesToGroup(GROUP1, GROUP1_ROLE)
+ .addGroupsToUser(USER1, GROUP1)
+ .write(context.getPolicyFile());
+ dropDb(ADMIN1, DB1, DB2);
+ createDb(ADMIN1, DB1, DB2);
+ Connection connection = context.createConnection(ADMIN1, "password");
+ Statement statement = context.createStatement(connection);
+ assertTrue(statement.executeQuery("DESCRIBE DATABASE default").next());
+ statement.execute("USE " + DB1);
+ assertTrue(statement.executeQuery("DESCRIBE DATABASE default").next());
+ assertTrue(statement.executeQuery("DESCRIBE DATABASE " + DB1).next());
+ assertTrue(statement.executeQuery("DESCRIBE DATABASE " + DB2).next());
+ statement.close();
+ connection.close();
+
+ connection = context.createConnection(USER1, "password");
+ statement = context.createStatement(connection);
+ context.assertAuthzException(statement, "DESCRIBE DATABASE default");
+ context.assertAuthzException(statement, "DESCRIBE DATABASE " + DB1);
+ statement.execute("USE " + DB1);
+ context.assertAuthzException(statement, "DESCRIBE DATABASE " + DB1);
+ context.assertAuthzException(statement, "DESCRIBE DATABASE " + DB2);
+ statement.close();
+ connection.close();
+ }
+
+ /**
+ * Tests that users without privileges cannot execute show indexes
+ * and that users with all on table can execute show indexes
+ */
+ @Test
+ public void testShowIndexes1() throws Exception {
+ // grant privilege to non-existent table to allow use db1
+ policyFile.addPermissionsToRole(GROUP1_ROLE, SELECT_DB1_NONTABLE)
+ .addRolesToGroup(GROUP1, GROUP1_ROLE)
+ .addGroupsToUser(USER1, GROUP1)
+ .write(context.getPolicyFile());
+ dropDb(ADMIN1, DB1);
+ createDb(ADMIN1, DB1);
+ createTable(ADMIN1, DB1, dataFile, TBL1);
+ Connection connection = context.createConnection(ADMIN1, "password");
+ Statement statement = context.createStatement(connection);
+ statement.execute("USE " + DB1);
+ statement.execute("DROP INDEX IF EXISTS " + INDEX1 + " ON " + TBL1);
+ statement
+ .execute("CREATE INDEX "
+ + INDEX1
+ + " ON TABLE "
+ + TBL1
+ + "(value) AS 'org.apache.hadoop.hive.ql.index.compact.CompactIndexHandler' WITH DEFERRED REBUILD");
+ statement.execute("DROP VIEW IF EXISTS " + VIEW1);
+ statement.execute("CREATE VIEW " + VIEW1 + " (value) AS SELECT value from " + TBL1 + " LIMIT 10");
+ statement.close();
+ connection.close();
+ connection = context.createConnection(USER1, "password");
+ statement = context.createStatement(connection);
+ statement.execute("USE " + DB1);
+ context.assertAuthzException(statement, "SHOW INDEX ON " + TBL1);
+ policyFile
+ .addPermissionsToRole(GROUP1_ROLE, SELECT_DB1_VIEW1)
+ .write(context.getPolicyFile());
+ context.assertAuthzException(statement, "SHOW INDEX ON " + TBL1);
+ policyFile.removePermissionsFromRole(GROUP1_ROLE, SELECT_DB1_VIEW1)
+ .addPermissionsToRole(GROUP1_ROLE, SELECT_DB1_TBL1)
+ .write(context.getPolicyFile());
+ verifyIndex(statement, TBL1, INDEX1);
+ policyFile.removePermissionsFromRole(GROUP1_ROLE, SELECT_DB1_TBL1)
+ .addPermissionsToRole(GROUP1_ROLE, INSERT_DB1_TBL1)
+ .write(context.getPolicyFile());
+ verifyIndex(statement, TBL1, INDEX1);
+ statement.close();
+ connection.close();
+ }
+
+ private void verifyIndex(Statement statement, String table, String index) throws Exception {
+ ResultSet rs = statement.executeQuery("SHOW INDEX ON " + table);
+ assertTrue(rs.next());
+ assertEquals(index, rs.getString(1).trim());
+ assertEquals(table, rs.getString(2).trim());
+ assertEquals("value", rs.getString(3).trim());
+ assertEquals("db_1__tb_1_index_1__", rs.getString(4).trim());
+ assertEquals("compact", rs.getString(5).trim());
+ }
+
+ /**
+ * Tests that users without privileges cannot execute show partitions
+ * and that users with select on table can execute show partitions
+ */
+ @Test
+ public void testShowPartitions1() throws Exception {
+ // grant privilege to non-existent table to allow use db1
+ policyFile.addPermissionsToRole(GROUP1_ROLE, SELECT_DB1_NONTABLE)
+ .addRolesToGroup(GROUP1, GROUP1_ROLE)
+ .addGroupsToUser(USER1, GROUP1)
+ .write(context.getPolicyFile());
+ dropDb(ADMIN1, DB1);
+ createDb(ADMIN1, DB1);
+ Connection connection = context.createConnection(ADMIN1, "password");
+ Statement statement = context.createStatement(connection);
+ statement.execute("USE " + DB1);
+ statement.execute("DROP TABLE IF EXISTS " + TBL1);
+ statement.execute("create table " + TBL1
+ + " (under_col int, value string) PARTITIONED BY (dt INT)");
+ statement.execute("load data local inpath '" + dataFile.getPath()
+ + "' into table " + TBL1 + " PARTITION (dt=3)");
+ statement.execute("DROP VIEW IF EXISTS " + VIEW1);
+ statement.execute("CREATE VIEW " + VIEW1 + " (value) AS SELECT value from " + TBL1 + " LIMIT 10");
+ statement.close();
+ connection.close();
+ connection = context.createConnection(USER1, "password");
+ statement = context.createStatement(connection);
+ statement.execute("USE " + DB1);
+ context.assertAuthzException(statement, "SHOW PARTITIONS " + TBL1);
+ policyFile
+ .addPermissionsToRole(GROUP1_ROLE, SELECT_DB1_VIEW1)
+ .write(context.getPolicyFile());
+ context.assertAuthzException(statement, "SHOW PARTITIONS " + TBL1);
+ policyFile
+ .removePermissionsFromRole(GROUP1_ROLE, SELECT_DB1_VIEW1)
+ .addPermissionsToRole(GROUP1_ROLE, SELECT_DB1_TBL1)
+ .write(context.getPolicyFile());
+ verifyParition(statement, TBL1);
+ policyFile.removePermissionsFromRole(GROUP1_ROLE, SELECT_DB1_TBL1)
+ .addPermissionsToRole(GROUP1_ROLE, INSERT_DB1_TBL1)
+ .write(context.getPolicyFile());
+ verifyParition(statement, TBL1);
+ statement.close();
+ connection.close();
+ }
+
+ private void verifyParition(Statement statement, String table) throws Exception {
+ ResultSet rs = statement.executeQuery("SHOW PARTITIONS " + TBL1);
+ assertTrue(rs.next());
+ assertEquals("dt=3", rs.getString(1).trim());
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/aef404c6/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestMetadataPermissions.java
----------------------------------------------------------------------
diff --git a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestMetadataPermissions.java b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestMetadataPermissions.java
new file mode 100644
index 0000000..cddd1d7
--- /dev/null
+++ b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestMetadataPermissions.java
@@ -0,0 +1,158 @@
+/*
+ * 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.hive;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import junit.framework.Assert;
+
+import org.apache.sentry.provider.file.PolicyFile;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+
+public class TestMetadataPermissions extends AbstractTestWithStaticLocalFS {
+ private Context context;
+ private PolicyFile policyFile;
+
+ @Before
+ public void setup() throws Exception {
+ context = createContext();
+ policyFile = PolicyFile.createAdminOnServer1(ADMIN1);
+
+/*
+ String testPolicies[] = {
+ "[groups]",
+ "admin_group = admin_role",
+ "user_group1 = db1_all,db2_all",
+ "user_group2 = db1_all",
+ "[roles]",
+ "db1_all = server=server1->db=db1",
+ "db2_all = server=server1->db=db2",
+ "admin_role = server=server1",
+ "[users]",
+ "user1 = user_group1",
+ "user2 = user_group2",
+ "admin = admin_group"
+ };
+ context.makeNewPolicy(testPolicies);
+*/
+ policyFile
+ .addRolesToGroup("user_group1", "db1_all", "db2_all")
+ .addRolesToGroup("user_group2", "db1_all")
+ .addPermissionsToRole("db1_all", "server=server1->db=db1")
+ .addPermissionsToRole("db2_all", "server=server1->db=db2")
+ .addGroupsToUser("user1", "user_group1")
+ .addGroupsToUser("user2", "user_group2")
+ .write(context.getPolicyFile());
+
+ Connection adminCon = context.createConnection(ADMIN1, "foo");
+ Statement adminStmt = context.createStatement(adminCon);
+ for (String dbName : new String[] { "db1", "db2" }) {
+ adminStmt.execute("USE default");
+ adminStmt.execute("DROP DATABASE IF EXISTS " + dbName + " CASCADE");
+ adminStmt.execute("CREATE DATABASE " + dbName);
+ adminStmt.execute("USE " + dbName);
+ for (String tabName : new String[] { "tab1", "tab2" }) {
+ adminStmt.execute("CREATE TABLE " + tabName + " (id int)");
+ }
+ }
+ context.close();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (context != null) {
+ context.close();
+ }
+ }
+
+ /**
+ * Ensure that a user with no privileges on a database cannot
+ * query that databases metadata.
+ */
+ @Test
+ public void testDescPrivilegesNegative() throws Exception {
+ String dbName = "db2";
+ Connection connection = context.createConnection("user2", "password");
+ Statement statement = context.createStatement(connection);
+ context.assertAuthzException(statement, "USE " + dbName);
+// TODO when DESCRIBE db.table is supported tests should be uncommented
+// for (String tabName : new String[] { "tab1", "tab2" }) {
+// context.assertAuthzException(statement, "DESCRIBE " + dbName + "." + tabName);
+// context.assertAuthzException(statement, "DESCRIBE EXTENDED " + dbName + "." + tabName);
+// }
+ statement.close();
+ connection.close();
+ }
+
+ /**
+ * Ensure that a user cannot describe databases to which the user
+ * has no privilege.
+ */
+ @Test
+ public void testDescDbPrivilegesNegative() throws Exception {
+ String dbName = "db2";
+ Connection connection = context.createConnection("user2", "password");
+ Statement statement = context.createStatement(connection);
+ context.assertAuthzException(statement, "DESCRIBE DATABASE " + dbName);
+ context.assertAuthzException(statement, "DESCRIBE DATABASE EXTENDED " + dbName);
+ statement.close();
+ connection.close();
+ }
+
+ /**
+ * Ensure that a user with privileges on a database can describe
+ * the database.
+ */
+ @Test
+ public void testDescDbPrivilegesPositive() throws Exception {
+ Connection connection = context.createConnection("user1", "password");
+ Statement statement = context.createStatement(connection);
+ for (String dbName : new String[] { "db1", "db2" }) {
+ statement.execute("USE " + dbName);
+ Assert.assertTrue(statement.executeQuery("DESCRIBE DATABASE " + dbName).next());
+ Assert.assertTrue(statement.executeQuery("DESCRIBE DATABASE EXTENDED " + dbName).next());
+ }
+ statement.close();
+ connection.close();
+ }
+
+ /**
+ * Ensure that a user with privileges on a table can describe the table.
+ */
+ @Test
+ public void testDescPrivilegesPositive() throws Exception {
+ Connection connection = context.createConnection("user1", "password");
+ Statement statement = context.createStatement(connection);
+ for (String dbName : new String[] { "db1", "db2" }) {
+ statement.execute("USE " + dbName);
+ Assert.assertTrue(statement.executeQuery("DESCRIBE DATABASE " + dbName).next());
+ for (String tabName : new String[] { "tab1", "tab2" }) {
+ Assert.assertTrue(statement.executeQuery("DESCRIBE " + tabName).next());
+ Assert.assertTrue(statement.executeQuery("DESCRIBE EXTENDED " + tabName).next());
+
+ }
+ }
+ statement.close();
+ connection.close();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/aef404c6/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestMovingToProduction.java
----------------------------------------------------------------------
diff --git a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestMovingToProduction.java b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestMovingToProduction.java
new file mode 100644
index 0000000..ae3105c
--- /dev/null
+++ b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestMovingToProduction.java
@@ -0,0 +1,231 @@
+/*
+ * 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.hive;
+
+import static org.junit.Assert.assertEquals;
+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.Statement;
+
+import junit.framework.Assert;
+
+import org.apache.sentry.provider.file.PolicyFile;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.io.Resources;
+
+public class TestMovingToProduction extends AbstractTestWithStaticLocalFS {
+ private Context context;
+ private final String SINGLE_TYPE_DATA_FILE_NAME = "kv1.dat";
+ private PolicyFile policyFile;
+
+
+ @Before
+ public void setUp() throws Exception {
+ 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();
+ policyFile = PolicyFile.createAdminOnServer1(ADMIN1);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (context != null) {
+ context.close();
+ }
+ }
+
+ /**
+ * Steps:
+ * 1. admin create DB_1, admin create GROUP_1, GROUP_2
+ * 2. admin grant all to GROUP_1 on DB_1
+ * 3. user in GROUP_1 create table tb_1 and load data into
+ * 4. admin create table production.tb_1.
+ * 5. admin grant all to GROUP_1 on production.tb_1.
+ * positive test cases:
+ * a)verify user in GROUP_1 can load data from DB_1.tb_1 to production.tb_1
+ * b)verify user in GROUP_1 has proper privilege on production.tb_1
+ * (read and insert)
+ * negative test cases:
+ * c)verify user in GROUP_2 cannot load data from DB_1.tb_1
+ * to production.tb_1
+ * d)verify user in GROUP_1 cannot drop production.tb_1
+ */
+ @Test
+ public void testMovingTable1() throws Exception {
+ policyFile
+ .addRolesToGroup("group1", "all_db1", "load_data", "select_proddb_tbl1", "insert_proddb_tbl1")
+ .addPermissionsToRole("load_data", "server=server1->uri=file://" + dataDir.getPath())
+ .addPermissionsToRole("all_db1", "server=server1->db=db_1")
+ .addGroupsToUser("user1", "group1")
+ .addGroupsToUser("user2", "group2")
+ .write(context.getPolicyFile());
+
+ String dbName1 = "db_1";
+ String dbName2 = "proddb";
+ String tableName1 = "tb_1";
+
+ Connection connection = context.createConnection(ADMIN1, "foo");
+ Statement statement = context.createStatement(connection);
+ statement.execute("DROP DATABASE IF EXISTS " + dbName1 + " CASCADE");
+ statement.execute("DROP DATABASE IF EXISTS " + dbName2 + " CASCADE");
+ statement.execute("CREATE DATABASE " + dbName1);
+ statement.execute("CREATE DATABASE " + dbName2);
+ statement.execute("DROP TABLE IF EXISTS " + dbName2 + "." + tableName1);
+ statement.execute("create table " + dbName2 + "." + tableName1
+ + " (under_col int comment 'the under column', value string)");
+ statement.close();
+ connection.close();
+
+ // a
+ connection = context.createConnection("user1", "foo");
+ statement = context.createStatement(connection);
+ statement.execute("USE " + dbName1);
+ statement.execute("DROP TABLE IF EXISTS " + tableName1);
+ statement.execute("create table " + tableName1
+ + " (under_col int comment 'the under column', value string)");
+ statement.execute("LOAD DATA INPATH 'file://" + dataDir.getPath()
+ + "' INTO TABLE " + tableName1);
+
+ policyFile
+ .addPermissionsToRole("insert_proddb_tbl1", "server=server1->db=proddb->table=tb_1->action=insert")
+ .write(context.getPolicyFile());
+ statement.execute("USE " + dbName2);
+ statement.execute("INSERT OVERWRITE TABLE "
+ + tableName1 + " SELECT * FROM " + dbName1
+ + "." + tableName1);
+
+ // b
+ policyFile
+ .addPermissionsToRole("select_proddb_tbl1", "server=server1->db=proddb->table=tb_1->action=select")
+ .write(context.getPolicyFile());
+ ResultSet resultSet = statement.executeQuery("SELECT * FROM " + tableName1 + " LIMIT 10");
+ int count = 0;
+ while(resultSet.next()) {
+ count++;
+ }
+ assertEquals(10, count);
+ statement.execute("DESCRIBE " + tableName1);
+
+ // c
+ connection = context.createConnection("user2", "foo");
+ statement = context.createStatement(connection);
+ context.assertAuthzException(statement, "USE " + dbName2);
+ context.assertAuthzException(statement, "INSERT OVERWRITE TABLE "
+ + dbName2 + "." + tableName1 + " SELECT * FROM " + dbName1
+ + "." + tableName1);
+ context.assertAuthzException(statement, "SELECT * FROM " + dbName2 + "." + tableName1 + " LIMIT 10");
+ statement.close();
+ connection.close();
+
+ // d
+ connection = context.createConnection("user1", "foo");
+ statement = context.createStatement(connection);
+ statement.execute("USE " + dbName2);
+ context.assertAuthzException(statement, "DROP TABLE " + tableName1);
+ statement.close();
+ connection.close();
+ }
+
+ /**
+ * repeat above tests, only difference is don't do 'USE <database>'
+ * in this test. Instead, access table objects across database by
+ * database.table
+ * @throws Exception
+ */
+ @Test
+ public void testMovingTable2() throws Exception {
+ policyFile
+ .addRolesToGroup("group1", "all_db1", "load_data", "select_proddb_tbl1", "insert_proddb_tbl1")
+ .addPermissionsToRole("all_db1", "server=server1->db=db_1")
+ .addPermissionsToRole("load_data", "server=server1->uri=file://" + dataDir.getPath())
+ .addGroupsToUser("user1", "group1")
+ .addGroupsToUser("user2", "group2")
+ .write(context.getPolicyFile());
+
+ String dbName1 = "db_1";
+ String dbName2 = "proddb";
+ String tableName1 = "tb_1";
+ Connection connection = context.createConnection("admin1", "foo");
+ Statement statement = context.createStatement(connection);
+ statement.execute("DROP DATABASE IF EXISTS " + dbName1 + " CASCADE");
+ statement.execute("DROP DATABASE IF EXISTS " + dbName2 + " CASCADE");
+ statement.execute("CREATE DATABASE " + dbName1);
+ statement.execute("CREATE DATABASE " + dbName2);
+ statement.execute("DROP TABLE IF EXISTS " + dbName2 + "." + tableName1);
+ statement.execute("create table " + dbName2 + "." + tableName1
+ + " (under_col int comment 'the under column', value string)");
+ statement.close();
+ connection.close();
+
+ // a
+ connection = context.createConnection("user1", "foo");
+ statement = context.createStatement(connection);
+ statement.execute("DROP TABLE IF EXISTS " + dbName1 + "." + tableName1);
+ statement.execute("create table " + dbName1 + "." + tableName1
+ + " (under_col int comment 'the under column', value string)");
+ statement.execute("LOAD DATA INPATH 'file://" + dataDir.getPath()
+ + "' INTO TABLE " + dbName1 + "." + tableName1);
+
+ policyFile
+ .addPermissionsToRole("insert_proddb_tbl1", "server=server1->db=proddb->table=tb_1->action=insert")
+ .write(context.getPolicyFile());
+ statement.execute("INSERT OVERWRITE TABLE "
+ + dbName2 + "." + tableName1 + " SELECT * FROM " + dbName1
+ + "." + tableName1);
+
+ // b
+ policyFile
+ .addPermissionsToRole("select_proddb_tbl1", "server=server1->db=proddb->table=tb_1->action=select")
+ .write(context.getPolicyFile());
+ assertTrue("user1 should be able to select data from "
+ + dbName2 + "." + dbName2 + "." + tableName1, statement.execute("SELECT * FROM "
+ + dbName2 + "." + tableName1 + " LIMIT 10"));
+ assertTrue("user1 should be able to describe table " + dbName2 + "." + tableName1,
+ statement.execute("DESCRIBE " + dbName2 + "." + tableName1));
+
+ // c
+ connection = context.createConnection("user2", "foo");
+ statement = context.createStatement(connection);
+
+ context.assertAuthzException(statement, "INSERT OVERWRITE TABLE "
+ + dbName2 + "." + tableName1 + " SELECT * FROM " + dbName1
+ + "." + tableName1);
+
+ context.assertAuthzException(statement, "SELECT * FROM "
+ + dbName2 + "." + tableName1 + " LIMIT 10");
+ statement.close();
+ connection.close();
+
+ // d
+ connection = context.createConnection("user1", "foo");
+ statement = context.createStatement(connection);
+ statement.execute("USE " + dbName2);
+ context.assertAuthzException(statement, "DROP TABLE " + tableName1);
+ statement.close();
+ connection.close();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/aef404c6/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestPerDBConfiguration.java
----------------------------------------------------------------------
diff --git a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestPerDBConfiguration.java b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestPerDBConfiguration.java
new file mode 100644
index 0000000..17f4de1
--- /dev/null
+++ b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestPerDBConfiguration.java
@@ -0,0 +1,486 @@
+/*
+ * 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.hive;
+
+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 org.apache.sentry.provider.file.PolicyFile;
+import org.apache.sentry.provider.file.SimplePolicyEngine;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.base.Charsets;
+import com.google.common.base.Joiner;
+import com.google.common.io.Files;
+import com.google.common.io.Resources;
+
+/**
+ * Test privileges per database policy files
+ */
+public class TestPerDBConfiguration extends AbstractTestWithStaticLocalFS {
+ private static final String MULTI_TYPE_DATA_FILE_NAME = "emp.dat";
+ private static final String DB2_POLICY_FILE = "db2-policy-file.ini";
+
+ private Context context;
+ private File dataFile;
+ private PolicyFile policyFile;
+
+ @Before
+ public void setup() throws Exception {
+ context = createContext();
+ policyFile = PolicyFile.createAdminOnServer1(ADMIN1);
+
+ File dataDir = context.getDataDir();
+ //copy data file to test dir
+ dataFile = new File(dataDir, MULTI_TYPE_DATA_FILE_NAME);
+ FileOutputStream to = new FileOutputStream(dataFile);
+ Resources.copy(Resources.getResource(MULTI_TYPE_DATA_FILE_NAME), to);
+ to.close();
+
+ }
+
+ @After
+ public void teardown() throws Exception {
+ if (context != null) {
+ context.close();
+ }
+ }
+
+ @Test
+ public void testPerDB() throws Exception {
+ PolicyFile db2PolicyFile = new PolicyFile();
+ File db2PolicyFileHandle = new File(context.getPolicyFile().getParent(), DB2_POLICY_FILE);
+ db2PolicyFile
+ .addRolesToGroup("user_group2", "select_tbl2")
+ .addPermissionsToRole("select_tbl2", "server=server1->db=db2->table=tbl2->action=select")
+ .write(db2PolicyFileHandle);
+
+ policyFile
+ .addRolesToGroup("user_group1", "select_tbl1")
+ .addRolesToGroup("user_group2", "select_tbl2")
+ .addPermissionsToRole("select_tbl1", "server=server1->db=db1->table=tbl1->action=select")
+ .addGroupsToUser("user1", "user_group1")
+ .addGroupsToUser("user2", "user_group2")
+ .addDatabase("db2", db2PolicyFileHandle.getPath())
+ .write(context.getPolicyFile());
+
+ // setup db objects needed by the test
+ Connection connection = context.createConnection(ADMIN1, "hive");
+ Statement statement = context.createStatement(connection);
+
+ statement.execute("DROP DATABASE IF EXISTS db1 CASCADE");
+ statement.execute("DROP DATABASE IF EXISTS db2 CASCADE");
+ statement.execute("CREATE DATABASE db1");
+ statement.execute("USE db1");
+ statement.execute("CREATE TABLE tbl1(B INT, A STRING) " +
+ " row format delimited fields terminated by '|' stored as textfile");
+ statement.execute("LOAD DATA LOCAL INPATH '" + dataFile.getPath() + "' INTO TABLE tbl1");
+ statement.execute("DROP DATABASE IF EXISTS db2 CASCADE");
+ statement.execute("CREATE DATABASE db2");
+ statement.execute("USE db2");
+ statement.execute("CREATE TABLE tbl2(B INT, A STRING) " +
+ " row format delimited fields terminated by '|' stored as textfile");
+ statement.execute("LOAD DATA LOCAL INPATH '" + dataFile.getPath() + "' INTO TABLE tbl2");
+ statement.close();
+ connection.close();
+
+ // test execution
+ connection = context.createConnection("user1", "password");
+ statement = context.createStatement(connection);
+ statement.execute("USE db1");
+ // test user1 can execute query on tbl1
+ verifyCount(statement, "SELECT COUNT(*) FROM tbl1");
+
+ // user1 cannot query db2.tbl2
+ context.assertAuthzException(statement, "USE db2");
+ context.assertAuthzException(statement, "SELECT COUNT(*) FROM db2.tbl2");
+ statement.close();
+ connection.close();
+
+ // test per-db file for db2
+
+ connection = context.createConnection("user2", "password");
+ statement = context.createStatement(connection);
+ statement.execute("USE db2");
+ // test user2 can execute query on tbl2
+ verifyCount(statement, "SELECT COUNT(*) FROM tbl2");
+
+ // user2 cannot query db1.tbl1
+ context.assertAuthzException(statement, "SELECT COUNT(*) FROM db1.tbl1");
+ context.assertAuthzException(statement, "USE db1");
+
+ statement.close();
+ connection.close();
+
+ //test cleanup
+ connection = context.createConnection(ADMIN1, "hive");
+ statement = context.createStatement(connection);
+ statement.execute("DROP DATABASE db1 CASCADE");
+ statement.execute("DROP DATABASE db2 CASCADE");
+ statement.close();
+ connection.close();
+ }
+
+ /**
+ * Multiple DB files with some containing badly formatted rules
+ * The privileges should work for good files
+ * No access for bad formatted ones
+ * @throws Exception
+ */
+ @Test
+ public void testMultiPerDBwithErrors() throws Exception {
+ String DB3_POLICY_FILE = "db3-policy-file.ini";
+ String DB4_POLICY_FILE = "db4-policy-file.ini";
+
+ File db2PolicyFileHandle = new File(context.getPolicyFile().getParent(), DB2_POLICY_FILE);
+ File db3PolicyFileHandle = new File(context.getPolicyFile().getParent(), DB3_POLICY_FILE);
+ File db4PolicyFileHandle = new File(context.getPolicyFile().getParent(), DB4_POLICY_FILE);
+
+ PolicyFile db2PolicyFile = new PolicyFile();
+ PolicyFile db3PolicyFile = new PolicyFile();
+ PolicyFile db4PolicyFile = new PolicyFile();
+ db2PolicyFile
+ .addRolesToGroup("user_group2", "select_tbl2")
+ .addPermissionsToRole("select_tbl2", "server=server1->db=db2->table=tbl2->action=select")
+ .write(db2PolicyFileHandle);
+ db3PolicyFile
+ .addRolesToGroup("user_group3", "select_tbl3_BAD")
+ .addPermissionsToRole("select_tbl3_BAD", "server=server1->db=db3------>table->action=select")
+ .write(db3PolicyFileHandle);
+ db4PolicyFile
+ .addRolesToGroup("user_group4", "select_tbl4")
+ .addPermissionsToRole("select_tbl4", "server=server1->db=db4->table=tbl4->action=select")
+ .write(db4PolicyFileHandle);
+ policyFile
+ .addRolesToGroup("user_group1", "select_tbl1")
+ .addRolesToGroup("user_group2", "select_tbl2")
+ .addPermissionsToRole("select_tbl1", "server=server1->db=db1->table=tbl1->action=select")
+ .addGroupsToUser("user1", "user_group1")
+ .addGroupsToUser("user2", "user_group2")
+ .addGroupsToUser("user3", "user_group3")
+ .addGroupsToUser("user4", "user_group4")
+ .addDatabase("db2", db2PolicyFileHandle.getPath())
+ .addDatabase("db3", db3PolicyFileHandle.getPath())
+ .addDatabase("db4", db4PolicyFileHandle.getPath())
+ .write(context.getPolicyFile());
+
+ // setup db objects needed by the test
+ Connection connection = context.createConnection(ADMIN1, "hive");
+ Statement statement = context.createStatement(connection);
+
+ statement.execute("DROP DATABASE IF EXISTS db1 CASCADE");
+ statement.execute("CREATE DATABASE db1");
+ statement.execute("USE db1");
+ statement.execute("CREATE TABLE tbl1(B INT, A STRING) " +
+ " row format delimited fields terminated by '|' stored as textfile");
+ statement.execute("LOAD DATA LOCAL INPATH '" + dataFile.getPath() + "' INTO TABLE tbl1");
+
+ statement.execute("DROP DATABASE IF EXISTS db2 CASCADE");
+ statement.execute("CREATE DATABASE db2");
+ statement.execute("USE db2");
+ statement.execute("CREATE TABLE tbl2(B INT, A STRING) " +
+ " row format delimited fields terminated by '|' stored as textfile");
+ statement.execute("LOAD DATA LOCAL INPATH '" + dataFile.getPath() + "' INTO TABLE tbl2");
+
+ statement.execute("DROP DATABASE IF EXISTS db3 CASCADE");
+ statement.execute("CREATE DATABASE db3");
+ statement.execute("USE db3");
+ statement.execute("CREATE TABLE tbl3(B INT, A STRING) " +
+ " row format delimited fields terminated by '|' stored as textfile");
+ statement.execute("LOAD DATA LOCAL INPATH '" + dataFile.getPath() + "' INTO TABLE tbl3");
+
+ statement.execute("DROP DATABASE IF EXISTS db4 CASCADE");
+ statement.execute("CREATE DATABASE db4");
+ statement.execute("USE db4");
+ statement.execute("CREATE TABLE tbl4(B INT, A STRING) " +
+ " row format delimited fields terminated by '|' stored as textfile");
+ statement.execute("LOAD DATA LOCAL INPATH '" + dataFile.getPath() + "' INTO TABLE tbl4");
+
+ statement.close();
+ connection.close();
+
+ // test execution
+ connection = context.createConnection("user1", "password");
+ statement = context.createStatement(connection);
+ statement.execute("USE db1");
+ // test user1 can execute query on tbl1
+ verifyCount(statement, "SELECT COUNT(*) FROM tbl1");
+ connection.close();
+
+ connection = context.createConnection("user2", "password");
+ statement = context.createStatement(connection);
+ statement.execute("USE db2");
+ // test user1 can execute query on tbl1
+ verifyCount(statement, "SELECT COUNT(*) FROM tbl2");
+ connection.close();
+
+ // verify no access to db3 due to badly formatted rule in db3 policy file
+ connection = context.createConnection("user3", "password");
+ statement = context.createStatement(connection);
+ context.assertAuthzException(statement, "USE db3");
+ // test user1 can execute query on tbl1
+ context.assertAuthzException(statement, "SELECT COUNT(*) FROM db3.tbl3");
+ connection.close();
+
+ connection = context.createConnection("user4", "password");
+ statement = context.createStatement(connection);
+ statement.execute("USE db4");
+ // test user1 can execute query on tbl1
+ verifyCount(statement, "SELECT COUNT(*) FROM tbl4");
+ connection.close();
+
+ //test cleanup
+ connection = context.createConnection(ADMIN1, "hive");
+ statement = context.createStatement(connection);
+ statement.execute("DROP DATABASE db1 CASCADE");
+ statement.execute("DROP DATABASE db2 CASCADE");
+ statement.execute("DROP DATABASE db3 CASCADE");
+ statement.execute("DROP DATABASE db4 CASCADE");
+ statement.close();
+ connection.close();
+ }
+
+ @Test
+ public void testPerDBPolicyFileWithURI() throws Exception {
+ File db2PolicyFileHandle = new File(context.getPolicyFile().getParent(), DB2_POLICY_FILE);
+
+ policyFile
+ .addRolesToGroup("user_group1", "select_tbl1")
+ .addRolesToGroup("user_group2", "select_tbl2")
+ .addPermissionsToRole("select_tbl1", "server=server1->db=db1->table=tbl1->action=select")
+ .addGroupsToUser("user1", "user_group1")
+ .addGroupsToUser("user2", "user_group2")
+ .addDatabase("db2", db2PolicyFileHandle.getPath())
+ .write(context.getPolicyFile());
+
+ PolicyFile db2PolicyFile = new PolicyFile();
+ db2PolicyFile
+ .addRolesToGroup("user_group2", "select_tbl2", "data_read", "insert_tbl2")
+ .addPermissionsToRole("select_tbl2", "server=server1->db=db2->table=tbl2->action=select")
+ .addPermissionsToRole("insert_tbl2", "server=server1->db=db2->table=tbl2->action=insert")
+ .addPermissionsToRole("data_read", "server=server1->URI=file://" + dataFile)
+ .write(db2PolicyFileHandle);
+ // ugly hack: needs to go away once this becomes a config property. Note that this property
+ // will not be set with external HS and this test will fail. Hope is this fix will go away
+ // by then.
+ System.setProperty(SimplePolicyEngine.ACCESS_ALLOW_URI_PER_DB_POLICYFILE, "true");
+ // setup db objects needed by the test
+ Connection connection = context.createConnection(ADMIN1, "hive");
+ Statement statement = context.createStatement(connection);
+
+ statement.execute("DROP DATABASE IF EXISTS db1 CASCADE");
+ statement.execute("DROP DATABASE IF EXISTS db2 CASCADE");
+ statement.execute("CREATE DATABASE db1");
+ statement.execute("USE db1");
+ statement.execute("CREATE TABLE tbl1(B INT, A STRING) " +
+ " row format delimited fields terminated by '|' stored as textfile");
+ statement.execute("LOAD DATA LOCAL INPATH '" + dataFile.getPath() + "' INTO TABLE tbl1");
+ statement.execute("DROP DATABASE IF EXISTS db2 CASCADE");
+ statement.execute("CREATE DATABASE db2");
+ statement.execute("USE db2");
+ statement.execute("CREATE TABLE tbl2(B INT, A STRING) " +
+ " row format delimited fields terminated by '|' stored as textfile");
+ statement.execute("LOAD DATA LOCAL INPATH '" + dataFile.getPath() + "' INTO TABLE tbl2");
+ statement.close();
+ connection.close();
+
+ // test execution
+ connection = context.createConnection("user1", "password");
+ statement = context.createStatement(connection);
+ statement.execute("USE db1");
+ // test user1 can execute query on tbl1
+ verifyCount(statement, "SELECT COUNT(*) FROM tbl1");
+
+ // user1 cannot query db2.tbl2
+ context.assertAuthzException(statement, "USE db2");
+ context.assertAuthzException(statement, "SELECT COUNT(*) FROM db2.tbl2");
+ statement.close();
+ connection.close();
+
+ // test per-db file for db2
+ connection = context.createConnection("user2", "password");
+ statement = context.createStatement(connection);
+ statement.execute("USE db2");
+ // test user2 can execute query on tbl2
+ verifyCount(statement, "SELECT COUNT(*) FROM tbl2");
+
+ // verify user2 can execute LOAD
+ statement.execute("LOAD DATA LOCAL INPATH '" + dataFile.getPath() + "' INTO TABLE tbl2");
+
+ // user2 cannot query db1.tbl1
+ context.assertAuthzException(statement, "SELECT COUNT(*) FROM db1.tbl1");
+ context.assertAuthzException(statement, "USE db1");
+
+ statement.close();
+ connection.close();
+
+ //test cleanup
+ connection = context.createConnection(ADMIN1, "hive");
+ statement = context.createStatement(connection);
+ statement.execute("DROP DATABASE db1 CASCADE");
+ statement.execute("DROP DATABASE db2 CASCADE");
+ statement.close();
+ connection.close();
+ System.setProperty(SimplePolicyEngine.ACCESS_ALLOW_URI_PER_DB_POLICYFILE, "false");
+ }
+
+ /**
+ * Test 'use default' statement. It should work as long as the user as privilege to assess any object in system
+ * @throws Exception
+ */
+ @Test
+ public void testDefaultDb() throws Exception {
+ policyFile
+ .addRolesToGroup("user_group1", "select_tbl1")
+ .addPermissionsToRole("select_tbl1", "server=server1->db=db1->table=tbl1->action=select")
+ .addGroupsToUser("user_1", "user_group1")
+ .addGroupsToUser("user_2", "user_group2")
+ .write(context.getPolicyFile());
+
+ // setup db objects needed by the test
+ Connection connection = context.createConnection(ADMIN1, "hive");
+ Statement statement = context.createStatement(connection);
+
+ statement.execute("USE default");
+
+ statement.execute("DROP DATABASE IF EXISTS db1 CASCADE");
+ statement.execute("CREATE DATABASE db1");
+ statement.execute("USE db1");
+ statement.execute("CREATE TABLE tbl1(B INT, A STRING) " +
+ " row format delimited fields terminated by '|' stored as textfile");
+ statement.execute("DROP DATABASE IF EXISTS db2 CASCADE");
+ statement.close();
+ connection.close();
+
+ // user_1 should be able to access default
+ connection = context.createConnection("user_1", "password");
+ statement = context.createStatement(connection);
+ statement.execute("USE default");
+ statement.close();
+ connection.close();
+
+ // user_2 should NOT be able to access default since it does have access to any other object
+ connection = context.createConnection("user_2", "password");
+ statement = context.createStatement(connection);
+ context.assertAuthzException(statement, "USE default");
+ statement.close();
+ connection.close();
+
+ }
+
+ @Test
+ public void testDefaultDBwithDbPolicy() throws Exception {
+ File db2PolicyFileHandle = new File(context.getPolicyFile().getParent(), DB2_POLICY_FILE);
+ File defaultPolicyFileHandle = new File(context.getPolicyFile().getParent(), "default.ini");
+
+ policyFile
+ .addRolesToGroup("user_group1", "select_tbl1")
+ .addRolesToGroup("user_group2", "select_tbl2")
+ .addPermissionsToRole("select_tbl1", "server=server1->db=db1->table=tbl1->action=select")
+ .addGroupsToUser("user_1", "user_group1")
+ .addGroupsToUser("user_2", "user_group2")
+ .addGroupsToUser("user_3", "user_group3")
+ .addDatabase("db2", db2PolicyFileHandle.getPath())
+ .addDatabase("default", defaultPolicyFileHandle.getPath())
+ .write(context.getPolicyFile());
+
+ PolicyFile db2PolicyFile = new PolicyFile();
+ db2PolicyFile
+ .addRolesToGroup("user_group2", "select_tbl2")
+ .addPermissionsToRole("select_tbl2", "server=server1->db=db2->table=tbl2->action=select")
+ .write(db2PolicyFileHandle);
+
+ PolicyFile defaultPolicyFile = new PolicyFile();
+ defaultPolicyFile
+ .addRolesToGroup("user_group2", "select_def")
+ .addPermissionsToRole("select_def", "server=server1->db=default->table=dtab->action=select")
+ .write(defaultPolicyFileHandle);
+
+ // setup db objects needed by the test
+ Connection connection = context.createConnection(ADMIN1, "hive");
+ Statement statement = context.createStatement(connection);
+ statement.execute("USE default");
+ statement.execute("CREATE TABLE dtab(B INT, A STRING) " +
+ " row format delimited fields terminated by '|' stored as textfile");
+
+ statement.execute("DROP DATABASE IF EXISTS db1 CASCADE");
+ statement.execute("DROP DATABASE IF EXISTS db2 CASCADE");
+ statement.execute("CREATE DATABASE db1");
+ statement.execute("USE db1");
+ statement.execute("CREATE TABLE tbl1(B INT, A STRING) " +
+ " row format delimited fields terminated by '|' stored as textfile");
+ statement.execute("DROP DATABASE IF EXISTS db2 CASCADE");
+ statement.execute("CREATE DATABASE db2");
+ statement.execute("USE db2");
+ statement.execute("CREATE TABLE tbl2(B INT, A STRING) " +
+ " row format delimited fields terminated by '|' stored as textfile");
+ statement.close();
+ connection.close();
+
+ // user_1 should be able to switch to default, but not the tables from default
+ connection = context.createConnection("user_1", "password");
+ statement = context.createStatement(connection);
+ statement.execute("USE db1");
+ statement.execute("USE default");
+ context.assertAuthzException(statement, "SELECT * FROM dtab");
+ statement.execute("USE db1");
+ context.assertAuthzException(statement, "SELECT * FROM default.dtab");
+
+ statement.close();
+ connection.close();
+
+ // user_2 should be able to access default and select from default's tables
+ connection = context.createConnection("user_2", "password");
+ statement = context.createStatement(connection);
+ statement.execute("USE db2");
+ statement.execute("USE default");
+ statement.execute("SELECT * FROM dtab");
+ statement.execute("USE db2");
+ statement.execute("SELECT * FROM default.dtab");
+ statement.close();
+ connection.close();
+
+ // user_3 should NOT be able to switch to default since it doesn't have access to any objects
+ connection = context.createConnection("user_3", "password");
+ statement = context.createStatement(connection);
+ context.assertAuthzException(statement, "USE default");
+ statement.close();
+ connection.close();
+ }
+
+ private void verifyCount(Statement statement, String query) throws SQLException {
+ ResultSet resultSet = statement.executeQuery(query);
+ int count = 0;
+ int countRows = 0;
+
+ while (resultSet.next()) {
+ count = resultSet.getInt(1);
+ countRows++;
+ }
+ assertTrue("Incorrect row count", countRows == 1);
+ assertTrue("Incorrect result", count == 12);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/aef404c6/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestPerDatabasePolicyFile.java
----------------------------------------------------------------------
diff --git a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestPerDatabasePolicyFile.java b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestPerDatabasePolicyFile.java
new file mode 100644
index 0000000..a89988a
--- /dev/null
+++ b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestPerDatabasePolicyFile.java
@@ -0,0 +1,134 @@
+/*
+ * 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.hive;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.sql.Connection;
+import java.sql.Statement;
+
+import org.apache.sentry.provider.file.PolicyFile;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.io.Resources;
+
+public class TestPerDatabasePolicyFile extends AbstractTestWithStaticLocalFS {
+ private static final String SINGLE_TYPE_DATA_FILE_NAME = "kv1.dat";
+ private static final String ADMIN1 = "admin1";
+ private Context context;
+ private PolicyFile policyFile;
+ private File globalPolicyFile;
+ private File dataDir;
+ private File dataFile;
+
+ @Before
+ public void setup() throws Exception {
+ policyFile = PolicyFile.createAdminOnServer1(ADMIN1);
+ context = createContext();
+ globalPolicyFile = context.getPolicyFile();
+ dataDir = context.getDataDir();
+ assertTrue("Could not delete " + globalPolicyFile, context.deletePolicyFile());
+ 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();
+ }
+ }
+
+ private void createSampleDbTable(Statement statement, String db, String table)
+ throws Exception {
+ statement.execute("DROP DATABASE IF EXISTS " + db + " CASCADE");
+ statement.execute("CREATE DATABASE " + db);
+ statement.execute("USE " + db);
+ statement.execute("CREATE TABLE " + table + "(a STRING)");
+ statement.execute("LOAD DATA LOCAL INPATH '" + dataFile.getPath() + "' INTO TABLE " + table);
+
+ }
+
+ /**
+ * Ensure that db specific file cannot grant to other db
+ */
+ @Test
+ public void testDbSpecificFileGrantsToOtherDb() throws Exception {
+ doTestDbSpecificFileGrants("server=server1->db=db1");
+ }
+ /**
+ * Ensure that db specific file cannot grant to all db
+ */
+ @Test
+ public void testDbSpecificFileGrantsToAllDb() throws Exception {
+ doTestDbSpecificFileGrants("server=server1");
+ }
+ /**
+ * Ensure that db specific file cannot grant to all servers
+ */
+ @Test
+ public void testDbSpecificFileGrantsToAllServers() throws Exception {
+ doTestDbSpecificFileGrants("server=*");
+ }
+ /**
+ * Ensure that db specific file cannot grant to all
+ */
+ @Test
+ public void testDbSpecificFileGrantsToAll() throws Exception {
+ doTestDbSpecificFileGrants("*");
+ }
+
+ public void doTestDbSpecificFileGrants(String grant) throws Exception {
+
+ policyFile.write(context.getPolicyFile());
+
+ // setup db objects needed by the test
+ Connection connection = context.createConnection(ADMIN1, "password");
+ Statement statement = context.createStatement(connection);
+ createSampleDbTable(statement, "db1", "tbl1");
+ createSampleDbTable(statement, "db2", "tbl1");
+ statement.close();
+ connection.close();
+
+ File specificPolicyFileFile = new File(context.getBaseDir(), "db2-policy.ini");
+
+ PolicyFile specificPolicyFile = new PolicyFile()
+ .addPermissionsToRole("db1_role", grant)
+ .addRolesToGroup("group1", "db1_role")
+ .addGroupsToUser("user1", "group1");
+ specificPolicyFile.write(specificPolicyFileFile);
+
+ policyFile.addDatabase("db2", specificPolicyFileFile.getPath());
+ policyFile.write(context.getPolicyFile());
+
+
+
+ // test execution
+ connection = context.createConnection("user1", "password");
+ statement = context.createStatement(connection);
+ // test user can query table
+ context.assertAuthzException(statement, "USE db1");
+ context.assertAuthzException(statement, "SELECT COUNT(a) FROM db1.tbl1");
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/aef404c6/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestPrivilegeAtTransform.java
----------------------------------------------------------------------
diff --git a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestPrivilegeAtTransform.java b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestPrivilegeAtTransform.java
new file mode 100644
index 0000000..0b71c87
--- /dev/null
+++ b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestPrivilegeAtTransform.java
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.sentry.tests.e2e.hive;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.sql.Connection;
+import java.sql.Statement;
+
+import org.apache.sentry.provider.file.PolicyFile;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.io.Resources;
+
+public class TestPrivilegeAtTransform extends AbstractTestWithStaticLocalFS {
+ private Context context;
+ private final String SINGLE_TYPE_DATA_FILE_NAME = "kv1.dat";
+ private File dataDir;
+ private File dataFile;
+ private PolicyFile policyFile;
+
+ @Before
+ public void setup() throws Exception {
+ context = createContext();
+ dataDir = context.getDataDir();
+ 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 = PolicyFile.createAdminOnServer1("admin1");
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (context != null) {
+ context.close();
+ }
+ }
+
+ /**
+ * Steps:
+ * 1. admin create database, create table, load data into it
+ * 2. all@server can issue transforms command
+ * 3. all@database cannot issue transform command
+ * 4. insert@table select@table cannot issue transform command
+ * 5. select@view cannot issue transform command
+ * 6. transform@server can issue the transform command
+ */
+ @Test
+ public void testTransform1() throws Exception {
+ policyFile
+ .addGroupsToUser("user1", "group1")
+ .addPermissionsToRole("all_db1", "server=server1->db=db_1")
+ .addRolesToGroup("group1", "all_db1");
+ policyFile.write(context.getPolicyFile());
+
+ // verify by SQL
+ // 1, 2
+ String dbName1 = "db_1";
+ String tableName1 = "tb_1";
+ String query = "select TRANSFORM(a.under_col, a.value) USING 'cat' AS (tunder_col, tvalue) FROM " + dbName1 + "." + tableName1 + " a";
+ Connection connection = context.createConnection("admin1", "foo");
+ Statement statement = context.createStatement(connection);
+ statement.execute("DROP DATABASE IF EXISTS " + dbName1 + " CASCADE");
+ statement.execute("CREATE DATABASE " + dbName1);
+ statement.execute("DROP TABLE IF EXISTS " + dbName1 + "." + tableName1);
+ statement.execute("create table " + dbName1 + "." + tableName1
+ + " (under_col int, value string)");
+ statement.execute("load data local inpath '" + dataFile.getPath()
+ + "' into table " + dbName1 + "." + tableName1);
+ assertTrue(query, statement.execute(query));
+
+ statement.close();
+ connection.close();
+
+ connection = context.createConnection("user1", "foo");
+ statement = context.createStatement(connection);
+
+ // 3
+ context.assertAuthzExecHookException(statement, query);
+
+ // 4
+ policyFile
+ .addPermissionsToRole("select_tb1", "server=server1->db=db_1->table=tb_1->action=select")
+ .addPermissionsToRole("insert_tb1", "server=server1->db=db_1->table=tb_1->action=insert")
+ .addRolesToGroup("group1", "select_tb1", "insert_tb1");
+ policyFile.write(context.getPolicyFile());
+ context.assertAuthzExecHookException(statement, query);
+
+ // 5
+ policyFile
+ .addPermissionsToRole("all_server1", "server=server1")
+ .addRolesToGroup("group1", "all_server1");
+ policyFile.write(context.getPolicyFile());
+ assertTrue(query, statement.execute(query));
+ statement.close();
+ connection.close();
+ }
+}