SENTRY-829: Fix Sentry Hive Test Failures in TestDbCrossDb class when running E2E (Anne Yu via Lenni Kuff)
Project: http://git-wip-us.apache.org/repos/asf/incubator-sentry/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-sentry/commit/19bbaacd Tree: http://git-wip-us.apache.org/repos/asf/incubator-sentry/tree/19bbaacd Diff: http://git-wip-us.apache.org/repos/asf/incubator-sentry/diff/19bbaacd Branch: refs/heads/hive_plugin_v2 Commit: 19bbaacd1de4d3e7e23083a85ac8466f3e26fab9 Parents: 1e26d56 Author: Lenni Kuff <lsk...@cloudera.com> Authored: Wed Aug 5 00:57:50 2015 -0700 Committer: Lenni Kuff <lsk...@cloudera.com> Committed: Wed Aug 5 00:57:50 2015 -0700 ---------------------------------------------------------------------- .../e2e/dbprovider/TestDatabaseProvider.java | 3 +- .../tests/e2e/dbprovider/TestDbCrossDbOps.java | 4 +- .../AbstractTestWithStaticConfiguration.java | 65 +++- .../tests/e2e/hive/PrivilegeResultSet.java | 124 ++++++ .../sentry/tests/e2e/hive/TestCrossDbOps.java | 380 +++++++++++++------ .../tests/e2e/hive/TestUserManagement.java | 2 +- ...actMetastoreTestWithStaticConfiguration.java | 7 +- 7 files changed, 448 insertions(+), 137 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/19bbaacd/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDatabaseProvider.java ---------------------------------------------------------------------- diff --git a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDatabaseProvider.java b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDatabaseProvider.java index 7df32fb..87b281b 100644 --- a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDatabaseProvider.java +++ b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDatabaseProvider.java @@ -52,6 +52,7 @@ public class TestDatabaseProvider extends AbstractTestWithStaticConfiguration { @BeforeClass public static void setupTestStaticConfiguration() throws Exception{ useSentryService = true; + clearDbAfterPerTest = false; AbstractTestWithStaticConfiguration.setupTestStaticConfiguration(); } @@ -61,7 +62,7 @@ public class TestDatabaseProvider extends AbstractTestWithStaticConfiguration { */ @Override @After - public void clearDB() throws Exception { + public void clearAfterPerTest() throws Exception { Connection connection; Statement statement; connection = context.createConnection(ADMIN1); http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/19bbaacd/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbCrossDbOps.java ---------------------------------------------------------------------- diff --git a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbCrossDbOps.java b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbCrossDbOps.java index 719dddf..8d23ea6 100644 --- a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbCrossDbOps.java +++ b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbCrossDbOps.java @@ -31,11 +31,13 @@ public class TestDbCrossDbOps extends TestCrossDbOps { public void setup() throws Exception { super.setupAdmin(); super.setup(); + clearAll(true); } @BeforeClass public static void setupTestStaticConfiguration() throws Exception{ - //policy_on_hdfs = true; useSentryService = true; + clearDbAfterPerTest = true; + clearDbBeforePerTest = true; AbstractTestWithStaticConfiguration.setupTestStaticConfiguration(); } } http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/19bbaacd/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/AbstractTestWithStaticConfiguration.java ---------------------------------------------------------------------- diff --git a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/AbstractTestWithStaticConfiguration.java b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/AbstractTestWithStaticConfiguration.java index 2a1c9f0..16695f5 100644 --- a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/AbstractTestWithStaticConfiguration.java +++ b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/AbstractTestWithStaticConfiguration.java @@ -32,7 +32,6 @@ import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Map; -import java.util.concurrent.TimeoutException; import junit.framework.Assert; @@ -121,6 +120,7 @@ public abstract class AbstractTestWithStaticConfiguration { protected static boolean enableHiveConcurrency = false; // indicate if the database need to be clear for every test case in one test class protected static boolean clearDbAfterPerTest = true; + protected static boolean clearDbBeforePerTest = false; protected static File baseDir; protected static File logDir; @@ -138,7 +138,6 @@ public abstract class AbstractTestWithStaticConfiguration { protected static Context context; protected final String semanticException = "SemanticException No valid privileges"; - public static void createContext() throws Exception { context = new Context(hiveServer, fileSystem, baseDir, confDir, dataDir, policyFileLocation); @@ -272,8 +271,10 @@ public abstract class AbstractTestWithStaticConfiguration { protected static void writePolicyFile(PolicyFile policyFile) throws Exception { policyFile.write(context.getPolicyFile()); if(policyOnHdfs) { + LOGGER.info("use policy file on HDFS"); dfs.writePolicyFile(context.getPolicyFile()); } else if(useSentryService) { + LOGGER.info("use sentry service, granting permissions"); grantPermissions(policyFile); } } @@ -286,16 +287,20 @@ public abstract class AbstractTestWithStaticConfiguration { ResultSet resultSet = statement.executeQuery("SHOW ROLES"); while( resultSet.next()) { Statement statement1 = context.createStatement(connection); - if(!resultSet.getString(1).equalsIgnoreCase("admin_role")) { - statement1.execute("DROP ROLE " + resultSet.getString(1)); + String roleName = resultSet.getString(1).trim(); + if(!roleName.equalsIgnoreCase("admin_role")) { + LOGGER.info("Dropping role :" + roleName); + statement1.execute("DROP ROLE " + roleName); } } // create roles and add privileges for (Map.Entry<String, Collection<String>> roleEntry : policyFile.getRolesToPermissions() .asMap().entrySet()) { + String roleName = roleEntry.getKey(); if(!roleEntry.getKey().equalsIgnoreCase("admin_role")){ - statement.execute("CREATE ROLE " + roleEntry.getKey()); + LOGGER.info("Creating role : " + roleName); + statement.execute("CREATE ROLE " + roleName); for (String privilege : roleEntry.getValue()) { addPrivilege(roleEntry.getKey(), privilege, statement); } @@ -306,7 +311,9 @@ public abstract class AbstractTestWithStaticConfiguration { .entrySet()) { for (String roleNames : groupEntry.getValue()) { for (String roleName : roleNames.split(",")) { - statement.execute("GRANT ROLE " + roleName + " TO GROUP " + groupEntry.getKey()); + String sql = "GRANT ROLE " + roleName + " TO GROUP " + groupEntry.getKey(); + LOGGER.info("Granting role to group: " + sql); + statement.execute(sql); } } } @@ -346,21 +353,31 @@ public abstract class AbstractTestWithStaticConfiguration { } } + LOGGER.info("addPrivilege"); if (columnName != null) { statement.execute("CREATE DATABASE IF NOT EXISTS " + dbName); statement.execute("USE " + dbName); - statement.execute("GRANT " + action + " ( " + columnName + " ) ON TABLE " + tableName + " TO ROLE " + roleName); + String sql = "GRANT " + action + " ( " + columnName + " ) ON TABLE " + tableName + " TO ROLE " + roleName; + LOGGER.info("Granting column level privilege: database = " + dbName + ", sql = " + sql); + statement.execute(sql); } else if (tableName != null) { statement.execute("CREATE DATABASE IF NOT EXISTS " + dbName); statement.execute("USE " + dbName); - statement.execute("GRANT " + action + " ON TABLE " + tableName + " TO ROLE " + roleName); + String sql = "GRANT " + action + " ON TABLE " + tableName + " TO ROLE " + roleName; + LOGGER.info("Granting table level privilege: database = " + dbName + ", sql = " + sql); + statement.execute(sql); } else if (dbName != null) { - statement.execute("GRANT " + action + " ON DATABASE " + dbName + " TO ROLE " + roleName); + String sql = "GRANT " + action + " ON DATABASE " + dbName + " TO ROLE " + roleName; + LOGGER.info("Granting db level privilege: " + sql); + statement.execute(sql); } else if (uriPath != null) { - statement.execute("GRANT " + action + " ON URI '" + uriPath + "' TO ROLE " + roleName);//ALL? + String sql = "GRANT " + action + " ON URI '" + uriPath + "' TO ROLE " + roleName; + LOGGER.info("Granting uri level privilege: " + sql); + statement.execute(sql);//ALL? } else if (serverName != null) { - statement.execute("GRANT ALL ON SERVER " + serverName + " TO ROLE " + roleName); - ; + String sql = "GRANT ALL ON SERVER " + serverName + " TO ROLE " + roleName; + LOGGER.info("Granting server level privilege: " + sql); + statement.execute(sql); } } } @@ -429,16 +446,30 @@ public abstract class AbstractTestWithStaticConfiguration { @Before public void setup() throws Exception{ + LOGGER.info("Before per test run setup"); dfs.createBaseDir(); + if (clearDbBeforePerTest) { + LOGGER.info("Before per test run clean up"); + clearAll(true); + } } @After - public void clearDB() throws Exception { + public void clearAfterPerTest() throws Exception { + LOGGER.info("After per test run clearAfterPerTest"); + if (clearDbAfterPerTest) { + clearAll(true); + } + } + + protected void clearAll(boolean clearDb) throws Exception { + LOGGER.info("About to run clearAll"); ResultSet resultSet; Connection connection = context.createConnection(ADMIN1); Statement statement = context.createStatement(connection); - if (clearDbAfterPerTest) { + if (clearDb) { + LOGGER.info("About to clear all databases and default database tables"); String[] dbs = { DB1, DB2, DB3 }; for (String db : dbs) { statement.execute("DROP DATABASE if exists " + db + " CASCADE"); @@ -453,10 +484,14 @@ public abstract class AbstractTestWithStaticConfiguration { } if(useSentryService) { + LOGGER.info("About to clear all roles"); resultSet = statement.executeQuery("SHOW roles"); List<String> roles = new ArrayList<String>(); while (resultSet.next()) { - roles.add(resultSet.getString(1)); + String roleName = resultSet.getString(1); + if (!roleName.toLowerCase().contains("admin")) { + roles.add(roleName); + } } for (String role : roles) { statement.execute("DROP Role " + role); http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/19bbaacd/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/PrivilegeResultSet.java ---------------------------------------------------------------------- diff --git a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/PrivilegeResultSet.java b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/PrivilegeResultSet.java new file mode 100644 index 0000000..cee05a0 --- /dev/null +++ b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/PrivilegeResultSet.java @@ -0,0 +1,124 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * 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 org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.List; + +/** + * This class holds ResultSet after query sentry privileges + * header: contain result header information, which is a array of string + * privilegeResultSet: contain privilege results from query + */ +public class PrivilegeResultSet { + private static final Logger LOGGER = LoggerFactory + .getLogger(PrivilegeResultSet.class); + + protected int colNum = 0; + protected List<String> header; + protected List<ArrayList<String>> privilegeResultSet; + + public PrivilegeResultSet() { + header = new ArrayList<String>(); + privilegeResultSet = new ArrayList<ArrayList<String>>(); + } + + public PrivilegeResultSet(Statement stmt, String query) { + LOGGER.info("Getting result set for " + query); + this.header = new ArrayList<String>(); + this.privilegeResultSet = new ArrayList<ArrayList<String>>(); + ResultSet rs = null; + try { + rs = stmt.executeQuery(query); + ResultSetMetaData rsmd = rs.getMetaData(); + this.colNum = rsmd.getColumnCount(); + for (int i = 1; i <= this.colNum; i++) { + this.header.add(rsmd.getColumnName(i).trim()); + } + while (rs.next()) { + ArrayList<String> row = new ArrayList<String>(); + for (int i = 1; i <= colNum; i++) { + row.add(rs.getString(i).trim()); + } + this.privilegeResultSet.add(row); + } + } catch (Exception ex) { + LOGGER.info("Exception when executing query: " + ex); + } finally { + try { + rs.close(); + } catch (Exception ex) { + LOGGER.error("failed to close result set: " + ex.getStackTrace()); + } + } + } + + protected List<ArrayList<String>> getResultSet() { + return this.privilegeResultSet; + } + + protected List<String> getHeader() { + return this.header; + } + + /** + * Given a column name, validate if one of its values equals to given colVal + */ + protected boolean verifyResultSetColumn(String colName, String colVal) { + for (int i = 0; i < this.colNum; i ++) { + if (this.header.get(i).equalsIgnoreCase(colName)) { + for (int j = 0; j < this.privilegeResultSet.size(); j ++) { + if (this.privilegeResultSet.get(j).get(i).equalsIgnoreCase(colVal)) { + LOGGER.info("Found " + colName + " contains a value = " + colVal); + return true; + } + } + } + } + LOGGER.error("Failed to detect " + colName + " contains a value = " + colVal); + return false; + } + + /** + * Unmarshall ResultSet into a string + */ + @Override + public String toString() { + String prettyPrintString = new String("\n"); + for (String h : this.header) { + prettyPrintString += h + ","; + } + prettyPrintString += "\n"; + for (ArrayList<String> row : this.privilegeResultSet) { + for (String val : row) { + if (val.isEmpty()) { + val = "null"; + } + prettyPrintString += val + ","; + } + prettyPrintString += "\n"; + } + return prettyPrintString; + } +} http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/19bbaacd/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestCrossDbOps.java ---------------------------------------------------------------------- diff --git a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestCrossDbOps.java b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestCrossDbOps.java index 38c361c..5b1e2b8 100644 --- a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestCrossDbOps.java +++ b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestCrossDbOps.java @@ -17,12 +17,15 @@ package org.apache.sentry.tests.e2e.hive; +import org.apache.sentry.provider.file.PolicyFile; +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.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; @@ -30,16 +33,20 @@ import java.util.List; import junit.framework.Assert; -import org.apache.sentry.provider.file.PolicyFile; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import com.google.common.io.Resources; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /* Tests privileges at table scope with cross database access */ public class TestCrossDbOps extends AbstractTestWithStaticConfiguration { + private static final Logger LOGGER = LoggerFactory + .getLogger(TestCrossDbOps.class); + private File dataFile; private PolicyFile policyFile; private String loadData; @@ -47,6 +54,8 @@ public class TestCrossDbOps extends AbstractTestWithStaticConfiguration { @BeforeClass public static void setupTestStaticConfiguration() throws Exception{ policyOnHdfs = true; + clearDbAfterPerTest = true; + clearDbBeforePerTest = true; AbstractTestWithStaticConfiguration.setupTestStaticConfiguration(); } @@ -59,8 +68,20 @@ public class TestCrossDbOps extends AbstractTestWithStaticConfiguration { Resources.copy(Resources.getResource(SINGLE_TYPE_DATA_FILE_NAME), to); to.close(); policyFile = PolicyFile.setAdminOnServer1(ADMINGROUP); + // Precreate policy file + policyFile.setUserGroupMapping(StaticUserGroup.getStaticMapping()); + writePolicyFile(policyFile); loadData = "server=server1->uri=file://" + dataFile.getPath(); + // debug + LOGGER.info("setMetastoreListener = " + String.valueOf(setMetastoreListener)); + clearAll(true); + } + private void validateReturnedResult(List<String> expected, List<String> returned) { + for (String obj : expected) { + assertTrue("expected " + obj + " not found in the " + returned.toString(), + returned.contains(obj)); + } } /* @@ -71,24 +92,106 @@ public class TestCrossDbOps extends AbstractTestWithStaticConfiguration { */ @Test public void testShowDatabasesAndShowTables() throws Exception { - // edit policy file + // admin create two databases + Connection connection = context.createConnection(ADMIN1); + Statement statement = context.createStatement(connection); + statement.execute("CREATE DATABASE " + DB1); + statement.execute("CREATE DATABASE " + DB2); + statement.execute("USE " + DB1); + statement.execute("CREATE TABLE TAB1(id int)"); + statement.executeQuery("SHOW TABLES"); + statement.execute("USE " + DB2); + statement.execute("CREATE TABLE TAB2(id int)"); + statement.execute("CREATE TABLE TAB3(id int)"); + + // load policy file and grant role with privileges policyFile - .addRolesToGroup(USERGROUP1, "select_tab1", "insert_tab2") - .addRolesToGroup(USERGROUP2, "select_tab3") - .addPermissionsToRole("select_tab1", "server=server1->db=" + DB1 + "->table=tab1->action=select") - .addPermissionsToRole("select_tab3", "server=server1->db=" + DB2 + "->table=tab3->action=select") - .addPermissionsToRole("insert_tab2", "server=server1->db=" + DB2 + "->table=tab2->action=insert") - .setUserGroupMapping(StaticUserGroup.getStaticMapping()); + .addRolesToGroup(USERGROUP1, "select_tab1", "insert_tab2") + .addRolesToGroup(USERGROUP2, "select_tab3") + .addPermissionsToRole("select_tab1", "server=server1->db=" + DB1 + "->table=tab1->action=select") + .addPermissionsToRole("select_tab3", "server=server1->db=" + DB2 + "->table=tab3->action=select") + .addPermissionsToRole("insert_tab2", "server=server1->db=" + DB2 + "->table=tab2->action=insert") + .setUserGroupMapping(StaticUserGroup.getStaticMapping()); writePolicyFile(policyFile); + // show grant to validate roles and privileges + if(useSentryService) { + PrivilegeResultSet pRset = new PrivilegeResultSet(statement, "SHOW GRANT ROLE select_tab1 ON DATABASE " + DB1); + LOGGER.info("SHOW GRANT ROLE select_tab1 ON DATABASE " + DB1 + " : " + pRset.toString()); + pRset.verifyResultSetColumn("database", DB1); + pRset.verifyResultSetColumn("table", "tab1"); + + pRset = new PrivilegeResultSet(statement, "SHOW GRANT ROLE insert_tab2 ON DATABASE " + DB2); + LOGGER.info("SHOW GRANT ROLE insert_tab2 ON DATABASE " + DB2 + " : " + pRset.toString()); + pRset.verifyResultSetColumn("database", DB2); + pRset.verifyResultSetColumn("table", "tab2"); + + pRset = new PrivilegeResultSet(statement, "SHOW GRANT ROLE select_tab3 ON DATABASE " + DB2); + LOGGER.info("SHOW GRANT ROLE select_tab3 ON DATABASE " + DB2 + " : " + pRset.toString()); + pRset.verifyResultSetColumn("database", DB2); + pRset.verifyResultSetColumn("table", "tab3"); + } + + // test show databases + // show databases shouldn't filter any of the dbs from the resultset + Connection conn = context.createConnection(USER1_1); + Statement stmt = context.createStatement(conn); + PrivilegeResultSet pRset = new PrivilegeResultSet(stmt, "SHOW DATABASES"); + LOGGER.info("found databases :" + pRset.toString()); + pRset.verifyResultSetColumn("database_name", DB1); + pRset.verifyResultSetColumn("database_name", DB2); + + // test show tables + stmt.execute("USE " + DB1); + pRset = new PrivilegeResultSet(stmt, "SHOW TABLES"); + LOGGER.info("found tables :" + pRset.toString()); + pRset.verifyResultSetColumn("tab_name", "tab1"); + + stmt.execute("USE " + DB2); + pRset = new PrivilegeResultSet(stmt, "SHOW TABLES"); + LOGGER.info("found tables :" + pRset.toString()); + pRset.verifyResultSetColumn("tab_name", "tab2"); + + try { + stmt.close(); + conn.close(); + } catch (Exception ex) { + // nothing to do + } + + // test show databases and show tables for user2_1 + conn = context.createConnection(USER2_1); + stmt = context.createStatement(conn); + + pRset = new PrivilegeResultSet(stmt, "SHOW DATABASES"); + pRset.verifyResultSetColumn("database_name", DB2); + + // test show tables + stmt.execute("USE " + DB2); + pRset = new PrivilegeResultSet(stmt, "SHOW TABLES"); + pRset.verifyResultSetColumn("tab_name", "tab3"); + + try { + stmt.execute("USE " + DB1); + Assert.fail("Expected SQL exception"); + } catch (SQLException e) { + context.verifyAuthzException(e); + } + + context.close(); + } + + /* + * Admin creates DB_1, DB2, tables (tab_1 ) and (tab_2, tab_3) in DB_1 and + * DB_2 respectively. User user1 has select on DB_1.tab_1, insert on + * DB2.tab_2 User user2 has select on DB2.tab_3 Test show database and show + * tables for both user1 and user2 + */ + @Test + public void testJDBCGetSchemasAndGetTables() throws Exception { // admin create two databases 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("DROP DATABASE IF EXISTS DB1 CASCADE"); - statement.execute("DROP DATABASE IF EXISTS DB2 CASCADE"); - statement.execute("CREATE DATABASE " + DB1); statement.execute("CREATE DATABASE " + DB2); statement.execute("USE " + DB1); @@ -98,89 +201,146 @@ public class TestCrossDbOps extends AbstractTestWithStaticConfiguration { statement.execute("CREATE TABLE TAB2(id int)"); statement.execute("CREATE TABLE TAB3(id int)"); + // edit policy file + policyFile.addRolesToGroup(USERGROUP1, "select_tab1", "insert_tab2") + .addRolesToGroup(USERGROUP2, "select_tab3") + .addPermissionsToRole("select_tab1", "server=server1->db=" + DB1 + "->table=tab1->action=select") + .addPermissionsToRole("select_tab3", "server=server1->db=" + DB2 + "->table=tab3->action=select") + .addPermissionsToRole("insert_tab2", "server=server1->db=" + DB2 + "->table=tab2->action=insert") + .setUserGroupMapping(StaticUserGroup.getStaticMapping()); + writePolicyFile(policyFile); + // test show databases // show databases shouldn't filter any of the dbs from the resultset Connection conn = context.createConnection(USER1_1); Statement stmt = context.createStatement(conn); + // test direct JDBC metadata API ResultSet res = stmt.executeQuery("SHOW DATABASES"); - List<String> result = new ArrayList<String>(); - result.add(DB1); - result.add(DB2); - result.add("default"); + res = conn.getMetaData().getSchemas(); + ResultSetMetaData resMeta = res.getMetaData(); + assertEquals(2, resMeta.getColumnCount()); + assertEquals("TABLE_SCHEM", resMeta.getColumnName(1)); + assertEquals("TABLE_CATALOG", resMeta.getColumnName(2)); + + List<String> expectedResult = new ArrayList<String>(); + List<String> returnedResult = new ArrayList<String>(); + expectedResult.add(DB1); + expectedResult.add(DB2); while (res.next()) { - String dbName = res.getString(1); - assertTrue(dbName, result.remove(dbName)); + returnedResult.add(res.getString(1).trim()); } - assertTrue(result.toString(), result.isEmpty()); + validateReturnedResult(expectedResult, returnedResult); + returnedResult.clear(); + expectedResult.clear(); res.close(); - // test show tables - stmt.execute("USE " + DB1); - res = stmt.executeQuery("SHOW TABLES"); - result.clear(); - result.add("tab1"); + // test direct JDBC metadata API + res = conn.getMetaData().getTables(null, DB1, "tab%", null); + expectedResult.add("tab1"); + while (res.next()) { + returnedResult.add(res.getString(3).trim()); + } + validateReturnedResult(expectedResult, returnedResult); + returnedResult.clear(); + expectedResult.clear(); + res.close(); + // test direct JDBC metadata API + res = conn.getMetaData().getTables(null, DB2, "tab%", null); + expectedResult.add("tab2"); while (res.next()) { - String tableName = res.getString(1); - assertTrue(tableName, result.remove(tableName)); + returnedResult.add(res.getString(3).trim()); } - assertTrue(result.toString(), result.isEmpty()); + validateReturnedResult(expectedResult, returnedResult); + returnedResult.clear(); + expectedResult.clear(); res.close(); - stmt.execute("USE " + DB2); - res = stmt.executeQuery("SHOW TABLES"); - result.clear(); - result.add("tab2"); + res = conn.getMetaData().getTables(null, "DB%", "tab%", null); + expectedResult.add("tab2"); + expectedResult.add("tab1"); + while (res.next()) { + returnedResult.add(res.getString(3).trim()); + } + validateReturnedResult(expectedResult, returnedResult); + returnedResult.clear(); + expectedResult.clear(); + res.close(); + + //test show columns + res = conn.getMetaData().getColumns(null, "DB%", "tab%","i%" ); + expectedResult.add("id"); while (res.next()) { - String tableName = res.getString(1); - assertTrue(tableName, result.remove(tableName)); + returnedResult.add(res.getString(4).trim()); } - assertTrue(result.toString(), result.isEmpty()); + validateReturnedResult(expectedResult, returnedResult); + returnedResult.clear(); + expectedResult.clear(); res.close(); - stmt.close(); conn.close(); - // test show databases and show tables for user2_1 + // test show databases and show tables for user2 conn = context.createConnection(USER2_1); - stmt = context.createStatement(conn); - res = stmt.executeQuery("SHOW DATABASES"); - result.clear(); - result.add(DB2); - result.add("default"); + + // test direct JDBC metadata API + res = conn.getMetaData().getSchemas(); + resMeta = res.getMetaData(); + assertEquals(2, resMeta.getColumnCount()); + assertEquals("TABLE_SCHEM", resMeta.getColumnName(1)); + assertEquals("TABLE_CATALOG", resMeta.getColumnName(2)); + + expectedResult.add(DB2); + expectedResult.add("default"); while (res.next()) { - String dbName = res.getString(1); - assertTrue(dbName, result.remove(dbName)); + returnedResult.add(res.getString(1).trim()); } - assertTrue(result.toString(), result.isEmpty()); + validateReturnedResult(expectedResult, returnedResult); + returnedResult.clear(); + expectedResult.clear(); res.close(); - // test show tables - stmt.execute("USE " + DB2); - res = stmt.executeQuery("SHOW TABLES"); - result.clear(); - result.add("tab3"); + // test JDBC direct API + res = conn.getMetaData().getTables(null, "DB%", "tab%", null); + expectedResult.add("tab3"); while (res.next()) { - String tableName = res.getString(1); - assertTrue(tableName, result.remove(tableName)); + returnedResult.add(res.getString(3).trim()); } - assertTrue(result.toString(), result.isEmpty()); + validateReturnedResult(expectedResult, returnedResult); + returnedResult.clear(); + expectedResult.clear(); res.close(); - try { - stmt.execute("USE " + DB1); - Assert.fail("Expected SQL exception"); - } catch (SQLException e) { - context.verifyAuthzException(e); + + //test show columns + res = conn.getMetaData().getColumns(null, "DB%", "tab%","i%" ); + expectedResult.add("id"); + + while (res.next()) { + returnedResult.add(res.getString(4).trim()); } - context.close(); - } + validateReturnedResult(expectedResult, returnedResult); + returnedResult.clear(); + expectedResult.clear(); + res.close(); + //test show columns + res = conn.getMetaData().getColumns(null, DB1, "tab%","i%" ); + while (res.next()) { + returnedResult.add(res.getString(4).trim()); + } + validateReturnedResult(expectedResult, returnedResult); + returnedResult.clear(); + expectedResult.clear(); + res.close(); + + context.close(); + } /** * 2.8 admin user create two database, DB_1, DB_2 admin grant all to USER1_1, @@ -190,16 +350,16 @@ public class TestCrossDbOps extends AbstractTestWithStaticConfiguration { */ @Test public void testDbPrivileges() throws Exception { + createDb(ADMIN1, DB1, DB2); + // edit policy file policyFile.addRolesToGroup(USERGROUP1, "db1_all,db2_all, load_data") - .addPermissionsToRole("db1_all", "server=server1->db=" + DB1) - .addPermissionsToRole("db2_all", "server=server1->db=" + DB2) - .addPermissionsToRole("load_data", "server=server1->URI=file://" + dataFile.getPath()) - .setUserGroupMapping(StaticUserGroup.getStaticMapping()); + .addPermissionsToRole("db1_all", "server=server1->db=" + DB1) + .addPermissionsToRole("db2_all", "server=server1->db=" + DB2) + .addPermissionsToRole("load_data", "server=server1->URI=file://" + dataFile.getPath()) + .setUserGroupMapping(StaticUserGroup.getStaticMapping()); writePolicyFile(policyFile); - dropDb(ADMIN1, DB1, DB2); - createDb(ADMIN1, DB1, DB2); for (String user : new String[]{USER1_1, USER1_2}) { for (String dbName : new String[]{DB1, DB2}) { Connection userConn = context.createConnection(user); @@ -225,12 +385,12 @@ public class TestCrossDbOps extends AbstractTestWithStaticConfiguration { */ @Test public void testAdminDbPrivileges() throws Exception { + createDb(ADMIN1, DB1); + policyFile - .setUserGroupMapping(StaticUserGroup.getStaticMapping()); + .setUserGroupMapping(StaticUserGroup.getStaticMapping()); writePolicyFile(policyFile); - dropDb(ADMIN1, DB1); - createDb(ADMIN1, DB1); Connection adminCon = context.createConnection(ADMIN1); Statement adminStmt = context.createStatement(adminCon); String tabName = DB1 + "." + "admin_tab1"; @@ -252,21 +412,21 @@ public class TestCrossDbOps extends AbstractTestWithStaticConfiguration { */ @Test public void testNegativeUserPrivileges() throws Exception { - // edit policy file - policyFile.addRolesToGroup(USERGROUP1, "db1_tab1_insert", "db1_tab2_all") - .addPermissionsToRole("db1_tab2_all", "server=server1->db=" + DB1 + "->table=table_2") - .addPermissionsToRole("db1_tab1_insert", "server=server1->db=" + DB1 + "->table=table_1->action=insert") - .setUserGroupMapping(StaticUserGroup.getStaticMapping()); - writePolicyFile(policyFile); - Connection adminCon = context.createConnection(ADMIN1); Statement adminStmt = context.createStatement(adminCon); adminStmt.execute("use default"); - adminStmt.execute("DROP DATABASE IF EXISTS " + DB1 + " CASCADE"); adminStmt.execute("CREATE DATABASE " + DB1); adminStmt.execute("create table " + DB1 + ".table_1 (id int)"); adminStmt.close(); adminCon.close(); + + // edit policy file + policyFile.addRolesToGroup(USERGROUP1, "db1_tab1_insert", "db1_tab2_all") + .addPermissionsToRole("db1_tab2_all", "server=server1->db=" + DB1 + "->table=table_2") + .addPermissionsToRole("db1_tab1_insert", "server=server1->db=" + DB1 + "->table=table_1->action=insert") + .setUserGroupMapping(StaticUserGroup.getStaticMapping()); + writePolicyFile(policyFile); + Connection userConn = context.createConnection(USER1_1); Statement userStmt = context.createStatement(userConn); context.assertAuthzException(userStmt, "select * from " + DB1 + ".table_1"); @@ -282,13 +442,6 @@ public class TestCrossDbOps extends AbstractTestWithStaticConfiguration { */ @Test public void testNegativeUserDMLPrivileges() throws Exception { - policyFile - .addPermissionsToRole("db1_tab2_all", "server=server1->db=" + DB1 + "->table=table_2") - .addRolesToGroup(USERGROUP1, "db1_tab2_all") - .setUserGroupMapping(StaticUserGroup.getStaticMapping()); - writePolicyFile(policyFile); - - dropDb(ADMIN1, DB1); createDb(ADMIN1, DB1); Connection adminCon = context.createConnection(ADMIN1); Statement adminStmt = context.createStatement(adminCon); @@ -296,6 +449,13 @@ public class TestCrossDbOps extends AbstractTestWithStaticConfiguration { adminStmt.execute("create table " + DB1 + ".table_2 (id int)"); adminStmt.close(); adminCon.close(); + + policyFile + .addPermissionsToRole("db1_tab2_all", "server=server1->db=" + DB1 + "->table=table_2") + .addRolesToGroup(USERGROUP1, "db1_tab2_all") + .setUserGroupMapping(StaticUserGroup.getStaticMapping()); + writePolicyFile(policyFile); + Connection userConn = context.createConnection(USER1_1); Statement userStmt = context.createStatement(userConn); context.assertAuthzException(userStmt, "insert overwrite table " + DB1 @@ -325,15 +485,6 @@ public class TestCrossDbOps extends AbstractTestWithStaticConfiguration { */ @Test public void testNegUserPrivilegesAll() throws Exception { - - policyFile - .addRolesToGroup(USERGROUP1, "db1_all") - .addRolesToGroup(USERGROUP2, "db1_tab1_select") - .addPermissionsToRole("db1_all", "server=server1->db=" + DB1) - .addPermissionsToRole("db1_tab1_select", "server=server1->db=" + DB1 + "->table=table_1->action=select") - .setUserGroupMapping(StaticUserGroup.getStaticMapping()); - writePolicyFile(policyFile); - // create dbs Connection adminCon = context.createConnection(ADMIN1); Statement adminStmt = context.createStatement(adminCon); @@ -343,7 +494,6 @@ public class TestCrossDbOps extends AbstractTestWithStaticConfiguration { adminStmt .execute("load data local inpath '" + dataFile.getPath() + "' into table table_def"); - adminStmt.execute("DROP DATABASE IF EXISTS " + DB1 + " CASCADE"); adminStmt.execute("CREATE DATABASE " + DB1); adminStmt.execute("use " + DB1); @@ -361,6 +511,14 @@ public class TestCrossDbOps extends AbstractTestWithStaticConfiguration { adminStmt.close(); adminCon.close(); + policyFile + .addRolesToGroup(USERGROUP1, "db1_all") + .addRolesToGroup(USERGROUP2, "db1_tab1_select") + .addPermissionsToRole("db1_all", "server=server1->db=" + DB1) + .addPermissionsToRole("db1_tab1_select", "server=server1->db=" + DB1 + "->table=table_1->action=select") + .setUserGroupMapping(StaticUserGroup.getStaticMapping()); + writePolicyFile(policyFile); + Connection userConn = context.createConnection(USER2_1); Statement userStmt = context.createStatement(userConn); @@ -404,15 +562,14 @@ public class TestCrossDbOps extends AbstractTestWithStaticConfiguration { */ @Test public void testSandboxOpt9() throws Exception { + createDb(ADMIN1, DB1, DB2); + policyFile - .addPermissionsToRole(GROUP1_ROLE, ALL_DB1, ALL_DB2, loadData) - .addRolesToGroup(USERGROUP1, GROUP1_ROLE) - .setUserGroupMapping(StaticUserGroup.getStaticMapping()); + .addPermissionsToRole(GROUP1_ROLE, ALL_DB1, ALL_DB2, loadData) + .addRolesToGroup(USERGROUP1, GROUP1_ROLE) + .setUserGroupMapping(StaticUserGroup.getStaticMapping()); writePolicyFile(policyFile); - dropDb(ADMIN1, DB1, DB2); - createDb(ADMIN1, DB1, DB2); - Connection connection = context.createConnection(USER1_1); Statement statement = context.createStatement(connection); @@ -454,8 +611,6 @@ public class TestCrossDbOps extends AbstractTestWithStaticConfiguration { context.assertAuthzException(statement, "CREATE TABLE " + DB1 + "." + TBL2 + " AS SELECT value from " + DB2 + "." + TBL2 + " LIMIT 10"); - - statement.close(); connection.close(); } @@ -473,18 +628,7 @@ public class TestCrossDbOps extends AbstractTestWithStaticConfiguration { */ @Test public void testCrossDbViewOperations() throws Exception { - // edit policy file - policyFile - .addRolesToGroup(USERGROUP1, "all_db1", "load_data", "select_tb2") - .addPermissionsToRole("all_db1", "server=server1->db=" + DB1) - .addPermissionsToRole("all_db2", "server=server1->db=" + DB2) - .addPermissionsToRole("select_tb2", "server=server1->db=" + DB2 + "->table=tb_1->action=select") - .addPermissionsToRole("load_data", "server=server1->URI=file://" + dataFile.getPath()) - .setUserGroupMapping(StaticUserGroup.getStaticMapping()); - writePolicyFile(policyFile); - // admin create two databases - dropDb(ADMIN1, DB1, DB2); createDb(ADMIN1, DB1, DB2); Connection connection = context.createConnection(ADMIN1); Statement statement = context.createStatement(connection); @@ -496,6 +640,16 @@ public class TestCrossDbOps extends AbstractTestWithStaticConfiguration { .execute("CREATE TABLE " + DB2 + "." + TBL2 + "(id int)"); context.close(); + // edit policy file + policyFile + .addRolesToGroup(USERGROUP1, "all_db1", "load_data", "select_tb2") + .addPermissionsToRole("all_db1", "server=server1->db=" + DB1) + .addPermissionsToRole("all_db2", "server=server1->db=" + DB2) + .addPermissionsToRole("select_tb2", "server=server1->db=" + DB2 + "->table=tb_1->action=select") + .addPermissionsToRole("load_data", "server=server1->URI=file://" + dataFile.getPath()) + .setUserGroupMapping(StaticUserGroup.getStaticMapping()); + writePolicyFile(policyFile); + connection = context.createConnection(USER1_1); statement = context.createStatement(connection); http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/19bbaacd/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestUserManagement.java ---------------------------------------------------------------------- diff --git a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestUserManagement.java b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestUserManagement.java index fa34c33..be9f601 100644 --- a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestUserManagement.java +++ b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestUserManagement.java @@ -51,7 +51,7 @@ public class TestUserManagement extends AbstractTestWithStaticConfiguration { } @Override @After - public void clearDB() throws Exception { + public void clearAfterPerTest() throws Exception { if (context != null) { context.close(); } http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/19bbaacd/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/metastore/AbstractMetastoreTestWithStaticConfiguration.java ---------------------------------------------------------------------- diff --git a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/metastore/AbstractMetastoreTestWithStaticConfiguration.java b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/metastore/AbstractMetastoreTestWithStaticConfiguration.java index 23027d1..2c14c82 100644 --- a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/metastore/AbstractMetastoreTestWithStaticConfiguration.java +++ b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/metastore/AbstractMetastoreTestWithStaticConfiguration.java @@ -54,16 +54,11 @@ public abstract class AbstractMetastoreTestWithStaticConfiguration extends @BeforeClass public static void setupTestStaticConfiguration() throws Exception { useSentryService = true; + clearDbAfterPerTest = false; testServerType = HiveServer2Type.InternalMetastore.name(); AbstractTestWithStaticConfiguration.setupTestStaticConfiguration(); } - @Override - @After - public void clearDB() throws Exception { - - } - protected static void writePolicyFile(PolicyFile policyFile) throws Exception { policyFile.write(context.getPolicyFile()); }