Re: SE-PostgreSQL Updated Revision (r1460) - Mailing list pgsql-hackers
From | KaiGai Kohei |
---|---|
Subject | Re: SE-PostgreSQL Updated Revision (r1460) |
Date | |
Msg-id | 497EDDF6.9040106@ak.jp.nec.com Whole thread Raw |
In response to | Re: SE-PostgreSQL Updated Revision (r1460) (Robert Haas <robertmhaas@gmail.com>) |
List | pgsql-hackers |
Robert Haas wrote: >> And, I have a question about documentation manner. >> - You represented "getpeercon()" function as a system call. >> But, it is actually a wrapper function of getsockopt(2) system call, >> so the "getpeercon(3)" is not a system call strictly. >> Is it necessary to represent these stuffs strictly correct? >> (Thus, I wrote it as "API" in the r1460.) > > Oh, OK. It sounds a little awkward to me to refer to it as an API. > Perhaps we could just refer to it as getpeercon(3) and not call it > either an API or a system call. I replaced all the "getpeercon()" by "getpeercon(3)", and removed expression both "system call" and "API". >> About 2, SELinux community provides its default security policy, >> and distributor's policy (including RedHat's one) is a derivative >> of the default policy. >> It is developed independent from distributor's cycle. >> http://oss.tresys.com/projects/refpolicy >> http://oss.tresys.com/repos/refpolicy/trunk/policy/modules/services/postgresql.te > > OK, I wasn't aware of that. I think perhaps you could spell this out > a little more in the docs so people understand that there is an > upstream version which includes SE-PostgreSQL support from version > <whatever>. I noted it as: | The upstreamed security policy (<literal>20080702</literal> | or later) already has a set of rules for SE-PostgreSQL, | as a part of PostgreSQL policy. The "<whatever>" is not a tag, is it? > Actually, I think this should probably be broken up into three > sections. All of the stuff about how PGACE is not very interesting to > anyone who isn't a developer, so it should be moved to someplace under > "Internals". I would suggest just adding a new chapter to the end of > that section, after "How the Planner Uses Statistics". > > The database ACL stuff properly belongs in the "Database Roles and > Privileges" section, and needs to be moved there, not just a > cross-reference. > > The discussion of enhanced security and SE-PostgreSQL is another new > chapter, probably immediately following "Database Roles and > Privileges". I would suggest calling it "Enhanced Security and > SE-PostgreSQL". OK, I deployed these section as you suggested. - The "Row-level Database ACLs" section is moved to the tail of Chapter 20. Database Roles and Privileges. - The new "Enhanced Security and SE-PostgreSQL" is moved to Chapter.21. - The new "Chapter 57. PGACE Security Framework" is moved to Chapter.57, next to the "56. How the Planner Uses Statistics". > I think in general that the current > documentation spends far too much time explaining what SE-PostgreSQL > is and not enough time discussing the issues that are likely to come > up when you're actually using it. For example, it seems to me that > anyone who has any interest in using SE-PostgreSQL to control access > to functions will need a much more complicated policy than what you > are proposing here, and there doesn't seem to be much discussion of > that issue. I'm not really looking for specific examples of how to > build a policy so much as general considerations that you should keep > in mind when trying to prevent information leakage via functions. I added a new section "21.3. Making a Security Policy", but it is still empty. I think it is not necessary to document comprehensive information about security policy, since it is not a SELinux document. My plan is to introduce a simple copy & pastable example and steps to build it (with standard toolchain) and to install it as an security policy module. Please wait for filling up the section... Thanks, -- OSS Platform Development Division, NEC KaiGai Kohei <kaigai@ak.jp.nec.com> 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 Tue Jan 27 18:48:27 2009 *************** *** 204,209 **** --- 204,214 ---- </row> <row> + <entry><link linkend="catalog-pg-security"><structname>pg_security</structname></link></entry> + <entry>text representation of security attribute</entry> + </row> + + <row> <entry><link linkend="catalog-pg-shdepend"><structname>pg_shdepend</structname></link></entry> <entry>dependencies on shared objects</entry> </row> *************** *** 977,982 **** --- 982,996 ---- </row> <row> + <entry><structfield>attkind</structfield></entry> + <entry><type>char</type></entry> + <entry></entry> + <entry> + A copy of <literal>pg_class.relkind</> of this columns's relation + </entry> + </row> + + <row> <entry><structfield>attnotnull</structfield></entry> <entry><type>bool</type></entry> <entry></entry> *************** *** 4195,4200 **** --- 4209,4270 ---- </sect1> + <sect1 id="catalog-pg-security"> + <title><structname>pg_security</structname></title> + + <indexterm zone="catalog-pg-security"> + <primary>pg_security</primary> + </indexterm> + + <para> + The catalog <structname>pg_security</structname> stores text + representations of security attributes managed by the PGACE framework. + </para> + + <para> + 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 <literal>security id</literal> and is part of the tuple header. + </para> + + <para> + When an new security attribute is given to the system, a new tuple is + added to <structname>pg_security</structname> and a new <literal>security + id</literal> is assigned by PGACE. On output, a + <literal>security id</literal> can be rendered as text using this + system catalog as a lookup table. + </para> + + <para> + See <xref linkend="pgace-security-label"> for more information. + </para> + + <table> + <title><structname>pg_security</>Columns</title> + + <tgroup cols=4> + <thead> + <row> + <entry>Name</entry> + <entry>Type</entry> + <entry>References</entry> + <entry>Description</entry> + </row> + </thead> + + <tbody> + <row> + <entry><structfield>seclabel</structfield></entry> + <entry><type>text</type></entry> + <entry></entry> + <entry>Text representation of security attribute</entry> + </row> + </tbody> + </tgroup> + </table> + </sect1> <sect1 id="catalog-pg-shdepend"> <title><structname>pg_shdepend</structname></title> diff -Nrpc base/doc/src/sgml/config.sgml sepgsql/doc/src/sgml/config.sgml *** base/doc/src/sgml/config.sgml Thu Jan 22 14:34:54 2009 --- sepgsql/doc/src/sgml/config.sgml Tue Jan 27 18:48:27 2009 *************** SET ENABLE_SEQSCAN TO OFF; *** 706,711 **** --- 706,784 ---- </listitem> </varlistentry> + <varlistentry id="guc-pgace-feature" xreflabel="pgace-feature"> + <term><varname>pgace_feature</varname> (<type>string</type>)</term> + <indexterm> + <primary><varname>pgace_feature</> configuration parameter</primary> + </indexterm> + <listitem> + <para> + An identifier name of current working enhanced security feature on + PGACE security framework. + (see <xref linkend="pgace-security-framework"> for more information) + This parameter can only be set at server start. + </para> + <para> + Currently, this parameter has two possible values. + The one is <literal>none</literal> not to enable any + enhanced security features, and the other is + <literal>selinux</literal> to enable SE-PostgreSQL + feature. + </para> + <para> + If you run <command>initdb</command> with + <option>--pgace-feature=selinux</option>, this parameter is + automatically specified to <literal>selinux</literal>. + Otherwise, the default is <literal>none</literal>. + </para> + </listitem> + </varlistentry> + + <varlistentry id="guc-sepostgresql" xreflabel="sepostgresql"> + <term><varname>sepostgresql</varname> (<type>string</type>)</term> + <indexterm> + <primary><varname>sepostgresql</> configuration parameter</primary> + </indexterm> + <listitem> + <para> + Enables to choose the current working mode of SE-PostgreSQL. + This parameter has four possible values to specify working mode of + SE-PostgreSQL. The <literal>default</literal> is a default + selection. It always follows the configuration on operating + system. The <literal>enforcing</literal> and + <literal>permissive</literal> 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 <literal>disabled</literal> disables SE-PostgreSQL. + This parameter is available on a binary with SELinux support + (<literal>--enable-selinux</literal>), and can only be set at + server start. + </para> + </listitem> + </varlistentry> + + <varlistentry id="guc-sepostgresql-row-level" xreflabel="sepostgresql-row-level"> + <term><varname>sepostgresql_row_level</varname> (<type>boolean</type>)</term> + <indexterm> + <primary><varname>sepostgresql_row_level</> configuration parameter</primary> + </indexterm> + <listitem> + <para> + Enables to turn on/off row-level access controls via SE-PostgreSQL. + The row-level access control feature requires additional 4-bytes + field for each tuples, so setting it <literal>off</literal> enables + to save the storage consumption, in return for the row-level granularity. + But we don't recommend it, unless you faces extremely severe requirements + for saving storage consumption. + The default is <literal>on</literal> which means row-level access + controls are available. + This parameter is available on a binary with SELinux support + (<literal>--enable-selinux</literal>), and can only be set at + server start. + </para> + </listitem> + </varlistentry> + </variablelist> </sect2> </sect1> 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 ---- <entry>too_many_rows</entry> </row> + <row> + <entry spanname="span13"><emphasis role="bold">Class SE — Enhanced Security Error</></entry> + </row> + + <row> + <entry><literal>SE000</literal></entry> + <entry>PGACE ERROR</entry> + <entry>pgace_framework_error</entry> + </row> + + <row> + <entry><literal>SE011</literal></entry> + <entry>ROWACL ERROR</entry> + <entry>errors_in_row_level_acls</entry> + </row> + + <row> + <entry><literal>SE021</literal></entry> + <entry>SELINUX ERROR</entry> + <entry>errors_in_sepostgresql</entry> + </row> + + <row> + <entry><literal>SE022</literal></entry> + <entry>SELINUX AUDIT</entry> + <entry>audit_records_of_sepostgresql</entry> + </row> + + <row> + <entry><literal>SE023</literal></entry> + <entry>SELINUX INFO</entry> + <entry>information_from_sepostgresql</entry> + </row> <row> <entry spanname="span13"><emphasis role="bold">Class XX — Internal Error</></entry> 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 Tue Jan 27 18:48:27 2009 *************** *** 45,50 **** --- 45,51 ---- <!entity runtime SYSTEM "runtime.sgml"> <!entity config SYSTEM "config.sgml"> <!entity user-manag SYSTEM "user-manag.sgml"> + <!entity sepgsql SYSTEM "sepgsql.sgml"> <!entity wal SYSTEM "wal.sgml"> <!-- programmer's guide --> *************** *** 84,89 **** --- 85,91 ---- <!entity planstats SYSTEM "planstats.sgml"> <!entity indexam SYSTEM "indexam.sgml"> <!entity nls SYSTEM "nls.sgml"> + <!entity pgace SYSTEM "pgace.sgml"> <!entity plhandler SYSTEM "plhandler.sgml"> <!entity protocol SYSTEM "protocol.sgml"> <!entity sources SYSTEM "sources.sgml"> diff -Nrpc base/doc/src/sgml/pgace.sgml sepgsql/doc/src/sgml/pgace.sgml *** base/doc/src/sgml/pgace.sgml Thu Jan 1 09:00:00 1970 --- sepgsql/doc/src/sgml/pgace.sgml Tue Jan 27 18:48:27 2009 *************** *** 0 **** --- 1,234 ---- + <chapter id="pgace-security-framework"> + <title>PGACE Security Framework</title> + + <para> + This chapter introduces the design of PGACE (PostgreSQL Access + Control Extension) security framework. + </para> + <para> + It enables to host various kind of enhanced security features + based on individual security design, granularity and platforms + with minimum impact toward the core PostgreSQL implementation. + </para> + <para> + Currently, it hosts two security features. + + The one is Row-level ACLs feature. It is always enabled as an + enhancement of common database ACLs in row-level granularity, + as a hardwired DAC (Discretionary Access Control) feature. + + It also allows users to choose a MAC (Mandatory Access Control) + via a GUC option <literal>pgace_feature</literal> on the startup + time. Its default is <literal>none</literal>, but currently we + have <literal>selinux</literal> option as a candidate. + </para> + <para> + 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. + </para> + + <sect1 id="pgace-security-hooks"> + <title>PGACE Security Hooks</title> + <para> + This section introduces the overview of security hooks and + the way to invoke your security feature via the hooks. + </para> + <para> + All the security hooks are defined at + <filename>src/backend/security/pgaceHooks.c</filename>. + + The security hooks are entry point of any enhanced security + feature chosen by users, so invoked ones can return its + decision on the given strategic point. + </para> + <para> + For example, the following <literal>pgaceHeapTupleInsert</literal> + is invoked just before inserting a new tuple into a relation. + + If the hook returns <literal>false</literal> 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 <literal>rel</literal> and <literal>tuple</literal> show + the target relation and tuple in this example. + </para> + <programlisting> + 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; + } + </programlisting> + <para> + This example shows a hard-wired security feature (Row-level ACLs) + and one or no selectable feature can be invoked on a tuple insertion. + + Is allows users to shoose an enhanced security feature from the + candidates via <literal>pgace_feature</literal> GUC option. + An integer variable of <literal>pgace_feature</literal> reflects + the configuration. + </para> + <para> + In this example, SE-PostgreSQL is an only candidate when the binary + is compiled with <option>--enable-selinux</option> option. + </para> + <para> + If you add a new security feature, you should add a new case + branch in the <literal>switch</literal> 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 <literal>HAVE_FOO_SECURITY</literal> is + defined on build-time. + </para> + <programlisting> + 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; + } + </programlisting> + <para> + Please note that individual specifications of security hooks are + described in <filename>src/backend/security/pgaceHooks.c</filename> + as a source code comment. + It will help you to understand. + + If a part of given hooks are unnecessary for your security design, + keep it as is. + </para> + </sect1> + + <sect1 id="pgace-security-label"> + <title>Management of Security Label</title> + <para> + A security label is a human readable security attribute which can + be exported/imported via <literal>security_label</literal> 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. + </para> + <para> + It enables us to handle security labels in text form, but they + are internally handled as an alternative identifier. + + We call it as a <literal>security id</literal>. + It is an object identifier (oid) of <literal>pg_security</literal> + system catalog which holds human readable text form of security labels. + + So, we can mutually translate security id and security label via + <literal>pg_security</literal> system catalog. + </para> + <para> + The <literal>security id</literal> of tuple is stored within the + padding field of <literal>HeapTupleHeader</literal>, as if oid doing. + + We can fetch it via <literal>HeapTupleGetSecLabel()</literal> + macro. If <literal>pgaceTupleDescHasSecLabel()</literal> security + hook returns <literal>true</literal> for the given relation, it + means a new tuple within the relation should have a field to store + its <literal>security id</literal>. + + We can set it via <literal>HeapTupleSetSecLabel()</literal> macro. + </para> + <para> + A few utility functions are provided. + + <literal>pgaceLookupSecurityId()</literal> returns a security id + towards given security label in text format. If it is not on + <literal>pg_security</literal>, it automatically inserts a new + entry and returns its security id. + + <literal>pgaceLookupSecurityLabel()</literal> returns a security + label for the given sid. + If it is not on <literal>pg_security</literal>, it returns + <literal>NULL</literal>, so the guest should handle it as a + something like default or unlabeled. + </para> + <para> + The <literal>security_label</literal> system column allows users + to input a security label in text format on <command>INSERT</command>, + <command>UPDATE</command>, <command>COPY</command> and so on. + + The given security label is translated into security id automatically, + and put on the security field of tuples. If user provides nothing as + a security label, it is initialized as <literal>InvalidOid</literal>. + + The <literal>pgaceHeapTupleInsert()</literal> 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 <literal>security_label</literal>, + 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 + <literal>pgaceUnlabeledSecurityLabel()</literal> hook. + </para> + <para> + The Row-level Database ACLs uses this facility to manage security + labels to store its ACLs. Tuples have a capability to store both types + of security ids simultaneously, but enhanced security features should + not touch the row-level ACLs. + </para> + </sect1> + </chapter> 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 Tue Jan 27 18:48:27 2009 *************** *** 148,153 **** --- 148,154 ---- &config; &client-auth; &user-manag; + &sepgsql; &manage-ag; &charset; &maintenance; *************** *** 242,247 **** --- 243,249 ---- &storage; &bki; &planstats; + &pgace; </part> 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 Sun Jan 25 21:01:21 2009 *************** PostgreSQL documentation *** 234,239 **** --- 234,252 ---- </para> </listitem> </varlistentry> + + <varlistentry> + <term><option>--pgace-feature=<replaceable>FEATURE</></option></term> + <listitem> + <para> + Selects an enhanced security feature, and writes it to + <filename>postgresql.conf</filename>. + The default is <literal>none</literal> which means no enhanced + security feature is activated. Currently, the only available + enhanced security feature is <literal>selinux</literal>. + </para> + </listitem> + </varlistentry> </variablelist> </para> 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 Sun Jan 25 21:01:21 2009 *************** PostgreSQL documentation *** 634,639 **** --- 634,662 ---- </para> </listitem> </varlistentry> + + <varlistentry> + <term><option>--security-acl</option></term> + <listitem> + <para> + Dumps row-level ACLs with table contents. + ACLs can be restored via writable system column + <literal>security_acl</literal>. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>--security-label</option></term> + <listitem> + <para> + Dumps security labels managed by available enhanced security feature + with table contents. + Labels can be restored via writable system column + <literal>security_label</literal>. + </para> + </listitem> + </varlistentry> </variablelist> </para> 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 Sun Jan 25 21:01:21 2009 *************** PostgreSQL documentation *** 334,339 **** --- 334,361 ---- </listitem> </varlistentry> + <varlistentry> + <term><option>--security-acl</option></term> + <listitem> + <para> + Dumps row-level ACLs with table contents. + ACLs can be restored via writable system column + <literal>security_acl</literal>. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>--security-label</option></term> + <listitem> + <para> + Dumps security labels managed by available enhanced security feature + with table contents. + Labels can be restored via writable system column + <literal>security_label</literal>. + </para> + </listitem> + </varlistentry> </variablelist> </para> diff -Nrpc base/doc/src/sgml/sepgsql.sgml sepgsql/doc/src/sgml/sepgsql.sgml *** base/doc/src/sgml/sepgsql.sgml Thu Jan 1 09:00:00 1970 --- sepgsql/doc/src/sgml/sepgsql.sgml Tue Jan 27 18:48:27 2009 *************** *** 0 **** --- 1,1018 ---- + <chapter id="enhanced-security-and-sepostgresql"> + <title>Enhanced Security and SE-PostgreSQL</title> + <para> + This chapter introduces enhanced security features which enable + <productname>PostgreSQL</productname> to provide mandatory + access controls, fine-grained access controls, and integration + of security policy between the operating system and + <productname>PostgreSQL</productname>. + </para> + <para> + The current version of <productname>PostgreSQL</productname> + has two enhanced security features: Row-level Database ACLs and + SE-PostgreSQL (Security Enhanced PostgreSQL). + + 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. + + See, <xref linkend="pgace-security-framework"> for more details. + </para> + + <para> + The Row-level Database ACLs feature enables + <productname>PostgreSQL</productname> to apply existing DAC + (Discretionary Access Control) policy down to the level of individual + database rows. + + Permissions can be set individually for <command>SELECT</command>, + <command>UPDATE</command> and <command>DELETE</command>. + Tuples for which permission is denied are silently filtered from the + result set. + + It is also introduced at <xref linkend="row-level-database-acls">. + </para> + + <para> + 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 bypassed 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. + </para> + + <para> + 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>--enable-selinux</option> option + at <command>configure</command> time, + and use the <option>--pgace-feature=selinux</option> option to + <command>initdb</command>. + <screen> + <prompt>$ </prompt><userinput>./configure --enable-selinux</userinput> + <prompt>$ </prompt><userinput>make install</userinput> + <prompt>$ </prompt><userinput>initdb --pgace-feature=selinux</userinput> + </screen> + </para> + + <sect1 id="sepostgresql-features"> + <title>SE-PostgreSQL Features</title> + + <sect2 id="sepostgresql-single-unified-security-policy"> + <title>Single unified security policy</title> + + <para> + 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 + <command>write(2)</command>, while database objects are accessed + via SQL queries. + </para> + <para> + 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. + </para> + <para> + 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. + </para> + <para> + For example, when we store information labeled as + <literal>Classified</literal>, 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 <literal>root</literal>.) + </para> + + <sect3 id="sepostgresql-security-context"> + <title>Security Context</title> + <para> + 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. + </para> + <para> + The security context is a formatted string independent of + the type of object being labeled, such as: + <synopsis>system_u:object_r:postgresql_db_t:SystemHigh</synopsis>. + + 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. + </para> + <para> + For example, when a process labeled as + <literal>system_u:system_r:postgresql_t:s0</literal> tries to + write a log message to <filename>/var/log/postgresql.log</filename> + labeled as <literal>system_u:object_r:postgresql_log_t:s0</literal>, + it issues a <literal>write(2)</literal> 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. + </para> + <para> + 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 + <literal>security_label</literal> system column. + </para> + </sect3> + + <sect3 id="sepostgresql-client-privileges"> + <title>Client Privileges</title> + <para> + 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 + <literal>getpeercon(3)</literal>, 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. + </para> + + <para> + The security context of the connected client can be fetched using + the <literal>sepgsql_getcon()</literal> function, like this: + <screen> + <prompt>$ </prompt><userinput>id -Z</userinput> + unconfined_u:unconfined_r:unconfined_t:Classified + <prompt>$ </prompt><userinput>psql -q</userinput> + <prompt>postgres=# </prompt><userinput>SELECT sepgsql_getcon();</userinput> + sepgsql_getcon + --------------------------------------------------- + unconfined_u:unconfined_r:unconfined_t:Classified + (1 row) + </screen> + </para> + + <para> + When connecting to SE-PostgreSQL via a TCP/IP socket, labeled + networking must be set up to ensure that + <literal>getpeercon(3)</literal> returns the correct security + context. + See <xref linkend="sepostgresql-labeled-networks"> for more + defails. + </para> + </sect3> + + <sect3 id="sepostgresql-mac"> + <title>Mandatory Access Controls</title> + <para> + 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 <literal>root</literal> 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 <command>chmod</command> or + <command>GRANT</command>. But in a MAC design, security policy + restricts these types of changes. + </para> + <para> + 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. + </para> + <para> + 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. + </para> + </sect3> + </sect2> + + <sect2 id="sepostgresql-functionality"> + <title>The functionality of SE-PostgreSQL</title> + + <sect3 id="sepostgresql-security-label"> + <title>security_label system column</title> + <para> + SE-PostgreSQL enables to import/export security context of + tuples via <literal>security_label</literal> system column + which is available v8.4, or later. + </para> + <para> + The following example shows a case when we export security + context of tuples and its data via <command>SELECT</command>. + </para> + <screen> + <prompt>postgres=# </prompt><userinput>SELECT security_label, * FROM drink;</userinput> + 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) + </screen> + <para> + 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 <literal>security_label</literal> system column as + a target. + </para> + <screen> + <prompt># </prompt><userinput>INSERT INTO drink (security_label, id, name, price) + VALUES('system_u:object_r:sepgsql_ro_table_t', 7, 'tea', 130);</userinput> + </screen> + <para> + We can also change security context of tuples using + <literal>UPDATE</literal> statement. + </para> + <screen> + <prompt># </prompt><userinput>UPDATE drink SET security_label = 'system_u:object_r:sepgsql_ro_table_t' WHERE id < 4;</userinput> + </screen> + <para> + 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. + </para> + <para> + <command>SELECT INTO</command> or <command>CREATE TABLE AS</command> + including <literal>security_label</literal> system column as a target + is handled like a series of <literal>INSERT</literal> statements with + explicit security contexts. + </para> + <screen> + <prompt># </prompt><userinput>SELECT security_label, id, name, price / 2 AS price INTO discount FROM drink;</userinput> + 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) + </screen> + <para> + 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 + <literal>pg_class</literal> is considered as the one of table. + </para> + </sect3> + + <sect3> + <title>Access controls on Tuples</title> + <para> + 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. + </para> + <para> + The following example shows the case when two users with different + security contexts try to <command>SELECT</command> the same table + with same SQL. + A <literal>Classified</literal> user can whole of the table. + But <literal>Classified</literal> tuples are invisible from + other users. + </para> + <screen> + <prompt>$ </prompt><userinput>id -Z</userinput> + unconfined_u:unconfined_r:unconfined_t:Classified + <prompt>$ </prompt><userinput>psql -q postgres</userinput> + <prompt>postgres=# </prompt><userinput>SELECT security_label, * FROM drink;</userinput> + 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) + </screen> + <para> + It shows the <literal>Classified</literal> user got 6 tuples + with unconditional <command>SELECT</command> on drink table. + + However, the unclassified (not labeled) user got 4 tuples + with same SQL, because 2 tuples were filtered out by SE-PostgreSQL. + </para> + <screen> + <prompt>$ </prompt><userinput>id -Z</userinput> + unconfined_u:unconfined_r:unconfined_t + <prompt>$ </prompt><userinput>psql -q postgres</userinput> + <prompt>postgres=# </prompt><userinput>SELECT security_label, * FROM drink;</userinput> + 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) + </screen> + </sect3> + + <sect3> + <title>Access controls on Tables and Columns</title> + <para> + SE-PostgreSQL also applies access controls to + tables and columns, but these are handled differently than row-level + security. + </para> + <para> + 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. + </para> + <para> + The following example shows a case when we declared a + <literal>ccredit</literal> column to store credit card numbers + as a secret column, hidden from unclassified users. + </para> + <screen> + 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'); + </screen> + + <screen> + $ 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) + </screen> + <para> + In the first query, the user tried to refer all the columns; + SE-PostgreSQL prevents query execution because it contains + a reference to <literal>ccredit</literal> column which is + labeled as <literal>sepgsql_secret_table_t</literal>. + + Then, the user tried to refer to all columns except the + <literal>ccredit</literal> column, so SE-PostgreSQL allowed the user + to execute the query, because no access control rules were violated. + </para> + </sect3> + <sect3> + <title>Access Controls on Functions</title> + <para> + SE-PostgreSQL also prevents clients from invoking functions for + which they do not have the necessary privileges. + </para> + <para> + In the current default security policy, a function declared by + administrative users (like <literal>unconfined_t</literal> domain) + is labeled as <literal>sepgsql_proc_t</literal>. Those declared + by normal users (like <literal>staff_t</literal> domain) are labeled + as <literal>staff_sepgsql_proc_exec_t</literal> 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 <literal>sepgsql_proc_t</literal>. + </para> + <para> + 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 <literal>sepgsql_trusted_proc_exec_t</literal>. + 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. + </para> + <para> + The following example declares a trusted procedure + <literal>show_credit</literal> to expose some, but not all, of the + information stored in <literal>customer.credit</literal>. + + Assume that a client within <literal>staff_t</literal> domain + cannot access the <literal>credit</literal> column. A trusted + trusted procedure can provide access, because the sub-queries + from the procedure are handled as an administrative domain. + </para> + <screen> + # 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 + </screen> + <screen> + $ 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=# + </screen> + </sect3> + </sect2> + + <sect2> + <title>Limitations</title> + <para> + 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 was required by the upper B2 class of TCSEC and by + ISO/IEC15408 now, also known as CC (Common Criteria). + </para> + <para> + 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. + </para> + </sect2> + </sect1> + + <sect1 id="sepostgresql-administration"> + <title>SE-PostgreSQL Administration</title> + + <sect2> + <title>Build and Installation</title> + <sect3> + <title>Requirement</title> + <para> + We need the following packages to build and install + SE-PostgreSQL properly. Please check it at first. + </para> + + <variablelist> + <varlistentry> + <term><literal>Linux kernel</literal></term> + <listitem> + <para> + Linux kernel has to support SELinux feature, at least. + In addition, it is necessary to provide an interface to + obtain a list of supported object classes and permissions + via <filename>/selinux/class</filename>, which is available + on the Linux kernel 2.6.23 or later. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>Security policy</literal></term> + <listitem> + <para> + The security policy of SELinux is neccesary to contain access + control rules related to database objects. + The upstreamed security policy (<literal>20080702</literal> + or later) already has a set of rules for SE-PostgreSQL, + as a part of PostgreSQL policy. + </para> + <para> + In <literal>Red Hat EL</literal> or <literal>Fedora</literal>, + check the version number of <literal>selinux-policy</literal> + rpm package is <literal>3.4.2</literal>, or later. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>libselinux</literal></term> + <listitem> + <para> + <literal>libselinux</literal> is a library to communicate + between applications and in-kernel SELinux, so it provides + us various kind of APIs and header definitions. + It is necessary to provide header definitions of object + classes and permissions related to database. Rest of + requirements are already included in older version. + </para> + <para> + In <literal>Red Hat EL</literal> or <literal>Fedora</literal>, + check the version number of <literal>libselinux</literal> + and <literal>libselinux-devel</literal> rpm packages are + <literal>2.0.46</literal>, or later. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><command>checkmodule</command></term> + <listitem> + <para> + The <command>checkmodule</command> is a policy compiler + for a modular policy package, such as + <literal>sepostgresql-devel.pp</literal> we provided. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><command>semodule</command></term> + <listitem> + <para> + The <command>semodule</command> is a command to manage + modular policy packages. It enables to link/unlink, + upgrade or load/unload modular policy packages, such as + <literal>sepostgresql-devel.pp</literal> we provided. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><command>restorecon</command></term> + <listitem> + <para> + The <command>restorecon</command> enables to assign + correct security context for files, directories and + any other objects on filesystem, based on the security + policy configuration. + It helps to assign correct security context on + installed files by hand. + </para> + </listitem> + </varlistentry> + </variablelist> + </sect3> + + <sect3> + <title>Build</title> + <para> + SE-PostgreSQL feature is disabled in the default build. + So, we have to add <option>--enable-selinux</option> option + to configure script. It enables to build your PostgreSQL + with a feature to suppor SELinux. + </para> + <screen> + <prompt>$ </prompt><userinput>./configure --enable-selinux</userinput> + <prompt>$ </prompt><userinput>make</userinput> + <prompt>$ </prompt><userinput>make -C src/backend/security/sepgsql/policy</userinput> + </screen> + <para> + Please note that the recent upstreamed security policy of SELinux + contains a set of rules for SE-PostgreSQL, so we are not always + necessary to build security policy module. + </para> + <para> + 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. + </para> + <para> + It is stored in + <filename>src/backend/security/sepgsql/policy</filename>, + and can be also build and installed as a binary security policy + module. + </para> + </sect3> + + <sect3> + <title>Installation</title> + <para> + 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 <filename>sepostgresql-devel.pp</filename> also. + </para> + <screen> + <prompt># </prompt><userinput>make install</userinput> + <prompt># </prompt><userinput>/usr/sbin/semodule -i src/backend/security/sepgsql/policy/sepostgresql-devel.pp</userinput> + <prompt># </prompt><userinput>/sbin/restorecon -R /usr/local/pgsql</userinput> + </screen> + <para> + <command>semodule</command> is a command to install and uninstall + a security policy module. <command>restorecon</command> is a command + to assign given directories its default security context recursively. + </para> + + <para> + As we note later, all the files and directories to store database + cluster should be labeled as <literal>postgresql_db_t</literal>. + The default security policy assumes it is constructed at + <filename>/var/lib/pgsql/data</filename> as RPM doing. + + If you want to set up it on another directory, you need to label + it by hand. + </para> + <screen> + <prompt># </prompt><userinput>mkdir -p $PGDATA</userinput> + <prompt># </prompt><userinput>chcon -t postgresql_db_t -R $PGDATA</userinput> + </screen> + <para> + Then, we need to run <command>initdb</command> to initialize + the database cluster. It is necessary to specify an option of + <option>--pgace-feature=selinux</option> which enables to initialize + database cluster with proper security context. + + Without this option, no enhanced security feature will be activated + for the database cluster. + </para> + <screen> + <prompt>$ </prompt><userinput>initdb --pgace-feature=selinux</userinput> + <prompt>$ </prompt><userinput>pg_ctl start</userinput> + </screen> + </sect3> + </sect2> + + <sect2> + <title>Backup and Restore</title> + <para> + When we restore a database from backups, we have to restore + its security context correctly as GRANT statement doing on + the restored table. + </para> + + <para> + The <command>pg_dump</command> and <command>pg_dumpall</command> + have <option>--security-label</option> option to dump databases + with its security context. + + The dumped image can be restored with proper security context. + </para> + + <para> + Needless to say, a process which invokes <command>pg_dump</command> + 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 <command>pg_restore</command> has to have + enough permission to create/insert these objects with the specified + security context. + </para> + <screen> + <prompt>$ </prompt><userinput>pg_dump --security-label postgres</userinput> + : + (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) + : + </screen> + <para> + 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 <command>CREATE TABLE</command> + statement. + </para> + </sect2> + + <sect2 id="sepostgresql-labeled-networks"> + <title>Labeled Networks</title> + <para> + Labeled Networks is a technology which makes it possible to + obtain the security context of peer process communicating + via a TCP/IP connection. + </para> + + <para> + This technology contains two facilities. + One is <literal>Labeled IPsec</literal>, + and the other is <literal>Static Fallback Context</literal>. + + This section shows the way to set up both labeled networks + technology. + </para> + + <sect3> + <title>Labeled IPsec</title> + <para> + When communicating using an encrypted channel + with IPsec, the key-exchange daemon <command>racoon</command> + 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 + <command>getpeercon(3)</command>. + </para> + + <para> + This section introduces the steps to set up labeled ipsec, + but it is necessity minimum configuration, so we recommend + you to refer external technical documents related to ipsec + for more details. + </para> + + <sect4> + <title>Example Environment</title> + <para> + In this introduction, we assume the server host where SE-PostgreSQL + works has an IP address of <literal>192.168.1.10</literal> and + the client host has IP address of <literal>192.168.1.200</literal>. + + They are wired to same network, and can communicate each other + directly, without any router. + </para> + + <para> + The purpose of the following configuration is to obtain + the security context of the process working on the client host + (<literal>192.168.1.200</literal>) from SE-PostgreSQL daemon + working on the server host (<literal>192.168.1.10</literal>), + when a connection is established. + </para> + </sect4> + + <sect4> + <title>Adding a SPD entry</title> + <para> + 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. + </para> + + <para> + This example shows esp/transport mode should be applied on + outbounding packets from <literal>192.168.1.10</literal> + to <literal>192.168.1.200</literal>, and inbounding packets + from <literal>192.168.1.200</literal> to + <literal>192.168.1.10</literal>. + <programlisting> + 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; + </programlisting> + In addition, the second line of each entries enables to + turn on security context delivery during key exchanging. + </para> + <para> + You can load the above configuration using + <command>setkey</command> command. + + Save your configuration into a temporary file, + and invoke <command>setkey</command> with the file + as an argument. + <screen> + <prompt># </prompt><userinput>/sbin/setkey -f <your configuration file></userinput> + </screen> + </para> + <para> + 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. + </para> + </sect4> + + <sect4> + <title>Racoon configuration</title> + <para> + In the next, we have to edit a configuration file of + <command>racoon</command> to specify encryption algorithm, + authentication method and so on. + + This example uses pre shared key to authenticate the peer + host (<literal>192.168.1.200</literal>) for simplification. + + Note that you have to switch the IP addresses on the client side. + </para> + + <para> + An additional entry to + <filename>/etc/racoon/racoon.conf</filename>. + <programlisting> + 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 ; + } + } + </programlisting> + </para> + <para> + We have to put a set of key string and IP address of destination + in <filename>/etc/racoon/psk.txt</filename>. + + The key string has also to be same in the client side. + <programlisting> + # 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 + </programlisting> + </para> + </sect4> + + <sect4> + <title>Restart Racoon</title> + <para> + Restart racoon daemon in both peers. + </para> + <screen> + <prompt># </prompt><userinput>service racoon restart</userinput> + </screen> + </sect4> + </sect3> + + <sect3> + <title>Static Fallback Context</title> + <para> + 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. + </para> + <para> + SELinux provides an alternative method to identify a security + context of peer process inside the <literal>getpeercon(3)</literal>, + 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. + </para> + <para> + <command>netlabelctl</command> within + <literal>netlabel_tools</literal> + package can be used to set up static fallback context. + </para> + <para> + The following example shows a case when we associate a security + context with connections come from <literal>192.168.1.0/24</literal> + via all network interfaces. + <screen> + <prompt># </prompt><userinput>/sbin/netlabelctl unlbl add default address:192.168.1.0/24 label:user_u:user_r:user_t:s0</userinput> + </screen> + The following example shows a case when we associate a security + context with connections come from <literal>192.168.2.0/24</literal> + via <literal>eth0</literal>. + <screen> + <prompt># </prompt><userinput>/sbin/netlabelctl unlbl add dev:eth0 address:192.168.2.0/24 label:staff_u:staff_r:staff_t:s0:c0</userinput> + </screen> + </para> + </sect3> + </sect2> + </sect1> + + <sect1 id="sepostgresql-policy"> + <title>Making a Security Policy</title> + <para> + This section introduces steps to make your own security policy + modules, and to install them. + </para> + </sect1> + </chapter> diff -Nrpc base/doc/src/sgml/user-manag.sgml sepgsql/doc/src/sgml/user-manag.sgml *** base/doc/src/sgml/user-manag.sgml Wed Oct 29 13:39:02 2008 --- sepgsql/doc/src/sgml/user-manag.sgml Tue Jan 27 18:48:27 2009 *************** DROP ROLE <replaceable>name</replaceable *** 502,505 **** --- 502,655 ---- </para> </sect1> + <sect1 id="row-level-database-acls"> + <title>Row-level Database ACLs</title> + <para> + This section 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. + </para> + + <sect2> + <title>Design</title> + <para> + 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. + </para> + <para> + This feature is implemented as a guest of PGACE security framework, + but wired feature, not a selectable one. + </para> + <para> + 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. + </para> + <para> + We provides four kind of permissions on tuples. + These are <literal>SELECT</literal>, <literal>UPDATE</literal>, + <literal>DELETE</literal> and <literal>REFERENCES</literal>. + + An <literal>INSERT</literal> 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. + </para> + <para> + 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. + </para> + <para> + This feature is activated via table option of + <literal>row_level_acl</literal>. It can heve either of + <literal>on</literal> or <literal>off</literal> in the default. + + It enables us to refer or set per-tuple ACLs via the + <literal>security_acl</literal> system column. + We can modify it via <literal>UPDATE</literal>, + <literal>INSERT</literal> with explict ACLs on the system column. + + A feature to set default ACLs is also available. + A new table option of <literal>default_row_acl</literal> enables to + specify a default ACLs of for newly inserted tuples. + </para> + </sect2> + + <sect2> + <title>Administration</title> + <sect3> + <title>Setup Row-level ACLs</title> + <para> + The <literal>row_level_acl</literal> table option on + <literal>CREATE TABLE</literal> or <literal>ALTER TABLE</literal> + is used to activate the Row-level Database ACLs. + </para> + <screen> + <prompt># </prompt><userinput>CREATE TABLE drink ( + id int primary key, + name text, + price int + ) WITH (row_level_acl=on);</userinput> + NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "drink_pkey" for table "drink" + CREATE TABLE + </screen> + <para> + We can set Row-level ACLs via <literal>security_acl</literal> + system column. For example: + </para> + <screen> + <prompt># </prompt><userinput>UPDATE drink SET security_acl = '{=r/postgres}' WHERE id in (3,4,5);</userinput> + UPDATE 3 + <prompt># </prompt><userinput>SELECT security_acl, * FROM drink order by id;</userinput> + 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) + </screen> + <para> + The database user must have ownership of the relation or privileges + of database superuser in order to update + <literal>security_acl</literal>. + + 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. + </para> + </sect3> + + <sect3> + <title>Backup and Restore</title> + <para> + The <literal>--security-acl</literal> option to + <command>pg_dump</command> and <command>pg_dumpall</command> + can be used to dump tables with row-level ACLs. With this option, + the output will contain the <literal>security_acl</literal> system + column if the row-level ACLs feature is enabled on the target + table. + </para> + <screen> + <prompt>$ </prompt><userinput>pg_dump --security-acl postgres</userinput> + : + 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 + \. + : + </screen> + </sect3> + </sect2> + </sect1> </chapter>
pgsql-hackers by date: