diff --git a/ql/src/java/org/apache/hadoop/hive/ql/Driver.java b/ql/src/java/org/apache/hadoop/hive/ql/Driver.java index 9040d9b..33a0c97 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/Driver.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/Driver.java @@ -103,6 +103,7 @@ import org.apache.hadoop.hive.ql.security.authorization.AuthorizationUtils; import org.apache.hadoop.hive.ql.security.authorization.plugin.HiveOperationType; import org.apache.hadoop.hive.ql.security.authorization.plugin.HivePrivilegeObject; +import org.apache.hadoop.hive.ql.security.authorization.plugin.HivePrivilegeObject.HivePrivObjectActionType; import org.apache.hadoop.hive.ql.security.authorization.plugin.HivePrivilegeObject.HivePrivilegeObjectType; import org.apache.hadoop.hive.ql.session.SessionState; import org.apache.hadoop.hive.ql.session.SessionState.LogHelper; @@ -739,13 +740,30 @@ private void doAuthorizationV2(SessionState ss, HiveOperation op, HashSet newIOPrivRequirement(SQLPrivTypeGrant[] inGrants, + SQLPrivTypeGrant[] outGrants) { + List privReqs = new ArrayList(); + privReqs.add(new PrivRequirement(inGrants, IOType.INPUT)); + privReqs.add(new PrivRequirement(outGrants, IOType.OUTPUT)); + return privReqs; + } + + private SQLPrivTypeGrant[] getReqPrivs() { + return reqPrivs; } - private SQLPrivTypeGrant[] getInputPrivs() { - return inputPrivs; + private IOType getIOType() { + return ioType; } - private SQLPrivTypeGrant[] getOutputPrivs() { - return outputPrivs; + private HivePrivObjectActionType getActionType() { + return actionType; } + } - private static Map op2Priv; + private static Map> op2Priv; private static SQLPrivTypeGrant[] OWNER_PRIV_AR = arr(SQLPrivTypeGrant.OWNER_PRIV); private static SQLPrivTypeGrant[] SEL_NOGRANT_AR = arr(SQLPrivTypeGrant.SELECT_NOGRANT); @@ -63,153 +101,246 @@ static { - op2Priv = new HashMap(); + op2Priv = new HashMap>(); - op2Priv.put(HiveOperationType.EXPLAIN, new InOutPrivs(SEL_NOGRANT_AR, + op2Priv.put(HiveOperationType.EXPLAIN, PrivRequirement.newIOPrivRequirement +(SEL_NOGRANT_AR, SEL_NOGRANT_AR)); //?? op2Priv.put(HiveOperationType.CREATEDATABASE, - new InOutPrivs(ADMIN_PRIV_AR, OWNER_INS_SEL_DEL_NOGRANT_AR)); + PrivRequirement.newIOPrivRequirement +(ADMIN_PRIV_AR, OWNER_INS_SEL_DEL_NOGRANT_AR)); - op2Priv.put(HiveOperationType.DROPDATABASE, new InOutPrivs(null, OWNER_PRIV_AR)); + op2Priv.put(HiveOperationType.DROPDATABASE, PrivRequirement.newIOPrivRequirement +(null, OWNER_PRIV_AR)); // this should be database usage privilege once it is supported - op2Priv.put(HiveOperationType.SWITCHDATABASE, new InOutPrivs(null, null)); + op2Priv.put(HiveOperationType.SWITCHDATABASE, PrivRequirement.newIOPrivRequirement +(null, null)); // lock operations not controlled for now - op2Priv.put(HiveOperationType.LOCKDB, new InOutPrivs(null, null)); - op2Priv.put(HiveOperationType.UNLOCKDB, new InOutPrivs(null, null)); - - op2Priv.put(HiveOperationType.DROPTABLE, new InOutPrivs(OWNER_PRIV_AR, null)); - op2Priv.put(HiveOperationType.DESCTABLE, new InOutPrivs(SEL_NOGRANT_AR, null)); - op2Priv.put(HiveOperationType.SHOWPARTITIONS, new InOutPrivs(SEL_NOGRANT_AR, null)); - op2Priv.put(HiveOperationType.DESCFUNCTION, new InOutPrivs(null, null)); + op2Priv.put(HiveOperationType.LOCKDB, PrivRequirement.newIOPrivRequirement +(null, null)); + op2Priv.put(HiveOperationType.UNLOCKDB, PrivRequirement.newIOPrivRequirement +(null, null)); + + op2Priv.put(HiveOperationType.DROPTABLE, PrivRequirement.newIOPrivRequirement +(OWNER_PRIV_AR, null)); + op2Priv.put(HiveOperationType.DESCTABLE, PrivRequirement.newIOPrivRequirement +(SEL_NOGRANT_AR, null)); + op2Priv.put(HiveOperationType.SHOWPARTITIONS, PrivRequirement.newIOPrivRequirement +(SEL_NOGRANT_AR, null)); + op2Priv.put(HiveOperationType.DESCFUNCTION, PrivRequirement.newIOPrivRequirement +(null, null)); // meta store check command - require admin priv - op2Priv.put(HiveOperationType.MSCK, new InOutPrivs(ADMIN_PRIV_AR, null)); + op2Priv.put(HiveOperationType.MSCK, PrivRequirement.newIOPrivRequirement +(ADMIN_PRIV_AR, null)); //alter table commands require table ownership // There should not be output object, but just in case the table is incorrectly added // to output instead of input, adding owner requirement on output will catch that as well - op2Priv.put(HiveOperationType.ALTERTABLE_ADDCOLS, new InOutPrivs(OWNER_PRIV_AR, OWNER_PRIV_AR)); - op2Priv.put(HiveOperationType.ALTERTABLE_REPLACECOLS, new InOutPrivs(OWNER_PRIV_AR, OWNER_PRIV_AR)); - op2Priv.put(HiveOperationType.ALTERTABLE_RENAMECOL, new InOutPrivs(OWNER_PRIV_AR, OWNER_PRIV_AR)); - op2Priv.put(HiveOperationType.ALTERTABLE_RENAMEPART, new InOutPrivs(OWNER_PRIV_AR, OWNER_PRIV_AR)); - op2Priv.put(HiveOperationType.ALTERTABLE_RENAME, new InOutPrivs(OWNER_PRIV_AR, OWNER_PRIV_AR)); - op2Priv.put(HiveOperationType.ALTERTABLE_TOUCH, new InOutPrivs(OWNER_PRIV_AR, OWNER_PRIV_AR)); - op2Priv.put(HiveOperationType.ALTERTABLE_ARCHIVE, new InOutPrivs(OWNER_PRIV_AR, OWNER_PRIV_AR)); - op2Priv.put(HiveOperationType.ALTERTABLE_UNARCHIVE, new InOutPrivs(OWNER_PRIV_AR, OWNER_PRIV_AR)); - op2Priv.put(HiveOperationType.ALTERTABLE_PROPERTIES, new InOutPrivs(OWNER_PRIV_AR, OWNER_PRIV_AR)); - op2Priv.put(HiveOperationType.ALTERTABLE_SERIALIZER, new InOutPrivs(OWNER_PRIV_AR, OWNER_PRIV_AR)); - op2Priv.put(HiveOperationType.ALTERTABLE_PARTCOLTYPE, new InOutPrivs(OWNER_PRIV_AR, OWNER_PRIV_AR)); - op2Priv.put(HiveOperationType.ALTERPARTITION_SERIALIZER, new InOutPrivs(OWNER_PRIV_AR, OWNER_PRIV_AR)); - op2Priv.put(HiveOperationType.ALTERTABLE_SERDEPROPERTIES, new InOutPrivs(OWNER_PRIV_AR, OWNER_PRIV_AR)); - op2Priv.put(HiveOperationType.ALTERPARTITION_SERDEPROPERTIES, new InOutPrivs(OWNER_PRIV_AR, OWNER_PRIV_AR)); - op2Priv.put(HiveOperationType.ALTERTABLE_CLUSTER_SORT, new InOutPrivs(OWNER_PRIV_AR, OWNER_PRIV_AR)); - op2Priv.put(HiveOperationType.ALTERTABLE_BUCKETNUM, new InOutPrivs(OWNER_PRIV_AR, OWNER_PRIV_AR)); - op2Priv.put(HiveOperationType.ALTERPARTITION_BUCKETNUM, new InOutPrivs(OWNER_PRIV_AR, OWNER_PRIV_AR)); - op2Priv.put(HiveOperationType.ALTERTABLE_PROTECTMODE, new InOutPrivs(OWNER_PRIV_AR, OWNER_PRIV_AR)); - op2Priv.put(HiveOperationType.ALTERPARTITION_PROTECTMODE, new InOutPrivs(OWNER_PRIV_AR, OWNER_PRIV_AR)); - op2Priv.put(HiveOperationType.ALTERTABLE_FILEFORMAT, new InOutPrivs(OWNER_PRIV_AR, OWNER_PRIV_AR)); - op2Priv.put(HiveOperationType.ALTERPARTITION_FILEFORMAT, new InOutPrivs(OWNER_PRIV_AR, OWNER_PRIV_AR)); - op2Priv.put(HiveOperationType.ALTERTABLE_LOCATION, new InOutPrivs(OWNER_PRIV_AR, OWNER_INS_SEL_DEL_NOGRANT_AR)); - op2Priv.put(HiveOperationType.ALTERPARTITION_LOCATION, new InOutPrivs(OWNER_PRIV_AR, OWNER_INS_SEL_DEL_NOGRANT_AR)); - op2Priv.put(HiveOperationType.ALTERTABLE_MERGEFILES, new InOutPrivs(OWNER_PRIV_AR, OWNER_PRIV_AR)); - op2Priv.put(HiveOperationType.ALTERPARTITION_MERGEFILES, new InOutPrivs(OWNER_PRIV_AR, OWNER_PRIV_AR)); - op2Priv.put(HiveOperationType.ALTERTABLE_SKEWED, new InOutPrivs(OWNER_PRIV_AR, OWNER_PRIV_AR)); - op2Priv.put(HiveOperationType.ALTERTBLPART_SKEWED_LOCATION, new InOutPrivs(OWNER_PRIV_AR, OWNER_INS_SEL_DEL_NOGRANT_AR)); - op2Priv.put(HiveOperationType.ALTERTABLE_COMPACT, new InOutPrivs(OWNER_PRIV_AR, OWNER_PRIV_AR)); - op2Priv.put(HiveOperationType.TRUNCATETABLE, new InOutPrivs(OWNER_PRIV_AR, OWNER_PRIV_AR)); + op2Priv.put(HiveOperationType.ALTERTABLE_ADDCOLS, PrivRequirement.newIOPrivRequirement +(OWNER_PRIV_AR, OWNER_PRIV_AR)); + op2Priv.put(HiveOperationType.ALTERTABLE_REPLACECOLS, PrivRequirement.newIOPrivRequirement +(OWNER_PRIV_AR, OWNER_PRIV_AR)); + op2Priv.put(HiveOperationType.ALTERTABLE_RENAMECOL, PrivRequirement.newIOPrivRequirement +(OWNER_PRIV_AR, OWNER_PRIV_AR)); + op2Priv.put(HiveOperationType.ALTERTABLE_RENAMEPART, PrivRequirement.newIOPrivRequirement +(OWNER_PRIV_AR, OWNER_PRIV_AR)); + op2Priv.put(HiveOperationType.ALTERTABLE_RENAME, PrivRequirement.newIOPrivRequirement +(OWNER_PRIV_AR, OWNER_PRIV_AR)); + op2Priv.put(HiveOperationType.ALTERTABLE_TOUCH, PrivRequirement.newIOPrivRequirement +(OWNER_PRIV_AR, OWNER_PRIV_AR)); + op2Priv.put(HiveOperationType.ALTERTABLE_ARCHIVE, PrivRequirement.newIOPrivRequirement +(OWNER_PRIV_AR, OWNER_PRIV_AR)); + op2Priv.put(HiveOperationType.ALTERTABLE_UNARCHIVE, PrivRequirement.newIOPrivRequirement +(OWNER_PRIV_AR, OWNER_PRIV_AR)); + op2Priv.put(HiveOperationType.ALTERTABLE_PROPERTIES, PrivRequirement.newIOPrivRequirement +(OWNER_PRIV_AR, OWNER_PRIV_AR)); + op2Priv.put(HiveOperationType.ALTERTABLE_SERIALIZER, PrivRequirement.newIOPrivRequirement +(OWNER_PRIV_AR, OWNER_PRIV_AR)); + op2Priv.put(HiveOperationType.ALTERTABLE_PARTCOLTYPE, PrivRequirement.newIOPrivRequirement +(OWNER_PRIV_AR, OWNER_PRIV_AR)); + op2Priv.put(HiveOperationType.ALTERPARTITION_SERIALIZER, PrivRequirement.newIOPrivRequirement +(OWNER_PRIV_AR, OWNER_PRIV_AR)); + op2Priv.put(HiveOperationType.ALTERTABLE_SERDEPROPERTIES, PrivRequirement.newIOPrivRequirement +(OWNER_PRIV_AR, OWNER_PRIV_AR)); + op2Priv.put(HiveOperationType.ALTERPARTITION_SERDEPROPERTIES, PrivRequirement.newIOPrivRequirement +(OWNER_PRIV_AR, OWNER_PRIV_AR)); + op2Priv.put(HiveOperationType.ALTERTABLE_CLUSTER_SORT, PrivRequirement.newIOPrivRequirement +(OWNER_PRIV_AR, OWNER_PRIV_AR)); + op2Priv.put(HiveOperationType.ALTERTABLE_BUCKETNUM, PrivRequirement.newIOPrivRequirement +(OWNER_PRIV_AR, OWNER_PRIV_AR)); + op2Priv.put(HiveOperationType.ALTERPARTITION_BUCKETNUM, PrivRequirement.newIOPrivRequirement +(OWNER_PRIV_AR, OWNER_PRIV_AR)); + op2Priv.put(HiveOperationType.ALTERTABLE_PROTECTMODE, PrivRequirement.newIOPrivRequirement +(OWNER_PRIV_AR, OWNER_PRIV_AR)); + op2Priv.put(HiveOperationType.ALTERPARTITION_PROTECTMODE, PrivRequirement.newIOPrivRequirement +(OWNER_PRIV_AR, OWNER_PRIV_AR)); + op2Priv.put(HiveOperationType.ALTERTABLE_FILEFORMAT, PrivRequirement.newIOPrivRequirement +(OWNER_PRIV_AR, OWNER_PRIV_AR)); + op2Priv.put(HiveOperationType.ALTERPARTITION_FILEFORMAT, PrivRequirement.newIOPrivRequirement +(OWNER_PRIV_AR, OWNER_PRIV_AR)); + op2Priv.put(HiveOperationType.ALTERTABLE_LOCATION, PrivRequirement.newIOPrivRequirement +(OWNER_PRIV_AR, OWNER_INS_SEL_DEL_NOGRANT_AR)); + op2Priv.put(HiveOperationType.ALTERPARTITION_LOCATION, PrivRequirement.newIOPrivRequirement +(OWNER_PRIV_AR, OWNER_INS_SEL_DEL_NOGRANT_AR)); + op2Priv.put(HiveOperationType.ALTERTABLE_MERGEFILES, PrivRequirement.newIOPrivRequirement +(OWNER_PRIV_AR, OWNER_PRIV_AR)); + op2Priv.put(HiveOperationType.ALTERPARTITION_MERGEFILES, PrivRequirement.newIOPrivRequirement +(OWNER_PRIV_AR, OWNER_PRIV_AR)); + op2Priv.put(HiveOperationType.ALTERTABLE_SKEWED, PrivRequirement.newIOPrivRequirement +(OWNER_PRIV_AR, OWNER_PRIV_AR)); + op2Priv.put(HiveOperationType.ALTERTBLPART_SKEWED_LOCATION, PrivRequirement.newIOPrivRequirement +(OWNER_PRIV_AR, OWNER_INS_SEL_DEL_NOGRANT_AR)); + op2Priv.put(HiveOperationType.ALTERTABLE_COMPACT, PrivRequirement.newIOPrivRequirement +(OWNER_PRIV_AR, OWNER_PRIV_AR)); + op2Priv.put(HiveOperationType.TRUNCATETABLE, PrivRequirement.newIOPrivRequirement +(OWNER_PRIV_AR, OWNER_PRIV_AR)); //table ownership for create/drop/alter index - op2Priv.put(HiveOperationType.CREATEINDEX, new InOutPrivs(OWNER_PRIV_AR, OWNER_INS_SEL_DEL_NOGRANT_AR)); - op2Priv.put(HiveOperationType.DROPINDEX, new InOutPrivs(OWNER_PRIV_AR, OWNER_PRIV_AR)); - op2Priv.put(HiveOperationType.ALTERINDEX_REBUILD, new InOutPrivs(OWNER_PRIV_AR, OWNER_PRIV_AR)); - op2Priv.put(HiveOperationType.ALTERINDEX_PROPS, new InOutPrivs(OWNER_PRIV_AR, OWNER_PRIV_AR)); + op2Priv.put(HiveOperationType.CREATEINDEX, PrivRequirement.newIOPrivRequirement +(OWNER_PRIV_AR, OWNER_INS_SEL_DEL_NOGRANT_AR)); + op2Priv.put(HiveOperationType.DROPINDEX, PrivRequirement.newIOPrivRequirement +(OWNER_PRIV_AR, OWNER_PRIV_AR)); + op2Priv.put(HiveOperationType.ALTERINDEX_REBUILD, PrivRequirement.newIOPrivRequirement +(OWNER_PRIV_AR, OWNER_PRIV_AR)); + op2Priv.put(HiveOperationType.ALTERINDEX_PROPS, PrivRequirement.newIOPrivRequirement +(OWNER_PRIV_AR, OWNER_PRIV_AR)); // require view ownership for alter/drop view - op2Priv.put(HiveOperationType.ALTERVIEW_PROPERTIES, new InOutPrivs(OWNER_PRIV_AR, OWNER_PRIV_AR)); - op2Priv.put(HiveOperationType.DROPVIEW_PROPERTIES, new InOutPrivs(OWNER_PRIV_AR, OWNER_PRIV_AR)); - op2Priv.put(HiveOperationType.ALTERVIEW_RENAME, new InOutPrivs(OWNER_PRIV_AR, OWNER_PRIV_AR)); - op2Priv.put(HiveOperationType.DROPVIEW, new InOutPrivs(OWNER_PRIV_AR, OWNER_PRIV_AR)); - - op2Priv.put(HiveOperationType.ANALYZE_TABLE, new InOutPrivs(arr(SQLPrivTypeGrant.SELECT_NOGRANT, SQLPrivTypeGrant.INSERT_NOGRANT), null)); - op2Priv.put(HiveOperationType.SHOWDATABASES, new InOutPrivs(null, null)); - op2Priv.put(HiveOperationType.SHOWTABLES, new InOutPrivs(null, null)); + op2Priv.put(HiveOperationType.ALTERVIEW_PROPERTIES, PrivRequirement.newIOPrivRequirement +(OWNER_PRIV_AR, OWNER_PRIV_AR)); + op2Priv.put(HiveOperationType.DROPVIEW_PROPERTIES, PrivRequirement.newIOPrivRequirement +(OWNER_PRIV_AR, OWNER_PRIV_AR)); + op2Priv.put(HiveOperationType.ALTERVIEW_RENAME, PrivRequirement.newIOPrivRequirement +(OWNER_PRIV_AR, OWNER_PRIV_AR)); + op2Priv.put(HiveOperationType.DROPVIEW, PrivRequirement.newIOPrivRequirement +(OWNER_PRIV_AR, OWNER_PRIV_AR)); + + op2Priv.put(HiveOperationType.ANALYZE_TABLE, PrivRequirement.newIOPrivRequirement +(arr(SQLPrivTypeGrant.SELECT_NOGRANT, SQLPrivTypeGrant.INSERT_NOGRANT), null)); + op2Priv.put(HiveOperationType.SHOWDATABASES, PrivRequirement.newIOPrivRequirement +(null, null)); + op2Priv.put(HiveOperationType.SHOWTABLES, PrivRequirement.newIOPrivRequirement +(null, null)); // operations that require insert/delete privileges - op2Priv.put(HiveOperationType.ALTERTABLE_DROPPARTS, new InOutPrivs(DEL_NOGRANT_AR, null)); + op2Priv.put(HiveOperationType.ALTERTABLE_DROPPARTS, PrivRequirement.newIOPrivRequirement +(DEL_NOGRANT_AR, null)); // in alter-table-add-partition, the table is output, and location is input - op2Priv.put(HiveOperationType.ALTERTABLE_ADDPARTS, new InOutPrivs(OWNER_INS_SEL_DEL_NOGRANT_AR, INS_NOGRANT_AR)); + op2Priv.put(HiveOperationType.ALTERTABLE_ADDPARTS, PrivRequirement.newIOPrivRequirement +(OWNER_INS_SEL_DEL_NOGRANT_AR, INS_NOGRANT_AR)); // select with grant for exporting contents - op2Priv.put(HiveOperationType.EXPORT, new InOutPrivs(SEL_GRANT_AR, null)); - op2Priv.put(HiveOperationType.IMPORT, new InOutPrivs(INS_NOGRANT_AR, null)); + op2Priv.put(HiveOperationType.EXPORT, PrivRequirement.newIOPrivRequirement +(SEL_GRANT_AR, null)); + op2Priv.put(HiveOperationType.IMPORT, PrivRequirement.newIOPrivRequirement +(INS_NOGRANT_AR, null)); // operations require select priv - op2Priv.put(HiveOperationType.SHOWCOLUMNS, new InOutPrivs(SEL_NOGRANT_AR, null)); - op2Priv.put(HiveOperationType.SHOW_TABLESTATUS, new InOutPrivs(SEL_NOGRANT_AR, null)); - op2Priv.put(HiveOperationType.SHOW_TBLPROPERTIES, new InOutPrivs(SEL_NOGRANT_AR, null)); - op2Priv.put(HiveOperationType.CREATETABLE_AS_SELECT, new InOutPrivs(SEL_NOGRANT_AR, null)); - - // QUERY,LOAD op can contain an insert & ovewrite, so require insert+delete privileges on output - op2Priv.put(HiveOperationType.QUERY, new InOutPrivs(SEL_NOGRANT_AR, - arr(SQLPrivTypeGrant.INSERT_NOGRANT, SQLPrivTypeGrant.DELETE_NOGRANT))); - - op2Priv.put(HiveOperationType.LOAD, new InOutPrivs(OWNER_INS_SEL_DEL_NOGRANT_AR, + op2Priv.put(HiveOperationType.SHOWCOLUMNS, PrivRequirement.newIOPrivRequirement +(SEL_NOGRANT_AR, null)); + op2Priv.put(HiveOperationType.SHOW_TABLESTATUS, PrivRequirement.newIOPrivRequirement +(SEL_NOGRANT_AR, null)); + op2Priv.put(HiveOperationType.SHOW_TBLPROPERTIES, PrivRequirement.newIOPrivRequirement +(SEL_NOGRANT_AR, null)); + op2Priv.put(HiveOperationType.CREATETABLE_AS_SELECT, PrivRequirement.newIOPrivRequirement +(SEL_NOGRANT_AR, null)); + + // QUERY,LOAD op can contain an insert & overwrite, + // require delete privilege if this is an insert-overwrite + op2Priv.put(HiveOperationType.QUERY, + arr( + new PrivRequirement(SEL_NOGRANT_AR, IOType.INPUT), + new PrivRequirement(INS_NOGRANT_AR, IOType.OUTPUT, null), + new PrivRequirement(DEL_NOGRANT_AR, IOType.OUTPUT, HivePrivObjectActionType.INSERT_OVERWRITE) + ) + ); + + op2Priv.put(HiveOperationType.LOAD, PrivRequirement.newIOPrivRequirement +(OWNER_INS_SEL_DEL_NOGRANT_AR, arr(SQLPrivTypeGrant.INSERT_NOGRANT, SQLPrivTypeGrant.DELETE_NOGRANT))); // show create table is more sensitive information, includes table properties etc // for now require select WITH GRANT - op2Priv.put(HiveOperationType.SHOW_CREATETABLE, new InOutPrivs(SEL_GRANT_AR, null)); + op2Priv.put(HiveOperationType.SHOW_CREATETABLE, PrivRequirement.newIOPrivRequirement +(SEL_GRANT_AR, null)); // for now allow only create-view with 'select with grant' // the owner will also have select with grant privileges on new view - op2Priv.put(HiveOperationType.CREATEVIEW, new InOutPrivs(SEL_GRANT_AR, null)); - - op2Priv.put(HiveOperationType.SHOWFUNCTIONS, new InOutPrivs(null, null)); - op2Priv.put(HiveOperationType.SHOWINDEXES, new InOutPrivs(null, null)); - op2Priv.put(HiveOperationType.SHOWLOCKS, new InOutPrivs(null, null)); - op2Priv.put(HiveOperationType.CREATEFUNCTION, new InOutPrivs(null, ADMIN_PRIV_AR)); - op2Priv.put(HiveOperationType.DROPFUNCTION, new InOutPrivs(null, ADMIN_PRIV_AR)); - op2Priv.put(HiveOperationType.CREATEMACRO, new InOutPrivs(null, ADMIN_PRIV_AR)); - op2Priv.put(HiveOperationType.DROPMACRO, new InOutPrivs(null, ADMIN_PRIV_AR)); - op2Priv.put(HiveOperationType.SHOW_COMPACTIONS, new InOutPrivs(null, null)); - op2Priv.put(HiveOperationType.SHOW_TRANSACTIONS, new InOutPrivs(null, null)); - - op2Priv.put(HiveOperationType.LOCKTABLE, new InOutPrivs(null, null)); - op2Priv.put(HiveOperationType.UNLOCKTABLE, new InOutPrivs(null, null)); + op2Priv.put(HiveOperationType.CREATEVIEW, PrivRequirement.newIOPrivRequirement +(SEL_GRANT_AR, null)); + + op2Priv.put(HiveOperationType.SHOWFUNCTIONS, PrivRequirement.newIOPrivRequirement +(null, null)); + op2Priv.put(HiveOperationType.SHOWINDEXES, PrivRequirement.newIOPrivRequirement +(null, null)); + op2Priv.put(HiveOperationType.SHOWLOCKS, PrivRequirement.newIOPrivRequirement +(null, null)); + op2Priv.put(HiveOperationType.CREATEFUNCTION, PrivRequirement.newIOPrivRequirement +(null, ADMIN_PRIV_AR)); + op2Priv.put(HiveOperationType.DROPFUNCTION, PrivRequirement.newIOPrivRequirement +(null, ADMIN_PRIV_AR)); + op2Priv.put(HiveOperationType.CREATEMACRO, PrivRequirement.newIOPrivRequirement +(null, ADMIN_PRIV_AR)); + op2Priv.put(HiveOperationType.DROPMACRO, PrivRequirement.newIOPrivRequirement +(null, ADMIN_PRIV_AR)); + op2Priv.put(HiveOperationType.SHOW_COMPACTIONS, PrivRequirement.newIOPrivRequirement +(null, null)); + op2Priv.put(HiveOperationType.SHOW_TRANSACTIONS, PrivRequirement.newIOPrivRequirement +(null, null)); + + op2Priv.put(HiveOperationType.LOCKTABLE, PrivRequirement.newIOPrivRequirement +(null, null)); + op2Priv.put(HiveOperationType.UNLOCKTABLE, PrivRequirement.newIOPrivRequirement +(null, null)); // require db ownership, if there is a file require SELECT , INSERT, and DELETE op2Priv.put(HiveOperationType.CREATETABLE, - new InOutPrivs(OWNER_INS_SEL_DEL_NOGRANT_AR, OWNER_PRIV_AR)); + PrivRequirement.newIOPrivRequirement +(OWNER_INS_SEL_DEL_NOGRANT_AR, OWNER_PRIV_AR)); - op2Priv.put(HiveOperationType.ALTERDATABASE, new InOutPrivs(null, ADMIN_PRIV_AR)); - op2Priv.put(HiveOperationType.ALTERDATABASE_OWNER, new InOutPrivs(null, ADMIN_PRIV_AR)); - op2Priv.put(HiveOperationType.DESCDATABASE, new InOutPrivs(null, null)); + op2Priv.put(HiveOperationType.ALTERDATABASE, PrivRequirement.newIOPrivRequirement +(null, ADMIN_PRIV_AR)); + op2Priv.put(HiveOperationType.ALTERDATABASE_OWNER, PrivRequirement.newIOPrivRequirement +(null, ADMIN_PRIV_AR)); + op2Priv.put(HiveOperationType.DESCDATABASE, PrivRequirement.newIOPrivRequirement +(null, null)); // The following actions are authorized through SQLStdHiveAccessController, // and it is not using this privilege mapping, but it might make sense to move it here - op2Priv.put(HiveOperationType.CREATEROLE, new InOutPrivs(null, null)); - op2Priv.put(HiveOperationType.DROPROLE, new InOutPrivs(null, null)); - op2Priv.put(HiveOperationType.GRANT_PRIVILEGE, new InOutPrivs(null, + op2Priv.put(HiveOperationType.CREATEROLE, PrivRequirement.newIOPrivRequirement +(null, null)); + op2Priv.put(HiveOperationType.DROPROLE, PrivRequirement.newIOPrivRequirement +(null, null)); + op2Priv.put(HiveOperationType.GRANT_PRIVILEGE, PrivRequirement.newIOPrivRequirement +(null, null)); - op2Priv.put(HiveOperationType.REVOKE_PRIVILEGE, new InOutPrivs(null, + op2Priv.put(HiveOperationType.REVOKE_PRIVILEGE, PrivRequirement.newIOPrivRequirement +(null, null)); - op2Priv.put(HiveOperationType.SHOW_GRANT, new InOutPrivs(null, null)); - op2Priv.put(HiveOperationType.GRANT_ROLE, new InOutPrivs(null, null)); - op2Priv.put(HiveOperationType.REVOKE_ROLE, new InOutPrivs(null, null)); - op2Priv.put(HiveOperationType.SHOW_ROLES, new InOutPrivs(null, null)); - op2Priv.put(HiveOperationType.SHOW_ROLE_GRANT, new InOutPrivs(null, + op2Priv.put(HiveOperationType.SHOW_GRANT, PrivRequirement.newIOPrivRequirement +(null, null)); + op2Priv.put(HiveOperationType.GRANT_ROLE, PrivRequirement.newIOPrivRequirement +(null, null)); + op2Priv.put(HiveOperationType.REVOKE_ROLE, PrivRequirement.newIOPrivRequirement +(null, null)); + op2Priv.put(HiveOperationType.SHOW_ROLES, PrivRequirement.newIOPrivRequirement +(null, null)); + op2Priv.put(HiveOperationType.SHOW_ROLE_GRANT, PrivRequirement.newIOPrivRequirement +(null, null)); - op2Priv.put(HiveOperationType.SHOW_ROLE_PRINCIPALS, new InOutPrivs(null, + op2Priv.put(HiveOperationType.SHOW_ROLE_PRINCIPALS, PrivRequirement.newIOPrivRequirement +(null, null)); } /** - * Convenience method so that creation of this array in InOutPrivs constructor + * Convenience method so that creation of this array in PrivRequirement constructor * is not too verbose * * @param grantList @@ -219,12 +350,47 @@ return grantList; } - public static SQLPrivTypeGrant[] getInputPrivs(HiveOperationType opType) { - return op2Priv.get(opType).getInputPrivs(); + /** + * Convenience method so that creation of list of PrivRequirement is not too verbose + * @param privReqList + * @return + */ + private static List arr(PrivRequirement... privReqList){ + return Arrays.asList(privReqList); } - public static SQLPrivTypeGrant[] getOutputPrivs(HiveOperationType opType) { - return op2Priv.get(opType).getOutputPrivs(); + /** + * Get the privileges required for this operation on hive object when it is + * IOType + * + * @param hiveOpType + * @param hObj + * @param ioType + * @return + */ + public static RequiredPrivileges getRequiredPrivs(HiveOperationType hiveOpType, + HivePrivilegeObject hObj, IOType ioType) { + List opPrivs = op2Priv.get(hiveOpType); + RequiredPrivileges reqPrivs = new RequiredPrivileges(); + + // Find the PrivRequirements that match on IOType and ActionType, and add + // the privilege + // required to reqPrivs + for (PrivRequirement opPriv : opPrivs) { + if (opPriv.getIOType() != ioType) { + continue; + } + if (opPriv.getActionType() != null) { + // if action type is specified, the action type of the hive object has + // to match + if (hObj.getActionType() != opPriv.getActionType()) { + continue; + } + } + reqPrivs.addAll(opPriv.getReqPrivs()); + } + + return reqPrivs; } // for unit tests 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 229c063..8937cfa 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 @@ -35,6 +35,7 @@ import org.apache.hadoop.hive.ql.security.authorization.plugin.HivePrincipal.HivePrincipalType; import org.apache.hadoop.hive.ql.security.authorization.plugin.HivePrivilegeObject; import org.apache.hadoop.hive.ql.security.authorization.plugin.HivePrivilegeObject.HivePrivilegeObjectType; +import org.apache.hadoop.hive.ql.security.authorization.plugin.sqlstd.Operation2Privilege.IOType; public class SQLStdHiveAuthorizationValidator implements HiveAuthorizationValidator { @@ -56,57 +57,58 @@ public SQLStdHiveAuthorizationValidator(HiveMetastoreClientFactory metastoreClie @Override public void checkPrivileges(HiveOperationType hiveOpType, List inputHObjs, - List outputHObjs) throws HiveAuthzPluginException, HiveAccessControlException { + List outputHObjs) throws HiveAuthzPluginException, + HiveAccessControlException { - if(LOG.isDebugEnabled()){ + if (LOG.isDebugEnabled()) { String msg = "Checking privileges for operation " + hiveOpType + " by user " - + authenticator.getUserName() + " on " + " input objects " + inputHObjs - + " and output objects " + outputHObjs; + + authenticator.getUserName() + " on " + " input objects " + inputHObjs + + " and output objects " + outputHObjs; LOG.debug(msg); } String userName = authenticator.getUserName(); IMetaStoreClient metastoreClient = metastoreClientFactory.getHiveMetastoreClient(); - // get privileges required on input and check - SQLPrivTypeGrant[] inputPrivs = Operation2Privilege.getInputPrivs(hiveOpType); - checkPrivileges(inputPrivs, inputHObjs, metastoreClient, userName); - - // get privileges required on input and check - SQLPrivTypeGrant[] outputPrivs = Operation2Privilege.getOutputPrivs(hiveOpType); - checkPrivileges(outputPrivs, outputHObjs, metastoreClient, userName); + // check privileges on input and output objects + checkPrivileges(hiveOpType, inputHObjs, metastoreClient, userName, IOType.INPUT); + checkPrivileges(hiveOpType, outputHObjs, metastoreClient, userName, IOType.OUTPUT); } - private void checkPrivileges(SQLPrivTypeGrant[] reqPrivs, List hObjs, - IMetaStoreClient metastoreClient, String userName) throws HiveAuthzPluginException, - HiveAccessControlException { - RequiredPrivileges requiredInpPrivs = new RequiredPrivileges(); - requiredInpPrivs.addAll(reqPrivs); - - // check if this user has these privileges on the objects - for (HivePrivilegeObject hObj : hObjs) { - RequiredPrivileges availPrivs = null; - if (hObj.getType() == HivePrivilegeObjectType.LOCAL_URI - || hObj.getType() == HivePrivilegeObjectType.DFS_URI) { - availPrivs = SQLAuthorizationUtils.getPrivilegesFromFS(new Path(hObj.getTableViewURI()), - conf, userName); + private void checkPrivileges(HiveOperationType hiveOpType, List hiveObjects, + IMetaStoreClient metastoreClient, String userName, IOType ioType) + throws HiveAuthzPluginException, HiveAccessControlException { + + // Compare required privileges and available privileges for each hive object + for (HivePrivilegeObject hiveObj : hiveObjects) { - } else if (hObj.getType() == HivePrivilegeObjectType.PARTITION) { + RequiredPrivileges requiredPrivs = Operation2Privilege.getRequiredPrivs(hiveOpType, hiveObj, + ioType); + + // find available privileges + RequiredPrivileges availPrivs; + if (hiveObj.getType() == HivePrivilegeObjectType.LOCAL_URI + || hiveObj.getType() == HivePrivilegeObjectType.DFS_URI) { + availPrivs = SQLAuthorizationUtils.getPrivilegesFromFS(new Path(hiveObj.getTableViewURI()), + conf, userName); + } else if (hiveObj.getType() == HivePrivilegeObjectType.PARTITION) { // sql std authorization is managing privileges at the table/view levels // only // ignore partitions + continue; } else { // get the privileges that this user has on the object availPrivs = SQLAuthorizationUtils.getPrivilegesFromMetaStore(metastoreClient, userName, - hObj, privController.getCurrentRoleNames(), privController.isUserAdmin()); + hiveObj, privController.getCurrentRoleNames(), privController.isUserAdmin()); } - Collection missingPriv = requiredInpPrivs.findMissingPrivs(availPrivs); + + // Verify that there are no missing privileges + Collection missingPriv = requiredPrivs.findMissingPrivs(availPrivs); SQLAuthorizationUtils.assertNoMissingPrivilege(missingPriv, new HivePrincipal(userName, - HivePrincipalType.USER), hObj); + HivePrincipalType.USER), hiveObj); } } - } diff --git a/ql/src/test/queries/clientnegative/authorization_insertoverwrite_nodel.q b/ql/src/test/queries/clientnegative/authorization_insertoverwrite_nodel.q new file mode 100644 index 0000000..417c879 --- /dev/null +++ b/ql/src/test/queries/clientnegative/authorization_insertoverwrite_nodel.q @@ -0,0 +1,12 @@ +set hive.security.authorization.manager=org.apache.hadoop.hive.ql.security.authorization.plugin.sqlstd.SQLStdHiveAuthorizerFactoryForTest; +set hive.security.authenticator.manager=org.apache.hadoop.hive.ql.security.SessionStateConfigUserAuthenticator; +set hive.security.authorization.enabled=true; + +-- check insert overwrite without delete priv +create table t1(i int); +grant insert on table t1 to user user1; +show grant on table t1; + +set user.name=user1; +create table user1tab(i int); +insert overwrite table t1 select * from user1tab; diff --git a/ql/src/test/queries/clientpositive/authorization_insert.q b/ql/src/test/queries/clientpositive/authorization_insert.q new file mode 100644 index 0000000..5de6f50 --- /dev/null +++ b/ql/src/test/queries/clientpositive/authorization_insert.q @@ -0,0 +1,22 @@ +set hive.security.authorization.manager=org.apache.hadoop.hive.ql.security.authorization.plugin.sqlstd.SQLStdHiveAuthorizerFactoryForTest; +set hive.security.authenticator.manager=org.apache.hadoop.hive.ql.security.SessionStateConfigUserAuthenticator; + +set user.name=user1; +-- current user has been set (comment line before the set cmd is resulting in parse error!!) + +CREATE TABLE t_auth_ins(i int); + +CREATE TABLE t_select(i int); +GRANT ALL ON TABLE t_select TO ROLE public; + +-- grant insert privilege to another user +GRANT INSERT ON t_auth_ins TO USER userWIns; +GRANT INSERT,DELETE ON t_auth_ins TO USER userWInsAndDel; +SHOW GRANT ON TABLE t_auth_ins; + + +set user.name=userWIns; +INSERT INTO TABLE t_auth_ins SELECT * from t_select; + +set user.name=userWInsAndDel; +INSERT OVERWRITE TABLE t_auth_ins SELECT * from t_select; diff --git a/ql/src/test/results/clientnegative/authorization_insertoverwrite_nodel.q.out b/ql/src/test/results/clientnegative/authorization_insertoverwrite_nodel.q.out new file mode 100644 index 0000000..21ad8d8 --- /dev/null +++ b/ql/src/test/results/clientnegative/authorization_insertoverwrite_nodel.q.out @@ -0,0 +1,32 @@ +PREHOOK: query: -- check insert overwrite without delete priv +create table t1(i int) +PREHOOK: type: CREATETABLE +PREHOOK: Output: database:default +POSTHOOK: query: -- check insert overwrite without delete priv +create table t1(i int) +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: database:default +POSTHOOK: Output: default@t1 +PREHOOK: query: grant insert on table t1 to user user1 +PREHOOK: type: GRANT_PRIVILEGE +PREHOOK: Output: default@t1 +POSTHOOK: query: grant insert on table t1 to user user1 +POSTHOOK: type: GRANT_PRIVILEGE +POSTHOOK: Output: default@t1 +PREHOOK: query: show grant on table t1 +PREHOOK: type: SHOW_GRANT +POSTHOOK: query: show grant on table t1 +POSTHOOK: type: SHOW_GRANT +default t1 thejas USER DELETE true -1 thejas +default t1 thejas USER INSERT true -1 thejas +default t1 thejas USER SELECT true -1 thejas +default t1 thejas USER UPDATE true -1 thejas +default t1 user1 USER INSERT false -1 thejas +PREHOOK: query: create table user1tab(i int) +PREHOOK: type: CREATETABLE +PREHOOK: Output: database:default +POSTHOOK: query: create table user1tab(i int) +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: database:default +POSTHOOK: Output: default@user1tab +FAILED: HiveAccessControlException Permission denied. Principal [name=user1, type=USER] does not have following privileges on Object [type=TABLE_OR_VIEW, name=default.t1] : [DELETE] diff --git a/ql/src/test/results/clientpositive/authorization_insert.q.out b/ql/src/test/results/clientpositive/authorization_insert.q.out new file mode 100644 index 0000000..a4c9365 --- /dev/null +++ b/ql/src/test/results/clientpositive/authorization_insert.q.out @@ -0,0 +1,68 @@ +PREHOOK: query: -- current user has been set (comment line before the set cmd is resulting in parse error!!) + +CREATE TABLE t_auth_ins(i int) +PREHOOK: type: CREATETABLE +PREHOOK: Output: database:default +POSTHOOK: query: -- current user has been set (comment line before the set cmd is resulting in parse error!!) + +CREATE TABLE t_auth_ins(i int) +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: database:default +POSTHOOK: Output: default@t_auth_ins +PREHOOK: query: CREATE TABLE t_select(i int) +PREHOOK: type: CREATETABLE +PREHOOK: Output: database:default +POSTHOOK: query: CREATE TABLE t_select(i int) +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: database:default +POSTHOOK: Output: default@t_select +PREHOOK: query: GRANT ALL ON TABLE t_select TO ROLE public +PREHOOK: type: GRANT_PRIVILEGE +PREHOOK: Output: default@t_select +POSTHOOK: query: GRANT ALL ON TABLE t_select TO ROLE public +POSTHOOK: type: GRANT_PRIVILEGE +POSTHOOK: Output: default@t_select +PREHOOK: query: -- grant insert privilege to another user +GRANT INSERT ON t_auth_ins TO USER userWIns +PREHOOK: type: GRANT_PRIVILEGE +PREHOOK: Output: default@t_auth_ins +POSTHOOK: query: -- grant insert privilege to another user +GRANT INSERT ON t_auth_ins TO USER userWIns +POSTHOOK: type: GRANT_PRIVILEGE +POSTHOOK: Output: default@t_auth_ins +PREHOOK: query: GRANT INSERT,DELETE ON t_auth_ins TO USER userWInsAndDel +PREHOOK: type: GRANT_PRIVILEGE +PREHOOK: Output: default@t_auth_ins +POSTHOOK: query: GRANT INSERT,DELETE ON t_auth_ins TO USER userWInsAndDel +POSTHOOK: type: GRANT_PRIVILEGE +POSTHOOK: Output: default@t_auth_ins +PREHOOK: query: SHOW GRANT ON TABLE t_auth_ins +PREHOOK: type: SHOW_GRANT +POSTHOOK: query: SHOW GRANT ON TABLE t_auth_ins +POSTHOOK: type: SHOW_GRANT +default t_auth_ins user1 USER DELETE true -1 user1 +default t_auth_ins user1 USER INSERT true -1 user1 +default t_auth_ins user1 USER SELECT true -1 user1 +default t_auth_ins user1 USER UPDATE true -1 user1 +default t_auth_ins userWIns USER INSERT false -1 user1 +default t_auth_ins userWInsAndDel USER DELETE false -1 user1 +default t_auth_ins userWInsAndDel USER INSERT false -1 user1 +PREHOOK: query: INSERT INTO TABLE t_auth_ins SELECT * from t_select +PREHOOK: type: QUERY +PREHOOK: Input: default@t_select +PREHOOK: Output: default@t_auth_ins +POSTHOOK: query: INSERT INTO TABLE t_auth_ins SELECT * from t_select +POSTHOOK: type: QUERY +POSTHOOK: Input: default@t_select +POSTHOOK: Output: default@t_auth_ins +POSTHOOK: Lineage: t_auth_ins.i SIMPLE [(t_select)t_select.FieldSchema(name:i, type:int, comment:null), ] +PREHOOK: query: INSERT OVERWRITE TABLE t_auth_ins SELECT * from t_select +PREHOOK: type: QUERY +PREHOOK: Input: default@t_select +PREHOOK: Output: default@t_auth_ins +POSTHOOK: query: INSERT OVERWRITE TABLE t_auth_ins SELECT * from t_select +POSTHOOK: type: QUERY +POSTHOOK: Input: default@t_select +POSTHOOK: Output: default@t_auth_ins +POSTHOOK: Lineage: t_auth_ins.i SIMPLE [(t_select)t_select.FieldSchema(name:i, type:int, comment:null), ] +POSTHOOK: Lineage: t_auth_ins.i SIMPLE [(t_select)t_select.FieldSchema(name:i, type:int, comment:null), ]