Repository: incubator-hawq Updated Branches: refs/heads/ranger 9de76890c -> 64ae1a875 (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/64ae1a87 Tree: http://git-wip-us.apache.org/repos/asf/incubator-hawq/tree/64ae1a87 Diff: http://git-wip-us.apache.org/repos/asf/incubator-hawq/diff/64ae1a87 Branch: refs/heads/ranger Commit: 64ae1a8758e8ae27b042c3a3adafae60ef32da75 Parents: b22d208 Author: xunzhang <[email protected]> Authored: Mon Dec 5 19:12:18 2016 +0800 Committer: xunzhang <[email protected]> Committed: Sun Dec 11 13:59:48 2016 +0800 ---------------------------------------------------------------------- src/backend/catalog/aclchk.c | 68 ++++++++++++- src/backend/libpq/rangerrest.c | 164 ++++++++++++++++++++++++++++++- src/backend/libpq/rangerrest.h | 39 -------- src/backend/parser/parse_relation.c | 81 ++++++++++++++- src/include/parser/parse_relation.h | 1 + src/include/utils/acl.h | 25 +++++ src/include/utils/rangerrest.h | 39 ++++++++ 7 files changed, 371 insertions(+), 46 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/64ae1a87/src/backend/catalog/aclchk.c ---------------------------------------------------------------------- diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c index 06f20f3..2837331 100644 --- a/src/backend/catalog/aclchk.c +++ b/src/backend/catalog/aclchk.c @@ -2664,6 +2664,72 @@ List *getActionName(AclMode mask) return actions; } +/* + * return: List of RangerPrivilegeResults + * arg_list: List of RangerPrivilegeArgs + */ +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) @@ -2687,11 +2753,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 */ http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/64ae1a87/src/backend/libpq/rangerrest.c ---------------------------------------------------------------------- diff --git a/src/backend/libpq/rangerrest.c b/src/backend/libpq/rangerrest.c index 032a6c0..2a9625e 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,133 @@ char* AclObjectKindStr[] = "none" /* MUST BE LAST */ }; +/* + * args: List of RangerRequestJsonArgs + */ +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 +257,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); @@ -309,13 +436,44 @@ _exit: } /* + * arg_list: List of RangerRequestJsonArgs + */ +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 */ 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/64ae1a87/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/64ae1a87/src/backend/parser/parse_relation.c ---------------------------------------------------------------------- diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c index 811d2e2..0c6e0fb 100644 --- a/src/backend/parser/parse_relation.c +++ b/src/backend/parser/parse_relation.c @@ -2712,12 +2712,88 @@ warnAutoRange(ParseState *pstate, RangeVar *relation, int location) void ExecCheckRTPerms(List *rangeTable) { + if (enable_ranger) + { + ExecCheckRTPermsWithRanger(rangeTable); + return; + } + /* ListCell *l; - foreach(l, rangeTable) { ExecCheckRTEPerms((RangeTblEntry *) lfirst(l)); } + */ +} + +/* + * 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 +2839,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/64ae1a87/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/64ae1a87/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/64ae1a87/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
