@@ -1512,62 +1512,76 @@ REVOKE ALL ON accounts FROM PUBLIC;
1512
1512
<title>Row Security Policies</title>
1513
1513
1514
1514
<indexterm zone="ddl-rowsecurity">
1515
- <primary>row security</primary>
1515
+ <primary>row-level security</primary>
1516
1516
</indexterm>
1517
1517
1518
1518
<indexterm zone="ddl-rowsecurity">
1519
1519
<primary>policy</primary>
1520
1520
</indexterm>
1521
1521
1522
1522
<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.
1530
1532
</para>
1531
1533
1532
1534
<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.
1540
1544
</para>
1541
1545
1542
1546
<para>
1543
1547
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.
1552
1552
</para>
1553
1553
1554
1554
<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.
1566
1580
</para>
1567
1581
1568
1582
<para>
1569
1583
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.
1571
1585
</para>
1572
1586
1573
1587
<para>
@@ -1587,46 +1601,40 @@ REVOKE ALL ON accounts FROM PUBLIC;
1587
1601
1588
1602
<para>
1589
1603
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.
1592
1607
</para>
1593
1608
1594
1609
<para>
1595
1610
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
1597
1612
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.
1600
1615
</para>
1601
1616
1602
1617
<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:
1606
1622
</para>
1607
1623
1608
1624
<programlisting>
1609
- -- Create the table first
1610
1625
CREATE TABLE accounts (manager text, company text, contact_email text);
1611
- ALTER TABLE accounts ENABLE ROW LEVEL SECURITY;
1612
- </programlisting>
1613
1626
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;
1619
1628
1620
- <programlisting>
1621
1629
CREATE POLICY account_managers ON accounts TO managers
1622
1630
USING (manager = current_user);
1623
1631
</programlisting>
1624
1632
1625
1633
<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
1627
1635
<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:
1630
1638
</para>
1631
1639
1632
1640
<programlisting>
@@ -1635,10 +1643,10 @@ CREATE POLICY user_policy ON users
1635
1643
</programlisting>
1636
1644
1637
1645
<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:
1642
1650
</para>
1643
1651
1644
1652
<programlisting>
@@ -1648,16 +1656,17 @@ CREATE POLICY user_policy ON users
1648
1656
</programlisting>
1649
1657
1650
1658
<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.
1656
1664
</para>
1657
1665
1658
1666
<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:
1661
1670
</para>
1662
1671
1663
1672
<programlisting>
@@ -1726,7 +1735,7 @@ GRANT UPDATE
1726
1735
postgres=> set role admin;
1727
1736
SET
1728
1737
postgres=> 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
1730
1739
----------+--------+-----+-----+-----------+--------------+------------+-------------+-----------
1731
1740
admin | xxx | 0 | 0 | Admin | 111-222-3333 | | /root | /bin/dash
1732
1741
bob | xxx | 1 | 1 | Bob | 123-456-7890 | | /home/bob | /bin/zsh
@@ -1739,7 +1748,7 @@ SET
1739
1748
postgres=> table passwd;
1740
1749
ERROR: permission denied for relation passwd
1741
1750
postgres=> 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
1743
1752
----------+-----------+--------------+------------+-------------+-----------
1744
1753
admin | Admin | 111-222-3333 | | /root | /bin/dash
1745
1754
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
1748
1757
1749
1758
postgres=> update passwd set username = 'joe';
1750
1759
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
1752
1761
postgres=> update passwd set real_name = 'Alice Doe';
1753
1762
UPDATE 1
1754
1763
postgres=> update passwd set real_name = 'John Doe' where username = 'admin';
@@ -1759,11 +1768,16 @@ postgres=> delete from passwd;
1759
1768
ERROR: permission denied for relation passwd
1760
1769
postgres=> insert into passwd (username) values ('xxx');
1761
1770
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
1763
1772
postgres=> update passwd set pwhash = 'abc';
1764
1773
UPDATE 1
1765
1774
</programlisting>
1766
1775
1776
+ <para>
1777
+ For additional details see <xref linkend="sql-createpolicy">
1778
+ and <xref linkend="sql-altertable">.
1779
+ </para>
1780
+
1767
1781
</sect1>
1768
1782
1769
1783
<sect1 id="ddl-schemas">
0 commit comments