summaryrefslogtreecommitdiff
path: root/doc/src
diff options
context:
space:
mode:
authorStephen Frost <sfrost@snowman.net>2016-12-05 15:50:55 -0500
committerStephen Frost <sfrost@snowman.net>2016-12-05 15:50:55 -0500
commit093129c9d9fc231649b3cc27b8086443ccbbbc22 (patch)
tree5e41352a48f7a33a68687623da2fb48dce9b9174 /doc/src
parent2bbdc6875d03bb826a4fd113eac45a72c68bc929 (diff)
Add support for restrictive RLS policies
We have had support for restrictive RLS policies since 9.5, but they were only available through extensions which use the appropriate hooks. This adds support into the grammer, catalog, psql and pg_dump for restrictive RLS policies, thus reducing the cases where an extension is necessary. In passing, also move away from using "AND"d and "OR"d in comments. As pointed out by Alvaro, it's not really appropriate to attempt to make verbs out of "AND" and "OR", so reword those comments which attempted to. Reviewed By: Jeevan Chalke, Dean Rasheed Discussion: https://postgr.es/m/20160901063404.GY4028@tamriel.snowman.net
Diffstat (limited to 'doc/src')
-rw-r--r--doc/src/sgml/catalogs.sgml13
-rw-r--r--doc/src/sgml/ddl.sgml58
-rw-r--r--doc/src/sgml/ref/alter_policy.sgml7
-rw-r--r--doc/src/sgml/ref/create_policy.sgml38
4 files changed, 112 insertions, 4 deletions
diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index 561e228558d..c4246dcd866 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -4748,6 +4748,13 @@
</row>
<row>
+ <entry><structfield>polpermissive</structfield></entry>
+ <entry><type>boolean</type></entry>
+ <entry></entry>
+ <entry>Is the policy permissive or restrictive?</entry>
+ </row>
+
+ <row>
<entry><structfield>polroles</structfield></entry>
<entry><type>oid[]</type></entry>
<entry><literal><link linkend="catalog-pg-authid"><structname>pg_authid</structname></link>.oid</literal></entry>
@@ -8438,6 +8445,12 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx
<entry>Name of policy</entry>
</row>
<row>
+ <entry><structfield>polpermissive</structfield></entry>
+ <entry><type>text</type></entry>
+ <entry></entry>
+ <entry>Is the policy permissive or restrictive?</entry>
+ </row>
+ <row>
<entry><structfield>roles</structfield></entry>
<entry><type>name[]</type></entry>
<entry></entry>
diff --git a/doc/src/sgml/ddl.sgml b/doc/src/sgml/ddl.sgml
index 157512c7abd..7e1bc0e5341 100644
--- a/doc/src/sgml/ddl.sgml
+++ b/doc/src/sgml/ddl.sgml
@@ -1599,9 +1599,11 @@ REVOKE ALL ON accounts FROM PUBLIC;
<para>
When multiple policies apply to a given query, they are combined using
- <literal>OR</literal>, so that a row is accessible if any policy allows
- it. This is similar to the rule that a given role has the privileges
- of all roles that they are a member of.
+ either <literal>OR</literal> (for permissive policies, which are the
+ default) or using <literal>AND</literal> (for restrictive policies).
+ This is similar to the rule that a given role has the privileges
+ of all roles that they are a member of. Permissive vs. restrictive
+ policies are discussed further below.
</para>
<para>
@@ -1764,6 +1766,56 @@ UPDATE 1
</programlisting>
<para>
+ All of the policies constructed thus far have been permissive policies,
+ meaning that when multiple policies are applied they are combined using
+ the "OR" boolean operator. While permissive policies can be constructed
+ to only allow access to rows in the intended cases, it can be simpler to
+ combine permissive policies with restrictive policies (which the records
+ must pass and which are combined using the "AND" boolean operator).
+ Building on the example above, we add a restrictive policy to require
+ the administrator to be connected over a local unix socket to access the
+ records of the passwd table:
+ </para>
+
+<programlisting>
+CREATE POLICY admin_local_only ON passwd AS RESTRICTIVE TO admin
+ USING (pg_catalog.inet_client_addr() IS NULL);
+</programlisting>
+
+ <para>
+ We can then see that an administrator connecting over a network will not
+ see any records, due to the restrictive policy:
+ </para>
+
+<programlisting>
+=&gt; SELECT current_user;
+ current_user
+--------------
+ admin
+(1 row)
+
+=&gt; select inet_client_addr();
+ inet_client_addr
+------------------
+ 127.0.0.1
+(1 row)
+
+=&gt; SELECT current_user;
+ current_user
+--------------
+ admin
+(1 row)
+
+=&gt; TABLE passwd;
+ user_name | pwhash | uid | gid | real_name | home_phone | extra_info | home_dir | shell
+-----------+--------+-----+-----+-----------+------------+------------+----------+-------
+(0 rows)
+
+=&gt; UPDATE passwd set pwhash = NULL;
+UPDATE 0
+</programlisting>
+
+ <para>
Referential integrity checks, such as unique or primary key constraints
and foreign key references, always bypass row security to ensure that
data integrity is maintained. Care must be taken when developing
diff --git a/doc/src/sgml/ref/alter_policy.sgml b/doc/src/sgml/ref/alter_policy.sgml
index a9b1541322d..df347d180ea 100644
--- a/doc/src/sgml/ref/alter_policy.sgml
+++ b/doc/src/sgml/ref/alter_policy.sgml
@@ -35,7 +35,12 @@ ALTER POLICY <replaceable class="parameter">name</replaceable> ON <replaceable c
<para>
<command>ALTER POLICY</command> changes the definition of an existing
- row-level security policy.
+ row-level security policy. Note that <command>ALTER POLICY</command>
+ only allows the set of roles to which the policy applies and the
+ <literal>USING</literal> and <literal>WITH CHECK</literal> expressions to
+ be modified. To change other properties of a policy, such as the command
+ to which it applies or whether it is permissive or restrictive, the policy
+ must be dropped and recreated.
</para>
<para>
diff --git a/doc/src/sgml/ref/create_policy.sgml b/doc/src/sgml/ref/create_policy.sgml
index 89d27879b1e..f0486effaf5 100644
--- a/doc/src/sgml/ref/create_policy.sgml
+++ b/doc/src/sgml/ref/create_policy.sgml
@@ -22,6 +22,7 @@ PostgreSQL documentation
<refsynopsisdiv>
<synopsis>
CREATE POLICY <replaceable class="parameter">name</replaceable> ON <replaceable class="parameter">table_name</replaceable>
+ [ AS { PERMISSIVE | RESTRICTIVE } ]
[ FOR { ALL | SELECT | INSERT | UPDATE | DELETE } ]
[ TO { <replaceable class="parameter">role_name</replaceable> | PUBLIC | CURRENT_USER | SESSION_USER } [, ...] ]
[ USING ( <replaceable class="parameter">using_expression</replaceable> ) ]
@@ -120,6 +121,33 @@ CREATE POLICY <replaceable class="parameter">name</replaceable> ON <replaceable
</varlistentry>
<varlistentry>
+ <term><replaceable class="parameter">PERMISSIVE</replaceable></term>
+ <listitem>
+ <para>
+ Specify that the policy is to be created as a permissive policy.
+ All permissive policies which are applicable to a given query will
+ be combined together using the boolean "OR" operator. By creating
+ permissive policies, administrators can add to the set of records
+ which can be accessed. Policies are PERMISSIVE by default.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><replaceable class="parameter">RESTRICTIVE</replaceable></term>
+ <listitem>
+ <para>
+ Specify that the policy is to be created as a restrictive policy.
+ All restrictive policies which are applicable to a given query will
+ be combined together using the boolean "AND" operator. By creating
+ restrictive policies, administrators can reduce the set of records
+ which can be accessed as all restrictive policies must be passed for
+ each record.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><replaceable class="parameter">command</replaceable></term>
<listitem>
<para>
@@ -391,6 +419,16 @@ CREATE POLICY <replaceable class="parameter">name</replaceable> ON <replaceable
</para>
<para>
+ Note that there needs to be at least one permissive policy to grant
+ access to records before restrictive policies can be usefully used to
+ reduce that access. If only restrictive policies exist, then no records
+ will be accessible. When a mix of permissive and restrictive policies
+ are present, a record is only accessible if at least one of the
+ permissive policies passes, in addition to all the restrictive
+ policies.
+ </para>
+
+ <para>
Generally, the system will enforce filter conditions imposed using
security policies prior to qualifications that appear in user queries,
in order to prevent inadvertent exposure of the protected data to