*** a/doc/src/sgml/catalogs.sgml --- b/doc/src/sgml/catalogs.sgml *************** *** 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,4270 ---- + + <structname>pg_security</structname> + + + 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. + + + + <structname>pg_security</>Columns + + + + + Name + Type + References + Description + + + + + + seclabel + text + + Text representation of security attribute + + + +
+
<structname>pg_shdepend</structname> *** 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. + + + + +