Repository: incubator-hawq Updated Branches: refs/heads/ranger fcc3b869c -> 9de76890c (forced update)
Package oids inside one query to request RPS: ExecCheckRTPerms entry. Project: http://git-wip-us.apache.org/repos/asf/incubator-hawq/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-hawq/commit/9de76890 Tree: http://git-wip-us.apache.org/repos/asf/incubator-hawq/tree/9de76890 Diff: http://git-wip-us.apache.org/repos/asf/incubator-hawq/diff/9de76890 Branch: refs/heads/ranger Commit: 9de76890c4e7987f484c9f84939afb2edd6bda00 Parents: b22d208 Author: xunzhang <[email protected]> Authored: Mon Dec 5 19:12:18 2016 +0800 Committer: xunzhang <[email protected]> Committed: Sun Dec 11 13:07:10 2016 +0800 ---------------------------------------------------------------------- src/backend/catalog/aclchk.c | 76 ++++++++++++++- src/backend/cdb/cdbutil.c | 1 + src/backend/libpq/rangerrest.c | 158 ++++++++++++++++++++++++++++++- src/backend/libpq/rangerrest.h | 39 -------- src/backend/parser/parse_relation.c | 83 +++++++++++++++- src/include/parser/parse_relation.h | 1 + src/include/utils/acl.h | 25 +++++ src/include/utils/rangerrest.h | 39 ++++++++ 8 files changed, 376 insertions(+), 46 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/9de76890/src/backend/catalog/aclchk.c ---------------------------------------------------------------------- diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c index 06f20f3..3ff4a99 100644 --- a/src/backend/catalog/aclchk.c +++ b/src/backend/catalog/aclchk.c @@ -227,6 +227,7 @@ restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs, if (avail_goptions == ACL_NO_RIGHTS) { if (enable_ranger) { + elog(LOG, "restrict_and_check_grant: here\n"); if (pg_rangercheck(objkind, objectId, grantorId, whole_mask | ACL_GRANT_OPTION_FOR(whole_mask), ACLMASK_ANY) != ACLCHECK_OK) @@ -2664,10 +2665,73 @@ List *getActionName(AclMode mask) return actions; } +List *pg_rangercheck_batch(List *arg_list) +{ + List *aclresults = NIL; + List *requestargs = NIL; + ListCell *arg; + foreach(arg, arg_list) { + RangerPrivilegeArgs *arg_ptr = (RangerPrivilegeArgs *) lfirst(arg); + AclObjectKind objkind = arg_ptr->objkind; + Oid object_oid = arg_ptr->object_oid; + char *objectname = getNameFromOid(objkind, object_oid); + char *rolename = getRoleName(arg_ptr->roleid); + List* actions = getActionName(arg_ptr->mask); + bool isAll = (arg_ptr->how == ACLMASK_ALL) ? true: false; + RangerPrivilegeResults *aclresult = (RangerPrivilegeResults *) palloc(sizeof(RangerPrivilegeResults)); + aclresult->result = -1; //check_privilege_from_ranger(rolename, objkind, objectname, actions, isAll); + aclresult->relOid = object_oid; + aclresults = lappend(aclresults, aclresult); + + RangerRequestJsonArgs *requestarg = (RangerRequestJsonArgs *) palloc(sizeof(RangerRequestJsonArgs)); + requestarg->user = rolename; + requestarg->kind = objkind; + requestarg->object = objectname; + requestarg->actions = actions; + requestarg->how = isAll; + requestargs = lappend(requestargs, requestarg); + + if (objectname) + { + pfree(objectname); + objectname = NULL; + } + if(rolename) + { + pfree(rolename); + rolename = NULL; + } + if(actions) + { + list_free_deep(actions); + actions = NIL; + } + } // foreach + + RangerACLResult ret = check_privilege_from_ranger_batch(requestargs); + + ListCell *result; + int k = 0; + foreach(result, aclresults) { + RangerPrivilegeResults *result_ptr = (RangerPrivilegeResults *) lfirst(result); + result_ptr->result = ret; + ++k; + } + + if(requestargs) { + list_free_deep(requestargs); + requestargs = NULL; + } + + elog(LOG, "oids%d\n", arg_list->length); + return aclresults; +} + AclResult pg_rangercheck(AclObjectKind objkind, Oid object_oid, Oid roleid, AclMode mask, AclMaskHow how) { + elog(LOG, "pg_rangercheck: here\n"); char* objectname = getNameFromOid(objkind, object_oid); char* rolename = getRoleName(roleid); List* actions = getActionName(mask); @@ -2687,11 +2751,9 @@ pg_rangercheck(AclObjectKind objkind, Oid object_oid, Oid roleid, list_free_deep(actions); actions = NIL; } - return ACLCHECK_OK; } - /* * Relay for the various pg_*_mask routines depending on object kind */ @@ -3678,6 +3740,7 @@ pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode) { if(enable_ranger) { + elog(LOG, "pg_class_aclcheck: here\n"); return pg_rangercheck(ACL_KIND_CLASS, table_oid, roleid, mode, ACLMASK_ANY); } else @@ -3694,6 +3757,7 @@ pg_database_aclcheck(Oid db_oid, Oid roleid, AclMode mode) { if(enable_ranger) { + elog(LOG, "pg_database_aclcheck: here\n"); return pg_rangercheck(ACL_KIND_DATABASE, db_oid, roleid, mode, ACLMASK_ANY); } else @@ -3710,6 +3774,7 @@ pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode) { if(enable_ranger) { + elog(LOG, "pg_proc_aclcheck: here\n"); return pg_rangercheck(ACL_KIND_PROC, proc_oid, roleid, mode, ACLMASK_ANY); } else @@ -3726,6 +3791,7 @@ pg_language_aclcheck(Oid lang_oid, Oid roleid, AclMode mode) { if(enable_ranger) { + elog(LOG, "pg_language_aclcheck: here\n"); return pg_rangercheck(ACL_KIND_LANGUAGE, lang_oid, roleid, mode, ACLMASK_ANY); } else @@ -3742,6 +3808,7 @@ pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode) { if(enable_ranger) { + elog(LOG, "pg_namespace_aclcheck: here\n"); return pg_rangercheck(ACL_KIND_NAMESPACE, nsp_oid, roleid, mode, ACLMASK_ANY); } else @@ -3758,6 +3825,7 @@ pg_tablespace_aclcheck(Oid spc_oid, Oid roleid, AclMode mode) { if(enable_ranger) { + elog(LOG, "pg_tablespace_aclcheck: here\n"); return pg_rangercheck(ACL_KIND_TABLESPACE, spc_oid, roleid, mode, ACLMASK_ANY); } else @@ -3775,6 +3843,7 @@ pg_foreign_data_wrapper_aclcheck(Oid fdw_oid, Oid roleid, AclMode mode) { if(enable_ranger) { + elog(LOG, "pg_foreign_data_wrapper_aclcheck: here\n"); return pg_rangercheck(ACL_KIND_FDW, fdw_oid, roleid, mode, ACLMASK_ANY); } else @@ -3792,6 +3861,7 @@ pg_foreign_server_aclcheck(Oid srv_oid, Oid roleid, AclMode mode) { if(enable_ranger) { + elog(LOG, "pg_foreign_server_aclcheck: here\n"); return pg_rangercheck(ACL_KIND_FOREIGN_SERVER, srv_oid, roleid, mode, ACLMASK_ANY); } else @@ -3809,6 +3879,7 @@ pg_extprotocol_aclcheck(Oid ptcid, Oid roleid, AclMode mode) { if(enable_ranger) { + elog(LOG, "pg_extprotocol_aclcheck: here\n"); return pg_rangercheck(ACL_KIND_EXTPROTOCOL, ptcid, roleid, mode, ACLMASK_ANY); } else @@ -3825,6 +3896,7 @@ pg_filesystem_aclcheck(Oid fsysid, Oid roleid, AclMode mode) { if(enable_ranger) { + elog(LOG, "pg_filesystem_aclcheck: here\n"); return pg_rangercheck(ACL_KIND_FILESYSTEM, fsysid, roleid, mode, ACLMASK_ANY); } else http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/9de76890/src/backend/cdb/cdbutil.c ---------------------------------------------------------------------- diff --git a/src/backend/cdb/cdbutil.c b/src/backend/cdb/cdbutil.c index 0391881..03395a9 100644 --- a/src/backend/cdb/cdbutil.c +++ b/src/backend/cdb/cdbutil.c @@ -585,6 +585,7 @@ cdb_setup(void) if (Gp_role == GP_ROLE_DISPATCH) { + elog(LOG, "cdb_setup: here\n"); /* check mirrored entry db configuration */ buildMirrorQDDefinition(); http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/9de76890/src/backend/libpq/rangerrest.c ---------------------------------------------------------------------- diff --git a/src/backend/libpq/rangerrest.c b/src/backend/libpq/rangerrest.c index 032a6c0..e5dc47a 100644 --- a/src/backend/libpq/rangerrest.c +++ b/src/backend/libpq/rangerrest.c @@ -25,7 +25,7 @@ *------------------------------------------------------------------------- */ #include <json-c/json.h> -#include "rangerrest.h" +#include "utils/rangerrest.h" #include "utils/elog.h" #include "utils/palloc.h" #include "postgres.h" @@ -95,6 +95,130 @@ char* AclObjectKindStr[] = "none" /* MUST BE LAST */ }; +json_object *create_ranger_request_json_batch(List *args) +{ + json_object *juser = NULL; + json_object *jaccess = json_object_new_array(); + json_object *jrequest = json_object_new_object(); + char *user = NULL; + ListCell *arg; + + foreach(arg, args) + { + RangerRequestJsonArgs *arg_ptr = (RangerRequestJsonArgs *) lfirst(arg); + if (user == NULL) + { + user = arg_ptr->user; + juser = json_object_new_string(user); + } + AclObjectKind kind = arg_ptr->kind; + char* object = arg_ptr->object; + char* how = arg_ptr->how; + Assert(user != NULL && object != NULL && privilege != NULL && how != NULL); + elog(LOG, "build json for ranger request, user:%s, kind:%s, object:%s", + user, AclObjectKindStr[kind], object); + + json_object *jresource = json_object_new_object(); + json_object *jelement = json_object_new_object(); + json_object *jactions = json_object_new_array(); + + switch(kind) + { + case ACL_KIND_CLASS: + case ACL_KIND_SEQUENCE: + case ACL_KIND_PROC: + case ACL_KIND_NAMESPACE: + case ACL_KIND_LANGUAGE: + { + char *ptr = NULL; char *name = NULL; + char *first = NULL; // could be a database or protocol or tablespace + char *second = NULL; // could be a schema or language + char *third = NULL; // could be a table or sequence or function + int idx = 0; + for (name = strtok_r(object, ".", &ptr); + name; + name = strtok_r(NULL, ".", &ptr), idx++) + { + if (idx == 0) + { + first = pstrdup(name); + } + else if (idx == 1) + { + second = pstrdup(name); + } + else + { + third = pstrdup(name); + } + } + + if (first != NULL) + { + json_object *jfirst = json_object_new_string(first); + json_object_object_add(jresource, "database", jfirst); + } + if (second != NULL) + { + json_object *jsecond = json_object_new_string(second); + json_object_object_add(jresource, + (kind == ACL_KIND_LANGUAGE) ? "language" : "schema", jsecond); + } + if (third != NULL) + { + json_object *jthird = json_object_new_string(third); + elog(LOG, "JTHIRD %s\n", jthird); + json_object_object_add(jresource, + (kind == ACL_KIND_CLASS) ? "table" : + (kind == ACL_KIND_SEQUENCE) ? "sequence" : "function", jthird); + } + + if (first != NULL) + pfree(first); + if (second != NULL) + pfree(second); + if (third != NULL) + pfree(third); + break; + } + case ACL_KIND_OPER: + case ACL_KIND_CONVERSION: + case ACL_KIND_DATABASE: + case ACL_KIND_TABLESPACE: + case ACL_KIND_TYPE: + case ACL_KIND_FILESYSTEM: + case ACL_KIND_FDW: + case ACL_KIND_FOREIGN_SERVER: + case ACL_KIND_EXTPROTOCOL: + { + json_object *jobject = json_object_new_string(object); + json_object_object_add(jresource, AclObjectKindStr[kind], jobject); + break; + } + default: + elog(ERROR, "unrecognized objkind: %d", (int) kind); + } // switch + + json_object_object_add(jelement, "resource", jresource); + + //ListCell *cell; + //foreach(cell, arg_ptr->actions) + //{ + char tmp[7] = "select"; + json_object* jaction = json_object_new_string((char *)tmp); + //json_object* jaction = json_object_new_string((char *)cell->data.ptr_value); + json_object_array_add(jactions, jaction); + //} + json_object_object_add(jelement, "privileges", jactions); + json_object_array_add(jaccess, jelement); + + } // foreach + + json_object_object_add(jrequest, "user", juser); + json_object_object_add(jrequest, "access", jaccess); + return jrequest; +} + /** * Create a JSON object for Ranger request given some parameters. * @@ -130,7 +254,7 @@ json_object* create_ranger_request_json(char* user, AclObjectKind kind, char* ob { Assert(user != NULL && object != NULL && privilege != NULL && how != NULL); - ListCell *cell = NULL; + ListCell *cell; elog(LOG, "build json for ranger request, user:%s, kind:%s, object:%s", user, AclObjectKindStr[kind], object); @@ -308,6 +432,34 @@ _exit: curl_global_cleanup(); } +int check_privilege_from_ranger_batch(List *arg_list) +{ + json_object* jrequest = create_ranger_request_json_batch(arg_list); + Assert(jrequest != NULL); + char *request = json_object_to_json_string(jrequest); + elog(LOG, "Send JSON request to Ranger: %s", request); + Assert(request != NULL); + struct curl_context_t curl_context; + memset(&curl_context, 0, sizeof(struct curl_context_t)); + + /* call GET method to send request*/ + call_ranger_rest(&curl_context, request); + + /* free the JSON object */ + json_object_put(jrequest); + + /* parse the JSON-format result */ + RangerACLResult ret = parse_ranger_response(curl_context.response.buffer); + + /* free response buffer */ + if (curl_context.response.buffer != NULL) + { + pfree(curl_context.response.buffer); + } + + return ret; +} + /* * Check the privilege from Ranger for one role */ @@ -315,7 +467,7 @@ int check_privilege_from_ranger(char* user, AclObjectKind kind, char* object, List* actions, char* how) { json_object* jrequest = create_ranger_request_json(user, kind, object, - actions, how); + actions, how); Assert(jrequest != NULL); char* request = json_object_to_json_string(jrequest); http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/9de76890/src/backend/libpq/rangerrest.h ---------------------------------------------------------------------- diff --git a/src/backend/libpq/rangerrest.h b/src/backend/libpq/rangerrest.h deleted file mode 100644 index 4b73f46..0000000 --- a/src/backend/libpq/rangerrest.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -/*------------------------------------------------------------------------- - * - * rangerrest.h - * routines to interact with Ranger REST API - * - *------------------------------------------------------------------------- - */ -#ifndef RANGERREST_H -#define RANGERREST_H - -#include <curl/curl.h> - -typedef enum -{ - RANGERCHECK_OK = 0, - RANGERCHECK_NO_PRIV, - RANGERCHECK_UNKNOWN -} RangerACLResult; - -#endif http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/9de76890/src/backend/parser/parse_relation.c ---------------------------------------------------------------------- diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c index 811d2e2..08fb045 100644 --- a/src/backend/parser/parse_relation.c +++ b/src/backend/parser/parse_relation.c @@ -2712,12 +2712,90 @@ warnAutoRange(ParseState *pstate, RangeVar *relation, int location) void ExecCheckRTPerms(List *rangeTable) { + if (enable_ranger) + { + ExecCheckRTPermsWithRanger(rangeTable); + return; + } + /* ListCell *l; - + int i = 0; foreach(l, rangeTable) { ExecCheckRTEPerms((RangeTblEntry *) lfirst(l)); + i ++; } + */ +} + +/* + * 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; + } } /* @@ -2763,9 +2841,10 @@ ExecCheckRTEPerms(RangeTblEntry *rte) */ if (enable_ranger) { + elog(LOG, "ExecCheckRTEPerms: here"); /* ranger check required permission should all be approved.*/ if (pg_rangercheck(ACL_KIND_CLASS, relOid, userid, requiredPerms, ACLMASK_ALL) - != ACLCHECK_OK) + != RANGERCHECK_OK) { /* * If the table is a partition, return an error message that includes http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/9de76890/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/9de76890/src/include/utils/acl.h ---------------------------------------------------------------------- diff --git a/src/include/utils/acl.h b/src/include/utils/acl.h index b0ddde9..0fb9ca3 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" /* @@ -299,6 +300,7 @@ extern AclResult pg_foreign_server_nativecheck(Oid srv_oid, Oid roleid, AclMode 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); @@ -339,4 +341,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 */ http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/9de76890/src/include/utils/rangerrest.h ---------------------------------------------------------------------- diff --git a/src/include/utils/rangerrest.h b/src/include/utils/rangerrest.h new file mode 100644 index 0000000..4b73f46 --- /dev/null +++ b/src/include/utils/rangerrest.h @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/*------------------------------------------------------------------------- + * + * rangerrest.h + * routines to interact with Ranger REST API + * + *------------------------------------------------------------------------- + */ +#ifndef RANGERREST_H +#define RANGERREST_H + +#include <curl/curl.h> + +typedef enum +{ + RANGERCHECK_OK = 0, + RANGERCHECK_NO_PRIV, + RANGERCHECK_UNKNOWN +} RangerACLResult; + +#endif
