HAWQ-1001. Implement HAWQ basic user ACL check through Ranger.
Project: http://git-wip-us.apache.org/repos/asf/incubator-hawq/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-hawq/commit/a5a02b19 Tree: http://git-wip-us.apache.org/repos/asf/incubator-hawq/tree/a5a02b19 Diff: http://git-wip-us.apache.org/repos/asf/incubator-hawq/diff/a5a02b19 Branch: refs/heads/ran5 Commit: a5a02b197998261eed364b7c22c77b7da6afd3b0 Parents: ca9f649 Author: hzhang2 <zhanghuan...@163.com> Authored: Mon Dec 12 14:46:38 2016 +0800 Committer: hzhang2 <zhanghuan...@163.com> Committed: Mon Dec 12 14:46:38 2016 +0800 ---------------------------------------------------------------------- src/backend/catalog/aclchk.c | 733 +++++++++++++++++++++++++++++-- src/backend/parser/parse_relation.c | 126 +++++- src/include/parser/parse_relation.h | 1 + src/include/utils/acl.h | 59 +++ 4 files changed, 857 insertions(+), 62 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/a5a02b19/src/backend/catalog/aclchk.c ---------------------------------------------------------------------- diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c index 3fa616f..a633d60 100644 --- a/src/backend/catalog/aclchk.c +++ b/src/backend/catalog/aclchk.c @@ -25,6 +25,7 @@ #include "catalog/catalog.h" #include "catalog/catquery.h" #include "catalog/dependency.h" + #include "catalog/indexing.h" #include "catalog/gp_persistent.h" #include "catalog/pg_authid.h" @@ -59,7 +60,7 @@ #include "cdb/cdbdisp.h" #include "cdb/dispatcher.h" - +#define ACTION_LENGTH 12 static void ExecGrant_Relation(InternalGrant *grantStmt); static void ExecGrant_Database(InternalGrant *grantStmt); static void ExecGrant_Fdw(InternalGrant *grantStmt); @@ -225,10 +226,18 @@ restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs, */ if (avail_goptions == ACL_NO_RIGHTS) { - if (pg_aclmask(objkind, objectId, grantorId, - whole_mask | ACL_GRANT_OPTION_FOR(whole_mask), - ACLMASK_ANY) == ACL_NO_RIGHTS) - aclcheck_error(ACLCHECK_NO_PRIV, objkind, objname); + if (enable_ranger && !fallBackToNativeCheck(objkind, objectId, grantorId)) { + if (pg_rangercheck(objkind, objectId, grantorId, + whole_mask | ACL_GRANT_OPTION_FOR(whole_mask), + ACLMASK_ANY) != ACLCHECK_OK) + aclcheck_error(ACLCHECK_NO_PRIV, objkind, objname); + } + else { + if (pg_aclmask(objkind, objectId, grantorId, + whole_mask | ACL_GRANT_OPTION_FOR(whole_mask), + ACLMASK_ANY) == ACL_NO_RIGHTS) + aclcheck_error(ACLCHECK_NO_PRIV, objkind, objname); + } } /* @@ -2240,6 +2249,471 @@ has_rolcatupdate(Oid roleid) return rolcatupdate; } +char *getRoleName(Oid role_id) +{ + Assert(OidIsValid(role_id)); + int fetchCount; + char* role_name = caql_getcstring_plus( + NULL, + &fetchCount, + NULL, + cql("SELECT rolname FROM pg_authid " + " WHERE oid = :1 ", + ObjectIdGetDatum(role_id))); + + if (role_name == NULL) + elog(ERROR, "oid [%u] not found in table pg_authid", role_id); + return role_name; +} + +char *getClassNameFromOid(Oid object_oid) +{ + StringInfoData tname; + initStringInfo(&tname); + + Assert(OidIsValid(object_oid)); + char* rel_name = caql_getcstring( + NULL, + cql("SELECT relname FROM pg_class " + " WHERE oid = :1", + ObjectIdGetDatum(object_oid))); + if (rel_name == NULL) + elog(ERROR, "oid [%u] not found in table pg_class", object_oid); + + int fetchCount=0; + Oid schema_name_oid = caql_getoid_plus( + NULL, + &fetchCount, + NULL, + cql("SELECT relnamespace FROM pg_class " + " WHERE oid = :1", + ObjectIdGetDatum(object_oid))); + if (schema_name_oid == InvalidOid) + elog(ERROR, "oid [%u] not found in table pg_class", object_oid); + + char* schema_name= caql_getcstring( + NULL, + cql("select nspname from pg_namespace " + " WHERE oid = :1", + ObjectIdGetDatum(schema_name_oid))); + if (schema_name == NULL) + elog(ERROR, "oid [%u] not found in table pg_namespace", object_oid); + + char* database_name = get_database_name(MyDatabaseId); + if (database_name == NULL) + elog(ERROR, "oid [%u] not found current database", object_oid); + + appendStringInfo(&tname, database_name); + appendStringInfo(&tname, "."); + appendStringInfo(&tname, schema_name); + appendStringInfo(&tname, "."); + appendStringInfo(&tname, rel_name); + pfree(rel_name); + pfree(schema_name); + pfree(database_name); + + return tname.data; +} + +char *getSequenceNameFromOid(Oid object_oid) +{ + StringInfoData tname; + initStringInfo(&tname); + + Assert(OidIsValid(object_oid)); + char* seq_name = caql_getcstring( + NULL, + cql("SELECT relname FROM pg_class " + " WHERE oid = :1", + ObjectIdGetDatum(object_oid))); + if (seq_name == NULL) + elog(ERROR, "oid [%u] not found in table pg_class", object_oid); + + int fetchCount=0; + Oid schema_name_oid = caql_getoid_plus( + NULL, + &fetchCount, + NULL, + cql("SELECT relnamespace FROM pg_class " + " WHERE oid = :1", + ObjectIdGetDatum(object_oid))); + if (schema_name_oid == InvalidOid) + elog(ERROR, "oid [%u] not found in table pg_class", object_oid); + + char* schema_name= caql_getcstring( + NULL, + cql("select nspname from pg_namespace " + " WHERE oid = :1", + ObjectIdGetDatum(schema_name_oid))); + if (schema_name == NULL) + elog(ERROR, "oid [%u] not found in table pg_namespace", object_oid); + + char* database_name = get_database_name(MyDatabaseId); + if (database_name == NULL) + elog(ERROR, "oid [%u] not found current database", object_oid); + + appendStringInfo(&tname, database_name); + appendStringInfo(&tname, "."); + appendStringInfo(&tname, schema_name); + appendStringInfo(&tname, "."); + appendStringInfo(&tname, seq_name); + pfree(seq_name); + pfree(schema_name); + pfree(database_name); + + return tname.data; +} +char *getDatabaseNameFromOid(Oid object_oid) +{ + Assert(OidIsValid(object_oid)); + char* dbname = caql_getcstring( + NULL, + cql("SELECT datname FROM pg_database " + " WHERE oid = :1", + ObjectIdGetDatum(object_oid))); + if (dbname == NULL) + elog(ERROR, "oid [%u] not found in table pg_database", object_oid); + + return dbname; +} +char *getProcNameFromOid(Oid object_oid) +{ + StringInfoData tname; + initStringInfo(&tname); + + Assert(OidIsValid(object_oid)); + char* proc_name = caql_getcstring( + NULL, + cql("SELECT proname FROM pg_proc " + " WHERE oid = :1", + ObjectIdGetDatum(object_oid))); + if (proc_name == NULL) + elog(ERROR, "oid [%u] not found in table pg_proc", object_oid); + + int fetchCount=0; + Oid schema_name_oid = caql_getoid_plus( + NULL, + &fetchCount, + NULL, + cql("SELECT pronamespace FROM pg_proc " + " WHERE oid = :1", + ObjectIdGetDatum(object_oid))); + if (schema_name_oid == InvalidOid) + elog(ERROR, "oid [%u] not found in table pg_class", object_oid); + + char* schema_name= caql_getcstring( + NULL, + cql("select nspname from pg_namespace " + " WHERE oid = :1", + ObjectIdGetDatum(schema_name_oid))); + if (schema_name == NULL) + elog(ERROR, "oid [%u] not found in table pg_namespace", object_oid); + + char* database_name = get_database_name(MyDatabaseId); + if (database_name == NULL) + elog(ERROR, "oid [%u] not found current database", object_oid); + + appendStringInfo(&tname, database_name); + appendStringInfo(&tname, "."); + appendStringInfo(&tname, schema_name); + appendStringInfo(&tname, "."); + appendStringInfo(&tname, proc_name); + pfree(proc_name); + pfree(schema_name); + pfree(database_name); + + return tname.data; +} +char *getOperNameFromOid(Oid object_oid) +{ + Assert(OidIsValid(object_oid)); + char* typename = caql_getcstring( + NULL, + cql("SELECT oprname FROM pg_operator " + " WHERE oid = :1", + ObjectIdGetDatum(object_oid))); + if (typename == NULL) + elog(ERROR, "oid [%u] not found in table pg_operator", object_oid); + + return typename; +} +char *getTypeNameFromOid(Oid object_oid) +{ + Assert(OidIsValid(object_oid)); + char* typename = caql_getcstring( + NULL, + cql("SELECT typname FROM pg_type " + " WHERE oid = :1", + ObjectIdGetDatum(object_oid))); + if (typename == NULL) + elog(ERROR, "oid [%u] not found in table pg_type", object_oid); + + return typename; +} +char *getLanguageNameFromOid(Oid object_oid) +{ + StringInfoData tname; + initStringInfo(&tname); + + Assert(OidIsValid(object_oid)); + char* lang_name = caql_getcstring( + NULL, + cql("SELECT lanname FROM pg_language " + " WHERE oid = :1", + ObjectIdGetDatum(object_oid))); + if (lang_name == NULL) + elog(ERROR, "oid [%u] not found in table pg_language", object_oid); + + + + char* database_name = get_database_name(MyDatabaseId); + if (database_name == NULL) + elog(ERROR, "oid [%u] not found current database", object_oid); + + appendStringInfo(&tname, database_name); + appendStringInfo(&tname, "."); + appendStringInfo(&tname, lang_name); + + pfree(lang_name); + pfree(database_name); + + return tname.data; +} +char *getNamespaceNameFromOid(Oid object_oid) +{ + + StringInfoData tname; + initStringInfo(&tname); + + Assert(OidIsValid(object_oid)); + char* schema_name = caql_getcstring( + NULL, + cql("SELECT nspname FROM pg_namespace " + " WHERE oid = :1", + ObjectIdGetDatum(object_oid))); + if (schema_name == NULL) + elog(ERROR, "oid [%u] not found in table pg_namespace", object_oid); + + + char* database_name = get_database_name(MyDatabaseId); + if (database_name == NULL) + elog(ERROR, "oid [%u] not found current database", object_oid); + + appendStringInfo(&tname, database_name); + appendStringInfo(&tname, "."); + appendStringInfo(&tname, schema_name); + + pfree(schema_name); + pfree(database_name); + + return tname.data; +} +char *getConversionNameFromOid(Oid object_oid) +{ + Assert(OidIsValid(object_oid)); + char* typename = caql_getcstring( + NULL, + cql("SELECT conname FROM pg_conversion " + " WHERE oid = :1", + ObjectIdGetDatum(object_oid))); + if (typename == NULL) + elog(ERROR, "oid [%u] not found in table pg_conversion", object_oid); + + return typename; +} +char *getTablespaceNameFromOid(Oid object_oid) +{ + Assert(OidIsValid(object_oid)); + char* typename = caql_getcstring( + NULL, + cql("SELECT spcname FROM pg_tablespace " + " WHERE oid = :1", + ObjectIdGetDatum(object_oid))); + if (typename == NULL) + elog(ERROR, "oid [%u] not found in table pg_tablespace", object_oid); + + return typename; +} +char *getFilespaceNameFromOid(Oid object_oid) +{ + Assert(OidIsValid(object_oid)); + char* typename = caql_getcstring( + NULL, + cql("SELECT fsname FROM pg_filespace " + " WHERE oid = :1", + ObjectIdGetDatum(object_oid))); + if (typename == NULL) + elog(ERROR, "oid [%u] not found in table pg_filespace", object_oid); + + return typename; +} +char *getFilesystemNameFromOid(Oid object_oid) +{ + Assert(OidIsValid(object_oid)); + char* typename = caql_getcstring( + NULL, + cql("SELECT fsysname FROM pg_filesystem " + " WHERE oid = :1", + ObjectIdGetDatum(object_oid))); + if (typename == NULL) + elog(ERROR, "oid [%u] not found in table pg_filesystem", object_oid); + + return typename; +} +char *getFDWNameFromOid(Oid object_oid) +{ + Assert(OidIsValid(object_oid)); + char* typename = caql_getcstring( + NULL, + cql("SELECT fdwname FROM pg_foreign_data_wrapper " + " WHERE oid = :1", + ObjectIdGetDatum(object_oid))); + if (typename == NULL) + elog(ERROR, "oid [%u] not found in table pg_foreign_data_wrapper", object_oid); + + return typename; +} +char *getForeignServerNameFromOid(Oid object_oid) +{ + Assert(OidIsValid(object_oid)); + char* typename = caql_getcstring( + NULL, + cql("SELECT srvname FROM pg_foreign_server " + " WHERE oid = :1", + ObjectIdGetDatum(object_oid))); + if (typename == NULL) + elog(ERROR, "oid [%u] not found in table pg_foreign_server", object_oid); + + return typename; +} +char *getExtprotocolNameFromOid(Oid object_oid) +{ + Assert(OidIsValid(object_oid)); + char* typename = caql_getcstring( + NULL, + cql("SELECT ptcname FROM pg_extprotocol " + " WHERE oid = :1", + ObjectIdGetDatum(object_oid))); + if (typename == NULL) + elog(ERROR, "oid [%u] not found in table pg_extprotocol", object_oid); + + return typename; +} + +char *getNameFromOid(AclObjectKind objkind, Oid object_oid) +{ + switch (objkind) + { + case ACL_KIND_CLASS: + return getClassNameFromOid(object_oid); + case ACL_KIND_SEQUENCE: + return getSequenceNameFromOid(object_oid); + case ACL_KIND_DATABASE: + return getDatabaseNameFromOid(object_oid); + case ACL_KIND_PROC: + return getProcNameFromOid(object_oid); + case ACL_KIND_OPER: + return getOperNameFromOid(object_oid); + case ACL_KIND_TYPE: + return getTypeNameFromOid(object_oid); + case ACL_KIND_CONVERSION: + return getConversionNameFromOid(object_oid); + case ACL_KIND_LANGUAGE: + return getLanguageNameFromOid(object_oid); + case ACL_KIND_NAMESPACE: + return getNamespaceNameFromOid(object_oid); + case ACL_KIND_TABLESPACE: + return getTablespaceNameFromOid(object_oid); + case ACL_KIND_FILESPACE: + return getFilespaceNameFromOid(object_oid); + case ACL_KIND_FILESYSTEM: + return getFilesystemNameFromOid(object_oid); + case ACL_KIND_FDW: + return getFDWNameFromOid(object_oid); + case ACL_KIND_FOREIGN_SERVER: + return getForeignServerNameFromOid(object_oid); + case ACL_KIND_EXTPROTOCOL: + return getExtprotocolNameFromOid(object_oid); + default: + elog(ERROR, "unrecognized objkind: %d", + (int) objkind); + /* not reached, but keep compiler quiet */ + return NULL; + } +} + +char actionName[12][12] = {"INSERT","SELECT","UPDATE", "DELETE", + "TRUNCATE", "REFERENCES", "TRIGGER", "EXECUTE", "USAGE", + "CREATE", "CREATE_TEMP", "CONNECT"}; + +List *getActionName(AclMode mask) +{ + List* actions = NIL; + int i = 0; + while(mask > 0) + { + if((mask & 1) > 0) + { + char* action = palloc(sizeof(char) * ACTION_LENGTH); + strncpy(action, actionName[i], ACTION_LENGTH); + actions = lappend(actions, action); + } + mask = mask >> 1; + i++; + } + return actions; +} + + +bool fallBackToNativeCheck(AclObjectKind objkind, Oid obj_oid, Oid roleid) +{ + //for heap table, we fall back to native check. + if(objkind == ACL_KIND_CLASS) + { + char relstorage = get_rel_relstorage(obj_oid); + if(relstorage == 'h') + { + return true; + } + } + return false; +} +/* + * return: List of RangerPrivilegeResults + * arg_list: List of RangerPrivilegeArgs + */ +List *pg_rangercheck_batch(List *arg_list) +{ + return NIL; +} + +AclResult +pg_rangercheck(AclObjectKind objkind, Oid object_oid, Oid roleid, + AclMode mask, AclMaskHow how) +{ + char* objectname = getNameFromOid(objkind, object_oid); + char* rolename = getRoleName(roleid); + List* actions = getActionName(mask); + bool isAll = (how == ACLMASK_ALL) ? true: false; + + elog(LOG, "rangeraclcheck kind:%d,objectname:%s,role:%s,mask:%u\n",objkind,objectname,rolename,mask); + int ret = check_privilege_from_ranger(rolename, objkind, objectname, actions, isAll); + + if(objectname){ + pfree(objectname); + objectname = NULL; + } + if(rolename){ + pfree(rolename); + rolename = NULL; + } + if(actions){ + list_free_deep(actions); + actions = NIL; + } + return ACLCHECK_OK; +} + /* * Relay for the various pg_*_mask routines depending on object kind */ @@ -3085,6 +3559,135 @@ pg_filesystem_aclmask(Oid fsysOid, Oid roleid, return result; } + +/* + * Exported routine for checking a user's access privileges to a table + * + * Returns ACLCHECK_OK if the user has any of the privileges identified by + * 'mode'; otherwise returns a suitable error code (in practice, always + * ACLCHECK_NO_PRIV). + */ +AclResult +pg_class_nativecheck(Oid table_oid, Oid roleid, AclMode mode) +{ + if (pg_class_aclmask(table_oid, roleid, mode, ACLMASK_ANY) != 0) + return ACLCHECK_OK; + else + return ACLCHECK_NO_PRIV; +} + +/* + * Exported routine for checking a user's access privileges to a database + */ +AclResult +pg_database_nativecheck(Oid db_oid, Oid roleid, AclMode mode) +{ + if (pg_database_aclmask(db_oid, roleid, mode, ACLMASK_ANY) != 0) + return ACLCHECK_OK; + else + return ACLCHECK_NO_PRIV; +} + +/* + * Exported routine for checking a user's access privileges to a function + */ +AclResult +pg_proc_nativecheck(Oid proc_oid, Oid roleid, AclMode mode) +{ + if (pg_proc_aclmask(proc_oid, roleid, mode, ACLMASK_ANY) != 0) + return ACLCHECK_OK; + else + return ACLCHECK_NO_PRIV; +} + +/* + * Exported routine for checking a user's access privileges to a language + */ +AclResult +pg_language_nativecheck(Oid lang_oid, Oid roleid, AclMode mode) +{ + if (pg_language_aclmask(lang_oid, roleid, mode, ACLMASK_ANY) != 0) + return ACLCHECK_OK; + else + return ACLCHECK_NO_PRIV; +} + +/* + * Exported routine for checking a user's access privileges to a namespace + */ +AclResult +pg_namespace_nativecheck(Oid nsp_oid, Oid roleid, AclMode mode) +{ + if (pg_namespace_aclmask(nsp_oid, roleid, mode, ACLMASK_ANY) != 0) + return ACLCHECK_OK; + else + return ACLCHECK_NO_PRIV; +} + +/* + * Exported routine for checking a user's access privileges to a tablespace + */ +AclResult +pg_tablespace_nativecheck(Oid spc_oid, Oid roleid, AclMode mode) +{ + if (pg_tablespace_aclmask(spc_oid, roleid, mode, ACLMASK_ANY) != 0) + return ACLCHECK_OK; + else + return ACLCHECK_NO_PRIV; +} + +/* + * Exported routine for checking a user's access privileges to a foreign + * data wrapper + */ +AclResult +pg_foreign_data_wrapper_nativecheck(Oid fdw_oid, Oid roleid, AclMode mode) +{ + if (pg_foreign_data_wrapper_aclmask(fdw_oid, roleid, mode, ACLMASK_ANY) != 0) + return ACLCHECK_OK; + else + return ACLCHECK_NO_PRIV; +} + +/* + * Exported routine for checking a user's access privileges to a foreign + * server + */ +AclResult +pg_foreign_server_nativecheck(Oid srv_oid, Oid roleid, AclMode mode) +{ + if (pg_foreign_server_aclmask(srv_oid, roleid, mode, ACLMASK_ANY) != 0) + return ACLCHECK_OK; + else + return ACLCHECK_NO_PRIV; +} + +/* + * Exported routine for checking a user's access privileges to an + * external protocol + */ +AclResult +pg_extprotocol_nativecheck(Oid ptcid, Oid roleid, AclMode mode) +{ + if (pg_extprotocol_aclmask(ptcid, roleid, mode, ACLMASK_ANY) != 0) + return ACLCHECK_OK; + else + return ACLCHECK_NO_PRIV; +} + +/* + * Exported routine for checking a user's access privileges to a filesystem + */ +AclResult +pg_filesystem_nativecheck(Oid fsysid, Oid roleid, AclMode mode) +{ + if (pg_filesystem_aclmask(fsysid, roleid, mode, ACLMASK_ANY) != 0) + return ACLCHECK_OK; + else + return ACLCHECK_NO_PRIV; +} + + /* * Exported routine for checking a user's access privileges to a table * @@ -3095,10 +3698,14 @@ pg_filesystem_aclmask(Oid fsysOid, Oid roleid, AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode) { - if (pg_class_aclmask(table_oid, roleid, mode, ACLMASK_ANY) != 0) - return ACLCHECK_OK; - else - return ACLCHECK_NO_PRIV; + if(enable_ranger && !fallBackToNativeCheck(ACL_KIND_CLASS, table_oid, roleid)) + { + return pg_rangercheck(ACL_KIND_CLASS, table_oid, roleid, mode, ACLMASK_ANY); + } + else + { + return pg_class_nativecheck(table_oid, roleid, mode); + } } /* @@ -3107,10 +3714,14 @@ pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode) AclResult pg_database_aclcheck(Oid db_oid, Oid roleid, AclMode mode) { - if (pg_database_aclmask(db_oid, roleid, mode, ACLMASK_ANY) != 0) - return ACLCHECK_OK; - else - return ACLCHECK_NO_PRIV; + if(enable_ranger && !fallBackToNativeCheck(ACL_KIND_DATABASE, db_oid, roleid)) + { + return pg_rangercheck(ACL_KIND_DATABASE, db_oid, roleid, mode, ACLMASK_ANY); + } + else + { + return pg_database_nativecheck(db_oid, roleid, mode); + } } /* @@ -3119,10 +3730,14 @@ pg_database_aclcheck(Oid db_oid, Oid roleid, AclMode mode) AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode) { - if (pg_proc_aclmask(proc_oid, roleid, mode, ACLMASK_ANY) != 0) - return ACLCHECK_OK; - else - return ACLCHECK_NO_PRIV; + if(enable_ranger && !fallBackToNativeCheck(ACL_KIND_PROC, proc_oid, roleid)) + { + return pg_rangercheck(ACL_KIND_PROC, proc_oid, roleid, mode, ACLMASK_ANY); + } + else + { + return pg_proc_nativecheck(proc_oid, roleid, mode); + } } /* @@ -3131,10 +3746,14 @@ pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode) AclResult pg_language_aclcheck(Oid lang_oid, Oid roleid, AclMode mode) { - if (pg_language_aclmask(lang_oid, roleid, mode, ACLMASK_ANY) != 0) - return ACLCHECK_OK; - else - return ACLCHECK_NO_PRIV; + if(enable_ranger && !fallBackToNativeCheck(ACL_KIND_LANGUAGE, lang_oid, roleid)) + { + return pg_rangercheck(ACL_KIND_LANGUAGE, lang_oid, roleid, mode, ACLMASK_ANY); + } + else + { + return pg_language_nativecheck(lang_oid, roleid, mode); + } } /* @@ -3143,10 +3762,14 @@ pg_language_aclcheck(Oid lang_oid, Oid roleid, AclMode mode) AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode) { - if (pg_namespace_aclmask(nsp_oid, roleid, mode, ACLMASK_ANY) != 0) - return ACLCHECK_OK; - else - return ACLCHECK_NO_PRIV; + if(enable_ranger && !fallBackToNativeCheck(ACL_KIND_NAMESPACE, nsp_oid, roleid)) + { + return pg_rangercheck(ACL_KIND_NAMESPACE, nsp_oid, roleid, mode, ACLMASK_ANY); + } + else + { + return pg_namespace_nativecheck(nsp_oid, roleid, mode); + } } /* @@ -3155,10 +3778,14 @@ pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode) AclResult pg_tablespace_aclcheck(Oid spc_oid, Oid roleid, AclMode mode) { - if (pg_tablespace_aclmask(spc_oid, roleid, mode, ACLMASK_ANY) != 0) - return ACLCHECK_OK; - else - return ACLCHECK_NO_PRIV; + if(enable_ranger && !fallBackToNativeCheck(ACL_KIND_TABLESPACE, spc_oid, roleid)) + { + return pg_rangercheck(ACL_KIND_TABLESPACE, spc_oid, roleid, mode, ACLMASK_ANY); + } + else + { + return pg_tablespace_nativecheck(spc_oid, roleid, mode); + } } /* @@ -3168,10 +3795,14 @@ pg_tablespace_aclcheck(Oid spc_oid, Oid roleid, AclMode mode) AclResult pg_foreign_data_wrapper_aclcheck(Oid fdw_oid, Oid roleid, AclMode mode) { - if (pg_foreign_data_wrapper_aclmask(fdw_oid, roleid, mode, ACLMASK_ANY) != 0) - return ACLCHECK_OK; - else - return ACLCHECK_NO_PRIV; + if(enable_ranger && !fallBackToNativeCheck(ACL_KIND_FDW, fdw_oid, roleid)) + { + return pg_rangercheck(ACL_KIND_FDW, fdw_oid, roleid, mode, ACLMASK_ANY); + } + else + { + return pg_foreign_data_wrapper_nativecheck(fdw_oid, roleid, mode); + } } /* @@ -3181,10 +3812,14 @@ pg_foreign_data_wrapper_aclcheck(Oid fdw_oid, Oid roleid, AclMode mode) AclResult pg_foreign_server_aclcheck(Oid srv_oid, Oid roleid, AclMode mode) { - if (pg_foreign_server_aclmask(srv_oid, roleid, mode, ACLMASK_ANY) != 0) - return ACLCHECK_OK; - else - return ACLCHECK_NO_PRIV; + if(enable_ranger && !fallBackToNativeCheck(ACL_KIND_FOREIGN_SERVER, srv_oid, roleid)) + { + return pg_rangercheck(ACL_KIND_FOREIGN_SERVER, srv_oid, roleid, mode, ACLMASK_ANY); + } + else + { + return pg_foreign_server_nativecheck(srv_oid, roleid, mode); + } } /* @@ -3194,10 +3829,14 @@ pg_foreign_server_aclcheck(Oid srv_oid, Oid roleid, AclMode mode) AclResult pg_extprotocol_aclcheck(Oid ptcid, Oid roleid, AclMode mode) { - if (pg_extprotocol_aclmask(ptcid, roleid, mode, ACLMASK_ANY) != 0) - return ACLCHECK_OK; - else - return ACLCHECK_NO_PRIV; + if(enable_ranger && !fallBackToNativeCheck(ACL_KIND_EXTPROTOCOL, ptcid, roleid)) + { + return pg_rangercheck(ACL_KIND_EXTPROTOCOL, ptcid, roleid, mode, ACLMASK_ANY); + } + else + { + return pg_extprotocol_nativecheck(ptcid, roleid, mode); + } } /* @@ -3206,10 +3845,14 @@ pg_extprotocol_aclcheck(Oid ptcid, Oid roleid, AclMode mode) AclResult pg_filesystem_aclcheck(Oid fsysid, Oid roleid, AclMode mode) { - if (pg_filesystem_aclmask(fsysid, roleid, mode, ACLMASK_ANY) != 0) - return ACLCHECK_OK; - else - return ACLCHECK_NO_PRIV; + if(enable_ranger && !fallBackToNativeCheck(ACL_KIND_FILESYSTEM, fsysid, roleid)) + { + return pg_rangercheck(ACL_KIND_FILESYSTEM, fsysid, roleid, mode, ACLMASK_ANY); + } + else + { + return pg_filesystem_nativecheck(fsysid, roleid, mode); + } } /* http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/a5a02b19/src/backend/parser/parse_relation.c ---------------------------------------------------------------------- diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c index b49b72e..62d815c 100644 --- a/src/backend/parser/parse_relation.c +++ b/src/backend/parser/parse_relation.c @@ -35,35 +35,34 @@ #include <ctype.h> -#include "access/genam.h" -#include "access/heapam.h" #include "catalog/catquery.h" +#include "access/genam.h" #include "catalog/heap.h" +#include "access/heapam.h" +#include "catalog/indexing.h" #include "catalog/namespace.h" #include "catalog/pg_exttable.h" #include "catalog/pg_proc_callback.h" #include "catalog/pg_namespace.h" #include "catalog/pg_database.h" #include "catalog/pg_type.h" -#include "catalog/indexing.h" #include "funcapi.h" #include "miscadmin.h" #include "nodes/makefuncs.h" #include "nodes/relation.h" /* CdbRelColumnInfo */ #include "optimizer/pathnode.h" /* cdb_rte_find_pseudo_column() */ #include "parser/parsetree.h" +#include "parser/parse_coerce.h" #include "parser/parse_expr.h" #include "parser/parse_relation.h" #include "parser/parse_type.h" -#include "parser/parse_coerce.h" #include "utils/acl.h" +#include "utils/array.h" #include "utils/builtins.h" +#include "utils/fmgroids.h" +#include "utils/guc.h" #include "utils/lsyscache.h" #include "utils/syscache.h" -#include "utils/array.h" -#include "utils/fmgroids.h" - - /* GUC parameter */ bool add_missing_from; @@ -2713,8 +2712,13 @@ warnAutoRange(ParseState *pstate, RangeVar *relation, int location) void ExecCheckRTPerms(List *rangeTable) { + if (enable_ranger) + { + if(rangeTable!=NULL) + ExecCheckRTPermsWithRanger(rangeTable); + return; + } ListCell *l; - foreach(l, rangeTable) { ExecCheckRTEPerms((RangeTblEntry *) lfirst(l)); @@ -2722,6 +2726,76 @@ ExecCheckRTPerms(List *rangeTable) } /* + * ExecCheckRTPerms + * Batch implementation: Check access permissions for all relations listed in a range table with enable_ranger is true. + */ +void +ExecCheckRTPermsWithRanger(List *rangeTable) +{ + List *ranger_check_args = NIL; + ListCell *l; + foreach(l, rangeTable) + { + + AclMode requiredPerms; + Oid relOid; + Oid userid; + RangeTblEntry *rte = (RangeTblEntry *) lfirst(l); + + if (rte->rtekind != RTE_RELATION) + return; + requiredPerms = rte->requiredPerms; + if (requiredPerms == 0) + return; + + relOid = rte->relid; + userid = rte->checkAsUser ? rte->checkAsUser : GetUserId(); + + RangerPrivilegeArgs *ranger_check_arg = (RangerPrivilegeArgs *) palloc(sizeof(RangerPrivilegeArgs)); + ranger_check_arg->objkind = ACL_KIND_CLASS; + ranger_check_arg->object_oid = relOid; + ranger_check_arg->roleid = userid; + ranger_check_arg->mask = requiredPerms; + ranger_check_arg->how = ACLMASK_ALL; + ranger_check_args = lappend(ranger_check_args, ranger_check_arg); + + } // foreach + + // ranger ACL check with package Oids + List *aclresults = NIL; + aclresults = pg_rangercheck_batch(ranger_check_args); + if (aclresults == NIL) + { + elog(ERROR, "ERROR\n"); + return; + } + + // check result + ListCell *result; + foreach(result, aclresults) + { + RangerPrivilegeResults *result_ptr = (RangerPrivilegeResults *) lfirst(result); + if(result_ptr->result != RANGERCHECK_OK) + { + Oid relOid = result_ptr->relOid; + const char *rel_name = get_rel_name_partition(relOid); + aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_CLASS, rel_name); + } + } + + if (ranger_check_args) + { + list_free_deep(ranger_check_args); + ranger_check_args = NIL; + } + if (aclresults) + { + list_free_deep(aclresults); + aclresults = NIL; + } +} + +/* * ExecCheckRTEPerms * Check access permissions for a single RTE. */ @@ -2762,15 +2836,33 @@ ExecCheckRTEPerms(RangeTblEntry *rte) /* * We must have *all* the requiredPerms bits, so use aclmask not aclcheck. */ - if (pg_class_aclmask(relOid, userid, requiredPerms, ACLMASK_ALL) - != requiredPerms) + if (enable_ranger && !fallBackToNativeCheck(ACL_KIND_CLASS, relOid, userid)) { - /* - * If the table is a partition, return an error message that includes - * the name of the parent table. - */ - const char *rel_name = get_rel_name_partition(relOid); - aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_CLASS, rel_name); + elog(LOG, "ExecCheckRTEPerms: here"); + /* ranger check required permission should all be approved.*/ + if (pg_rangercheck(ACL_KIND_CLASS, relOid, userid, requiredPerms, ACLMASK_ALL) + != RANGERCHECK_OK) + { + /* + * If the table is a partition, return an error message that includes + * the name of the parent table. + */ + const char *rel_name = get_rel_name_partition(relOid); + aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_CLASS, rel_name); + } + } + else + { + if (pg_class_aclmask(relOid, userid, requiredPerms, ACLMASK_ALL) + != requiredPerms) + { + /* + * If the table is a partition, return an error message that includes + * the name of the parent table. + */ + const char *rel_name = get_rel_name_partition(relOid); + aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_CLASS, rel_name); + } } } http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/a5a02b19/src/include/parser/parse_relation.h ---------------------------------------------------------------------- diff --git a/src/include/parser/parse_relation.h b/src/include/parser/parse_relation.h index 4c13a79..3af717f 100644 --- a/src/include/parser/parse_relation.h +++ b/src/include/parser/parse_relation.h @@ -101,6 +101,7 @@ extern Name attnumAttName(Relation rd, int attid); extern Oid attnumTypeId(Relation rd, int attid); extern void ExecCheckRTPerms(List *rangeTable); +extern void ExecCheckRTPermsWithRanger(List *); extern void ExecCheckRTEPerms(RangeTblEntry *rte); #endif /* PARSE_RELATION_H */ http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/a5a02b19/src/include/utils/acl.h ---------------------------------------------------------------------- diff --git a/src/include/utils/acl.h b/src/include/utils/acl.h index 80c21ff..62a13a2 100644 --- a/src/include/utils/acl.h +++ b/src/include/utils/acl.h @@ -26,6 +26,7 @@ #include "nodes/parsenodes.h" #include "utils/array.h" +#include "utils/rangerrest.h" /* @@ -288,6 +289,41 @@ extern AclResult pg_foreign_server_aclcheck(Oid srv_oid, Oid roleid, AclMode mod extern AclResult pg_extprotocol_aclcheck(Oid ptc_oid, Oid roleid, AclMode mode); extern AclResult pg_filesystem_aclcheck(Oid fsys_oid, Oid roleid, AclMode mode); +extern AclResult pg_class_nativecheck(Oid table_oid, Oid roleid, AclMode mode); +extern AclResult pg_database_nativecheck(Oid db_oid, Oid roleid, AclMode mode); +extern AclResult pg_proc_nativecheck(Oid proc_oid, Oid roleid, AclMode mode); +extern AclResult pg_language_nativecheck(Oid lang_oid, Oid roleid, AclMode mode); +extern AclResult pg_namespace_nativecheck(Oid nsp_oid, Oid roleid, AclMode mode); +extern AclResult pg_tablespace_nativecheck(Oid spc_oid, Oid roleid, AclMode mode); +extern AclResult pg_foreign_data_wrapper_nativecheck(Oid fdw_oid, Oid roleid, AclMode mode); +extern AclResult pg_foreign_server_nativecheck(Oid srv_oid, Oid roleid, AclMode mode); +extern AclResult pg_extprotocol_nativecheck(Oid ptc_oid, Oid roleid, AclMode mode); +extern AclResult pg_filesystem_nativecheck(Oid fsys_oid, Oid roleid, AclMode mode); + +extern List *pg_rangercheck_batch(List *); +extern AclResult +pg_rangercheck(AclObjectKind objkind, Oid table_oid, Oid roleid, + AclMode mask, AclMaskHow how); +extern bool fallBackToNativeCheck(AclObjectKind objkind, Oid table_oid, Oid roleid); +extern char *getNameFromOid(AclObjectKind objkind, Oid object_oid); +extern char *getClassNameFromOid(Oid object_oid); +extern char *getSequenceNameFromOid(Oid object_oid); +extern char *getDatabaseNameFromOid(Oid object_oid); +extern char *getProcNameFromOid(Oid object_oid); +extern char *getOperNameFromOid(Oid object_oid); +extern char *getTypeNameFromOid(Oid object_oid); +extern char *getLanguageNameFromOid(Oid object_oid); +extern char *getNamespaceNameFromOid(Oid object_oid); +extern char *getConversionNameFromOid(Oid object_oid); +extern char *getTablespaceNameFromOid(Oid object_oid); +extern char *getFilespaceNameFromOid(Oid object_oid); +extern char *getFilesystemNameFromOid(Oid object_oid); +extern char *getFDWNameFromOid(Oid object_oid); +extern char *getForeignServerNameFromOid(Oid object_oid); +extern char *getExtprotocolNameFromOid(Oid object_oid); +extern List *getActionName(AclMode mask); +extern char *getRoleName(Oid role_id); + extern void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname); @@ -306,4 +342,27 @@ extern bool pg_conversion_ownercheck(Oid conv_oid, Oid roleid); extern bool pg_foreign_server_ownercheck(Oid srv_oid, Oid roleid); extern bool pg_extprotocol_ownercheck(Oid ptc_oid, Oid roleid); +typedef struct RangerPrivilegeArgs +{ + AclObjectKind objkind; + Oid object_oid; + Oid roleid; + AclMode mask; + AclMaskHow how; +} RangerPrivilegeArgs; + +typedef struct RangerPrivilegeResults +{ + RangerACLResult result; + Oid relOid; +} RangerPrivilegeResults; + +typedef struct RangerRequestJsonArgs { + char* user; + AclObjectKind kind; + char* object; + List* actions; + char* how; +} RangerRequestJsonArgs; + #endif /* ACL_H */