Repository: sentry
Updated Branches:
  refs/heads/branch-2.0 d77edb505 -> b72d4fb22


SENTRY-2226: Support Hive operation ALTER TABLE EXCHANGE. (Na Li, reviewed by 
Sergio Pena, Kalyan Kumar Kalvagadda)


Project: http://git-wip-us.apache.org/repos/asf/sentry/repo
Commit: http://git-wip-us.apache.org/repos/asf/sentry/commit/b72d4fb2
Tree: http://git-wip-us.apache.org/repos/asf/sentry/tree/b72d4fb2
Diff: http://git-wip-us.apache.org/repos/asf/sentry/diff/b72d4fb2

Branch: refs/heads/branch-2.0
Commit: b72d4fb226114900abae99dfab5a5bc28d2892b8
Parents: d77edb5
Author: lina.li <lina...@cloudera.com>
Authored: Fri May 11 11:17:09 2018 -0500
Committer: Sergio Pena <sergio.p...@cloudera.com>
Committed: Thu May 17 13:58:13 2018 -0500

----------------------------------------------------------------------
 .../hive/authz/HiveAuthzPrivilegesMap.java      |  12 ++
 .../TestDbColumnLevelMetaDataOps.java           | 124 +++++++++++++++++++
 2 files changed, 136 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/sentry/blob/b72d4fb2/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/authz/HiveAuthzPrivilegesMap.java
----------------------------------------------------------------------
diff --git 
a/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/authz/HiveAuthzPrivilegesMap.java
 
b/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/authz/HiveAuthzPrivilegesMap.java
index ffa193f..4f932ea 100644
--- 
a/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/authz/HiveAuthzPrivilegesMap.java
+++ 
b/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/authz/HiveAuthzPrivilegesMap.java
@@ -112,6 +112,16 @@ public class HiveAuthzPrivilegesMap {
         setOperationType(HiveOperationType.DDL).
         build();
 
+    // input required privilege from Hive: SELECT on column level and DELETE 
on table level
+    // output required privilege from Hive: INSERT on table level
+    // Sentry makes it more restrictive, and requires ALL at input, INSERT and 
ALTER at output
+    HiveAuthzPrivileges alterTableExchangePrivilege = new 
HiveAuthzPrivileges.AuthzPrivilegeBuilder().
+        addInputObjectPriviledge(AuthorizableType.Table, 
EnumSet.of(DBModelAction.ALL)).
+        addOutputObjectPriviledge(AuthorizableType.Table, 
EnumSet.of(DBModelAction.INSERT, DBModelAction.ALTER)).
+        setOperationScope(HiveOperationScope.TABLE).
+        setOperationType(HiveOperationType.DDL).
+        build();
+
     HiveAuthzPrivileges alterPartPrivilege = new 
HiveAuthzPrivileges.AuthzPrivilegeBuilder().
         addInputObjectPriviledge(AuthorizableType.Table, 
EnumSet.of(DBModelAction.ALTER)).
         setOperationScope(HiveOperationScope.TABLE).
@@ -240,6 +250,8 @@ public class HiveAuthzPrivilegesMap {
     hiveAuthzStmtPrivMap.put(HiveOperation.ALTERTABLE_ADDCOLS, 
alterTablePrivilege);
     hiveAuthzStmtPrivMap.put(HiveOperation.ALTERTABLE_REPLACECOLS, 
alterTablePrivilege);
     hiveAuthzStmtPrivMap.put(HiveOperation.ALTERTABLE_PARTCOLTYPE, 
alterPartPrivilege);
+    hiveAuthzStmtPrivMap.put(HiveOperation.ALTERTABLE_EXCHANGEPARTITION, 
alterTableExchangePrivilege);
+
     hiveAuthzStmtPrivMap.put(HiveOperation.ALTERTABLE_BUCKETNUM, 
alterPartPrivilege);
     hiveAuthzStmtPrivMap.put(HiveOperation.ALTERPARTITION_BUCKETNUM, 
alterPartPrivilege);
 

http://git-wip-us.apache.org/repos/asf/sentry/blob/b72d4fb2/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbColumnLevelMetaDataOps.java
----------------------------------------------------------------------
diff --git 
a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbColumnLevelMetaDataOps.java
 
b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbColumnLevelMetaDataOps.java
index 3735179..c065f7f 100644
--- 
a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbColumnLevelMetaDataOps.java
+++ 
b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbColumnLevelMetaDataOps.java
@@ -371,4 +371,128 @@ public class TestDbColumnLevelMetaDataOps extends 
AbstractTestWithStaticConfigur
     String query = "SHOW TABLE EXTENDED IN " + TEST_COL_METADATA_OPS_DB + " 
LIKE " + TEST_COL_METADATA_OPS_TB;
     validateSemanticException(query, USER1_1);
   }
+
+  /**
+   * User cannot exchange partition of tables without any privilege on input 
table and output table
+   * @throws Exception
+   */
+  @Test
+  public void testAlterTableExchangeNoPrivilege() throws Exception {
+    final String PAR_ROLE_NAME = "config1_user_role";
+    final String PAR_GROUP_NAME = USERGROUP1;
+    final String PAR_DB_NAME = "config1_test_database1";
+    final String PAR_INPUT_TABLE_NAME = "aliens";
+    final String PAR_OUTPUT_TABLE_NAME = "movie_stars";
+
+    establishSession(ADMIN1);
+    statement.execute("DROP DATABASE IF EXISTS " + PAR_DB_NAME + " CASCADE");
+    statement.execute("CREATE DATABASE " + PAR_DB_NAME);
+    statement.execute("CREATE ROLE " + PAR_ROLE_NAME);
+    statement.execute("GRANT ROLE " + PAR_ROLE_NAME + " TO GROUP " + 
PAR_GROUP_NAME);
+    statement.execute("CREATE TABLE " + PAR_DB_NAME + "." + 
PAR_INPUT_TABLE_NAME + " (name string) PARTITIONED BY (home_planet string, diet 
string)");
+    statement.execute("CREATE TABLE " + PAR_DB_NAME + "." + 
PAR_OUTPUT_TABLE_NAME + " (name string) PARTITIONED BY (home_planet string, 
diet string)");
+    statement.execute("ALTER TABLE " + PAR_DB_NAME + "." + 
PAR_INPUT_TABLE_NAME + " ADD PARTITION (home_planet='earth', diet='milk 
shakes')");
+    statement.execute("ALTER TABLE " + PAR_DB_NAME + "." + 
PAR_INPUT_TABLE_NAME + " ADD PARTITION (home_planet='trapis-4', diet='sentient 
lifeforms with cheese')");
+
+    String query = "ALTER TABLE " + PAR_DB_NAME + "." + PAR_OUTPUT_TABLE_NAME 
+ " EXCHANGE PARTITION (home_planet='earth', diet='milk shakes') WITH TABLE " + 
PAR_DB_NAME + "." + PAR_INPUT_TABLE_NAME;
+    validateSemanticException(query, USER1_1);
+  }
+
+  /**
+   * User cannot exchange partition of tables without input required privilege
+   * @throws Exception
+   */
+  @Test
+  public void testAlterTableExchangeNoPrivilegeOnInput() throws Exception {
+    final String PAR_ROLE_NAME = "config1_user_role";
+    final String PAR_GROUP_NAME = USERGROUP1;
+    final String PAR_DB_NAME = "config1_test_database2";
+    final String PAR_INPUT_TABLE_NAME = "aliens";
+    final String PAR_OUTPUT_TABLE_NAME = "movie_stars";
+
+    establishSession(ADMIN1);
+    statement.execute("DROP DATABASE IF EXISTS " + PAR_DB_NAME + " CASCADE");
+    statement.execute("CREATE DATABASE " + PAR_DB_NAME);
+    statement.execute("CREATE ROLE " + PAR_ROLE_NAME);
+    statement.execute("GRANT ROLE " + PAR_ROLE_NAME + " TO GROUP " + 
PAR_GROUP_NAME);
+    statement.execute("CREATE TABLE " + PAR_DB_NAME + "." + 
PAR_INPUT_TABLE_NAME + " (name string) PARTITIONED BY (home_planet string, diet 
string)");
+    statement.execute("CREATE TABLE " + PAR_DB_NAME + "." + 
PAR_OUTPUT_TABLE_NAME + " (name string) PARTITIONED BY (home_planet string, 
diet string)");
+    statement.execute("ALTER TABLE " + PAR_DB_NAME + "." + 
PAR_INPUT_TABLE_NAME + " ADD PARTITION (home_planet='earth', diet='milk 
shakes')");
+    statement.execute("ALTER TABLE " + PAR_DB_NAME + "." + 
PAR_INPUT_TABLE_NAME + " ADD PARTITION (home_planet='trapis-4', diet='sentient 
lifeforms with cheese')");
+
+    // grant propert privilege to output table
+    statement.execute("GRANT INSERT ON TABLE " + PAR_DB_NAME + "." + 
PAR_OUTPUT_TABLE_NAME + " TO ROLE " + PAR_ROLE_NAME);
+    statement.execute("GRANT ALTER ON TABLE " + PAR_DB_NAME + "." + 
PAR_OUTPUT_TABLE_NAME + " TO ROLE " + PAR_ROLE_NAME);
+
+    // move a partition from a source table to target table and alter each 
table's metadata.
+    // ALTER TABLE <dest_table> EXCHANGE PARTITION (<[partial] partition 
spec>) WITH TABLE <src_table>
+    String query = "ALTER TABLE " + PAR_DB_NAME + "." + PAR_OUTPUT_TABLE_NAME 
+ " EXCHANGE PARTITION (home_planet='earth', diet='milk shakes') WITH TABLE " + 
PAR_DB_NAME + "." + PAR_INPUT_TABLE_NAME;
+    validateSemanticException(query, USER1_1);
+  }
+
+  /**
+   * User cannot exchange partition of tables without output required privilege
+   * @throws Exception
+   */
+  @Test
+  public void testAlterTableExchangeNoPrivilegeOnOutput() throws Exception {
+    final String PAR_ROLE_NAME = "config1_user_role";
+    final String PAR_GROUP_NAME = USERGROUP1;
+    final String PAR_DB_NAME = "config1_test_database3";
+    final String PAR_INPUT_TABLE_NAME = "aliens";
+    final String PAR_OUTPUT_TABLE_NAME = "movie_stars";
+
+    establishSession(ADMIN1);
+    statement.execute("DROP DATABASE IF EXISTS " + PAR_DB_NAME + " CASCADE");
+    statement.execute("CREATE DATABASE " + PAR_DB_NAME);
+    statement.execute("CREATE ROLE " + PAR_ROLE_NAME);
+    statement.execute("GRANT ROLE " + PAR_ROLE_NAME + " TO GROUP " + 
PAR_GROUP_NAME);
+    statement.execute("CREATE TABLE " + PAR_DB_NAME + "." + 
PAR_INPUT_TABLE_NAME + " (name string) PARTITIONED BY (home_planet string, diet 
string)");
+    statement.execute("CREATE TABLE " + PAR_DB_NAME + "." + 
PAR_OUTPUT_TABLE_NAME + " (name string) PARTITIONED BY (home_planet string, 
diet string)");
+    statement.execute("ALTER TABLE " + PAR_DB_NAME + "." + 
PAR_INPUT_TABLE_NAME + " ADD PARTITION (home_planet='earth', diet='milk 
shakes')");
+    statement.execute("ALTER TABLE " + PAR_DB_NAME + "." + 
PAR_INPUT_TABLE_NAME + " ADD PARTITION (home_planet='trapis-4', diet='sentient 
lifeforms with cheese')");
+
+    // grant propert privilege to input table
+    statement.execute("GRANT ALL ON TABLE " + PAR_DB_NAME + "." + 
PAR_INPUT_TABLE_NAME + " TO ROLE " + PAR_ROLE_NAME);
+
+    // move a partition from a source table to target table and alter each 
table's metadata.
+    // ALTER TABLE <dest_table> EXCHANGE PARTITION (<[partial] partition 
spec>) WITH TABLE <src_table>
+    String query = "ALTER TABLE " + PAR_DB_NAME + "." + PAR_OUTPUT_TABLE_NAME 
+ " EXCHANGE PARTITION (home_planet='earth', diet='milk shakes') WITH TABLE " + 
PAR_DB_NAME + "." + PAR_INPUT_TABLE_NAME;
+    validateSemanticException(query, USER1_1);
+  }
+
+  /**
+   * User can exchange partition of tables with both input and output required 
privileges
+   * @throws Exception
+   */
+  @Test
+  public void testAlterTableExchangeWithPrivilege() throws Exception {
+    final String PAR_ROLE_NAME = "config1_user_role";
+    final String PAR_GROUP_NAME = USERGROUP1;
+    final String PAR_DB_NAME = "config1_test_database4";
+    final String PAR_INPUT_TABLE_NAME = "aliens";
+    final String PAR_OUTPUT_TABLE_NAME = "movie_stars";
+
+    establishSession(ADMIN1);
+    statement.execute("DROP DATABASE IF EXISTS " + PAR_DB_NAME + " CASCADE");
+    statement.execute("CREATE DATABASE " + PAR_DB_NAME);
+    statement.execute("CREATE ROLE " + PAR_ROLE_NAME);
+    statement.execute("GRANT ROLE " + PAR_ROLE_NAME + " TO GROUP " + 
PAR_GROUP_NAME);
+    statement.execute("CREATE TABLE " + PAR_DB_NAME + "." + 
PAR_INPUT_TABLE_NAME + " (name string) PARTITIONED BY (home_planet string, diet 
string)");
+    statement.execute("CREATE TABLE " + PAR_DB_NAME + "." + 
PAR_OUTPUT_TABLE_NAME + " (name string) PARTITIONED BY (home_planet string, 
diet string)");
+    statement.execute("ALTER TABLE " + PAR_DB_NAME + "." + 
PAR_INPUT_TABLE_NAME + " ADD PARTITION (home_planet='earth', diet='milk 
shakes')");
+    statement.execute("ALTER TABLE " + PAR_DB_NAME + "." + 
PAR_INPUT_TABLE_NAME + " ADD PARTITION (home_planet='trapis-4', diet='sentient 
lifeforms with cheese')");
+
+    // grant propert privilege to input table
+    statement.execute("GRANT ALL ON TABLE " + PAR_DB_NAME + "." + 
PAR_INPUT_TABLE_NAME + " TO ROLE " + PAR_ROLE_NAME);
+    // grant propert privilege to output table
+    statement.execute("GRANT INSERT ON TABLE " + PAR_DB_NAME + "." + 
PAR_OUTPUT_TABLE_NAME + " TO ROLE " + PAR_ROLE_NAME);
+    statement.execute("GRANT ALTER ON TABLE " + PAR_DB_NAME + "." + 
PAR_OUTPUT_TABLE_NAME + " TO ROLE " + PAR_ROLE_NAME);
+
+    // move a partition from a source table to target table and alter each 
table's metadata.
+    // ALTER TABLE <dest_table> EXCHANGE PARTITION (<[partial] partition 
spec>) WITH TABLE <src_table>
+    String query = "ALTER TABLE " + PAR_DB_NAME + "." + PAR_OUTPUT_TABLE_NAME 
+ " EXCHANGE PARTITION (home_planet='earth', diet='milk shakes') WITH TABLE " + 
PAR_DB_NAME + "." + PAR_INPUT_TABLE_NAME;
+    establishSession(USER1_1);
+    statement.execute(query);
+  }
 }

Reply via email to