Commit cbd96eff authored by Peter Eisentraut's avatar Peter Eisentraut

doc: Some improvements on CREATE POLICY and ALTER POLICY documentation

parent d0035257
...@@ -90,11 +90,8 @@ ALTER POLICY <replaceable class="parameter">name</replaceable> ON <replaceable c ...@@ -90,11 +90,8 @@ ALTER POLICY <replaceable class="parameter">name</replaceable> ON <replaceable c
<term><replaceable class="parameter">using_expression</replaceable></term> <term><replaceable class="parameter">using_expression</replaceable></term>
<listitem> <listitem>
<para> <para>
The USING expression for the policy. This expression will be added as a The <literal>USING</literal> expression for the policy.
security-barrier qualification to queries which use the table See <xref linkend="sql-createpolicy"> for details.
automatically. If multiple policies are being applied for a given
table then they are all combined and added using OR. The USING
expression applies to records which are being retrieved from the table.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
...@@ -103,11 +100,8 @@ ALTER POLICY <replaceable class="parameter">name</replaceable> ON <replaceable c ...@@ -103,11 +100,8 @@ ALTER POLICY <replaceable class="parameter">name</replaceable> ON <replaceable c
<term><replaceable class="parameter">check_expression</replaceable></term> <term><replaceable class="parameter">check_expression</replaceable></term>
<listitem> <listitem>
<para> <para>
The with-check expression for the policy. This expression will be The <literal>WITH CHECK</literal> expression for the policy.
added as a WITH CHECK OPTION qualification to queries which use the See <xref linkend="sql-createpolicy"> for details.
table automatically. If multiple policies are being applied for a
given table then they are all combined and added using OR. The WITH
CHECK expression applies to records which are being added to the table.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
......
...@@ -39,13 +39,13 @@ CREATE POLICY <replaceable class="parameter">name</replaceable> ON <replaceable ...@@ -39,13 +39,13 @@ CREATE POLICY <replaceable class="parameter">name</replaceable> ON <replaceable
</para> </para>
<para> <para>
A policy grants the ability to SELECT, INSERT, UPDATE, or DELETE rows A policy grants the permission to select, insert, update, or delete rows
which match the relevant policy expression. Existing table rows are that match the relevant policy expression. Existing table rows are
checked against the expression specified via USING, while new rows that checked against the expression specified via <literal>USING</literal>, while new rows that
would be created via INSERT or UPDATE are checked against the expression would be created via <literal>INSERT</literal> or <literal>UPDATE</literal> are checked against the expression
specified via WITH CHECK. When a USING expression returns true for a given specified via <literal>WITH CHECK</literal>. When a <literal>USING</literal> expression returns true for a given
row then that row is visible to the user, while if a false or null is row then that row is visible to the user, while if a false or null is
returned then the row is not visible. When a WITH CHECK expression returned then the row is not visible. When a <literal>WITH CHECK</literal> expression
returns true for a row then that row is added, while if a false or null is returns true for a row then that row is added, while if a false or null is
returned then an error occurs. returned then an error occurs.
</para> </para>
...@@ -56,20 +56,21 @@ CREATE POLICY <replaceable class="parameter">name</replaceable> ON <replaceable ...@@ -56,20 +56,21 @@ CREATE POLICY <replaceable class="parameter">name</replaceable> ON <replaceable
in order to prevent the inadvertent exposure of the protected data to in order to prevent the inadvertent exposure of the protected data to
user-defined functions which might not be trustworthy. However, user-defined functions which might not be trustworthy. However,
functions and operators marked by the system (or the system functions and operators marked by the system (or the system
administrator) as LEAKPROOF may be evaluated before policy administrator) as <literal>LEAKPROOF</literal> may be evaluated before policy
expressions, as they are assumed to be trustworthy. expressions, as they are assumed to be trustworthy.
</para> </para>
<para> <para>
For INSERT and UPDATE queries, WITH CHECK expressions are enforced after For <command>INSERT</command> and <command>UPDATE</command> statements,
BEFORE triggers are fired, and before any data modifications are made. <literal>WITH CHECK</literal> expressions are enforced after
Thus a BEFORE ROW trigger may modify the data to be inserted, affecting <literal>BEFORE</literal> triggers are fired, and before any data modifications are made.
the result of the security policy check. WITH CHECK expressions are Thus a <literal>BEFORE ROW</literal> trigger may modify the data to be inserted, affecting
the result of the security policy check. <literal>WITH CHECK</literal> expressions are
enforced before any other constraints. enforced before any other constraints.
</para> </para>
<para> <para>
Policy names are per-table, therefore one policy name can be used for many Policy names are per-table. Therefore, one policy name can be used for many
different tables and have a definition for each table which is appropriate to different tables and have a definition for each table which is appropriate to
that table. that table.
</para> </para>
...@@ -78,46 +79,19 @@ CREATE POLICY <replaceable class="parameter">name</replaceable> ON <replaceable ...@@ -78,46 +79,19 @@ CREATE POLICY <replaceable class="parameter">name</replaceable> ON <replaceable
Policies can be applied for specific commands or for specific roles. The Policies can be applied for specific commands or for specific roles. The
default for newly created policies is that they apply for all commands and default for newly created policies is that they apply for all commands and
roles, unless otherwise specified. If multiple policies apply to a given roles, unless otherwise specified. If multiple policies apply to a given
query, they will be combined using OR (although <literal>ON CONFLICT DO statement, they will be combined using <quote>or</quote> (although <literal>ON CONFLICT DO
UPDATE</> and <literal>INSERT</> policies are not combined in this way, but UPDATE</> and <literal>INSERT</> policies are not combined in this way, but
rather enforced as noted at each stage of <literal>ON CONFLICT</> execution). rather enforced as noted at each stage of <literal>ON CONFLICT</> execution).
Further, for commands which can have both USING and WITH CHECK policies (ALL
and UPDATE), if no WITH CHECK policy is defined then the USING policy will be
used for both what rows are visible (normal USING case) and which rows will
be allowed to be added (WITH CHECK case).
</para> </para>
<para> <para>
Note that while policies will be applied for explicit queries against tables Further, for commands that can have both <literal>USING</literal>
in the system, they are not applied when the system is performing internal and <literal>WITH CHECK</literal> policies (<literal>ALL</literal>
referential integrity checks or validating constraints. This means there are and <literal>UPDATE</literal>), if no <literal>WITH CHECK</literal> policy
indirect ways to determine that a given value exists. An example of this is is defined, then the <literal>USING</literal> policy will be used for both
attempting to insert a duplicate value into a column which is the primary key what rows are visible (normal <literal>USING</literal> case) and which rows
or has a unique constraint. If the insert fails then the user can infer that will be allowed to be added (<literal>WITH CHECK</literal> case).
the value already exists (this example assumes that the user is permitted by
policy to insert records which they are not allowed to see). Another example
is where a user is allowed to insert into a table which references another,
otherwise hidden table. Existence can be determined by the user inserting
values into the referencing table, where success would indicate that the
value exists in the referenced table. These issues can be addressed by
carefully crafting policies which prevent users from being able to insert,
delete, or update records at all which might possibly indicate a value they
are not otherwise able to see, or by using generated values (e.g.: surrogate
keys) instead.
</para> </para>
<para>
Regarding how policy expressions interact with the user: as the expressions
are added to the user's query directly, they will be run with the rights of
the user running the overall query. Therefore, users who are using a given
policy must be able to access any tables or functions referenced in the
expression or they will simply receive a permission denied error when
attempting to query the table that has row-level security enabled. This does not change how views
work, however. As with normal queries and views, permission checks and
policies for the tables which are referenced by a view will use the view
owner's rights and any policies which apply to the view owner.
</para>
</refsect1> </refsect1>
<refsect1> <refsect1>
...@@ -194,15 +168,14 @@ CREATE POLICY <replaceable class="parameter">name</replaceable> ON <replaceable ...@@ -194,15 +168,14 @@ CREATE POLICY <replaceable class="parameter">name</replaceable> ON <replaceable
the table if row level security is enabled and only rows where the the table if row level security is enabled and only rows where the
expression evaluates to true will be allowed. An error will be thrown expression evaluates to true will be allowed. An error will be thrown
if the expression evaluates to false or null for any of the records if the expression evaluates to false or null for any of the records
inserted or any of the records which result from the update. inserted or any of the records that result from the update.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
</variablelist> </variablelist>
</refsect1>
<refsect1> <refsect2>
<title>Per-Command policies</title> <title>Per-Command policies</title>
<variablelist> <variablelist>
...@@ -216,20 +189,21 @@ CREATE POLICY <replaceable class="parameter">name</replaceable> ON <replaceable ...@@ -216,20 +189,21 @@ CREATE POLICY <replaceable class="parameter">name</replaceable> ON <replaceable
<literal>ALL</literal> policy exists and more specific policies <literal>ALL</literal> policy exists and more specific policies
exist, then both the <literal>ALL</literal> policy and the more exist, then both the <literal>ALL</literal> policy and the more
specific policy (or policies) will be combined using specific policy (or policies) will be combined using
<literal>OR</literal>, as usual for overlapping policies. <quote>or</quote>, as usual for overlapping policies.
Additionally, <literal>ALL</literal> policies will be applied to Additionally, <literal>ALL</literal> policies will be applied to
both the selection side of a query and the modification side, using both the selection side of a query and the modification side, using
the USING policy for both if only a USING policy has been defined. the <literal>USING</literal> policy for both if only a <literal>USING</literal> policy has been defined.
</para>
<para>
As an example, if an <literal>UPDATE</literal> is issued, then the As an example, if an <literal>UPDATE</literal> is issued, then the
<literal>ALL</literal> policy will be applicable to both what the <literal>ALL</literal> policy will be applicable to both what the
<literal>UPDATE</literal> will be able to select out as rows to be <literal>UPDATE</literal> will be able to select out as rows to be
updated (with the USING expression being applied), and it will be updated (with the <literal>USING</literal> expression being applied), and it will be
applied to rows which result from the <literal>UPDATE</literal> applied to rows that result from the <literal>UPDATE</literal>
statement, to check if they are permitted to be added to the table statement, to check if they are permitted to be added to the table
(using the WITH CHECK expression, if defined, and the USING expression (using the <literal>WITH CHECK</literal> expression, if defined, and the <literal>USING</literal> expression
otherwise). If an INSERT or UPDATE command attempts to add rows to otherwise). If an <command>INSERT</command> or <command>UPDATE</command> command attempts to add rows to
the table which do not pass the <literal>ALL</literal> WITH CHECK the table that do not pass the <literal>ALL</literal> <literal>WITH CHECK</literal>
expression, the entire command will be aborted. Note that if only a expression, the entire command will be aborted. Note that if only a
<literal>USING</literal> clause is specified then that clause will be <literal>USING</literal> clause is specified then that clause will be
used for both <literal>USING</literal> and used for both <literal>USING</literal> and
...@@ -244,9 +218,9 @@ CREATE POLICY <replaceable class="parameter">name</replaceable> ON <replaceable ...@@ -244,9 +218,9 @@ CREATE POLICY <replaceable class="parameter">name</replaceable> ON <replaceable
<para> <para>
Using <literal>SELECT</literal> for a policy means that it will apply Using <literal>SELECT</literal> for a policy means that it will apply
to <literal>SELECT</literal> commands. The result is that only those to <literal>SELECT</literal> commands. The result is that only those
records from the relation which pass the <literal>SELECT</literal> records from the relation that pass the <literal>SELECT</literal>
policy will be returned, even if other records exist in the relation. policy will be returned, even if other records exist in the relation.
The <literal>SELECT</literal> policy only accepts the USING expression The <literal>SELECT</literal> policy only accepts the <literal>USING</literal> expression
as it only ever applies in cases where records are being retrieved from as it only ever applies in cases where records are being retrieved from
the relation. the relation.
</para> </para>
...@@ -258,18 +232,18 @@ CREATE POLICY <replaceable class="parameter">name</replaceable> ON <replaceable ...@@ -258,18 +232,18 @@ CREATE POLICY <replaceable class="parameter">name</replaceable> ON <replaceable
<listitem> <listitem>
<para> <para>
Using <literal>INSERT</literal> for a policy means that it will apply Using <literal>INSERT</literal> for a policy means that it will apply
to <literal>INSERT</literal> commands. Rows being inserted which do to <literal>INSERT</literal> commands. Rows being inserted that do
not pass this policy will result in a policy violation ERROR and the not pass this policy will result in a policy violation error, and the
entire <literal>INSERT</literal> command will be aborted. The entire <literal>INSERT</literal> command will be aborted. The
<literal>INSERT</literal> policy only accepts the WITH CHECK expression <literal>INSERT</literal> policy only accepts the <literal>WITH CHECK</literal> expression
as it only ever applies in cases where records are being added to the as it only ever applies in cases where records are being added to the
relation. relation.
</para> </para>
<para> <para>
Note that <literal>INSERT</literal> with <literal>ON CONFLICT DO Note that <literal>INSERT</literal> with <literal>ON CONFLICT DO
UPDATE</literal> requires that any <literal>INSERT</literal> policy UPDATE</literal> requires that any <literal>INSERT</literal> policy
WITH CHECK expression passes for any rows appended to the relation by <literal>WITH CHECK</literal> expression passes for any rows appended to the relation by
the INSERT path only. the <literal>INSERT</literal> path only.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
...@@ -291,8 +265,8 @@ CREATE POLICY <replaceable class="parameter">name</replaceable> ON <replaceable ...@@ -291,8 +265,8 @@ CREATE POLICY <replaceable class="parameter">name</replaceable> ON <replaceable
defines what rows are allowed to be added back into the relation defines what rows are allowed to be added back into the relation
(similar to the <literal>INSERT</literal> policy). Any rows whose (similar to the <literal>INSERT</literal> policy). Any rows whose
resulting values do not pass the <literal>WITH CHECK</literal> resulting values do not pass the <literal>WITH CHECK</literal>
expression will cause an ERROR and the entire command will be aborted. expression will cause an error, and the entire command will be aborted.
Note that if only a <literal>USING</literal> clause is specified then Note that if only a <literal>USING</literal> clause is specified, then
that clause will be used for both <literal>USING</literal> and that clause will be used for both <literal>USING</literal> and
<literal>WITH CHECK</literal> cases. <literal>WITH CHECK</literal> cases.
</para> </para>
...@@ -304,11 +278,11 @@ CREATE POLICY <replaceable class="parameter">name</replaceable> ON <replaceable ...@@ -304,11 +278,11 @@ CREATE POLICY <replaceable class="parameter">name</replaceable> ON <replaceable
<literal>UPDATE</literal> policy must always pass when the <literal>UPDATE</literal> policy must always pass when the
<literal>UPDATE</literal> path is taken. Any existing row that <literal>UPDATE</literal> path is taken. Any existing row that
necessitates that the <literal>UPDATE</literal> path be taken must pass necessitates that the <literal>UPDATE</literal> path be taken must pass
the (UPDATE or ALL) <literal>USING</literal> qualifications (combined the (<literal>UPDATE</literal> or <literal>ALL</literal>) <literal>USING</literal> qualifications (combined
using <literal>OR</literal>), which are always enforced as WITH CHECK using <quote>or</quote>), which are always enforced as <literal>WITH CHECK</literal>
options in this context (the <literal>UPDATE</literal> path will options in this context. (The <literal>UPDATE</literal> path will
<emphasis>never</> be silently avoided; an error will be thrown <emphasis>never</> be silently avoided; an error will be thrown
instead). Finally, the final row appended to the relation must pass instead.) Finally, the final row appended to the relation must pass
any <literal>WITH CHECK</literal> options that a conventional any <literal>WITH CHECK</literal> options that a conventional
<literal>UPDATE</literal> is required to pass. <literal>UPDATE</literal> is required to pass.
</para> </para>
...@@ -320,14 +294,14 @@ CREATE POLICY <replaceable class="parameter">name</replaceable> ON <replaceable ...@@ -320,14 +294,14 @@ CREATE POLICY <replaceable class="parameter">name</replaceable> ON <replaceable
<listitem> <listitem>
<para> <para>
Using <literal>DELETE</literal> for a policy means that it will apply Using <literal>DELETE</literal> for a policy means that it will apply
to <literal>DELETE</literal> commands. Only rows which pass this to <literal>DELETE</literal> commands. Only rows that pass this
policy will be seen by a <literal>DELETE</literal> command. Rows may policy will be seen by a <literal>DELETE</literal> command. There can be rows
be visible through a <literal>SELECT</literal> which are not seen by a that are visible through a <literal>SELECT</literal> that are not seen by a
<literal>DELETE</literal>, as they do not pass the USING expression <literal>DELETE</literal>, if they do not pass the <literal>USING</literal> expression
for the <literal>DELETE</literal>, and rows which are not visible for the <literal>DELETE</literal>. Conversely, there can be rows that are not visible
through the <literal>SELECT</literal> policy may be deleted if they through the <literal>SELECT</literal> policy but may be deleted if they
pass the <literal>DELETE</literal> USING policy. The pass the <literal>DELETE</literal> <literal>USING</literal> policy. The
<literal>DELETE</literal> policy only accepts the USING expression as <literal>DELETE</literal> policy only accepts the <literal>USING</literal> expression as
it only ever applies in cases where records are being extracted from it only ever applies in cases where records are being extracted from
the relation for deletion. the relation for deletion.
</para> </para>
...@@ -335,6 +309,7 @@ CREATE POLICY <replaceable class="parameter">name</replaceable> ON <replaceable ...@@ -335,6 +309,7 @@ CREATE POLICY <replaceable class="parameter">name</replaceable> ON <replaceable
</varlistentry> </varlistentry>
</variablelist> </variablelist>
</refsect2>
</refsect1> </refsect1>
<refsect1> <refsect1>
...@@ -345,11 +320,35 @@ CREATE POLICY <replaceable class="parameter">name</replaceable> ON <replaceable ...@@ -345,11 +320,35 @@ CREATE POLICY <replaceable class="parameter">name</replaceable> ON <replaceable
</para> </para>
<para> <para>
In order to maintain <firstterm>referential integrity</firstterm> between Note that while policies will be applied for explicit queries against tables
two related tables, policies are not applied when the system performs in the system, they are not applied when the system is performing internal
checks on foreign key constraints. referential integrity checks or validating constraints. This means there are
indirect ways to determine that a given value exists. An example of this is
attempting to insert a duplicate value into a column which is the primary key
or has a unique constraint. If the insert fails then the user can infer that
the value already exists. (This example assumes that the user is permitted by
policy to insert records which they are not allowed to see.) Another example
is where a user is allowed to insert into a table which references another,
otherwise hidden table. Existence can be determined by the user inserting
values into the referencing table, where success would indicate that the
value exists in the referenced table. These issues can be addressed by
carefully crafting policies that prevent users from being able to insert,
delete, or update records at all which might possibly indicate a value they
are not otherwise able to see, or by using generated values (e.g., surrogate
keys) instead.
</para> </para>
<para>
Regarding how policy expressions interact with the user: as the expressions
are added to the user's query directly, they will be run with the rights of
the user running the overall query. Therefore, users who are using a given
policy must be able to access any tables or functions referenced in the
expression or they will simply receive a permission denied error when
attempting to query the table that has row-level security enabled. This does not change how views
work, however. As with normal queries and views, permission checks and
policies for the tables which are referenced by a view will use the view
owner's rights and any policies which apply to the view owner.
</para>
</refsect1> </refsect1>
<refsect1> <refsect1>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment