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_shdependdependencies on shared objects
***************
*** 977,982 ****
--- 982,996 ----
+ attkind
+ char
+
+
+ A copy of pg_class.relkind> of this columns's relation
+
+
+
+ attnotnullbool
***************
*** 4195,4200 ****
--- 4209,4281 ----
+
+ pg_security
+
+
+ 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.
+
+
+
+ pg_security>Columns
+
+
+
+
+ Name
+ Type
+ References
+ Description
+
+
+
+
+
+ seclabel
+ text
+
+ Text representation of security attribute
+
+
+
+
+ pg_shdepend
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.
+
+
+
+
+