hawq-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From hubertzh...@apache.org
Subject [2/2] incubator-hawq git commit: HAWQ-1001. Implement HAWQ basic user ACL check through Ranger.
Date Fri, 16 Dec 2016 03:55:51 GMT
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/111655e3
Tree: http://git-wip-us.apache.org/repos/asf/incubator-hawq/tree/111655e3
Diff: http://git-wip-us.apache.org/repos/asf/incubator-hawq/diff/111655e3

Branch: refs/heads/master
Commit: 111655e36c545293d84fd1881448b3d2262a6c3c
Parents: 78aa094
Author: hzhang2 <zhanghuan929@163.com>
Authored: Fri Dec 16 11:49:58 2016 +0800
Committer: hzhang2 <zhanghuan929@163.com>
Committed: Fri Dec 16 11:49:58 2016 +0800

----------------------------------------------------------------------
 src/backend/catalog/aclchk.c        | 811 +++++++++++++++++++++++++++++--
 src/backend/parser/parse_relation.c | 126 ++++-
 src/include/parser/parse_relation.h |   1 +
 src/include/utils/acl.h             |  60 +++
 4 files changed, 936 insertions(+), 62 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/111655e3/src/backend/catalog/aclchk.c
----------------------------------------------------------------------
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index 3fa616f..f13502e 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,549 @@ 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, "%s", database_name);
+  appendStringInfoChar(&tname, '.');
+  appendStringInfo(&tname, "%s", schema_name);
+  appendStringInfoChar(&tname, '.');
+  appendStringInfo(&tname, "%s", 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, "%s", database_name);
+  appendStringInfoChar(&tname, '.');
+  appendStringInfo(&tname, "%s", schema_name);
+  appendStringInfoChar(&tname, '.');
+  appendStringInfo(&tname, "%s", 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, "%s", database_name);
+  appendStringInfoChar(&tname, '.');
+  appendStringInfo(&tname, "%s", schema_name);
+  appendStringInfoChar(&tname, '.');
+  appendStringInfo(&tname, "%s", 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, "%s", database_name);
+  appendStringInfoChar(&tname, '.');
+  appendStringInfo(&tname, "%s", 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, "%s", database_name);
+  appendStringInfoChar(&tname, '.');
+  appendStringInfo(&tname, "%s", 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;
+}
+
+bool fallBackToNativeChecks(AclObjectKind objkind, List* table_list, Oid roleid)
+{
+  //for heap table, we fall back to native check.
+  if(objkind == ACL_KIND_CLASS)
+  {
+    ListCell   *l;
+    foreach(l, table_list)
+    {
+      RangeTblEntry *rte=(RangeTblEntry *) lfirst(l);
+      char relstorage = get_rel_relstorage(rte->relid);
+      if(relstorage == 'h')
+      {
+        return true;
+      }
+    }
+
+  }
+  return false;
+}
+
+/*
+ * 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;
+    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);
+
+  } // 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) {
+    ListCell   *cell = list_head(requestargs);
+    while (cell != NULL)
+    {
+      ListCell   *tmp = cell;
+      cell = lnext(cell);
+      RangerRequestJsonArgs* requestarg =
+          (RangerRequestJsonArgs*)lfirst(tmp);
+      pfree(requestarg->user);
+      pfree(requestarg->object);
+      pfree(requestarg->actions);
+    }
+
+    list_free_deep(requestargs);
+    requestargs = NULL;
+  }
+
+  if(ret != RANGERCHECK_OK){
+    elog(ERROR, "ACL check failed\n");
+  }
+  elog(LOG, "oids%d\n", arg_list->length);
+  return aclresults;
+}
+
+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 ret;
+}
+
 /*
  * Relay for the various pg_*_mask routines depending on object kind
  */
@@ -3085,6 +3637,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 +3776,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 +3792,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 +3808,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 +3824,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 +3840,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 +3856,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 +3873,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 +3890,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 +3907,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 +3923,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/111655e3/src/backend/parser/parse_relation.c
----------------------------------------------------------------------
diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c
index b49b72e..176ed0b 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 && !fallBackToNativeChecks(ACL_KIND_CLASS,rangeTable,GetUserId()))
+  {
+    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, "ACL check failed\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/111655e3/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/111655e3/src/include/utils/acl.h
----------------------------------------------------------------------
diff --git a/src/include/utils/acl.h b/src/include/utils/acl.h
index 80c21ff..a8c9e64 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,42 @@ 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 bool fallBackToNativeChecks(AclObjectKind objkind, List* table_list, 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 +343,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 */



Mime
View raw message