diff -Nrpc base/doc/src/sgml/catalogs.sgml sepgsql/doc/src/sgml/catalogs.sgml *** base/doc/src/sgml/catalogs.sgml Fri Jan 23 10:23:37 2009 --- sepgsql/doc/src/sgml/catalogs.sgml Fri Jan 23 10:55:35 2009 *************** *** 204,209 **** --- 204,214 ---- + pg_security + text representation of security attribute + + + pg_shdepend dependencies on shared objects *************** *** 977,982 **** --- 982,996 ---- + attkind + char + + + A copy of pg_class.relkind of this columns's relation + + + + attnotnull bool *************** *** 4195,4200 **** --- 4209,4281 ---- + + <structname>pg_security</structname> + + + pg_security + + + + The catalog pg_security stores text representation + of security attributes managed by PGACE framework. + + + + When a security module is enabled on PGACE framework and it utilizes security + attribute to make its decision, we have to associate a security attribute with + a tuple. In generally, security attribute is a formatted string and massive + objects tend to share same attribute. So, it is not efficient to store it + as a text for each object. The number of security attribute is much less + than the number of object, in other word. + + + + PGACE provides a facility to associate them effectively, + using pg_security system catalog. + + It enables a security module to put an object identifier into padding area + of tuple header, called as security id. + + + + security id means an object identifier (oid) of a tuple + within pg_security system catalog, which contains + a text representation. + So, we can translate security id to text representation on exporting, and + vice versa. When a new text representation is given, a new tuple is added + to pg_security and a new security id + is assigned by PGACE. + + + + See for more information. + + + + <structname>pg_security</>Columns + + + + + Name + Type + References + Description + + + + + + seclabel + text + + Text representation of security attribute + + + +
+
<structname>pg_shdepend</structname> diff -Nrpc base/doc/src/sgml/errcodes.sgml sepgsql/doc/src/sgml/errcodes.sgml *** base/doc/src/sgml/errcodes.sgml Mon Dec 29 20:19:56 2008 --- sepgsql/doc/src/sgml/errcodes.sgml Sat Jan 3 16:58:53 2009 *************** *** 1420,1425 **** --- 1420,1458 ---- too_many_rows
+ + Class SE — Enhanced Security Error + + + + SE000 + PGACE ERROR + pgace_framework_error + + + + SE011 + ROWACL ERROR + errors_in_row_level_acls + + + + SE021 + SELINUX ERROR + errors_in_sepostgresql + + + + SE022 + SELINUX AUDIT + audit_records_of_sepostgresql + + + + SE023 + SELINUX INFO + information_from_sepostgresql + Class XX — Internal Error diff -Nrpc base/doc/src/sgml/filelist.sgml sepgsql/doc/src/sgml/filelist.sgml *** base/doc/src/sgml/filelist.sgml Mon Jan 5 17:36:07 2009 --- sepgsql/doc/src/sgml/filelist.sgml Mon Jan 5 17:41:04 2009 *************** *** 139,144 **** --- 139,145 ---- + diff -Nrpc base/doc/src/sgml/postgres.sgml sepgsql/doc/src/sgml/postgres.sgml *** base/doc/src/sgml/postgres.sgml Tue May 13 14:48:54 2008 --- sepgsql/doc/src/sgml/postgres.sgml Fri Jun 13 20:36:54 2008 *************** *** 254,259 **** --- 254,260 ---- &features; &release; &contrib; + &security; &external-projects; &cvs; &docguide; diff -Nrpc base/doc/src/sgml/ref/initdb.sgml sepgsql/doc/src/sgml/ref/initdb.sgml *** base/doc/src/sgml/ref/initdb.sgml Wed Oct 1 14:42:02 2008 --- sepgsql/doc/src/sgml/ref/initdb.sgml Fri Jan 9 12:22:29 2009 *************** PostgreSQL documentation *** 234,239 **** --- 234,252 ---- + + + + + + Selects an enhanced security feature, and write it out on the + postgresql.conf. + This default is none which means no enhanced + security feature is activated on initdb. + The following options are available now: selinux. + + + diff -Nrpc base/doc/src/sgml/ref/pg_dump.sgml sepgsql/doc/src/sgml/ref/pg_dump.sgml *** base/doc/src/sgml/ref/pg_dump.sgml Tue Jan 6 14:45:31 2009 --- sepgsql/doc/src/sgml/ref/pg_dump.sgml Fri Jan 9 12:22:29 2009 *************** PostgreSQL documentation *** 634,639 **** --- 634,660 ---- + + + + + + Dumps Row-level ACLs with table contents. + It can be restored via writable system column security_acl. + + + + + + + + + Dumps security labels managed by available enhanced security feature + with table contents. + It can be restored via writable system column security_label. + + + diff -Nrpc base/doc/src/sgml/ref/pg_dumpall.sgml sepgsql/doc/src/sgml/ref/pg_dumpall.sgml *** base/doc/src/sgml/ref/pg_dumpall.sgml Tue Jan 6 14:45:31 2009 --- sepgsql/doc/src/sgml/ref/pg_dumpall.sgml Fri Jan 9 12:22:29 2009 *************** PostgreSQL documentation *** 334,339 **** --- 334,359 ---- + + + + + Dumps Row-level ACLs with table contents. + It can be restored via writable system column security_acl. + + + + + + + + + Dumps security labels managed by available enhanced security feature + with table contents. + It can be restored via writable system column security_label. + + + diff -Nrpc base/doc/src/sgml/security.sgml sepgsql/doc/src/sgml/security.sgml *** base/doc/src/sgml/security.sgml Thu Jan 1 09:00:00 1970 --- sepgsql/doc/src/sgml/security.sgml Sun Dec 21 16:20:46 2008 *************** *** 0 **** --- 1,1457 ---- + + Enhanced Security Features + + + + This chapter introduces enhanced security features built in core + PostgreSQL and its framework. These feature can provide mandatory + access controls, fine-grained access controls, integration of security + policy between operating system and database management system, + and so on. + + + + The current version of PostgreSQL have two of enhanced security + features. The one is SE-PostgreSQL (Security Enhanced PostgreSQL), + and the other is Row-level Database ACLs. + Both of them are implemented on the common security framework named + as PGACE (PostgreSQL Access Control Extensions). It provides basic + facilities to manage security attribute of database objects and + hooks to acquire controls on some of strategic points. It enables + to implement enhanced security features with minimum impact for + the core PostgreSQL. + + + + SE-PostgreSQL provides additional fine-grained mandatory access + controls on accesses to database objects via SQL. It makes a + decision whether the given request come from clients should be + allowed, or not, in communicating with in-kernel SELinux. + + SELinux holds its security policy which is a set of white listed + rules, and provides its access control decisions to the kernel + and userspace object manager. + + The key concept of SE-PostgreSQL is integration of access controls + between operating system and database management systems. + It makes and applies its access control decision based on a single + unified security policy of operating system. It applies the security + context of peer process as privileges of client, independent from + database authentication. + + Its providing access controls are not bypassable for any clients + even if they are privileged database user, so it is called as a + MAC (Mandatory Access Controls) feature. + + It enables to prevent information leaks and manipulation from + malicious insider, reduce damages from SQL injection and application + bugs. + + + + The Row-level Database ACLs enables to apply existing DAC + (Discretionary Access Control) policy in row-level granuality. + + It enables to set permissions for SELECT, + UPDATE and DELETE. + This facility filteres violated tuples from the result set, + and user shows as if these are not exist here. + + + + The PGACE security framework allows to host two security + features simultaneously. The DAC feature is hardcoded + as Row-level Database ACLs, but MAC feature is selectable + by users. + + SE-PostgreSQL is a candidate of MAC features, and we need + to enable it explicitly. + It need to specify option + at configure script, + and at + initdb. + + $ ./configure --enable-selinux + $ make install + $ initdb --pgace-feature=selinux + + + The Row-level Database ACLs feature is always enabled in + default build. + + + + + SE-PostgreSQL Features + + + Single unified security policy + + + We can find out that filesystem and database have similar + capabilities which enables to store our information assets, + and have to apply its access controls to keep confidentiality + and integrity, when it got a request from users. + + + In case of filesystem, user invokes a proper system call + to access filesystem objects, like write(2) + invocation for ~/.bashrc. + + Meanwhile, he can also make a request to database objects + via SQL queries. + + + Both of filesystem and database have its access control + feature. The UNIX permission is well known semantics + with long history, and the database ACLs are also well + knows based on SQL standards. + + However, unfortunately, they works independently each other, + so we have a possibility either of subsystem makes inconsistent + decison, even if they can store same information asset. + + Please note that the differences between filesystem and database + is the way to store or access our information asset, not a + differences in confidentiality, values and so on. + + + Now we have SELinux on some of Linux distributions, which can + be a reliable foundation for comprehensive and integrated + security. + + SE-PostgreSQL makes its access control decision based on the + security policy of SELinux, so we can get always consistent + results in access controls. + + For example, when we store an information labeled as + Classified, it does not allow users without + proper privileges to refer it independent from whether it is + stored in filesystem, or database. + + + This characterisct gives us another benefit. The step to make + decision works independently from the existing access controls + in databases, so it enables to apply mandatory access control + policy, even if user is a database superuser. + + It is similar that SELinux restricts privileges of + root user on operating system. + + + + Security Context + + The security policy of SELinux is a set of access controls + rules which show who is allowed to do what kind of accesses + on what objects. + + Any rules are described as a relationship of two entities + identified by common format called as security context. + + + The security context is a formatted string independent from + sort of objects, like: + system_u:object_r:postgresql_db_t:SystemHigh. + + It is generally assigned to files of database cluster managed + by PostgreSQL, however, please note that it does not use any + filesystem specific attribute, like path-name. + + In SELinux, it assigns a security context for any processes, + files, sockets and other resources, and makes its decision + based on these security contexts. + + It typically checks whether the policy has an allowed relationship + between a security context of process and the one of resource, + or not. + + + For example, when a process labeled as + system_u:system_r:postgresql_t:s0 tries to + write a log message to /var/log/postgresql.log + labeled as system_u:object_r:postgresql_log_t:s0, + write(2) ystem call is hooked in the kernel and + SELinux search its security policy to find out an entry of + relationship of the two security contexts. + + If founded entry allows the process to write it, SELinux does + nothing any more. Otherwise, SELinux prevent it. + + + + Any object managers which want a decision come from SELinux + (including kernel) should have a capability to manage security + context of its objects. + + For example, most of major filesystems support xattr (Extended + Attributes) facilities which allows to store individual security + context of files. + + SE-PostgreSQL also provides a facility to manage security context + of database objects. We can import/export them via + security_label system column. + + + + + Client Privileges + + The privileges of client is a significant factor also. + + Operating system assigns a process its user/group identifiers + and security context. These attributes are used in access + controls either of DAC and MAC. + + Database management system also manages privileges of client. + It assigns authenticated database roles and applies its + access controls based on database ACLs. + + Please note that here is no relationships between the attributes + of processes on operating system and client of databases. + + + One of the purpose in SE-PostgreSQL is to apply its access controls + on database objects, as if client accesses to filesystem objects. + + It requires we have to apply the security context of client process + to make a decision in access controls. It is independently given + from the authenticated database roles. + + Thus, SE-PostgreSQL need to know the security context of the + connected client process. + + + + SELinux provides an interesting API named as + getpeercon(). It enables to obtain a security + context of the peer process connected via given socket descriptor. + + We can see what security context is applied as the security + context of client, using sepgsql_getcon() + on SE-PostgreSQL as follows: + + $ id -Z + unconfined_u:unconfined_r:unconfined_t:Classified + $ psql -q + postgres=# SELECT sepgsql_getcon(); + sepgsql_getcon + --------------------------------------------------- + unconfined_u:unconfined_r:unconfined_t:Classified + (1 row) + + + + + We don't need any special configuration when we connect to + SE-PostgreSQL via UNIX domain socket (local connection). + + However, when we connect to SE-PostgreSQL via TCP/IP socket + (remote connection), it is necessary to set up labeled networking. + See for more + defails. + + + + + Mandatory Access Controls + + MAC (Mandatory Access Controls) is a kind of security designs, + and has a few significant characteristics compared to DAC + (Discreational Access Controls) design, like filesystem + permissions, database ACLs and so on. + + + At first, MAC design requires to apply its access control + policy on all the accesses for managed objects without any + exception, including root and similar + concepts. + + Next, any subject and object have to be identified by security + labels, and MAC policy is described as a set of relationship + between two labels. The security context of SELinux is a + sort of label, but is includes a bit more identifiers than + traditional trusted-operating system. + + Finally, it should not allow resource owners to change its + access control rights arbitrarily. DAC design allows us + to change them using chmod or + GRANT. But security policy restricts + them in MAC design. + + + SELinux is a MAC feature in operating system, so it applies + MAC policy for accesses to resources managed by operating + system like files, sockets and so on. + + + SE-PostgreSQL is a symmetric feature in database management + system. It also applies MAC policy for accesses to any + database objects, managed by database management system + as a literal. + + + + + + The functionality of SE-PostgreSQL + + + security_label system column + + SE-PostgreSQL enables to import/export security context of + tuples via security_label system column + which is available v8.4, or later. + + + The following example shows a case when we export security + context of tuples and its data via SELECT. + + + postgres=# SELECT security_label, * FROM drink; + security_label | id | name | price + ----------------------------------------------+----+-------+------- + system_u:object_r:sepgsql_table_t | 1 | water | 100 + system_u:object_r:sepgsql_table_t | 2 | coke | 120 + system_u:object_r:sepgsql_table_t | 3 | juice | 130 + system_u:object_r:sepgsql_table_t | 4 | cofee | 180 + system_u:object_r:sepgsql_table_t:Classified | 5 | beer | 240 + system_u:object_r:sepgsql_table_t:Classified | 6 | sake | 320 + (6 rows) + + + The security policy has rules to determine what security context + should be applied on newly inserted tuples. + SE-PostgreSQL assigns a proper security context for them according + to the rules in default. + + + However, we can explicitly specify a security context of a new + tuple with INSERT statement including + security_label system column as a target. + + + # INSERT INTO drink (security_label, id, name, price) + VALUES('system_u:object_r:sepgsql_ro_table_t', 7, 'tea', 130); + + + We can also change security context of tuples using + UPDATE statement, as INSERT + doing. + + + # UPDATE drink SET security_label = 'system_u:object_r:sepgsql_ro_table_t' WHERE id < 4; + + + No need to say, client has to have privileges to insert or update + security context of tuples. If not so, SE-PostgreSQL prevents to + change them. + + + SELECT INTO or CREATE TABLE AS + including security_label system column as a target + is considered as an iteration of INSERT with an + explicit security context. + + + # SELECT security_label, id, name, price / 2 AS price INTO discount FROM drink; + SELECT + postgres=# SELECT security_label, * FROM discount; + security_label | id | name | price + ----------------------------------------------+----+-------+------- + system_u:object_r:sepgsql_table_t | 1 | water | 50 + system_u:object_r:sepgsql_table_t | 2 | coke | 60 + system_u:object_r:sepgsql_table_t | 3 | juice | 65 + system_u:object_r:sepgsql_table_t | 4 | cofee | 90 + system_u:object_r:sepgsql_table_t:Classified | 5 | beer | 120 + system_u:object_r:sepgsql_table_t:Classified | 6 | sake | 160 + (6 rows) + + + Please note that PostgreSQL uses system catalogs to represent + metadata of tables, columns and so on. + SE-PostgreSQL considers tuples within these system catalogs + show the security context of them. + For example, security context of tuples within + pg_class is considered as the one of table. + + + + + Access controls on Tuples + + SE-PostgreSQL applies its access controls for each tuple. + + If client tries to select, update or delete violated tuples, + these tuples are filtered from the result set or ignored from + the target of updates/deletions, as if they are not exist + on the table. + + + The following example shows the case when two users with different + security context tries to SELECT same table + with same SQL. + A Classified user can whole of the table. + But Classified tuples are invisible from + other users. + + + $ id -Z + unconfined_u:unconfined_r:unconfined_t:Classified + $ psql -q postgres + postgres=# SELECT security_label, * FROM drink; + security_label | id | name | price + ----------------------------------------------+----+-------+------- + system_u:object_r:sepgsql_table_t | 1 | water | 100 + system_u:object_r:sepgsql_table_t | 2 | coke | 120 + system_u:object_r:sepgsql_table_t | 3 | juice | 130 + system_u:object_r:sepgsql_table_t | 4 | cofee | 180 + system_u:object_r:sepgsql_table_t:Classified | 5 | beer | 240 + system_u:object_r:sepgsql_table_t:Classified | 6 | sake | 320 + (6 rows) + + + It shows the Classified user got 6 tuples + with unconditional SELECT on drink table. + + However, the unclassified (not labeled) user got 4 tuples + with same SQL, because of filtering violated tuples. + + + $ id -Z + unconfined_u:unconfined_r:unconfined_t + $ psql -q postgres + postgres=# SELECT security_label, * FROM drink; + postgres=# SELECT security_label, * FROM drink; + security_label | id | name | price + -----------------------------------+----+-------+------- + system_u:object_r:sepgsql_table_t | 1 | water | 100 + system_u:object_r:sepgsql_table_t | 2 | coke | 120 + system_u:object_r:sepgsql_table_t | 3 | juice | 130 + system_u:object_r:sepgsql_table_t | 4 | cofee | 180 + (4 rows) + + + + + Access controls on Tables and Columns + + SE-PostgreSQL also enables to apply its access controls on + tables and columns. It prevents clients to access violated + objects, but it has a difference from ones in row-leve. + + + When client gives a query tree, SE-PostgreSQL walks on the + given one to pick up all appeared tables and columns. + If it contains one or more violated objects, SE-PostgreSQL + aborts query execution and returns an error to the client. + + + The following example shows a case when we declared + ccredit column to store credit card numbers + as a secret column from unclassified users. + The following SQL is declaration of table and initial records. + + + CREATE TABLE customer ( + cid integer primary key, + cname varchar(32), + credit varchar(32) + SECURITY_LABEL = 'system_u:object_r:sepgsql_secret_table_t' + ); + GRANT ALL ON customer TO PUBLIC; + + INSERT INTO customer (cid, cname, credit) + VALUES ( 10, 'jack', '1111-2222-3333-4444'), + ( 13, 'adam', '5555-6666-7777-8888'), + ( 14, 'liza', '9876-5432-1098-7654'); + + + + $ id -Z + staff_u:staff_r:staff_t + $ psql -q postgres + postgres=# SELECT * FROM customer; + ERROR: SELinux: denied { select } \ + scontext=staff_u:staff_r:staff_t \ + tcontext=system_u:object_r:sepgsql_secret_table_t \ + tclass=db_column name=customer.credit + postgres=# SELECT cid, cname FROM customer; + cid | cname + -----+------- + 10 | jack + 13 | adam + 14 | liza + (3 rows) + + + At the first query, he tried to refer all the columns, but + SE-PostgreSQL prevents query execution because it contains + a reference to ccredit column which is + labeled as sepgsql_secret_table_t. + + Then, he tried to refer rest of columns expect for the + ccredit column, so SE-PostgreSQL allows + to execute the query, because it does not contains any + violater tables and columns. + + + + Access Controls on Function + + SE-PostgreSQL also picks up invocations of function during + walks on the given query tree. It prevent clients to invoke + functions without proper privileges. + + + In the current default security policy, a function declared by + administrative users (like unconfined_t domain) + is labeled as sepgsql_proc_t. But, ones declared + by normal users (like staff_t domain) are labeled + as staff_sepgsql_proc_exec_t which does not allow + administrative users to invoke. + + Its purpose is to prevent administrative users to invoke malicious + function by mistake. They have to confirm its declaration and + relabel its security context to sepgsql_proc_t. + + + SE-PostgreSQL allows clients to change its privileges during + execution of specific functions called as trusted-procedures. + It has a similar concept to Set-uid program, security invoker + and so on. + + In the current default security policy, trusted procedures are + functions labeled as sepgsql_trusted_proc_exec_t. + It enables to execute these functions with administrative privileges, + so gives us a secure method to access confidential objects. + + It provides simplest all or nothing policy, however, it has + a capability to apply more flexible control, if you install your + own security policy module. + + + The following example declares a trusted procedure of + show_credit to expose information stored in + customer.credit with turned letter. + + At first, a client within staff_t domain + does not access credit column. But, it + can be accessed via trusted procedure, because the sub-queries + come from the procedure is handled as an administrative domain. + + + # CREATE OR REPLACE FUNCTION show_credit (integer) RETURNS text + LANGUAGE 'sql' + SECURITY_LABEL = 'system_u:object_r:sepgsql_trusted_proc_exec_t' + AS 'SELECT substring(credit from ''^[0-9]+-'') || ''xxxx-xxxx-xxxx'' + FROM customer WHERE CID = $1'; + CREATE FUNCTION + # \q + + + $ id -Z + staff_u:staff_r:staff_t + $ psql postgres + postgres=# SELECT * FROM customer; + ERROR: SELinux: denied { select } \ + scontext=staff_u:staff_r:staff_t \ + tcontext=system_u:object_r:sepgsql_secret_table_t \ + tclass=db_column name=customer.credit + postgres=# SELECT cid, cname, show_credit(cid) FROM customer; + cid | cname | show_credit + -----+-------+--------------------- + 10 | jack | 1111-xxxx-xxxx-xxxx + 13 | adam | 5555-xxxx-xxxx-xxxx + 14 | liza | 9876-xxxx-xxxx-xxxx + (3 rows) + + postgres=# + + + + + + The limitation + + SE-PostgreSQL dose not care about information leaks via covert channels. + It is a technical term used in security evaluation, and means a possibility + of inference to invisible data via illicit flows. + + + It had been originally required at upper B2 class of TCSEC, and evaluated + products had to declare explicit maximum bandwidth of covert channels. + It is now inherited to ISO/IEC15408 knows as CC (Common Criteria). + + + If your requirements contains elimination of covert channels, we don't + recommend to apply SE-PostgreSQL. However, it is generally considered + as a requirement of extreame condidential military region. + + + An example of covert channels are here. + + When a man tries to update or delete a tuple with primary key refered by + one or more invisible foreign keys, SE-PostgreSQL prevent the action to + keep its reference integrity, even if he cannot see the key. + + This error gives him a side-channel information which is an existance + of invisible foreign key. Such a behavior is called as covert channel. + + + An actual avoidance for the matter is to apply non-natural primary and + foreign keys. It enables to be impossible he infer any meaningful data. + + + + + + SE-PostgreSQL Administration + + + Build and Installation + + Requirement + + We need the following packages to build and install + SE-PostgreSQL properly. Please check it at first. + + + + + Linux kernel (2.6.23, or later) + + + + + libselinux and libselinux-devel (2.0.43, or later) + + + + + selinux-policy (3.4.2, or later) + + + + + policycoreutils (2.0.16, or later) + + + + + + + Build + + SE-PostgreSQL feature is disabled in the default build. + So, we have to add option + to configure script. It enables to build your PostgreSQL + with a feature to suppor SELinux. + + + $ ./configure --enable-selinux + $ make + $ make -C src/backend/security/sepgsql/policy + + + The current default security policy of SELinux contains a set of + rules for SE-PostgreSQL on selinux-policy-3.4.2 + or later. So, we don't need to install special purpose security + policy module now. + + + However, SE-PostgreSQL also provides an optinal policy module + for development Purpose. It enables several operations like + regression test, toggle audit logs and so on. + + + It is stored on src/backend/security/sepgsql/policy, + and can be also build and installed as a binary security policy + module. + + + + + Installation + + Please note that SELinux requires installed files, directories and + others should be labeled properly. RPM installation do it implicitly. + + But, when you install PostgreSQL from a tarball, you should assign + proper security context for them. The development policy module + has a list that shows what security context should be assigned to + what files, and will help you to manage them, so we recommend to + install the sepostgresql-devel.pp also. + + + # make install + # /usr/sbin/semodule -i src/backend/security/sepgsql/policy/sepostgresql-devel.pp + # /sbin/restorecon -R /usr/local/pgsql + + + semodule is a command to install and uninstall + a security policy module. restorecon is a command + to assign given directories its default security context recursively. + + + + As we note later, all the files and directories to store database + cluster should be labeled as postgresql_db_t. + The default security policy assumes it is constructed at + /var/lib/pgsql/data as RPM doing. + + If you want to set up it on another directory, you need to label + it by hand. + + + # mkdir -p $PGDATA + # chcon -t postgresql_db_t -R $PGDATA + + + Then, we need to run initdb to initialize + the database cluster. It is necessary to specify an option of + which enables to initialize + database cluster with proper security context. + + If we omit it, no enhanced security feature is activated on + the database cluster. + + + $ initdb --pgace-feature=selinux + $ pg_ctl start + + + + + + Configuration + + + GUC Parameters + + PGACE and SE-PostgreSQL have a few GUC parameters. + It is evaluated on startup time, so unable to change + them at runtime. + + + + + pgace_feature + + + Currently, It has two possible values. + The one is none not to enable any + enhanced security features, and the other is + selinux to enable SE-PostgreSQL + feature. + + + If you run initdb with + , this parameter is + automatically specified to selinux. + But its default is none. + + + + + + sepostgresql + + + It has four possible values to specify working mode of + SE-PostgreSQL. The default is a default + selection. It always follows the configuration on operating + system. The enforcing and + permissive make SE-PostgreSQL work in the + specified mode, independent from kernel setting. Please note + that those configuration requires in-kernel SELinux is not + disabled. The disabled disables the feature + of SE-PostgreSQL, so it works as if vanilla PostgreSQL. + + + + + + sepostgresql_row_level + + + It has two possible values true, or + false. + It enables to turn on/off the row-level access control feature, + however, we recomment you not to turn off the parameter, except + for the case when your system has extremely severe requirements + in storage comsumption. + + Its default is true which means SE-PostgreSQL + applies row-level access controls. + + + + + + + + + Backup and Restore + + When we restore a database from backups, we have to restore + its security context correctly as GRANT statement doing on + the restored table. + + + + The pg_dump and pg_dumpall + have option to dump databases + with its security context. + + The dumped image can be restored with proper security context. + + + + No need to say, a process which invokes pg_dump + has to be allowed to refer whole of the database, + because SE-PostgreSQL filters all violated tuples from the result + set, or aborts query execution if it contains references violated + columns and so on. + + These requirements are same when we restore the image. + A process which invokes pg_restore has to have + enough permission to create/insert these objects with specified + security context. + + + + $ pg_dump --security-label postgres + : + (snip) + : + -- + -- Name: drink; Type: TABLE; Schema: public; Owner: kaigai; Tablespace: + -- + + CREATE TABLE drink ( + id integer NOT NULL, + name character varying(48), + price integer + ) SECURITY_LABEL = 'system_u:object_r:sepgsql_table_t'; + : + (snip) + : + -- + -- Data for Name: drink; Type: TABLE DATA; Schema: public; Owner: kaigai + -- + + COPY drink (security_label, id, name, price) FROM stdin; + system_u:object_r:sepgsql_table_t 1 water 100 + system_u:object_r:sepgsql_table_t 2 coke 120 + system_u:object_r:sepgsql_table_t 3 juice 130 + system_u:object_r:sepgsql_table_t 4 cofee 180 + system_u:object_r:sepgsql_table_t:Classified 5 beer 240 + system_u:object_r:sepgsql_table_t:Classified 6 sake 320 + \. + : + (snip) + : + + + This example shows a backup image with explicitly specified security + context on tables and tuples. + + If a column has different security context from tables' one, it also + specified explicitly in the CREATE TABLE statement. + + + + + Labeled Networks + + Labeled Networks is an excellent technology. + It enables to obtain the security context of peer process communicating + via TCP/IP connection. + + + + This technology contains two facilities. + One is Labeled IPsec, + and the other is Static Fallbacked Context. + + This section shows the way to set up both labeled networks + technology. + + + + Labeled IPsec + + When we begin to communicate using an encrypted channel + with IPsec, racoon which is a key-exchange + daemon exchanges encryption keys of both peers. + + It does not exchange only encryption keys in actually, + but the security context of process connecting to is also + delivered to the peer side. + + The delivered security context is cached on the kernel, and + it is exported into applications, if it required via + getpeercon() API. + + + + This section introduces the steps to set up labeled ipsec. + + For more detailed information, visit Red Hat Enterprise Linux 4 - Security Guide + + + + Example Environment + + In this introduction, we assume the server host where SE-PostgreSQL + works has an IP address of 192.168.1.10 and + the client host has IP address of 192.168.1.200. + + They are wired to same network, and can communicate each other + directly, without any router. + + + + The purpose of the following configuration is to obtain + the security context of the process working on the client host + (192.168.1.200) from SE-PostgreSQL daemon + working on the server host (192.168.1.10), + when a connection is established. + + + + + Adding a SPD entry + + It is needed to add an SPD (Security Policy Database) entry + to indicate applying IPsec on channels between two host. + + Note that SPD is not a term of SELinux, it is a configuration + parameter of IPsec, although it's a bit confusable. + + + + This example shows esp/transport mode should be applied on + outbounding packets from 192.168.1.10 + to 192.168.1.200, and inbounding packets + from 192.168.1.200 to + 192.168.1.10. + + + spdadd 192.168.1.10 192.168.1.200 any + -ctx 1 1 "system_u:object_r:ipsec_spd_t:s0" + -P out ipsec + esp/transport//require; + + spdadd 192.168.1.200 192.168.1.10 any + -ctx 1 1 "system_u:object_r:ipsec_spd_t:s0" + -P in ipsec + esp/transport//require; + + + In addition, the second line of each entries enables to + turn on security context delivery during key exchanging. + + + + You can load the above configuration using + setkey command. + + Save your configuration into a temporary file, + and invoke setkey with the file + as an argument. + + # /sbin/setkey -f <your configuration file> + + + + + It is necessary to apply on both server side and client side. + + Note that you have to invert IP addreses on the client side. + + + + + Racoon configuration + + In the next, we have to edit a configuration file of + racoon to specify encryption algorithm, + authentication method and so on. + + This example uses pre shared key to authenticate the peer + host (192.168.1.200) for simplification. + + Note that you have to invert IP addresses on the client side. + + + + An additional entry to /etc/racoon/racoon.conf. + + remote 192.168.1.200 + { + exchange_mode aggressive, main; + my_identifier address; + proposal { + encryption_algorithm 3des; + hash_algorithm sha1; + authentication_method pre_shared_key; + dh_group 2 ; + } + } + + + + + We have to put a set of key string and IP address of destination + in /etc/racoon/psk.txt. + + The key string has also to be same in the client side. + + # file for pre-shared keys used for IKE authentication + # format is: 'identifier' 'key' + # For example: + # + # 10.1.1.1 flibbertigibbet + # www.example.com 12345 + # foo@www.example.com micropachycephalosaurus + 192.168.1.200 somethingsecrettext + + + + + + Restart Racoon + + Restart racoon daemon in both peers. + + + # service racoon restart + + + + + + Static Fallbacked Context + + We cannot apply labeled IPsec for any situation. + + It requires both server and cliets being SElinux'ed and IPsec is + available on their communication channel. + + + + SELinux provides an alternative method to identify a security + context of peer process inside the getpeercon() + API, when a connection come from unlabeled networks. + + This facility is called as static fallbacked context. + It enables to return a security context associated with IP address + or network interfaces, as if a new connection come from labeled + networks. + + + + netlabelctl within netlabel_tools + package can be used to set up static fallbacked context. + + + + The following example shows a case when we associate a security + context with connections come from 192.168.1.0/24 + via all network interfaces. + + # /sbin/netlabelctl unlbl add default address:192.168.1.0/24 label:user_u:user_r:user_t:s0 + + The following example shows a case when we associate a security + context with connections come from 192.168.2.0/24 + via eth0. + + # /sbin/netlabelctl unlbl add dev:eth0 address:192.168.2.0/24 label:staff_u:staff_r:staff_t:s0:c0 + + + + + + + + Row-level Database ACLs + + This chapter introduces design and implementation of the Row-level + Database ACLs in PostgreSQL. It enables to assign indivisual ACLs + for each tuples, and works as a supplemental facility of existing + database ACLs applied to tables, columns and so on. + + + + Design + + The design of Row-level Aatabase ACLs feature inherits many things + from existing access control mechanism. For example, it is a sort + of discretionary access control mechanism, so it allows owner of + resources to change its access control rights. It does not prevent + anything invoked from database superusers. + + + This feature is implemented as a guest of PGACE security framework, + but wired feature, not a selectable one. + + + It works as if here is a filter to drop violated tuples on scanning + the relation. Just before the executor scans relation, tables and + columns level ACLs are also checked, and the feature makes decision + whether the tuple should be returned, ot not. + + + We provides four kind of permissions on tuples. + These are SELECT, UPDATE, + DELETE and REFERENCES. + + Please note that INSERT permission is not available, + because the target does not exist when it should be checked. + + You should control insertion of tuples via table-level ACLs. + + + PostgreSQL has foreign key constrint as built-in trigger functions, + and it invokes another query to keep referential integrities. + It is an exception case of the filtering. In this case, it raises + an error to abort current transation, if the query tries to fetch + a violated tuple. + It helps referential integrities from global viewpoint, but, + please note that it has a possibility unprivilged users infer + existance of one or more invisible tuples. + + + This feature is activated via table option of + row_level_acl. It can heve either of + on or off in the default. + + It enables us to refer or set per-tuple ACLs via + security_acl system column newly added. + We can modify it via UPDATE, INSERT + with explict ACLs on the system column. + + A feature to set default ACLs is also available. + A new table option of default_row_acl enables to + specify a default ACLs of tuples, when no explicit ACLs are given + from users on its insertion. + + + + + Installation + + We don't need anything to install. + The Row-level Database ACLs are compiled in the default. + + + + + Administration + + Setup Row-level ACLs + + We need to add row_level_acl table option on + CREATE TABLE or ALTER TABLE + to activate the Row-level Database ACLs. + + + # CREATE TABLE drink ( + id int primary key, + name text, + price int + ) WITH (row_level_acl=on); + NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "drink_pkey" for table "drink" + CREATE TABLE + + + We can set Row-level ACLs via security_acl + system column which is writable. + The following queries are example to set up them. + + + # UPDATE drink SET security_acl = '{=r/postgres}' WHERE id in (3,4,5); + UPDATE 3 + # SELECT security_acl, * FROM drink order by id; + security_acl | id | name | price + --------------------------------+----+-------+------- + {kaigai=rwd/kaigai} | 1 | water | 100 + {kaigai=rwd/kaigai} | 2 | coke | 120 + {=r/kaigai} | 3 | juice | 130 + {=r/kaigai} | 4 | cofee | 180 + {=r/kaigai} | 5 | beer | 240 + {kaigai=r/kaigai,ymj=r/kaigai} | 6 | sake | 320 + (6 rows) + + + The database user must have ownership of the relation or privileges + of database superuser, whenever we tries to update the + security_acl. + + Please note that the feature considers the owner of table is the + owner of tuples stored in, not a man who inserted the tuple. + + + + + Backup and Restore + + The pg_dump and pg_dumpall + has a option to dump tables with Row-level ACLs, which is + --security-acl. + + + It enables to contain security_acl system + column if Row-level ALCs feature is enabled on the target + table. + + + $ pg_dump --security-acl postgres + : + CREATE TABLE drink ( + id integer NOT NULL, + name text, + price integer + ) + WITH (row_level_acl=on); + : + -- + -- Data for Name: drink; Type: TABLE DATA; Schema: public; Owner: kaigai + -- + + COPY drink (security_acl, id, name, price) FROM stdin; + {kaigai=rwd/kaigai} 1 water 100 + {kaigai=rwd/kaigai} 2 coke 120 + {=r/kaigai} 3 juice 130 + {=r/kaigai} 4 coffee 180 + {=r/kaigai} 5 beer 240 + {kaigai=r/kaigai,ymj=rw/kaigai} 6 sake 320 + \. + : + + + + + + + PGACE Security Framework + + This chapter introduces the design of PGACE (PostgreSQL Access + Control Extension) security framework. + + + It enables to host various kind of enhanced security features + based on different security design, granularity and platforms. + + The Row-level Database ACLs feature is always enabled as + a common DAC policy on databses, and it also gives users + a chance to choose one or no MAC features. + + + It allows users to choose a MAC feature via a GUC parameter of + pgace_feature at + $PGDATA/postgresql.conf. + Its default is none, and currently we have + selinux as a candidate. + + + PGACE consists of two major facilities. + The one is a set of security hooks deployed on some of strategic + points in the core PostgreSQL. It enables to implement new enhanced + security features with minimum impact to the core code. + The other is facilities to manage security attribute which can be + used to make a decision in access controls. + + + + Security Hooks + + All the security hooks are declared as inline functions at + src/include/security/pgace.h. + + The security hooks have entry points to invoke an enhanced security + feature chosen by users, so invoked one can return its decision on + the source strategic point. + + + For example, the following pgaceHeapTupleInsert + is invoked just before inserting a new tuple into a relation. + + If the hook returns false to the caller, + this insertion will be skipped. Otherwise, rest of steps will be + done notmally. + + The enhanced security feature can make its decision based on the + given arguments which shows context in the invocation of hook. + The rel and tuple show + the target relation and tuple in this example. + + + static inline bool + pgaceHeapTupleInsert(Relation rel, HeapTuple tuple, + bool is_internal, bool with_returning) + { + /* A wired DAC check */ + if (!rowaclHeapTupleInsert(rel, tuple, + is_internal, + with_returning)) + return false; + + switch (pgace_feature) + { + #ifdef HAVE_SELINUX + case PGACE_FEATURE_SELINUX: + if (sepgsqlIsEnabled()) + return sepgsqlHeapTupleInsert(rel, tuple, + is_internal, + with_returning); + break; + #endif + default: + break; + } + return true; + } + + + This example shows a wired security feature (Row-level Database + ACLs) and one or no selectable feature are invoked on a tuple + insertion. + + It allows users to choose one of enhanced security feature from + candidates via a GUC parameter of pgace_feature. + In this case, SE-PostgreSQL is an only candidate when the binary + is compiled with option. + + + If you add a new security feature, you should add a new case + branch in the switch statement and an option + to the GUC parameter, for users selection. + + The following example shows a case when someone add a new security + feature compiled when HAVE_FOO_SECURITY is + defined on build-time. + + + static inline bool + pgaceHeapTupleInsert(Relation rel, HeapTuple tuple, + bool is_internal, bool with_returning) + { + /* A wired DAC check */ + if (!rowaclHeapTupleInsert(rel, tuple, + is_internal, + with_returning)) + return false; + + switch (pgace_feature) + { + #ifdef HAVE_SELINUX + case PGACE_FEATURE_SELINUX: + if (sepgsqlIsEnabled()) + return sepgsqlHeapTupleInsert(rel, tuple, + is_internal, + with_returning); + break; + #endif + #ifdef HAVE_FOO_SECURITY + case PGACE_FEATURE_FOO_SECURITY: + return fooSecurityHeapTupleInsert(rel, tuple, + is_internal, + with_returning); + break; + #endif + default: + break; + } + return true; + } + + + Please note that individual specifications of security hooks are + described in src/include/security/pgace.h + as comment. It will help you to understand. + + If a part of given hooks are unnecessary for your security design, + keep it as is. + + + + + Security Label Management + + The security label is a human readable security attribute which + can be export/import via security_label system + column. + PGACE provides a common facility to manage the security label of + tuples for various kind of security features. + It enables an enhanced security feature chosen to store and featch + a security label of tuples, and allows it to make a decision in + access controls based on the label. + + + We can export/import the security labels in text format, but + they are handled as an alternative identifier internally. + + We call it as a security identifier (sid), and it has a length + of sizeof(Oid). The sid references to + an entry within pg_security system catalog, + and the entry holds a human readable text representation. + + + We can have the sid on the padding field of + HeapTupleHeader, as if oid doing. + We can fetch it with HeapTupleGetSecLabel(). + + If pgaceTupleDescHasSecLabel() hook returns + true for the given relation, it indicates + to allocate sid field on the tuples within the relation. + In this case, we can set a sid using + HeapTupleSetSecLabel() macro. + + + PGACE provides a few utility functions. + + pgaceLookupSecurityId() returns a sid + towards given security label in text format. If it is not on + pg_security, it automatically inserts a new + entry and returns its sid. + + pgaceLookupSecurityLabel() returns a security + label for the given sid. + If it is not on pg_security, it returns + NULL, so the guest should handler it as a + something like default or unlabeled. + + + The security_label system column allows users + to input a security label in text format on INSERT, + UPDATE, COPY and so on. + + The given security label is translated into sid automatically, and + put on the security field of tuples. If user provides nothing as + a security label, it is initialized as InvalidOid. + + The pgaceHeapTupleInsert() or others are invoked + later, so the enhanced security feature can know whether user gives + a proper security label or not. If no security label is given, it + can assign a default security label. If violated security label is + given, it can raise an error. + + Vice versa, when user refers security_label, + the sid of tuples are automatically translated into text format. + If the sid is invalid, the enhanced security feature can return + an alternative string using + pgaceUnlabeledSecurityLabel() hook. + + + The Row-level Database ACLs uses the facility to manage security + labels to store its ACLs. Tules have a capability to store both + of sids simultaneously, and enhanced security features should + not touch them. + + + + +