/** * Get Authorizable from inputs and put into inputHierarchy * * @param inputHierarchy * @param entity * @param sentryContext */ private void getInputHierarchyFromInputs( List<List<DBModelAuthorizable>> inputHierarchy, Set<ReadEntity> inputs) { for (ReadEntity readEntity : inputs) { // skip the tables/view that are part of expanded view definition // skip the Hive generated dummy entities created for queries like 'select <expr>' if (isChildTabForView(readEntity) || isDummyEntity(readEntity)) { continue; } if (readEntity.getAccessedColumns() != null && !readEntity.getAccessedColumns().isEmpty()) { addColumnHierarchy(inputHierarchy, readEntity); } else { List<DBModelAuthorizable> entityHierarchy = new ArrayList<DBModelAuthorizable>(); entityHierarchy.add(hiveAuthzBinding.getAuthServer()); entityHierarchy.addAll(getAuthzHierarchyFromEntity(readEntity)); inputHierarchy.add(entityHierarchy); } } }
/** * Add column level hierarchy to inputHierarchy * * @param inputHierarchy * @param entity * @param sentryContext */ private void addColumnHierarchy( List<List<DBModelAuthorizable>> inputHierarchy, ReadEntity entity) { List<DBModelAuthorizable> entityHierarchy = new ArrayList<DBModelAuthorizable>(); entityHierarchy.add(hiveAuthzBinding.getAuthServer()); entityHierarchy.addAll(getAuthzHierarchyFromEntity(entity)); switch (entity.getType()) { case TABLE: case PARTITION: List<String> cols = entity.getAccessedColumns(); for (String col : cols) { List<DBModelAuthorizable> colHierarchy = new ArrayList<DBModelAuthorizable>(entityHierarchy); colHierarchy.add(new Column(col)); inputHierarchy.add(colHierarchy); } break; default: inputHierarchy.add(entityHierarchy); } }
/** * Convert the input/output entities into authorizables. generate authorizables for cases like * Database and metadata operations where the compiler doesn't capture entities. invoke the hive * binding to validate permissions * * @param context * @param stmtAuthObject * @param stmtOperation * @throws AuthorizationException */ private void authorizeWithHiveBindings( HiveSemanticAnalyzerHookContext context, HiveAuthzPrivileges stmtAuthObject, HiveOperation stmtOperation) throws AuthorizationException { Set<ReadEntity> inputs = context.getInputs(); Set<WriteEntity> outputs = context.getOutputs(); List<List<DBModelAuthorizable>> inputHierarchy = new ArrayList<List<DBModelAuthorizable>>(); List<List<DBModelAuthorizable>> outputHierarchy = new ArrayList<List<DBModelAuthorizable>>(); if (LOG.isDebugEnabled()) { LOG.debug("stmtAuthObject.getOperationScope() = " + stmtAuthObject.getOperationScope()); LOG.debug("context.getInputs() = " + context.getInputs()); LOG.debug("context.getOutputs() = " + context.getOutputs()); } // Workaround to allow DESCRIBE <table> to be executed with only column-level privileges, while // still authorizing DESCRIBE [EXTENDED|FORMATTED] as table-level. // This is done by treating DESCRIBE <table> the same as SHOW COLUMNS, which only requires // column // level privs. if (isDescTableBasic) { stmtAuthObject = HiveAuthzPrivilegesMap.getHiveAuthzPrivileges(HiveOperation.SHOWCOLUMNS); } switch (stmtAuthObject.getOperationScope()) { case SERVER: // validate server level privileges if applicable. Eg create UDF,register jar etc .. List<DBModelAuthorizable> serverHierarchy = new ArrayList<DBModelAuthorizable>(); serverHierarchy.add(hiveAuthzBinding.getAuthServer()); inputHierarchy.add(serverHierarchy); break; case DATABASE: // workaround for database scope statements (create/alter/drop db) List<DBModelAuthorizable> dbHierarchy = new ArrayList<DBModelAuthorizable>(); dbHierarchy.add(hiveAuthzBinding.getAuthServer()); dbHierarchy.add(currDB); inputHierarchy.add(dbHierarchy); outputHierarchy.add(dbHierarchy); getInputHierarchyFromInputs(inputHierarchy, inputs); break; case TABLE: // workaround for add partitions if (partitionURI != null) { inputHierarchy.add(ImmutableList.of(hiveAuthzBinding.getAuthServer(), partitionURI)); } getInputHierarchyFromInputs(inputHierarchy, inputs); for (WriteEntity writeEntity : outputs) { if (filterWriteEntity(writeEntity)) { continue; } List<DBModelAuthorizable> entityHierarchy = new ArrayList<DBModelAuthorizable>(); entityHierarchy.add(hiveAuthzBinding.getAuthServer()); entityHierarchy.addAll(getAuthzHierarchyFromEntity(writeEntity)); outputHierarchy.add(entityHierarchy); } // workaround for metadata queries. // Capture the table name in pre-analyze and include that in the input entity list if (currTab != null) { List<DBModelAuthorizable> externalAuthorizableHierarchy = new ArrayList<DBModelAuthorizable>(); externalAuthorizableHierarchy.add(hiveAuthzBinding.getAuthServer()); externalAuthorizableHierarchy.add(currDB); externalAuthorizableHierarchy.add(currTab); inputHierarchy.add(externalAuthorizableHierarchy); } // workaround for DDL statements // Capture the table name in pre-analyze and include that in the output entity list if (currOutTab != null) { List<DBModelAuthorizable> externalAuthorizableHierarchy = new ArrayList<DBModelAuthorizable>(); externalAuthorizableHierarchy.add(hiveAuthzBinding.getAuthServer()); externalAuthorizableHierarchy.add(currOutDB); externalAuthorizableHierarchy.add(currOutTab); outputHierarchy.add(externalAuthorizableHierarchy); } break; case FUNCTION: /* The 'FUNCTION' privilege scope currently used for * - CREATE TEMP FUNCTION * - DROP TEMP FUNCTION. */ if (udfURI != null) { List<DBModelAuthorizable> udfUriHierarchy = new ArrayList<DBModelAuthorizable>(); udfUriHierarchy.add(hiveAuthzBinding.getAuthServer()); udfUriHierarchy.add(udfURI); inputHierarchy.add(udfUriHierarchy); for (WriteEntity writeEntity : outputs) { List<DBModelAuthorizable> entityHierarchy = new ArrayList<DBModelAuthorizable>(); entityHierarchy.add(hiveAuthzBinding.getAuthServer()); entityHierarchy.addAll(getAuthzHierarchyFromEntity(writeEntity)); outputHierarchy.add(entityHierarchy); } } break; case CONNECT: /* The 'CONNECT' is an implicit privilege scope currently used for * - USE <db> * It's allowed when the user has any privilege on the current database. For application * backward compatibility, we allow (optional) implicit connect permission on 'default' db. */ List<DBModelAuthorizable> connectHierarchy = new ArrayList<DBModelAuthorizable>(); connectHierarchy.add(hiveAuthzBinding.getAuthServer()); // by default allow connect access to default db Table currTbl = Table.ALL; Column currCol = Column.ALL; if (DEFAULT_DATABASE_NAME.equalsIgnoreCase(currDB.getName()) && "false" .equalsIgnoreCase( authzConf.get( HiveAuthzConf.AuthzConfVars.AUTHZ_RESTRICT_DEFAULT_DB.getVar(), "false"))) { currDB = Database.ALL; currTbl = Table.SOME; } connectHierarchy.add(currDB); connectHierarchy.add(currTbl); connectHierarchy.add(currCol); inputHierarchy.add(connectHierarchy); outputHierarchy.add(connectHierarchy); break; case COLUMN: for (ReadEntity readEntity : inputs) { if (readEntity.getAccessedColumns() != null && !readEntity.getAccessedColumns().isEmpty()) { addColumnHierarchy(inputHierarchy, readEntity); } else { List<DBModelAuthorizable> entityHierarchy = new ArrayList<DBModelAuthorizable>(); entityHierarchy.add(hiveAuthzBinding.getAuthServer()); entityHierarchy.addAll(getAuthzHierarchyFromEntity(readEntity)); entityHierarchy.add(Column.ALL); inputHierarchy.add(entityHierarchy); } } break; default: throw new AuthorizationException( "Unknown operation scope type " + stmtAuthObject.getOperationScope().toString()); } HiveAuthzBinding binding = null; try { binding = getHiveBindingWithPrivilegeCache(hiveAuthzBinding, context.getUserName()); } catch (SemanticException e) { // Will use the original hiveAuthzBinding binding = hiveAuthzBinding; } // validate permission binding.authorize( stmtOperation, stmtAuthObject, getCurrentSubject(context), inputHierarchy, outputHierarchy); }