@@ -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
16101625CREATE 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>
16211629CREATE 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
17261735postgres=> set role admin;
17271736SET
17281737postgres=> 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
17391748postgres=> table passwd;
17401749ERROR: permission denied for relation passwd
17411750postgres=> 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=> select username,real_name,home_phone,extra_info,home_dir,shell fro
17481757
17491758postgres=> update passwd set username = 'joe';
17501759ERROR: 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
17521761postgres=> update passwd set real_name = 'Alice Doe';
17531762UPDATE 1
17541763postgres=> update passwd set real_name = 'John Doe' where username = 'admin';
@@ -1759,11 +1768,16 @@ postgres=> delete from passwd;
17591768ERROR: permission denied for relation passwd
17601769postgres=> insert into passwd (username) values ('xxx');
17611770ERROR: 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
17631772postgres=> update passwd set pwhash = 'abc';
17641773UPDATE 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">
0 commit comments