Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit c1611db

Browse files
committed
Do some copy-editing on the docs for row-level security.
Clarifications, markup improvements, corrections of misleading or outright wrong statements.
1 parent 939d10c commit c1611db

File tree

4 files changed

+234
-193
lines changed

4 files changed

+234
-193
lines changed

doc/src/sgml/ddl.sgml

Lines changed: 84 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1512,62 +1512,76 @@ REVOKE ALL ON accounts FROM PUBLIC;
15121512
<title>Row Security Policies</title>
15131513

15141514
<indexterm zone="ddl-rowsecurity">
1515-
<primary>row security</primary>
1515+
<primary>row-level security</primary>
15161516
</indexterm>
15171517

15181518
<indexterm zone="ddl-rowsecurity">
15191519
<primary>policy</primary>
15201520
</indexterm>
15211521

15221522
<para>
1523-
In addition to the <xref linkend="ddl-priv"> system available through
1524-
<xref linkend="sql-grant">, tables can have row security policies
1525-
which limit the rows returned for normal queries and rows which can
1526-
be added through data modification commands. By default, tables do
1527-
not have any policies and all rows are visible and able to be added,
1528-
subject to the regular <xref linkend="ddl-priv"> system. This is
1529-
also known as Row Level Security.
1523+
In addition to the SQL-standard <link linkend="ddl-priv">privilege
1524+
system</link> available through <xref linkend="sql-grant">,
1525+
tables can have <firstterm>row security policies</> that restrict,
1526+
on a per-user basis, which rows can be returned by normal queries
1527+
or inserted, updated, or deleted by data modification commands.
1528+
This feature is also known as <firstterm>Row-Level Security</>.
1529+
By default, tables do not have any policies, so that if a user has
1530+
access privileges to a table according to the SQL privilege system,
1531+
all rows within it are equally available for querying or updating.
15301532
</para>
15311533

15321534
<para>
1533-
When row security is enabled on a table with
1534-
<xref linkend="sql-altertable">, all normal access to the table
1535-
(excluding the owner) for selecting rows or adding rows must be through
1536-
a policy. If no policy exists for the table, a default-deny policy is
1537-
used and no rows are visible or can be added. Privileges which operate
1538-
at the whole table level such as <literal>TRUNCATE</>, and
1539-
<literal>REFERENCES</> are not subject to row security.
1535+
When row security is enabled on a table (with
1536+
<link linkend="sql-altertable">ALTER TABLE ... ENABLE ROW LEVEL
1537+
SECURITY</>), all normal access to the table for selecting rows or
1538+
modifying rows must be allowed by a row security policy. (However, the
1539+
table's owner is typically not subject to row security policies.) If no
1540+
policy exists for the table, a default-deny policy is used, meaning that
1541+
no rows are visible or can be modified. Operations that apply to the
1542+
whole table, such as <command>TRUNCATE</> and <literal>REFERENCES</>,
1543+
are not subject to row security.
15401544
</para>
15411545

15421546
<para>
15431547
Row security policies can be specific to commands, or to roles, or to
1544-
both. The commands available are <literal>ALL</literal>,
1545-
<literal>SELECT</>, <literal>INSERT</>, <literal>UPDATE</>, and
1546-
<literal>DELETE</>. Multiple roles can be assigned to a given policy and
1547-
normal role membership and inheritance rules apply. Table owners,
1548-
superusers, and roles with the <literal>BYPASSRLS</> attribute bypass the
1549-
row security system when querying a table. Applications that expect to
1550-
bypass all row security through those mechanisms should
1551-
set <xref linkend="guc-row-security"> to <literal>off</>.
1548+
both. A policy can be specified to apply to <literal>ALL</literal>
1549+
commands, or to <literal>SELECT</>, <literal>INSERT</>, <literal>UPDATE</>,
1550+
or <literal>DELETE</>. Multiple roles can be assigned to a given
1551+
policy, and normal role membership and inheritance rules apply.
15521552
</para>
15531553

15541554
<para>
1555-
To specify which rows are visible and what rows can be added to the
1556-
table with row level security, an expression is required which returns
1557-
a Boolean result. This expression will be evaluated for each row prior
1558-
to other conditionals or functions which are part of the query. The
1559-
one exception to this rule are <literal>leakproof</literal> functions,
1560-
which are guaranteed to not leak information. Two expressions may be
1561-
specified to provide independent control over the rows which are
1562-
visible and the rows which are allowed to be added. The expression
1563-
is run as part of the query and with the privileges of the user
1564-
running the query, however, security definer functions can be used in
1565-
the expression.
1555+
To specify which rows are visible or modifiable according to a policy,
1556+
an expression is required that returns a Boolean result. This
1557+
expression will be evaluated for each row prior to any conditions or
1558+
functions coming from the user's query. (The only exceptions to this
1559+
rule are <literal>leakproof</literal> functions, which are guaranteed to
1560+
not leak information; the optimizer may choose to apply such functions
1561+
ahead of the row-security check.) Rows for which the expression does
1562+
not return <literal>true</> will not be processed. Separate expressions
1563+
may be specified to provide independent control over the rows which are
1564+
visible and the rows which are allowed to be modified. Policy
1565+
expressions are run as part of the query and with the privileges of the
1566+
user running the query, although security-definer functions can be used
1567+
to access data not available to the calling user.
1568+
</para>
1569+
1570+
<para>
1571+
Superusers and roles with the <literal>BYPASSRLS</> attribute always
1572+
bypass the row security system when accessing a table. Table owners
1573+
normally bypass row security as well, though a table owner can choose to
1574+
be subject to row security with <link linkend="sql-altertable">ALTER
1575+
TABLE ... FORCE ROW LEVEL SECURITY</>. Even in a table with that option
1576+
selected, the table owner will bypass row security if the
1577+
<xref linkend="guc-row-security"> configuration parameter is set
1578+
to <literal>off</>; this setting is typically used for purposes such as
1579+
backup and restore.
15661580
</para>
15671581

15681582
<para>
15691583
Enabling and disabling row security, as well as adding policies to a
1570-
table, is always the privilege of the owner only.
1584+
table, is always the privilege of the table owner only.
15711585
</para>
15721586

15731587
<para>
@@ -1587,46 +1601,40 @@ REVOKE ALL ON accounts FROM PUBLIC;
15871601

15881602
<para>
15891603
When multiple policies apply to a given query, they are combined using
1590-
<literal>OR</literal>, similar to how a given role has the privileges
1591-
of all roles which they are a member of.
1604+
<literal>OR</literal>, so that a row is accessible if any policy allows
1605+
it. This is similar to the rule that a given role has the privileges
1606+
of all roles that they are a member of.
15921607
</para>
15931608

15941609
<para>
15951610
Referential integrity checks, such as unique or primary key constraints
1596-
and foreign key references, will bypass row security to ensure that
1611+
and foreign key references, always bypass row security to ensure that
15971612
data integrity is maintained. Care must be taken when developing
1598-
schemas and row level policies to avoid a "covert channel" leak of
1599-
information through these referential integrity checks.
1613+
schemas and row level policies to avoid <quote>covert channel</> leaks of
1614+
information through such referential integrity checks.
16001615
</para>
16011616

16021617
<para>
1603-
To enable row security for a table,
1604-
the <command>ALTER TABLE</command> is used. For example, to enable
1605-
row level security for the table accounts, use:
1618+
As a simple example, here is how to create a policy on
1619+
the <literal>account</> relation to allow only members of
1620+
the <literal>managers</> role to access rows, and only rows of their
1621+
accounts:
16061622
</para>
16071623

16081624
<programlisting>
1609-
-- Create the table first
16101625
CREATE TABLE accounts (manager text, company text, contact_email text);
1611-
ALTER TABLE accounts ENABLE ROW LEVEL SECURITY;
1612-
</programlisting>
16131626

1614-
<para>
1615-
To create a policy on the account relation to allow the managers role
1616-
to view the rows of their accounts, the <command>CREATE POLICY</command>
1617-
command can be used:
1618-
</para>
1627+
ALTER TABLE accounts ENABLE ROW LEVEL SECURITY;
16191628

1620-
<programlisting>
16211629
CREATE POLICY account_managers ON accounts TO managers
16221630
USING (manager = current_user);
16231631
</programlisting>
16241632

16251633
<para>
1626-
If no role is specified, or the special <quote>user</quote> name
1634+
If no role is specified, or the special user name
16271635
<literal>PUBLIC</literal> is used, then the policy applies to all
1628-
users on the system. To allow all users to view their own row in
1629-
a user table, a simple policy can be used:
1636+
users on the system. To allow all users to access their own row in
1637+
a <literal>users</> table, a simple policy can be used:
16301638
</para>
16311639

16321640
<programlisting>
@@ -1635,10 +1643,10 @@ CREATE POLICY user_policy ON users
16351643
</programlisting>
16361644

16371645
<para>
1638-
To use a different policy for rows which are being added to the
1639-
table from those rows which are visible, the WITH CHECK clause
1640-
can be used. This would allow all users to view all rows in the
1641-
users table, but only modify their own:
1646+
To use a different policy for rows that are being added to the table
1647+
compared to those rows that are visible, the <literal>WITH CHECK</>
1648+
clause can be used. This policy would allow all users to view all rows
1649+
in the <literal>users</> table, but only modify their own:
16421650
</para>
16431651

16441652
<programlisting>
@@ -1648,16 +1656,17 @@ CREATE POLICY user_policy ON users
16481656
</programlisting>
16491657

16501658
<para>
1651-
Row security can be disabled with the <command>ALTER TABLE</command>
1652-
also. Note that disabling row security does not remove the
1653-
policies which are defined on the table, they are simply ignored
1654-
and all rows are visible and able to be added, subject to the
1655-
normal privileges system.
1659+
Row security can also be disabled with the <command>ALTER TABLE</>
1660+
command. Disabling row security does not remove any policies that are
1661+
defined on the table; they are simply ignored. Then all rows in the
1662+
table are visible and modifiable, subject to the standard SQL privileges
1663+
system.
16561664
</para>
16571665

16581666
<para>
1659-
Below is a larger example of how this feature can be used in
1660-
production environments, based on a Unix password file.
1667+
Below is a larger example of how this feature can be used in production
1668+
environments. The table <literal>passwd</> emulates a Unix password
1669+
file:
16611670
</para>
16621671

16631672
<programlisting>
@@ -1726,7 +1735,7 @@ GRANT UPDATE
17261735
postgres=&gt; set role admin;
17271736
SET
17281737
postgres=&gt; table passwd;
1729-
username | pwhash | uid | gid | real_name | home_phone | extra_info | home_dir | shell
1738+
username | pwhash | uid | gid | real_name | home_phone | extra_info | home_dir | shell
17301739
----------+--------+-----+-----+-----------+--------------+------------+-------------+-----------
17311740
admin | xxx | 0 | 0 | Admin | 111-222-3333 | | /root | /bin/dash
17321741
bob | xxx | 1 | 1 | Bob | 123-456-7890 | | /home/bob | /bin/zsh
@@ -1739,7 +1748,7 @@ SET
17391748
postgres=&gt; table passwd;
17401749
ERROR: permission denied for relation passwd
17411750
postgres=&gt; select username,real_name,home_phone,extra_info,home_dir,shell from passwd;
1742-
username | real_name | home_phone | extra_info | home_dir | shell
1751+
username | real_name | home_phone | extra_info | home_dir | shell
17431752
----------+-----------+--------------+------------+-------------+-----------
17441753
admin | Admin | 111-222-3333 | | /root | /bin/dash
17451754
bob | Bob | 123-456-7890 | | /home/bob | /bin/zsh
@@ -1748,7 +1757,7 @@ postgres=&gt; select username,real_name,home_phone,extra_info,home_dir,shell fro
17481757

17491758
postgres=&gt; update passwd set username = 'joe';
17501759
ERROR: permission denied for relation passwd
1751-
-- Allowed to change her own real_name, but no others
1760+
-- Alice is allowed to change her own real_name, but no others
17521761
postgres=&gt; update passwd set real_name = 'Alice Doe';
17531762
UPDATE 1
17541763
postgres=&gt; update passwd set real_name = 'John Doe' where username = 'admin';
@@ -1759,11 +1768,16 @@ postgres=&gt; delete from passwd;
17591768
ERROR: permission denied for relation passwd
17601769
postgres=&gt; insert into passwd (username) values ('xxx');
17611770
ERROR: permission denied for relation passwd
1762-
-- Alice can change her own password
1771+
-- Alice can change her own password; RLS silently prevents updating other rows
17631772
postgres=&gt; update passwd set pwhash = 'abc';
17641773
UPDATE 1
17651774
</programlisting>
17661775

1776+
<para>
1777+
For additional details see <xref linkend="sql-createpolicy">
1778+
and <xref linkend="sql-altertable">.
1779+
</para>
1780+
17671781
</sect1>
17681782

17691783
<sect1 id="ddl-schemas">

doc/src/sgml/ref/alter_policy.sgml

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,14 @@ PostgreSQL documentation
1616

1717
<refnamediv>
1818
<refname>ALTER POLICY</refname>
19-
<refpurpose>change the definition of a policy</refpurpose>
19+
<refpurpose>change the definition of a row level security policy</refpurpose>
2020
</refnamediv>
2121

2222
<refsynopsisdiv>
2323
<synopsis>
24+
ALTER POLICY <replaceable class="parameter">name</replaceable> ON <replaceable class="parameter">table_name</replaceable> RENAME TO <replaceable class="PARAMETER">new_name</replaceable>
25+
2426
ALTER POLICY <replaceable class="parameter">name</replaceable> ON <replaceable class="parameter">table_name</replaceable>
25-
[ RENAME TO <replaceable class="PARAMETER">new_name</replaceable> ]
2627
[ TO { <replaceable class="parameter">role_name</replaceable> | PUBLIC | CURRENT_USER | SESSION_USER } [, ...] ]
2728
[ USING ( <replaceable class="parameter">using_expression</replaceable> ) ]
2829
[ WITH CHECK ( <replaceable class="parameter">check_expression</replaceable> ) ]
@@ -33,14 +34,22 @@ ALTER POLICY <replaceable class="parameter">name</replaceable> ON <replaceable c
3334
<title>Description</title>
3435

3536
<para>
36-
<command>ALTER POLICY</command> changes the <replaceable class="parameter">
37-
definition</replaceable> of an existing policy.
37+
<command>ALTER POLICY</command> changes the definition of an existing
38+
row-level security policy.
3839
</para>
3940

4041
<para>
4142
To use <command>ALTER POLICY</command>, you must own the table that
4243
the policy applies to.
4344
</para>
45+
46+
<para>
47+
In the second form of <command>ALTER POLICY</command>, the role list,
48+
<replaceable class="parameter">using_expression</replaceable>, and
49+
<replaceable class="parameter">check_expression</replaceable> are replaced
50+
independently if specified. When one of those clauses is omitted, the
51+
corresponding part of the policy is unchanged.
52+
</para>
4453
</refsect1>
4554

4655
<refsect1>
@@ -79,9 +88,9 @@ ALTER POLICY <replaceable class="parameter">name</replaceable> ON <replaceable c
7988
<term><replaceable class="parameter">role_name</replaceable></term>
8089
<listitem>
8190
<para>
82-
The role to which the policy applies. Multiple roles can be specified at one time.
83-
To apply the policy to all roles, use <literal>PUBLIC</literal>, which is also
84-
the default.
91+
The role(s) to which the policy applies. Multiple roles can be
92+
specified at one time. To apply the policy to all roles,
93+
use <literal>PUBLIC</literal>.
8594
</para>
8695
</listitem>
8796
</varlistentry>

0 commit comments

Comments
 (0)