diff --git a/ql/src/java/org/apache/hadoop/hive/ql/parse/ImportSemanticAnalyzer.java b/ql/src/java/org/apache/hadoop/hive/ql/parse/ImportSemanticAnalyzer.java index 2d907ff6a4..f3f206b6e2 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/parse/ImportSemanticAnalyzer.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/parse/ImportSemanticAnalyzer.java @@ -79,10 +79,14 @@ public ImportSemanticAnalyzer(QueryState queryState) throws SemanticException { super(queryState); } - // FIXME : Note that the tableExists flag as used by Auth is kinda a hack and + // Note that the tableExists flag as used by Auth is kinda a hack and // assumes only 1 table will ever be imported - this assumption is broken by - // REPL LOAD. We need to fix this. Maybe by continuing the hack and replacing - // by a map, maybe by coming up with a better api for it. + // REPL LOAD. + // + // However, we've not chosen to expand this to a map of tables/etc, since + // we have expanded how auth works with REPL DUMP / REPL LOAD to simply + // require ADMIN privileges, rather than checking each object, which + // quickly becomes untenable, and even more so, costly on memory. private boolean tableExists = false; public boolean existsTable() { diff --git a/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzerFactory.java b/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzerFactory.java index 3c60e038a7..a24e038e30 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzerFactory.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzerFactory.java @@ -129,9 +129,9 @@ commandType.put(HiveParser.TOK_COMMIT, HiveOperation.COMMIT); commandType.put(HiveParser.TOK_ROLLBACK, HiveOperation.ROLLBACK); commandType.put(HiveParser.TOK_SET_AUTOCOMMIT, HiveOperation.SET_AUTOCOMMIT); - commandType.put(HiveParser.TOK_REPL_DUMP, HiveOperation.EXPORT); // piggyback on EXPORT security handling for now - commandType.put(HiveParser.TOK_REPL_LOAD, HiveOperation.IMPORT); // piggyback on IMPORT security handling for now - commandType.put(HiveParser.TOK_REPL_STATUS, HiveOperation.SHOW_TBLPROPERTIES); // TODO : also actually DESCDATABASE + commandType.put(HiveParser.TOK_REPL_DUMP, HiveOperation.REPLDUMP); + commandType.put(HiveParser.TOK_REPL_LOAD, HiveOperation.REPLLOAD); + commandType.put(HiveParser.TOK_REPL_STATUS, HiveOperation.REPLSTATUS); } static { diff --git a/ql/src/java/org/apache/hadoop/hive/ql/plan/HiveOperation.java b/ql/src/java/org/apache/hadoop/hive/ql/plan/HiveOperation.java index ecac31fa1b..d9b6969d16 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/plan/HiveOperation.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/plan/HiveOperation.java @@ -25,6 +25,9 @@ LOAD("LOAD", null, new Privilege[]{Privilege.ALTER_DATA}), EXPORT("EXPORT", new Privilege[]{Privilege.SELECT}, null), IMPORT("IMPORT", null, new Privilege[]{Privilege.ALTER_METADATA, Privilege.ALTER_DATA}), + REPLDUMP("REPLDUMP", new Privilege[]{Privilege.ALL}, null), + REPLLOAD("REPLLOAD", null, new Privilege[]{Privilege.ALL}), + REPLSTATUS("REPLSTATUS", new Privilege[]{Privilege.SELECT}, null), CREATEDATABASE("CREATEDATABASE", null, new Privilege[]{Privilege.CREATE}), DROPDATABASE("DROPDATABASE", null, new Privilege[]{Privilege.DROP}), SWITCHDATABASE("SWITCHDATABASE", null, null, true, false), diff --git a/ql/src/java/org/apache/hadoop/hive/ql/security/authorization/plugin/HiveOperationType.java b/ql/src/java/org/apache/hadoop/hive/ql/security/authorization/plugin/HiveOperationType.java index 7da44e8b6e..2fb2a3681b 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/security/authorization/plugin/HiveOperationType.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/security/authorization/plugin/HiveOperationType.java @@ -30,6 +30,9 @@ LOAD, EXPORT, IMPORT, + REPLDUMP, + REPLLOAD, + REPLSTATUS, CREATEDATABASE, DROPDATABASE, SWITCHDATABASE, diff --git a/ql/src/java/org/apache/hadoop/hive/ql/security/authorization/plugin/sqlstd/Operation2Privilege.java b/ql/src/java/org/apache/hadoop/hive/ql/security/authorization/plugin/sqlstd/Operation2Privilege.java index 9688f8c663..1b1c4716f6 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/security/authorization/plugin/sqlstd/Operation2Privilege.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/security/authorization/plugin/sqlstd/Operation2Privilege.java @@ -113,6 +113,7 @@ public HivePrivilegeObjectType getObjectType() { } private static Map> op2Priv; + private static List adminPrivOps; private static SQLPrivTypeGrant[] OWNER_PRIV_AR = arr(SQLPrivTypeGrant.OWNER_PRIV); private static SQLPrivTypeGrant[] SEL_NOGRANT_AR = arr(SQLPrivTypeGrant.SELECT_NOGRANT); @@ -130,6 +131,8 @@ public HivePrivilegeObjectType getObjectType() { static { + + adminPrivOps = new ArrayList(); op2Priv = new HashMap>(); op2Priv.put(HiveOperationType.EXPLAIN, PrivRequirement.newIOPrivRequirement @@ -293,6 +296,21 @@ public HivePrivilegeObjectType getObjectType() { IOType.OUTPUT, null, HivePrivilegeObjectType.TABLE_OR_VIEW), new PrivRequirement(OWNER_PRIV_AR, IOType.OUTPUT, null, HivePrivilegeObjectType.DATABASE))); + // Setting REPL DUMP and REPL LOAD as all requiring ADMIN privileges. + // We might wind up loosening this in the future, but right now, we do not want + // to do individual object based checks on every object possible, and thus, asking + // for a broad privilege such as this is the best route forward. REPL STATUS + // should use privileges similar to DESCRIBE DB/TABLE, and so, it asks for no + // output privileges, and asks for select-no-grant on input. + op2Priv.put(HiveOperationType.REPLDUMP, PrivRequirement.newIOPrivRequirement( + ADMIN_PRIV_AR, ADMIN_PRIV_AR)); + op2Priv.put(HiveOperationType.REPLLOAD, PrivRequirement.newIOPrivRequirement( + ADMIN_PRIV_AR, ADMIN_PRIV_AR)); + op2Priv.put(HiveOperationType.REPLSTATUS, PrivRequirement.newIOPrivRequirement( + SEL_NOGRANT_AR, null)); + adminPrivOps.add(HiveOperationType.REPLDUMP); + adminPrivOps.add(HiveOperationType.REPLLOAD); + // operations require select priv op2Priv.put(HiveOperationType.SHOWCOLUMNS, PrivRequirement.newIOPrivRequirement (SEL_NOGRANT_AR, null)); @@ -501,6 +519,16 @@ public static RequiredPrivileges getRequiredPrivs(HiveOperationType hiveOpType, return reqPrivs; } + /** + * Some operations are tagged as requiring admin privileges, ignoring any object that + * might be checked on it. This check is run in those cases. + * @param hiveOpType + * @return + */ + public static boolean isAdminPrivOperation(HiveOperationType hiveOpType){ + return adminPrivOps.contains(hiveOpType); + } + // for unit tests public static Set getOperationTypes() { return op2Priv.keySet(); diff --git a/ql/src/java/org/apache/hadoop/hive/ql/security/authorization/plugin/sqlstd/SQLStdHiveAuthorizationValidator.java b/ql/src/java/org/apache/hadoop/hive/ql/security/authorization/plugin/sqlstd/SQLStdHiveAuthorizationValidator.java index 2977675b3f..dc03f0974e 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/security/authorization/plugin/sqlstd/SQLStdHiveAuthorizationValidator.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/security/authorization/plugin/sqlstd/SQLStdHiveAuthorizationValidator.java @@ -95,6 +95,15 @@ private void checkPrivileges(HiveOperationType hiveOpType, List