Add String object access hooks
authorAndrew Dunstan <andrew@dunslane.net>
Tue, 22 Mar 2022 13:06:15 +0000 (09:06 -0400)
committerAndrew Dunstan <andrew@dunslane.net>
Tue, 22 Mar 2022 14:28:31 +0000 (10:28 -0400)
This caters for cases where the access is to an object identified by
name rather than Oid.

The first user of these is the GUC access controls

Joshua Brindle and Mark Dilger

Discussion: https://postgr.es/m/47F87A0E-C0E5-43A6-89F6-D403F2B45175@enterprisedb.com

src/backend/catalog/objectaccess.c
src/backend/utils/misc/guc.c
src/include/catalog/objectaccess.h
src/include/nodes/parsenodes.h
src/include/utils/acl.h

index 549fac45392ab4e17b051f6b84cfbcb54b25b840..38922294e285d447fad58ef87b6356489883f6da 100644 (file)
  * and logging plugins.
  */
 object_access_hook_type object_access_hook = NULL;
+object_access_hook_type_str object_access_hook_str = NULL;
+
 
 /*
  * RunObjectPostCreateHook
  *
- * It is entrypoint of OAT_POST_CREATE event
+ * OAT_POST_CREATE object ID based event hook entrypoint
  */
 void
 RunObjectPostCreateHook(Oid classId, Oid objectId, int subId,
@@ -46,7 +48,7 @@ RunObjectPostCreateHook(Oid classId, Oid objectId, int subId,
 /*
  * RunObjectDropHook
  *
- * It is entrypoint of OAT_DROP event
+ * OAT_DROP object ID based event hook entrypoint
  */
 void
 RunObjectDropHook(Oid classId, Oid objectId, int subId,
@@ -68,7 +70,7 @@ RunObjectDropHook(Oid classId, Oid objectId, int subId,
 /*
  * RunObjectTruncateHook
  *
- * It is the entrypoint of OAT_TRUNCATE event
+ * OAT_TRUNCATE object ID based event hook entrypoint
  */
 void
 RunObjectTruncateHook(Oid objectId)
@@ -84,7 +86,7 @@ RunObjectTruncateHook(Oid objectId)
 /*
  * RunObjectPostAlterHook
  *
- * It is entrypoint of OAT_POST_ALTER event
+ * OAT_POST_ALTER object ID based event hook entrypoint
  */
 void
 RunObjectPostAlterHook(Oid classId, Oid objectId, int subId,
@@ -107,7 +109,7 @@ RunObjectPostAlterHook(Oid classId, Oid objectId, int subId,
 /*
  * RunNamespaceSearchHook
  *
- * It is entrypoint of OAT_NAMESPACE_SEARCH event
+ * OAT_NAMESPACE_SEARCH object ID based event hook entrypoint
  */
 bool
 RunNamespaceSearchHook(Oid objectId, bool ereport_on_violation)
@@ -131,7 +133,7 @@ RunNamespaceSearchHook(Oid objectId, bool ereport_on_violation)
 /*
  * RunFunctionExecuteHook
  *
- * It is entrypoint of OAT_FUNCTION_EXECUTE event
+ * OAT_FUNCTION_EXECUTE object ID based event hook entrypoint
  */
 void
 RunFunctionExecuteHook(Oid objectId)
@@ -143,3 +145,129 @@ RunFunctionExecuteHook(Oid objectId)
                           ProcedureRelationId, objectId, 0,
                           NULL);
 }
+
+/* String versions */
+
+
+/*
+ * RunObjectPostCreateHookStr
+ *
+ * OAT_POST_CREATE object name based event hook entrypoint
+ */
+void
+RunObjectPostCreateHookStr(Oid classId, const char *objectName, int subId,
+                       bool is_internal)
+{
+   ObjectAccessPostCreate pc_arg;
+
+   /* caller should check, but just in case... */
+   Assert(object_access_hook_str != NULL);
+
+   memset(&pc_arg, 0, sizeof(ObjectAccessPostCreate));
+   pc_arg.is_internal = is_internal;
+
+   (*object_access_hook_str) (OAT_POST_CREATE,
+                          classId, objectName, subId,
+                          (void *) &pc_arg);
+}
+
+/*
+ * RunObjectDropHookStr
+ *
+ * OAT_DROP object name based event hook entrypoint
+ */
+void
+RunObjectDropHookStr(Oid classId, const char *objectName, int subId,
+                 int dropflags)
+{
+   ObjectAccessDrop drop_arg;
+
+   /* caller should check, but just in case... */
+   Assert(object_access_hook_str != NULL);
+
+   memset(&drop_arg, 0, sizeof(ObjectAccessDrop));
+   drop_arg.dropflags = dropflags;
+
+   (*object_access_hook_str) (OAT_DROP,
+                          classId, objectName, subId,
+                          (void *) &drop_arg);
+}
+
+/*
+ * RunObjectTruncateHookStr
+ *
+ * OAT_TRUNCATE object name based event hook entrypoint
+ */
+void
+RunObjectTruncateHookStr(const char *objectName)
+{
+   /* caller should check, but just in case... */
+   Assert(object_access_hook_str != NULL);
+
+   (*object_access_hook_str) (OAT_TRUNCATE,
+                          RelationRelationId, objectName, 0,
+                          NULL);
+}
+
+/*
+ * RunObjectPostAlterHookStr
+ *
+ * OAT_POST_ALTER object name based event hook entrypoint
+ */
+void
+RunObjectPostAlterHookStr(Oid classId, const char *objectName, int subId,
+                      Oid auxiliaryId, bool is_internal)
+{
+   ObjectAccessPostAlter pa_arg;
+
+   /* caller should check, but just in case... */
+   Assert(object_access_hook_str != NULL);
+
+   memset(&pa_arg, 0, sizeof(ObjectAccessPostAlter));
+   pa_arg.auxiliary_id = auxiliaryId;
+   pa_arg.is_internal = is_internal;
+
+   (*object_access_hook_str) (OAT_POST_ALTER,
+                          classId, objectName, subId,
+                          (void *) &pa_arg);
+}
+
+/*
+ * RunNamespaceSearchHookStr
+ *
+ * OAT_NAMESPACE_SEARCH object name based event hook entrypoint
+ */
+bool
+RunNamespaceSearchHookStr(const char *objectName, bool ereport_on_violation)
+{
+   ObjectAccessNamespaceSearch ns_arg;
+
+   /* caller should check, but just in case... */
+   Assert(object_access_hook_str != NULL);
+
+   memset(&ns_arg, 0, sizeof(ObjectAccessNamespaceSearch));
+   ns_arg.ereport_on_violation = ereport_on_violation;
+   ns_arg.result = true;
+
+   (*object_access_hook_str) (OAT_NAMESPACE_SEARCH,
+                          NamespaceRelationId, objectName, 0,
+                          (void *) &ns_arg);
+
+   return ns_arg.result;
+}
+
+/*
+ * RunFunctionExecuteHookStr
+ *
+ * OAT_FUNCTION_EXECUTE object name based event hook entrypoint
+ */
+void
+RunFunctionExecuteHookStr(const char *objectName)
+{
+   /* caller should check, but just in case... */
+   Assert(object_access_hook_str != NULL);
+
+   (*object_access_hook_str) (OAT_FUNCTION_EXECUTE,
+                          ProcedureRelationId, objectName, 0,
+                          NULL);
+}
index e7f0a380e60185a4c825db88c9aa55eacdd723f8..932aefc777d7420105dcf4a48bc5e3da50c9faec 100644 (file)
@@ -43,6 +43,7 @@
 #include "access/xlog_internal.h"
 #include "access/xlogrecovery.h"
 #include "catalog/namespace.h"
+#include "catalog/objectaccess.h"
 #include "catalog/pg_authid.h"
 #include "catalog/storage.h"
 #include "commands/async.h"
@@ -8736,6 +8737,18 @@ AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt)
        replace_auto_config_value(&head, &tail, name, value);
    }
 
+   /*
+    * Invoke the post-alter hook for altering this GUC variable.
+    *
+    * We do this here rather than at the end, because ALTER SYSTEM is not
+    * transactional.  If the hook aborts our transaction, it will be cleaner
+    * to do so before we touch any files.
+    */
+   InvokeObjectPostAlterHookArgStr(InvalidOid, name,
+                                   ACL_ALTER_SYSTEM,
+                                   altersysstmt->setstmt->kind,
+                                   false);
+
    /*
     * To ensure crash safety, first write the new file data to a temp file,
     * then atomically rename it into place.
@@ -8907,6 +8920,10 @@ ExecSetVariableStmt(VariableSetStmt *stmt, bool isTopLevel)
            ResetAllOptions();
            break;
    }
+
+   /* Invoke the post-alter hook for setting this GUC variable. */
+   InvokeObjectPostAlterHookArgStr(InvalidOid, stmt->name,
+                                   ACL_SET_VALUE, stmt->kind, false);
 }
 
 /*
index 508dfd0a6b36706cc96ea2487a6dfc6d728f96aa..4d54ae2a7d4ae2051a2790734c65399b580f4389 100644 (file)
@@ -121,15 +121,23 @@ typedef struct
    bool        result;
 } ObjectAccessNamespaceSearch;
 
-/* Plugin provides a hook function matching this signature. */
+/* Plugin provides a hook function matching one or both of these signatures. */
 typedef void (*object_access_hook_type) (ObjectAccessType access,
                                         Oid classId,
                                         Oid objectId,
                                         int subId,
                                         void *arg);
 
+typedef void (*object_access_hook_type_str) (ObjectAccessType access,
+                                        Oid classId,
+                                        const char *objectStr,
+                                        int subId,
+                                        void *arg);
+
 /* Plugin sets this variable to a suitable hook function. */
 extern PGDLLIMPORT object_access_hook_type object_access_hook;
+extern PGDLLIMPORT object_access_hook_type_str object_access_hook_str;
+
 
 /* Core code uses these functions to call the hook (see macros below). */
 extern void RunObjectPostCreateHook(Oid classId, Oid objectId, int subId,
@@ -142,6 +150,18 @@ extern void RunObjectPostAlterHook(Oid classId, Oid objectId, int subId,
 extern bool RunNamespaceSearchHook(Oid objectId, bool ereport_on_violation);
 extern void RunFunctionExecuteHook(Oid objectId);
 
+/* String versions */
+extern void RunObjectPostCreateHookStr(Oid classId, const char *objectStr, int subId,
+                                   bool is_internal);
+extern void RunObjectDropHookStr(Oid classId, const char *objectStr, int subId,
+                             int dropflags);
+extern void RunObjectTruncateHookStr(const char *objectStr);
+extern void RunObjectPostAlterHookStr(Oid classId, const char *objectStr, int subId,
+                                  Oid auxiliaryId, bool is_internal);
+extern bool RunNamespaceSearchHookStr(const char *objectStr, bool ereport_on_violation);
+extern void RunFunctionExecuteHookStr(const char *objectStr);
+
+
 /*
  * The following macros are wrappers around the functions above; these should
  * normally be used to invoke the hook in lieu of calling the above functions
@@ -194,4 +214,52 @@ extern void RunFunctionExecuteHook(Oid objectId);
            RunFunctionExecuteHook(objectId);   \
    } while(0)
 
+
+#define InvokeObjectPostCreateHookStr(classId,objectName,subId)            \
+   InvokeObjectPostCreateHookArgStr((classId),(objectName),(subId),false)
+#define InvokeObjectPostCreateHookArgStr(classId,objectName,subId,is_internal) \
+   do {                                                            \
+       if (object_access_hook_str)                                     \
+           RunObjectPostCreateHookStr((classId),(objectName),(subId),  \
+                                   (is_internal));                 \
+   } while(0)
+
+#define InvokeObjectDropHookStr(classId,objectName,subId)              \
+   InvokeObjectDropHookArgStr((classId),(objectName),(subId),0)
+#define InvokeObjectDropHookArgStr(classId,objectName,subId,dropflags) \
+   do {                                                            \
+       if (object_access_hook_str)                                     \
+           RunObjectDropHookStr((classId),(objectName),(subId),            \
+                             (dropflags));                         \
+   } while(0)
+
+#define InvokeObjectTruncateHookStr(objectName)                            \
+   do {                                                            \
+       if (object_access_hook_str)                                     \
+           RunObjectTruncateHookStr(objectName);                       \
+   } while(0)
+
+#define InvokeObjectPostAlterHookStr(className,objectName,subId)           \
+   InvokeObjectPostAlterHookArgStr((classId),(objectName),(subId),     \
+                                InvalidOid,false)
+#define InvokeObjectPostAlterHookArgStr(classId,objectName,subId,      \
+                                    auxiliaryId,is_internal)       \
+   do {                                                            \
+       if (object_access_hook_str)                                     \
+           RunObjectPostAlterHookStr((classId),(objectName),(subId),   \
+                                  (auxiliaryId),(is_internal));    \
+   } while(0)
+
+#define InvokeNamespaceSearchHookStr(objectName, ereport_on_violation) \
+   (!object_access_hook_str                                        \
+    ? true                                                         \
+    : RunNamespaceSearchHookStr((objectName), (ereport_on_violation)))
+
+#define InvokeFunctionExecuteHookStr(objectName)       \
+   do {                                        \
+       if (object_access_hook_str)                 \
+           RunFunctionExecuteHookStr(objectName);  \
+   } while(0)
+
+
 #endif                         /* OBJECTACCESS_H */
index 6f83a79a96c3d4ca7c2ba93206334c307cd8bf08..2f618cb22926831b3544233128cff16bd5ea13b5 100644 (file)
@@ -92,7 +92,9 @@ typedef uint32 AclMode;           /* a bitmask of privilege bits */
 #define ACL_CREATE     (1<<9)  /* for namespaces and databases */
 #define ACL_CREATE_TEMP (1<<10) /* for databases */
 #define ACL_CONNECT        (1<<11) /* for databases */
-#define N_ACL_RIGHTS   12      /* 1 plus the last 1<<x */
+#define ACL_SET_VALUE  (1<<12) /* for configuration parameters */
+#define ACL_ALTER_SYSTEM (1<<13) /* for configuration parameters */
+#define N_ACL_RIGHTS   14      /* 1 plus the last 1<<x */
 #define ACL_NO_RIGHTS  0
 /* Currently, SELECT ... FOR [KEY] UPDATE/SHARE requires UPDATE privileges */
 #define ACL_SELECT_FOR_UPDATE  ACL_UPDATE
index 1ce4c5556e70610b3f02ea0de992e5806b501318..91ce3d8e9c352b64ffcc2add234b72b25f899511 100644 (file)
@@ -146,9 +146,11 @@ typedef struct ArrayType Acl;
 #define ACL_CREATE_CHR         'C'
 #define ACL_CREATE_TEMP_CHR        'T'
 #define ACL_CONNECT_CHR            'c'
+#define ACL_SET_VALUE_CHR      's'
+#define ACL_ALTER_SYSTEM_CHR   'A'
 
 /* string holding all privilege code chars, in order by bitmask position */
-#define ACL_ALL_RIGHTS_STR "arwdDxtXUCTc"
+#define ACL_ALL_RIGHTS_STR "arwdDxtXUCTcsA"
 
 /*
  * Bitmasks defining "all rights" for each supported object type