SEPostgreSQL Abstraction

This wikipage introduces a new abstraction layer to implement access control features.
= Overview =
Nowadays, we have various kind of security models which can be applied on accesses to database objects.
The native database privilege mechanism is also one of the security models. It makes its access control decision based on the database roles and the ACL (access control list) of the database objects to be accessed.
On the other hand, we currently have SE-PostgreSQL which is proposed as a different approach to control accesses to database objects, based on another security model. It makes its access control decision based on a couple of security contexts and the security policy in kernel.
Both of security features has same purpose which is to control accesses to database obejcts using SQL queries. But their criterions are not identical.
Historically, the native database privilege is the only security model in PostgreSQL.
So, its logic has been hard-coded on the core routines (such as DefineRelation) directry, and it also requires the second security model to put its security hooks various kind of core routines.
However, fundamentally, the core routines should focues on whether the required operation is allowed by the security mechanism, or not. It is a separatable issue how the required operation is allowed.
The series of functions provides an abstraction layer to focus on what to be checked.
For example, the native database privilege requires the database role to be the owner of the table when it is modified with ALTER TABLE. On the other hand, SELinux requires the db_table:{setattr} should be allowed on the target table.
The security_class_alter_table invokes both of security model to check. The way to make its decision is encapsulated within the abstraction layer.
= References =
== Regular DMLs ==
=== security_table_permissions ===
 void security_table_permissions(Oid table_oid, Oid user_id, AclMode required_perms,
 Bitmapset selected_cols, Bitmapset modified_cols);
 
 table_oid : OID of the target relation
 user_id : OID of the database role to be checked
 required_perms : Bitmask of the database privileges (e.g, ACL_SELECT)
 selected_cols : Bitmap of the referenced columns
 modified_cols : Bitmap of the modified columns
This checks permissions on the target table and columns which are referenced or modified, then raises an error, if violated.
It should be invoked instead of the ExecCheckRTEPerms(). In addition, it is also available on the COPY TO/FROM and SELECT INTO statement.
Note that the native database privilege does not check INSERT permission on OpenIntoRel(), because it implicitly assumes the table owner can always insert tuples into the new table. However, it should be fundamentally checked.
== pg_database objects ==
=== security_database_create ===
 Datum security_database_create(const char *database_name, Oid dat_owner,
 Oid tblspc_oid, DefElem *given_secon);
 
 database_name : Name of the new database in creation
 dat_owner : OID of the new database owner
 tablespace_id : OID of the tablespace 
 given_secon : User given security context, if exist
This checks permissions to create a new database, then raises an error if violated.
It returns a security context to be assigned on the new database, if exist.
The native database privilege checks have_createdb_privilege(), the membership of the owner and ACL_CREATE on the tablespace.
=== security_database_alter ===
 Datum security_database_alter(Oid database_oid, const char *new_name, Oit tblspc_oid,
 Oid new_owner, DefElem *given_secon);
 
 database_oid : OID of the database to be altered
 new_name : The new name of the database, if given
 tblspc_oid : The new tablespace of the database, if given
 new_owner : The new owner of the database, if given
 given_secon : The new security context of the database, if given
This checks permissions to alter a certain database, then raises an error if violated.
It returns a security context to be assigned on the database, if given_secon is not NULL.
The native database privilege checks ownership of the database and corresponding permissions depending on ALTER options.
=== security_database_drop ===
 void security_database_drop(Oid database_oid);
 
 database_oid : OID of the database to be dropped
This checks permissions to drop a certain database, then raises an error if violated.
The native database privilege checks ownership of the database.
=== security_database_connect ===
 void security_database_connect(Oid database_oid)
 
 datbase_oid : OID of the database to be connected
This checks permissions to connect a certain database.
The native database privilege check ACL_CONNECT on the database.
=== security_database_reindex ===
 void security_database_reindex(Oid database_oid)
 
 database_oid : OID of the database to be reindexed
This checks permissions to reindex relations on a certain database.
The native database privilege checks ownership of the database.
=== security_database_comment ===
 void security_database_comment(Oid database_oid)
 
 database_oid : OID of the database to be commented
This checks permissions to comment on a certain database.
The native database privilege checks ownership of the database.
== pg_namespace objects ==
=== security_namespace_create ===
 Datum security_namespace_create(bool is_temp, DefElem *given_secon)
 
 is_temp : true, if temporary namespace
 given_secon : User given security context, if exist
This checks permissions to create a new schema, then raises an error if violated.
It returns a security context to be assigned on the new namespace, if exist.
The native database privilege checks ACL_CREATE or ACL_CREATE_TEMP on the database.
=== security_namespace_alter ===
 Datum security_namespace_alter(Oid namespace_oid, const char *new_name,
 Oid new_owner, DefElem *given_secon)
 
 namespace_oid : OID of the namespace to be altered
 new_name : The new name of the namespace, if given
 new_owner : The new owner of the namespace, if given
 given_secon : The new security context of the namespace, if given
This checks permission to alter a certain namespace, then it raises an error if violated.
It returns a security context to be assigned on the namespace, if given_secon is not NULL.
The native database privilege checks ownership of the namespace and ACL_CREATE on the database. (Renaming pg_temp is not allowed due to the hardwired rule.)
=== security_namespace_drop ===
 void security_namespace_drop(Oid namespace_oid)
 
 namespace_oid : OID of the namespace to be dropped
This checks permission to drop a certain namespace, then it raises an error if violated.
The native database privilege checks ownership of the namespace.
=== security_namespace_search ===
 bool security_namespace_search(Oid namespace_oid)
 
 namespace_oid : OID of the namespace to be searched at.
This checks permission to search at a certain namespace, then it raises an error if violated.
The native database privilege checks ACL_USAGE of the namespace.
=== security_namespace_comment ===
 void security_namespace_comment(Oid namespace_oid)
 
 namespace_oid : OID of the namespace to be commented on.
This checks permission to comment on a certain namespace, then it raises an error if violated.
The native database privilege checks ownership of the namespace.
== pg_class objects ==
=== security_class_create ===
 Datum *security_class_create(TupleDesc *tupdesc, const char *rel_name, char relkind,
 Oid rel_owner, Oid rel_tblspc, Oid rel_nspid, CreateStmt *stmt);
 tupdesc : TupleDesc object of the new relation in creation
 rel_name : Name of the new relation in creation
 rel_kind : Relkind of the new relation
 rel_owner : OID of the relation owner
 rel_tblspc : OID of the tablespace
 rel_nspid : OID of the namespace
 stmt : CreateStmt object, if exists.
This checks permissions to create a new table and columns, then raises an error if violated.
It returns an array of security context to be assigned on the new table and columns.
If the given relkind does not requires permission checks (such as RELKIND_TOASTVALUE), it just returns an array of the security contexts.
The native database privilege checks ACL_CREATE on the namespace and ACL_CREATE on the tablespace (if not default one).
=== security_class_create_copy ===
 Datum *security_class_create_copy(Relation relation);
 
 relation : relation of the source relation
This does not check anything, but returns an array of security context to be assigned on the new temporay table created by make_new_heap().
The temporary table is used to implement table-rewriting, so the table needs to have identical security contexts.
=== security_class_create_inherit ===
 void security_class_create_inherit(Relation parent);
 
 parent : relation of the parent relation
This checks permission to create a child function which inherits a certain table, then raises an error if violated.
The native database privilege checks the ownership of the parent table.
=== security_class_alter ===
 Datum security_class_alter(Oid relid, const char *new_name, Oid new_owner,
 Oid new_tblspc, Oid new_nspid, DefElem *new_secon);
 
 relid : OID of the relation to be altered
 new_name : New name of the relation, if given
 new_owner : New owner of the relation, if given
 new_tblspc : New tablespace of the relation, if given
 new_nspid : New namespace of the relation, if given
 new_secon : New security context of the relation, if given
This checks permissions to alter a certain table, then raises an error if violated.
It returns a security context to be assigned on the table, if new_secon is not NULL.
The native database privilege checks the ownership of the relation, and corresponding permissions depending on the options.
=== security_class_drop ===
 void security_class_drop(Oid relid);
 
 relid : OID of the relation to be dropped
This checks permissions to drop a certain table, then raises an error if violated.
The native database privilege checks the ownership of the relation.
=== security_class_lock ===
 void security_class_lock(Oid relid, LOCKMODE lockmode);
 
 relid : OID of the relation to be locked
 lockmode : required lock mode
This checks permissions to lock a certain table using LOCK command, then raises an error if violated.
The native database privilege checks either ACL_SELECT for AccessShareLock or ACL_UPDATE | ACL_DELETE | ACL_TRUNCATE for other lockmode.
=== security_class_trigger ===
 void security_class_trigger(Oid relid, Oid constrrelid, Oid func_oid);
 
 relid : OID of the relation on which the new trigger is set
 consrelid : OID of the relation which is constrained by the new trigger
 func_oid : OID of the trigger function
This checks permissions to create a trigger function on a certain table, then raises an error if violated.
The native database privilege checks ACL_TRIGGER on the relations.
=== security_class_reference ===
 void security_class_reference(Oid relid, int16 *attnums, int natts);
 
 relid : OID of the relation on which FK constraint is set
 attnums : An arrary of attribute numbers
 natts : The length of attnums array
This checks permission to create a foreign key constraint on a certain table, then raises an error if violated.
The native database privilege checks ACL_REFERENCE on the relations.
=== security_class_truncate ===
 void security_class_truncate(Relation rel)
 
 rel : Relation to be truncated
This checks permission to truncate a certain table, then raises an error if violated.
The native database privilege checks ACL_TRUNCATE on the relation.
=== security_class_reindex ===
 void security_class_reindex(Oid relid)
 
 relid : OID of the index to be reindexed
This checks permission to reindex indexes on a certain table or a certain index, then raises an error if violated.
The native database privilege checks ownership of the table.
=== security_class_vacuum ===
 bool security_class_vacuum(Relation vacuum_rel)
 
 vacuum_rel : The relation to be vacuumed
This checks permissions to vacuum a certain relation, then it returns false, then raises an error if violated.
The native database privilege checks either ownership of the relation or the database if not shared relation.
=== security_class_get_tid ===
 void security_class_get_tid(Oid relid);
This checks permissions to get the current transaction identifier on a certain relation, then raises an error if violated.
The native database privilege checks ACL_SELECT on the relation.
=== security_class_get_value ===
 void security_class_get_value(Oid relid);
 
 relid : OID of the sequence to be referenced
This checks permission to refer the current value of a certain sequence objects, then raises an error if violated.
The native database privilege checks either of ACL_SELECT or ACL_USAGE on the sequence object.
=== security_class_next_value ===
 void security_class_next_value(Oid relid);
 
 relid : OID of the sequence to be fetched
This checks permission to fetch the next value of a certain sequence objects, then raises an error if violated.
The native database privilege checks either of ACL_UPDATE or ACL_USAGE on the sequence object.
=== security_class_set_value ===
 void security_class_set_value(Oid relid);
 
 relid : OID of the sequence to be set a new value.
This checks permisson to set a descretional value of a certain sequence objects, then raises an error if violated.
The native database privilege checks ACL_UPDATE on the sequence object.
== pg_attribute objects ==
== pg_proc objects ==
== pg_language objects ==
== pg_tablespace objects ==
== pg_foreign_data_wrapper objects ==
== pg_foreign_server objects ==
== pg_type objects ==
== pg_oper objects ==
== pg_opclass objects ==
== pg_opfamily objects ==
== pg_conversion objects ==
== pg_ts_dict objects ==
== pg_ts_config objects ==
== pg_ts_parser objects ==
== pg_ts_template objects ==
Category:SELinux