From cc1ed40d57aa68322e43a7b0a3320a6c5aff010a Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Thu, 25 Nov 2010 11:48:49 -0500 Subject: [PATCH] Object access hook framework, with post-creation hook. After a SQL object is created, we provide an opportunity for security or logging plugins to get control; for example, a security label provider could use this to assign an initial security label to newly created objects. The basic infrastructure is (hopefully) reusable for other types of events that might require similar treatment. KaiGai Kohei, with minor adjustments. --- src/backend/catalog/heap.c | 4 ++ src/backend/catalog/pg_constraint.c | 4 ++ src/backend/catalog/pg_conversion.c | 5 +++ src/backend/catalog/pg_namespace.c | 4 ++ src/backend/catalog/pg_operator.c | 9 +++++ src/backend/catalog/pg_proc.c | 4 ++ src/backend/catalog/pg_type.c | 7 ++++ src/backend/commands/dbcommands.c | 4 ++ src/backend/commands/foreigncmds.c | 11 ++++++ src/backend/commands/functioncmds.c | 5 +++ src/backend/commands/opclasscmds.c | 9 +++++ src/backend/commands/proclang.c | 5 +++ src/backend/commands/tablecmds.c | 5 +++ src/backend/commands/tablespace.c | 5 +++ src/backend/commands/trigger.c | 5 +++ src/backend/commands/tsearchcmds.c | 14 +++++++ src/backend/commands/user.c | 4 ++ src/backend/rewrite/rewriteDefine.c | 5 +++ src/backend/storage/large_object/inv_api.c | 5 +++ src/backend/utils/init/globals.c | 7 ++++ src/include/catalog/objectaccess.h | 46 ++++++++++++++++++++++ 21 files changed, 167 insertions(+) create mode 100644 src/include/catalog/objectaccess.h diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index dcc53e13a1..9b7668c133 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -40,6 +40,7 @@ #include "catalog/index.h" #include "catalog/indexing.h" #include "catalog/namespace.h" +#include "catalog/objectaccess.h" #include "catalog/pg_attrdef.h" #include "catalog/pg_constraint.h" #include "catalog/pg_inherits.h" @@ -1188,6 +1189,9 @@ heap_create_with_catalog(const char *relname, } } + /* Post creation hook for new relation */ + InvokeObjectAccessHook(OAT_POST_CREATE, RelationRelationId, relid, 0); + /* * Store any supplied constraints and defaults. * diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c index 8b4f8c636f..db0507b8c7 100644 --- a/src/backend/catalog/pg_constraint.c +++ b/src/backend/catalog/pg_constraint.c @@ -18,6 +18,7 @@ #include "access/heapam.h" #include "catalog/dependency.h" #include "catalog/indexing.h" +#include "catalog/objectaccess.h" #include "catalog/pg_constraint.h" #include "catalog/pg_operator.h" #include "catalog/pg_type.h" @@ -360,6 +361,9 @@ CreateConstraintEntry(const char *constraintName, DEPENDENCY_NORMAL); } + /* Post creation hook for new constraint */ + InvokeObjectAccessHook(OAT_POST_CREATE, ConstraintRelationId, conOid, 0); + return conOid; } diff --git a/src/backend/catalog/pg_conversion.c b/src/backend/catalog/pg_conversion.c index 957818403f..5f1f1de451 100644 --- a/src/backend/catalog/pg_conversion.c +++ b/src/backend/catalog/pg_conversion.c @@ -18,6 +18,7 @@ #include "access/sysattr.h" #include "catalog/dependency.h" #include "catalog/indexing.h" +#include "catalog/objectaccess.h" #include "catalog/pg_conversion.h" #include "catalog/pg_conversion_fn.h" #include "catalog/pg_namespace.h" @@ -131,6 +132,10 @@ ConversionCreate(const char *conname, Oid connamespace, recordDependencyOnOwner(ConversionRelationId, HeapTupleGetOid(tup), conowner); + /* Post creation hook for new conversion */ + InvokeObjectAccessHook(OAT_POST_CREATE, + ConversionRelationId, HeapTupleGetOid(tup), 0); + heap_freetuple(tup); heap_close(rel, RowExclusiveLock); diff --git a/src/backend/catalog/pg_namespace.c b/src/backend/catalog/pg_namespace.c index 71ebd7aa82..0387423d9f 100644 --- a/src/backend/catalog/pg_namespace.c +++ b/src/backend/catalog/pg_namespace.c @@ -17,6 +17,7 @@ #include "access/heapam.h" #include "catalog/dependency.h" #include "catalog/indexing.h" +#include "catalog/objectaccess.h" #include "catalog/pg_namespace.h" #include "utils/builtins.h" #include "utils/rel.h" @@ -75,5 +76,8 @@ NamespaceCreate(const char *nspName, Oid ownerId) /* Record dependency on owner */ recordDependencyOnOwner(NamespaceRelationId, nspoid, ownerId); + /* Post creation hook for new schema */ + InvokeObjectAccessHook(OAT_POST_CREATE, NamespaceRelationId, nspoid, 0); + return nspoid; } diff --git a/src/backend/catalog/pg_operator.c b/src/backend/catalog/pg_operator.c index 73de672520..3e97374371 100644 --- a/src/backend/catalog/pg_operator.c +++ b/src/backend/catalog/pg_operator.c @@ -22,6 +22,7 @@ #include "catalog/dependency.h" #include "catalog/indexing.h" #include "catalog/namespace.h" +#include "catalog/objectaccess.h" #include "catalog/pg_namespace.h" #include "catalog/pg_operator.h" #include "catalog/pg_proc.h" @@ -273,6 +274,10 @@ OperatorShellMake(const char *operatorName, heap_freetuple(tup); + /* Post creation hook for new shell operator */ + InvokeObjectAccessHook(OAT_POST_CREATE, + OperatorRelationId, operatorObjectId, 0); + /* * Make sure the tuple is visible for subsequent lookups/updates. */ @@ -539,6 +544,10 @@ OperatorCreate(const char *operatorName, /* Add dependencies for the entry */ makeOperatorDependencies(tup); + /* Post creation hook for new operator */ + InvokeObjectAccessHook(OAT_POST_CREATE, + OperatorRelationId, operatorObjectId, 0); + heap_close(pg_operator_desc, RowExclusiveLock); /* diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c index 34cd862d27..d464979bc7 100644 --- a/src/backend/catalog/pg_proc.c +++ b/src/backend/catalog/pg_proc.c @@ -18,6 +18,7 @@ #include "access/xact.h" #include "catalog/dependency.h" #include "catalog/indexing.h" +#include "catalog/objectaccess.h" #include "catalog/pg_language.h" #include "catalog/pg_namespace.h" #include "catalog/pg_proc.h" @@ -616,6 +617,9 @@ ProcedureCreate(const char *procedureName, heap_freetuple(tup); + /* Post creation hook for new function */ + InvokeObjectAccessHook(OAT_POST_CREATE, ProcedureRelationId, retval, 0); + heap_close(rel, RowExclusiveLock); /* Verify function body */ diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c index d7fccdf07b..85368202d8 100644 --- a/src/backend/catalog/pg_type.c +++ b/src/backend/catalog/pg_type.c @@ -18,6 +18,7 @@ #include "access/xact.h" #include "catalog/dependency.h" #include "catalog/indexing.h" +#include "catalog/objectaccess.h" #include "catalog/pg_namespace.h" #include "catalog/pg_proc.h" #include "catalog/pg_type.h" @@ -155,6 +156,9 @@ TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId) NULL, false); + /* Post creation hook for new shell type */ + InvokeObjectAccessHook(OAT_POST_CREATE, TypeRelationId, typoid, 0); + /* * clean up and return the type-oid */ @@ -455,6 +459,9 @@ TypeCreate(Oid newTypeOid, NULL), rebuildDeps); + /* Post creation hook for new type */ + InvokeObjectAccessHook(OAT_POST_CREATE, TypeRelationId, typeObjectId, 0); + /* * finish up */ diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c index 8cbd7548f9..09c6632a3b 100644 --- a/src/backend/commands/dbcommands.c +++ b/src/backend/commands/dbcommands.c @@ -32,6 +32,7 @@ #include "catalog/catalog.h" #include "catalog/dependency.h" #include "catalog/indexing.h" +#include "catalog/objectaccess.h" #include "catalog/pg_authid.h" #include "catalog/pg_database.h" #include "catalog/pg_db_role_setting.h" @@ -572,6 +573,9 @@ createdb(const CreatedbStmt *stmt) /* Create pg_shdepend entries for objects within database */ copyTemplateDependencies(src_dboid, dboid); + /* Post creation hook for new database */ + InvokeObjectAccessHook(OAT_POST_CREATE, DatabaseRelationId, dboid, 0); + /* * Force a checkpoint before starting the copy. This will force dirty * buffers out to disk, to ensure source database is up-to-date on disk diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c index 4e6367c526..71ba806851 100644 --- a/src/backend/commands/foreigncmds.c +++ b/src/backend/commands/foreigncmds.c @@ -18,6 +18,7 @@ #include "catalog/catalog.h" #include "catalog/dependency.h" #include "catalog/indexing.h" +#include "catalog/objectaccess.h" #include "catalog/pg_foreign_data_wrapper.h" #include "catalog/pg_foreign_server.h" #include "catalog/pg_proc.h" @@ -415,6 +416,10 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt) recordDependencyOnOwner(ForeignDataWrapperRelationId, fdwId, ownerId); + /* Post creation hook for new foreign data wrapper */ + InvokeObjectAccessHook(OAT_POST_CREATE, + ForeignDataWrapperRelationId, fdwId, 0); + heap_close(rel, NoLock); } @@ -696,6 +701,9 @@ CreateForeignServer(CreateForeignServerStmt *stmt) recordDependencyOnOwner(ForeignServerRelationId, srvId, ownerId); + /* Post creation hook for new foreign server */ + InvokeObjectAccessHook(OAT_POST_CREATE, ForeignServerRelationId, srvId, 0); + heap_close(rel, NoLock); } @@ -967,6 +975,9 @@ CreateUserMapping(CreateUserMappingStmt *stmt) /* Record the mapped user dependency */ recordDependencyOnOwner(UserMappingRelationId, umId, useId); + /* Post creation hook for new user mapping */ + InvokeObjectAccessHook(OAT_POST_CREATE, UserMappingRelationId, umId, 0); + heap_close(rel, NoLock); } diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c index 62a2110251..2347cad694 100644 --- a/src/backend/commands/functioncmds.c +++ b/src/backend/commands/functioncmds.c @@ -37,6 +37,7 @@ #include "access/sysattr.h" #include "catalog/dependency.h" #include "catalog/indexing.h" +#include "catalog/objectaccess.h" #include "catalog/pg_aggregate.h" #include "catalog/pg_cast.h" #include "catalog/pg_language.h" @@ -1761,6 +1762,10 @@ CreateCast(CreateCastStmt *stmt) recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); } + /* Post creation hook for new cast */ + InvokeObjectAccessHook(OAT_POST_CREATE, + CastRelationId, myself.objectId, 0); + heap_freetuple(tuple); heap_close(relation, RowExclusiveLock); diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c index 132c4ee1e5..5055fb17cd 100644 --- a/src/backend/commands/opclasscmds.c +++ b/src/backend/commands/opclasscmds.c @@ -22,6 +22,7 @@ #include "access/sysattr.h" #include "catalog/dependency.h" #include "catalog/indexing.h" +#include "catalog/objectaccess.h" #include "catalog/pg_amop.h" #include "catalog/pg_amproc.h" #include "catalog/pg_namespace.h" @@ -307,6 +308,10 @@ CreateOpFamily(char *amname, char *opfname, Oid namespaceoid, Oid amoid) /* dependency on owner */ recordDependencyOnOwner(OperatorFamilyRelationId, opfamilyoid, GetUserId()); + /* Post creation hook for new operator family */ + InvokeObjectAccessHook(OAT_POST_CREATE, + OperatorFamilyRelationId, opfamilyoid, 0); + heap_close(rel, RowExclusiveLock); return opfamilyoid; @@ -703,6 +708,10 @@ DefineOpClass(CreateOpClassStmt *stmt) /* dependency on owner */ recordDependencyOnOwner(OperatorClassRelationId, opclassoid, GetUserId()); + /* Post creation hook for new operator class */ + InvokeObjectAccessHook(OAT_POST_CREATE, + OperatorClassRelationId, opclassoid, 0); + heap_close(rel, RowExclusiveLock); } diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c index a2e653af80..9d0d3b2154 100644 --- a/src/backend/commands/proclang.c +++ b/src/backend/commands/proclang.c @@ -17,6 +17,7 @@ #include "access/heapam.h" #include "catalog/dependency.h" #include "catalog/indexing.h" +#include "catalog/objectaccess.h" #include "catalog/pg_language.h" #include "catalog/pg_namespace.h" #include "catalog/pg_pltemplate.h" @@ -425,6 +426,10 @@ create_proc_lang(const char *languageName, bool replace, recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); } + /* Post creation hook for new procedural language */ + InvokeObjectAccessHook(OAT_POST_CREATE, + LanguageRelationId, myself.objectId, 0); + heap_close(rel, RowExclusiveLock); } diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index e8808e28c6..937992ba58 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -26,6 +26,7 @@ #include "catalog/index.h" #include "catalog/indexing.h" #include "catalog/namespace.h" +#include "catalog/objectaccess.h" #include "catalog/pg_constraint.h" #include "catalog/pg_depend.h" #include "catalog/pg_inherits.h" @@ -4080,6 +4081,10 @@ ATExecAddColumn(AlteredTableInfo *tab, Relation rel, heap_freetuple(reltup); + /* Post creation hook for new attribute */ + InvokeObjectAccessHook(OAT_POST_CREATE, + RelationRelationId, myrelid, newattnum); + heap_close(pgclass, RowExclusiveLock); /* Make the attribute's catalog entry visible */ diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c index 305ac46b40..5ba0f1ca9d 100644 --- a/src/backend/commands/tablespace.c +++ b/src/backend/commands/tablespace.c @@ -59,6 +59,7 @@ #include "catalog/catalog.h" #include "catalog/dependency.h" #include "catalog/indexing.h" +#include "catalog/objectaccess.h" #include "catalog/pg_tablespace.h" #include "commands/comment.h" #include "commands/defrem.h" @@ -333,6 +334,10 @@ CreateTableSpace(CreateTableSpaceStmt *stmt) /* Record dependency on owner */ recordDependencyOnOwner(TableSpaceRelationId, tablespaceoid, ownerId); + /* Post creation hook for new tablespace */ + InvokeObjectAccessHook(OAT_POST_CREATE, + TableSpaceRelationId, tablespaceoid, 0); + create_tablespace_directories(location, tablespaceoid); /* Record the filesystem change in XLOG */ diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index d69fdcf410..8195392f16 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -20,6 +20,7 @@ #include "catalog/catalog.h" #include "catalog/dependency.h" #include "catalog/indexing.h" +#include "catalog/objectaccess.h" #include "catalog/pg_constraint.h" #include "catalog/pg_proc.h" #include "catalog/pg_trigger.h" @@ -735,6 +736,10 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString, recordDependencyOnExpr(&myself, whenClause, whenRtable, DEPENDENCY_NORMAL); + /* Post creation hook for new trigger */ + InvokeObjectAccessHook(OAT_POST_CREATE, + TriggerRelationId, trigoid, 0); + /* Keep lock on target rel until end of xact */ heap_close(rel, NoLock); diff --git a/src/backend/commands/tsearchcmds.c b/src/backend/commands/tsearchcmds.c index 73b8c9248b..412b1d278d 100644 --- a/src/backend/commands/tsearchcmds.c +++ b/src/backend/commands/tsearchcmds.c @@ -23,6 +23,7 @@ #include "catalog/dependency.h" #include "catalog/indexing.h" #include "catalog/namespace.h" +#include "catalog/objectaccess.h" #include "catalog/pg_namespace.h" #include "catalog/pg_proc.h" #include "catalog/pg_ts_config.h" @@ -263,6 +264,9 @@ DefineTSParser(List *names, List *parameters) makeParserDependencies(tup); + /* Post creation hook for new text search parser */ + InvokeObjectAccessHook(OAT_POST_CREATE, TSParserRelationId, prsOid, 0); + heap_freetuple(tup); heap_close(prsRel, RowExclusiveLock); @@ -563,6 +567,10 @@ DefineTSDictionary(List *names, List *parameters) makeDictionaryDependencies(tup); + /* Post creation hook for new text search dictionary */ + InvokeObjectAccessHook(OAT_POST_CREATE, + TSDictionaryRelationId, dictOid, 0); + heap_freetuple(tup); heap_close(dictRel, RowExclusiveLock); @@ -1050,6 +1058,9 @@ DefineTSTemplate(List *names, List *parameters) makeTSTemplateDependencies(tup); + /* Post creation hook for new text search template */ + InvokeObjectAccessHook(OAT_POST_CREATE, TSTemplateRelationId, dictOid, 0); + heap_freetuple(tup); heap_close(tmplRel, RowExclusiveLock); @@ -1440,6 +1451,9 @@ DefineTSConfiguration(List *names, List *parameters) makeConfigurationDependencies(tup, false, mapRel); + /* Post creation hook for new text search configuration */ + InvokeObjectAccessHook(OAT_POST_CREATE, TSConfigRelationId, cfgOid, 0); + heap_freetuple(tup); if (mapRel) diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c index f1ff839877..2634ca10e6 100644 --- a/src/backend/commands/user.c +++ b/src/backend/commands/user.c @@ -17,6 +17,7 @@ #include "access/xact.h" #include "catalog/dependency.h" #include "catalog/indexing.h" +#include "catalog/objectaccess.h" #include "catalog/pg_auth_members.h" #include "catalog/pg_authid.h" #include "catalog/pg_database.h" @@ -402,6 +403,9 @@ CreateRole(CreateRoleStmt *stmt) rolemembers, roleNamesToIds(rolemembers), GetUserId(), false); + /* Post creation hook for new role */ + InvokeObjectAccessHook(OAT_POST_CREATE, AuthIdRelationId, roleid, 0); + /* * Close pg_authid, but keep lock till commit. */ diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c index 029a2888a7..4354897981 100644 --- a/src/backend/rewrite/rewriteDefine.c +++ b/src/backend/rewrite/rewriteDefine.c @@ -19,6 +19,7 @@ #include "catalog/dependency.h" #include "catalog/indexing.h" #include "catalog/namespace.h" +#include "catalog/objectaccess.h" #include "catalog/pg_rewrite.h" #include "catalog/storage.h" #include "miscadmin.h" @@ -177,6 +178,10 @@ InsertRule(char *rulname, DEPENDENCY_NORMAL); } + /* Post creation hook for new rule */ + InvokeObjectAccessHook(OAT_POST_CREATE, + RewriteRelationId, rewriteObjectId, 0); + heap_close(pg_rewrite_desc, RowExclusiveLock); return rewriteObjectId; diff --git a/src/backend/storage/large_object/inv_api.c b/src/backend/storage/large_object/inv_api.c index e2faf95d93..686770cd45 100644 --- a/src/backend/storage/large_object/inv_api.c +++ b/src/backend/storage/large_object/inv_api.c @@ -38,6 +38,7 @@ #include "catalog/catalog.h" #include "catalog/dependency.h" #include "catalog/indexing.h" +#include "catalog/objectaccess.h" #include "catalog/pg_largeobject.h" #include "catalog/pg_largeobject_metadata.h" #include "commands/comment.h" @@ -218,6 +219,10 @@ inv_create(Oid lobjId) recordDependencyOnOwner(LargeObjectRelationId, lobjId_new, GetUserId()); + /* Post creation hook for new large object */ + InvokeObjectAccessHook(OAT_POST_CREATE, + LargeObjectRelationId, lobjId_new, 0); + /* * Advance command counter to make new tuple visible to later operations. */ diff --git a/src/backend/utils/init/globals.c b/src/backend/utils/init/globals.c index 9aa2c0a498..5855fe4666 100644 --- a/src/backend/utils/init/globals.c +++ b/src/backend/utils/init/globals.c @@ -18,6 +18,7 @@ */ #include "postgres.h" +#include "catalog/objectaccess.h" #include "libpq/pqcomm.h" #include "miscadmin.h" #include "storage/backendid.h" @@ -117,3 +118,9 @@ int VacuumCostBalance = 0; /* working state for vacuum */ bool VacuumCostActive = false; int GinFuzzySearchLimit = 0; + +/* + * Hook on object accesses. This is intended as infrastructure for security + * and logging plugins. + */ +PGDLLIMPORT object_access_hook_type object_access_hook = NULL; diff --git a/src/include/catalog/objectaccess.h b/src/include/catalog/objectaccess.h new file mode 100644 index 0000000000..88508b0103 --- /dev/null +++ b/src/include/catalog/objectaccess.h @@ -0,0 +1,46 @@ +/* + * objectaccess.h + * + * Object access hooks. + * + * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + */ + +#ifndef OBJECTACCESS_H +#define OBJECTACCESS_H + +/* + * Object access hooks are intended to be called just before or just after + * performing certain actions on a SQL object. This is intended as + * infrastructure for security or logging pluggins. + * + * OAT_POST_CREATE should be invoked just after the the object is created. + * Typically, this is done after inserting the primary catalog records and + * associated dependencies. + * + * Other types may be added in the future. + */ +typedef enum ObjectAccessType +{ + OAT_POST_CREATE, +} ObjectAccessType; + +/* + * Hook, and a macro to invoke it. + */ + +typedef void (*object_access_hook_type)(ObjectAccessType access, + Oid classId, + Oid objectId, + int subId); + +extern PGDLLIMPORT object_access_hook_type object_access_hook; + +#define InvokeObjectAccessHook(access,classId,objectId,subId) \ + do { \ + if (object_access_hook) \ + (*object_access_hook)((access),(classId),(objectId),(subId)); \ + } while(0) + +#endif /* OBJECTACCESS_H */