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.
This commit is contained in:
Robert Haas 2010-11-25 11:48:49 -05:00
parent d3c1265443
commit cc1ed40d57
21 changed files with 167 additions and 0 deletions

View File

@ -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.
*

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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);
/*

View File

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

View File

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

View File

@ -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

View File

@ -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);
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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);
}

View File

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

View File

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

View File

@ -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);

View File

@ -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)

View File

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

View File

@ -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;

View File

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

View File

@ -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;

View File

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