*** a/doc/src/sgml/catalogs.sgml
--- b/doc/src/sgml/catalogs.sgml
***************
*** 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,4270 ----
+
+ pg_security
+
+
+ pg_security
+
+
+
+ The catalog pg_security stores text
+ representations of security attributes managed by the PGACE framework.
+
+
+
+ Security modules managed by the PGACE framework can associate security
+ attributes with individual tuples. Because the same security attribute
+ value is typically associated with many individual objects, all values
+ known to the system are stored here and referenced by OID. This OID is
+ called a security id and is part of the tuple header.
+
+
+
+ When an new security attribute is given to the system, a new tuple is
+ added to pg_security and a new security
+ id is assigned by PGACE. On output, a
+ security id can be rendered as text using this
+ system catalog as a lookup table.
+
+
+
+ See for more information.
+
+
+
+ pg_security>Columns
+
+
+
+
+ Name
+ Type
+ References
+ Description
+
+
+
+
+
+ seclabel
+ text
+
+ Text representation of security attribute
+
+
+
+
+ pg_shdepend
*** a/doc/src/sgml/errcodes.sgml
--- b/doc/src/sgml/errcodes.sgml
***************
*** 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>
*** a/doc/src/sgml/filelist.sgml
--- b/doc/src/sgml/filelist.sgml
***************
*** 139,144 ****
--- 139,145 ----
+
*** a/doc/src/sgml/postgres.sgml
--- b/doc/src/sgml/postgres.sgml
***************
*** 254,259 ****
--- 254,260 ----
&features;
&release;
&contrib;
+ &security;
&external-projects;
&cvs;
&docguide;
*** a/doc/src/sgml/ref/initdb.sgml
--- b/doc/src/sgml/ref/initdb.sgml
***************
*** 234,239 **** PostgreSQL documentation
--- 234,252 ----
+
+
+
+
+
+ Selects an enhanced security feature, and writes it to
+ postgresql.conf.
+ The default is none which means no enhanced
+ security feature is activated. Currently, the only available
+ enhanced security feature is selinux.
+
+
+
*** a/doc/src/sgml/ref/pg_dump.sgml
--- b/doc/src/sgml/ref/pg_dump.sgml
***************
*** 634,639 **** PostgreSQL documentation
--- 634,662 ----
+
+
+
+
+
+ Dumps row-level ACLs with table contents.
+ ACLs can be restored via writable system column
+ security_acl.
+
+
+
+
+
+
+
+
+ Dumps security labels managed by available enhanced security feature
+ with table contents.
+ Labels can be restored via writable system column
+ security_label.
+
+
+
*** a/doc/src/sgml/ref/pg_dumpall.sgml
--- b/doc/src/sgml/ref/pg_dumpall.sgml
***************
*** 334,339 **** PostgreSQL documentation
--- 334,361 ----
+
+
+
+
+ Dumps row-level ACLs with table contents.
+ ACLs can be restored via writable system column
+ security_acl.
+
+
+
+
+
+
+
+
+ Dumps security labels managed by available enhanced security feature
+ with table contents.
+ Labels can be restored via writable system column
+ security_label.
+
+
+
*** /dev/null
--- b/doc/src/sgml/security.sgml
***************
*** 0 ****
--- 1,1383 ----
+
+ Enhanced Security Features
+
+
+
+ This chapter introduces enhanced security features which enable
+ PostgreSQL to provide mandatory
+ access controls, fine-grained access controls, and integration of security
+ policy between the operating system and
+ PostgreSQL.
+
+
+
+ The current version of PostgreSQL has two enhanced security
+ features: SE-PostgreSQL (Security Enhanced PostgreSQL)
+ and Row-level Database ACLs.
+ Both are implemented using a common security framework called
+ PGACE (PostgreSQL Access Control Extensions), which provides basic
+ facilities to manage security attributes for database objects and
+ hooks to take control at strategic points within the core code.
+
+
+
+ SE-PostgreSQL provides additional fine-grained mandatory access
+ controls on accesses to database objects via SQL. It makes a
+ decision whether a given client request should be
+ allowed, or not, by 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.
+
+ The access controls implemented by SE-PostgrSQL may not be biased even
+ by privileged database users, making it an implementation of
+ MAC (Mandatory Access Control). This enables it to prevent information
+ leaks and manipulation from a hypothetical malicious insider and reduced
+ the risks posed by SQL injection or other application-level bugs.
+
+
+
+ The Row-level Database ACLs feature enables
+ PostgreSQL to apply existing DAC
+ (Discretionary Access Control) policy down to the level of individual
+ database rows.
+
+ Permissions can be set individually for SELECT,
+ UPDATE and DELETE.
+ Tuples for which permission is denied are silently filtered from the
+ result set.
+
+
+
+ The PGACE security framework can host two security
+ features simultaneously. Row-level Database ACLs are always provided as
+ a Discretionary Access Control (DAC) feature. Mandatory Access Control
+ (MAC) must be explicitly enabled, and the only current implementation is
+ SE-PostgreSQL.
+
+ To enable SE-PostgreSQL, specify option
+ at configure time,
+ and use the option to
+ initdb.
+
+ $ ./configure --enable-selinux
+ $ make install
+ $ initdb --pgace-feature=selinux
+
+
+
+
+
+
+ SE-PostgreSQL Features
+
+
+ Single unified security policy
+
+
+ Because files and databases have similar capabilities to store
+ information assets, similar access controls are needed to maintain
+ confidentiality and data integrity. Information stored in the
+ filesystem is accessed through system calls, such as
+ write(2), while database objects are accessed
+ via SQL queries.
+
+
+
+ Without specific support from the database, there is no way for a
+ system-level mandatory access control policy to also apply to database
+ objects. While access to the database files themselves could be
+ controlled, selective access to the contents of the database would
+ be forced to rely on whatever set of discretionary access controls
+ the database system provided.
+
+
+
+ SE-PostgreSQL overcomes this problem by making its access control
+ decision based on the security policy of SELinux. This means that
+ the same security contexts and policies which are applied to filesystem
+ objects can also be applied to database objects, providing a
+ reliable foundation for comprehensive and integrated
+ security.
+
+ For example, when we store information labeled as
+ Classified, it cannot be accesed by users without
+ proper privileges regardless of whether it is stored in the filesystem
+ or within the database. Because the decision to allow or deny access
+ is based only on the kernel's mandatory access control policy, and
+ not on PostgreSQL's existing Discretionary Access Control (DAC)
+ mechanisms, it cannot be subverted even by a database superuser.
+ (Similarly, SELinux in general can restrict privileges of any system
+ user, including root.)
+
+
+
+
+ Security Context
+
+ The SELinux security policy is a set of access controls
+ rules which define who is allowed to perform which operations
+ on which objects.
+
+ These rules are described as a relationship of two entities
+ identified by common format called a security context.
+
+
+ The security context is a formatted string independent of
+ the type of object being labeled, such as:
+ system_u:object_r:postgresql_db_t:SystemHigh.
+
+ Security contexts are used to label files, sockets, and other
+ resources, and access decisions are made by testing whether a particular
+ relationship between two labels is permitted by the access control
+ rules.
+
+
+ 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,
+ it issues a write(2) system call; SELinux searches
+ its security policy database to determine the relationship between the
+ two security contexts.
+
+ If the entry found entry allows the operation, SELinux takes no action;
+ otherwise, SELinux blocks the write.
+
+
+
+ Any object managers which want a decision come from SELinux
+ (including kernel) should have the capability to manage the security
+ contexts of their 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
+
+ In order to properly apply SELinux access controls, SE-PostgreSQL needs
+ to know the security context of each connected client. It does this using
+ the SELinux-supplied system call getpeercon(), which
+ provides the security context of the process connected to the remote
+ end of a particular socket.
+
+ Note that the peer's security context is unrelated to the database role
+ used to authenticate, although the role-based permissions are still
+ applied and can deny access to database objects independently of
+ SE-PostgreSQL.
+
+
+
+ The security context of the connected client can be fetched using
+ the sepgsql_getcon() function, like this:
+
+ $ 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)
+
+
+
+
+ When connecting to SE-PostgreSQL via a TCP/IP socket, labeled networking
+ must be set up to ensure that getpeercon() returns
+ the correct security context.
+ See for more
+ defails.
+
+
+
+
+ Mandatory Access Controls
+
+ MAC (Mandatory Access Controls) a system of security controls that is
+ significantly different from DAC (Discretionary Access Controls)
+ such as filesystem permissions and database ACLs.
+
+ The major difference is that MAC requires that access controls be applied
+ to all managed objects without exception, including, for example,
+ the root user.
+
+ Every subject and object must be identified by security
+ labels, and MAC policy is described as a set of relationships
+ between pairs of labels. The security context of SELinux is a
+ sort of label, but includes more identifiers than
+ traditional trusted-operating system.
+
+ Finally, MAC should not allow resource owners to change its
+ access control rights arbitrarily. DAC design allows us
+ to change them using chmod or
+ GRANT. But in a MAc design, security policy restricts
+ these types of changes.
+
+
+ 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 applies
+ these rules unless a different context is explicitly specified by
+ including the 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.
+
+
+ # UPDATE drink SET security_label = 'system_u:object_r:sepgsql_ro_table_t' WHERE id < 4;
+
+
+ To use this feature, the client must have privileges to insert or update
+ the security context of tuples. Otherwise, SE-PostgreSQL will block any
+ attempt to change them.
+
+
+ SELECT INTO or CREATE TABLE AS
+ including security_label system column as a target
+ is handled like a series of INSERT statements with
+ explicit security contexts.
+
+
+ # 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 the 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 contexts try to SELECT the 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 2 tuples were filtered out by SE-PostgreSQL.
+
+
+ $ 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 applies access controls to
+ tables and columns, but these are handled differently than row-level
+ security.
+
+
+ SE-PostgreSQL walks each query and considers the security contexts
+ of all tables and columns which appeare therin. If any of those
+ tables or columns are ones which the client is not permitted to access,
+ SE-PostgreSQL aborts query execution and returns an error to the client.
+
+
+ The following example shows a case when we declared a
+ ccredit column to store credit card numbers
+ as a secret column, hidden from unclassified users.
+
+
+ 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)
+
+
+ In the first query, the user tried to refer all the columns;
+ SE-PostgreSQL prevents query execution because it contains
+ a reference to ccredit column which is
+ labeled as sepgsql_secret_table_t.
+
+ Then, the user tried to refer to all columns except the
+ ccredit column, so SE-PostgreSQL allowed the user
+ to execute the query, because no access control rules were violated.
+
+
+
+ Access Controls on Functions
+
+ SE-PostgreSQL also prevents clients from invoking functions for
+ which they do not have the necessary privileges.
+
+
+ In the current default security policy, a function declared by
+ administrative users (like unconfined_t domain)
+ is labeled as sepgsql_proc_t. Those declared
+ by normal users (like staff_t domain) are labeled
+ as staff_sepgsql_proc_exec_t and therefore can't
+ be invoked by administrative users.
+
+ This system prevents administrative users from invoking 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 privileges during
+ execution of specific functions called as trusted procedures.
+ These are similar to security definer functions, but for security
+ contexts rather than database roles.
+
+ In the current default security policy, trusted procedures are
+ functions labeled as sepgsql_trusted_proc_exec_t.
+ This enables users to execute these functions with administrative
+ privileges, providing a secure method for accessing confidential objects.
+
+ This provides a simple all or nothing policy, but more complex
+ controls are possible if you install your own security policy module.
+
+
+ The following example declares a trusted procedure
+ show_credit to expose some, but not all, of the
+ information stored in customer.credit.
+
+ Assume that a client within staff_t domain
+ cannot access the credit column. A trusted
+ trusted procedure can provide access, because the sub-queries
+ from the procedure are 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=#
+
+
+
+
+
+ Limitations
+
+ SE-PostgreSQL does not prevent information leaks via covert channels.
+ In other words, clients may be able to infer information about data
+ they cannot directly access.
+
+ If your requirements include elimination of covert channels,
+ SE-PostgreSQL may not be an adequate solution. Covert channel
+ analysis is required by the upper B2 class of TCSEC and by
+ ISO/IEC15408, also known as CC (Common Criteria).
+
+
+ Covert channels are possible when, for example, a client attempts
+ to update or delete a tuple with primary key refered by
+ one or more invisible foreign keys. SE-PostgreSQL will prevent the
+ action to preserve reference integrity, even though the client
+ cannot see the key.
+
+ From this, the client can infer the existence of the invisible foreign
+ key, an inference to which he is not entitled.
+
+ As a practical matter, this scenario can sometimes be avoided by using
+ non-natural primary and foreign keys, such as UUIDs. This may make it
+ impossible to 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.
+
+ Without this option, no enhanced security feature will be activated for
+ 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, this parameter 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.
+ Otherwise, the default is none.
+
+
+
+
+
+ sepostgresql
+
+
+ This parameter 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 SE-PostgreSQL.
+
+
+
+
+
+ sepostgresql_row_level
+
+
+ This parameter has two possible values true, or
+ false. Setting this parameter to
+ false
+ turns off the row-level access control feature. This is not
+ recommended unless when your system has extremely severe
+ requirements with respect to storage comsumption.
+
+ The 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.
+
+
+
+ Needless to say, a process which invokes pg_dump
+ must be allowed to refer whole of the database,
+ because SE-PostgreSQL filters all inaccessible tuples from the result
+ set, or aborts query execution if it references inaccessible
+ columns, tables, or functions.
+
+ 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 the 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 that of the table, it
+ must be specified explicitly in the CREATE TABLE
+ statement.
+
+
+
+
+ Labeled Networks
+
+ Labeled Networks is a technology which makes it possible to
+ obtain the security context of peer process communicating
+ via a TCP/IP connection.
+
+
+
+ This technology contains two facilities.
+ One is Labeled IPsec,
+ and the other is Static Fallback Context.
+
+ This section shows the way to set up both labeled networks
+ technology.
+
+
+
+ Labeled IPsec
+
+ When communicating using an encrypted channel
+ with IPsec, the key-exchange daemon racoon
+ on each machine exchanges encryption keys with its peer.
+
+ In addition, the security context of the connecting process is
+ delivered to the peer.
+
+ The delivered security context is cached on the kernel, and
+ it is exported into applications via the
+ 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 do this on both server side and client side.
+
+ Note that you have to switch the 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 switch the 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 Fallback 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 fallback 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 fallback 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 makes it possible to assign ACLs
+ to each individual tuple, and works as a supplemental facility to existing
+ database ACLs applied to tables and columns.
+
+
+
+ Design
+
+ The design of Row-level Database ACLs feature inherits many things
+ from existing access control mechanism. For example, it is a sort
+ of discretionary access control mechanism, so it allows the owner of
+ a resource to change its access control rights, and does not affect
+ database superusers.
+
+
+ This feature is implemented as a guest of PGACE security framework,
+ but wired feature, not a selectable one.
+
+
+ It works as if there is a filter to drop inaccessible tuples on scanning
+ the relation. Just before the executor scans relation, tables and
+ columns level ACLs are also checked, and the feature makes a decision
+ as to whether the tuple should be returned, ot not.
+
+
+ We provides four kind of permissions on tuples.
+ These are SELECT, UPDATE,
+ DELETE and REFERENCES.
+
+ An INSERT permission would not make sense,
+ because the target does not exist when it should be checked.
+
+ You should control insertion of tuples via table-level ACLs.
+
+
+ PostgreSQL implements foreign key constraints as built-in trigger
+ functions, and it invokes another query to maintain referential
+ integrity.
+
+ 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
+ an inaccessible tuple.
+
+ As with SE-PostgreSQL, unprivileged users may be able to infer
+ information about tuples they cannot access directly.
+
+
+ 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 the
+ security_acl system column.
+ 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 for newly inserted tuples.
+
+
+
+
+ Administration
+
+ Setup Row-level ACLs
+
+ The row_level_acl table option on
+ CREATE TABLE or ALTER TABLE
+ is used 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. For example:
+
+
+ # 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 in order to update
+ security_acl.
+
+ Please note that this feature considers the owner of a tuple to be
+ the owner of the table in which they are stored, rather than the client
+ who inserted the tuple.
+
+
+
+
+ Backup and Restore
+
+ The --security-acl option to
+ pg_dump and pg_dumpall
+ can be used to dump tables with row-level ACLs. With this option,
+ the output will contain the security_acl system
+ column if the row-level ACLs 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 normally.
+
+ 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 this facility to manage security
+ labels to store its ACLs. Tules have a capability to store both types
+ of sids simultaneously, and enhanced security features should
+ not touch them.
+
+
+
+
+