Skip to content

Commit 65d7800

Browse files
craig[bot]spilchen
andcommitted
Merge #143079
143079: sql: validate RLS policy exemptions for constraints r=spilchen a=spilchen Unique and foreign key constraints on tables with row-level security (RLS) enabled are exempt from RLS policies when enforcing constraints. This exemption was implemented previously. This commit adds tests to validate that RLS policies do not interfere with constraint enforcement. Closes #136747 Epic: CRDB-45203 Release note: none Co-authored-by: Matt Spilchen <[email protected]>
2 parents bf94a1d + 7a7f2cc commit 65d7800

File tree

1 file changed

+235
-0
lines changed

1 file changed

+235
-0
lines changed

pkg/sql/logictest/testdata/logic_test/row_level_security

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1538,6 +1538,241 @@ SET ROLE root
15381538
statement ok
15391539
DROP TABLE force_check CASCADE;
15401540

1541+
# Test to make sure that the scan to enforce uniqueness is done without RLS policies.
1542+
subtest uniq
1543+
1544+
statement ok
1545+
CREATE TABLE uniq (rls_col TEXT, uniq_col INT8 UNIQUE);
1546+
1547+
statement ok
1548+
CREATE USER uniq_user;
1549+
1550+
statement ok
1551+
GRANT ALL ON uniq TO uniq_user;
1552+
1553+
statement ok
1554+
ALTER TABLE uniq OWNER TO uniq_user;
1555+
1556+
statement ok
1557+
SET ROLE uniq_user;
1558+
1559+
statement ok
1560+
ALTER TABLE uniq NO FORCE ROW LEVEL SECURITY, ENABLE ROW LEVEL SECURITY;
1561+
1562+
statement ok
1563+
CREATE POLICY access ON uniq USING (rls_col = 'cat');
1564+
1565+
statement ok
1566+
INSERT INTO uniq VALUES ('cat', 1), ('cat', 2), ('dog', 3), ('cat', 4), ('hamster', 5);
1567+
1568+
statement ok
1569+
ALTER TABLE uniq FORCE ROW LEVEL SECURITY;
1570+
1571+
statement error pq: duplicate key value violates unique constraint "uniq_uniq_col_key"\nDETAIL: Key \(uniq_col\)=\(3\) already exists.
1572+
INSERT INTO uniq VALUES ('cat', 3);
1573+
1574+
statement ok
1575+
INSERT INTO uniq VALUES ('cat', 6);
1576+
1577+
statement error pq: new row violates row-level security policy for table "uniq"
1578+
INSERT INTO uniq VALUES ('dog', 6);
1579+
1580+
statement error pq: duplicate key value violates unique constraint "uniq_uniq_col_key"\nDETAIL: Key \(uniq_col\)=\(5\) already exists.
1581+
UPDATE uniq SET uniq_col = 5 WHERE uniq_col = 1;
1582+
1583+
statement ok
1584+
UPDATE uniq SET uniq_col = 7 WHERE uniq_col = 1;
1585+
1586+
# Ensure that any attempts to update an invisible row will be a no-op
1587+
query TI
1588+
UPDATE uniq SET uniq_col = 8 WHERE uniq_col = 5 RETURNING rls_col, uniq_col;
1589+
----
1590+
1591+
statement ok
1592+
ALTER TABLE uniq NO FORCE ROW LEVEL SECURITY;
1593+
1594+
query TI
1595+
select rls_col, uniq_col FROM uniq ORDER BY uniq_col;
1596+
----
1597+
cat 2
1598+
dog 3
1599+
cat 4
1600+
hamster 5
1601+
cat 6
1602+
cat 7
1603+
1604+
statement ok
1605+
SET ROLE root;
1606+
1607+
statement ok
1608+
DROP TABLE uniq;
1609+
1610+
statement ok
1611+
DROP USER uniq_user;
1612+
1613+
# Test to make sure that the scan to enforce foreign keys is exempt from RLS policies.
1614+
subtest fk
1615+
1616+
statement ok
1617+
CREATE TABLE parent (key INT8 NOT NULL PRIMARY KEY);
1618+
1619+
statement ok
1620+
CREATE TABLE child (
1621+
rls_col TEXT,
1622+
key INT8 NOT NULL,
1623+
CONSTRAINT fk FOREIGN KEY (key) REFERENCES parent(key) ON DELETE CASCADE
1624+
);
1625+
1626+
statement ok
1627+
CREATE USER fk_user;
1628+
1629+
statement ok
1630+
GRANT ALL ON parent TO fk_user;
1631+
1632+
statement ok
1633+
GRANT ALL ON child TO fk_user;
1634+
1635+
statement ok
1636+
ALTER TABLE parent OWNER TO fk_user;
1637+
1638+
statement ok
1639+
ALTER TABLE child OWNER TO fk_user;
1640+
1641+
statement ok
1642+
SET ROLE fk_user;
1643+
1644+
statement ok
1645+
INSERT INTO parent SELECT * FROM generate_series(1,6);
1646+
1647+
statement ok
1648+
INSERT INTO child VALUES ('bedroom', 1), ('office', 2)
1649+
1650+
# Set RLS at the parent and ensure FK still enforced.
1651+
statement ok
1652+
ALTER TABLE parent ENABLE ROW LEVEL SECURITY, FORCE ROW LEVEL SECURITY;
1653+
1654+
statement error pq: insert on table "child" violates foreign key constraint "fk"
1655+
INSERT INTO child VALUES ('hall', 7);
1656+
1657+
statement ok
1658+
INSERT INTO child VALUES ('hall', 3);
1659+
1660+
# mimic the FK lookup to show that the given RLS policies will hide the value
1661+
query I
1662+
SELECT 1 FROM parent WHERE key = 3;
1663+
----
1664+
1665+
query I
1666+
SELECT key FROM child ORDER BY key;
1667+
----
1668+
1
1669+
2
1670+
3
1671+
1672+
# Set RLS at the child and ensure FK still enforced
1673+
statement ok
1674+
ALTER TABLE child ENABLE ROW LEVEL SECURITY, FORCE ROW LEVEL SECURITY;
1675+
1676+
statement ok
1677+
CREATE POLICY ins1 ON child FOR INSERT WITH CHECK (rls_col = 'bedroom');
1678+
1679+
statement error pq: insert on table "child" violates foreign key constraint "fk"
1680+
INSERT INTO child VALUES ('bedroom', 7);
1681+
1682+
statement error pq: new row violates row-level security policy for table "child"
1683+
INSERT INTO child VALUES ('deck', 7);
1684+
1685+
statement ok
1686+
INSERT INTO child VALUES ('bedroom', 4);
1687+
1688+
# Disable RLS at the parent so that we can do a delete and have it cascade down
1689+
statement ok
1690+
ALTER TABLE parent NO FORCE ROW LEVEL SECURITY;
1691+
1692+
statement ok
1693+
DELETE FROM parent WHERE key = 1;
1694+
1695+
statement ok
1696+
CREATE POLICY sel1 ON child FOR SELECT USING (true);
1697+
1698+
query I
1699+
SELECT key FROM child ORDER BY key;
1700+
----
1701+
2
1702+
3
1703+
4
1704+
1705+
statement ok
1706+
SET ROLE root
1707+
1708+
statement ok
1709+
DROP TABLE child;
1710+
1711+
statement ok
1712+
DROP TABLE parent;
1713+
1714+
statement ok
1715+
DROP USER fk_user;
1716+
1717+
# Ensure CHECK constraints can work alongside RLS policies
1718+
subtest check_constraint
1719+
1720+
statement ok
1721+
CREATE TABLE rgb_only (col text, check (col = 'red' or col = 'green' or col = 'blue'));
1722+
1723+
statement ok
1724+
CREATE USER rgb_only_user;
1725+
1726+
statement ok
1727+
ALTER TABLE rgb_only OWNER TO rgb_only_user;
1728+
1729+
statement ok
1730+
SET ROLE rgb_only_user;
1731+
1732+
statement ok
1733+
ALTER TABLE rgb_only ENABLE ROW LEVEL SECURITY, FORCE ROW LEVEL SECURITY;
1734+
1735+
statement ok
1736+
CREATE POLICY p_sel ON rgb_only FOR SELECT USING (true);
1737+
1738+
statement ok
1739+
CREATE POLICY p_subset ON rgb_only FOR INSERT WITH CHECK (col = 'red' or col = 'brown');
1740+
1741+
statement ok
1742+
INSERT INTO rgb_only VALUES ('red')
1743+
1744+
# Allowed by policy, reject by CHECK constraint
1745+
statement error pq: failed to satisfy CHECK constraint \(\(\(col = 'red':::STRING\) OR \(col = 'green':::STRING\)\) OR \(col = 'blue':::STRING\)\)
1746+
INSERT INTO rgb_only VALUES ('brown')
1747+
1748+
# Disallowed by policy, accepted by CHECK constraint
1749+
statement error pq: new row violates row-level security policy for table "rgb_only"
1750+
INSERT INTO rgb_only VALUES ('green')
1751+
1752+
statement ok
1753+
DROP POLICY p_subset ON rgb_only;
1754+
1755+
statement ok
1756+
CREATE POLICY p_disjoint ON rgb_only FOR INSERT WITH CHECK (col = 'black');
1757+
1758+
# Disallowed by both.
1759+
statement error pq: new row violates row-level security policy for table "rgb_only"
1760+
INSERT INTO rgb_only VALUES ('blue')
1761+
1762+
query T
1763+
SELECT col FROM rgb_only ORDER BY col;
1764+
----
1765+
red
1766+
1767+
statement ok
1768+
SET ROLE root;
1769+
1770+
statement ok
1771+
DROP TABLE rgb_only;
1772+
1773+
statement ok
1774+
DROP USER rgb_only_user;
1775+
15411776
subtest truncate
15421777

15431778
statement ok

0 commit comments

Comments
 (0)