Hi,
In the last meeting we discussed that we should try and catch DDLs at a
central place to block them for taking backup and for that we should try
and use object access hooks. The comments at top of the file
src/include/catalog/objectaccess.h read
* 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 object is created.
* Typically, this is done after inserting the primary catalog records and
* associated dependencies.
*
* OAT_DROP should be invoked just before deletion of objects; typically
* deleteOneObject(). Its arguments are packed within ObjectAccessDrop.
Please note that since object access hooks are called AFTER the creation of
objects we cannot use them to block object creation.
The way object access hooks work is that they have added a function
call InvokeObjectAccessHook at the end of every object creation. This means
that they have added a function call at the end
of CollationCreate, OperatorCreate, TypeShellMake and so on. If we choose
to add another object access hook type say OAT_PRE_CREATE, we will have to
call the function InvokeObjectAccessHook at the start of every object
create function, which again won't be a central place.
Another point discussed was that in future a new DDL might get introduced
via merge, so we should avoid doing a switch case on statement tag. I
propose a solution to this problem and that is to have any unknown DDL in
the deny list by default. This way we will always be on the safe side, and
if the we want to allow that particular DDL, it can always be added to
allow list.
It was discussed that event triggers might be using a central place to
catch DDLs, so we should explore its implementation. I looked at the
patches committed in the repository and found that they are calling a
function in each of the cases in standard_ProcessUtility to have the
triggers to fire added in a list. See the following code fragment to have
an idea
case T_CreateConversionStmt:
+ if (isCompleteQuery)
+ EventTriggerDDLCommandStart(parsetree);
CreateConversionCommand((CreateConversionStmt *) parsetree);
break;
case T_CreateCastStmt:
+ if (isCompleteQuery)
+ EventTriggerDDLCommandStart(parsetree);
CreateCast((CreateCastStmt *) parsetree);
break;
case T_CreateOpClassStmt:
+ if (isCompleteQuery)
+ EventTriggerDDLCommandStart(parsetree);
DefineOpClass((CreateOpClassStmt *) parsetree);
break;
Obviously we cannot adopt this approach because it will increase the
footprint of our code unnecessarily.
I therefore have to move forward with the switch case on statement tag
approach, unless we come up with some other idea.
Best Regards
--
Abbas
Architect
EnterpriseDB Corporation
The Enterprise PostgreSQL Company
Phone: 92-334-5100153
Website: www.enterprisedb.com
EnterpriseDB Blog: http://blogs.enterprisedb.com/
Follow us on Twitter: http://www.twitter.com/enterprisedb
This e-mail message (and any attachment) is intended for the use of
the individual or entity to whom it is addressed. This message
contains information from EnterpriseDB Corporation that may be
privileged, confidential, or exempt from disclosure under applicable
law. If you are not the intended recipient or authorized to receive
this for the intended recipient, any use, dissemination, distribution,
retention, archiving, or copying of this communication is strictly
prohibited. If you have received this e-mail in error, please notify
the sender immediately by reply e-mail and delete this message.
|