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 */

Reply via email to