Skip to content

Commit 7a7f2cc

Browse files
committed
sql: validate RLS policy exemptions for constraints
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
1 parent 7c6e428 commit 7a7f2cc

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

+235
Original file line numberDiff line numberDiff line change
@@ -1457,6 +1457,241 @@ SET ROLE root
14571457
statement ok
14581458
DROP TABLE force_check CASCADE;
14591459

1460+
# Test to make sure that the scan to enforce uniqueness is done without RLS policies.
1461+
subtest uniq
1462+
1463+
statement ok
1464+
CREATE TABLE uniq (rls_col TEXT, uniq_col INT8 UNIQUE);
1465+
1466+
statement ok
1467+
CREATE USER uniq_user;
1468+
1469+
statement ok
1470+
GRANT ALL ON uniq TO uniq_user;
1471+
1472+
statement ok
1473+
ALTER TABLE uniq OWNER TO uniq_user;
1474+
1475+
statement ok
1476+
SET ROLE uniq_user;
1477+
1478+
statement ok
1479+
ALTER TABLE uniq NO FORCE ROW LEVEL SECURITY, ENABLE ROW LEVEL SECURITY;
1480+
1481+
statement ok
1482+
CREATE POLICY access ON uniq USING (rls_col = 'cat');
1483+
1484+
statement ok
1485+
INSERT INTO uniq VALUES ('cat', 1), ('cat', 2), ('dog', 3), ('cat', 4), ('hamster', 5);
1486+
1487+
statement ok
1488+
ALTER TABLE uniq FORCE ROW LEVEL SECURITY;
1489+
1490+
statement error pq: duplicate key value violates unique constraint "uniq_uniq_col_key"\nDETAIL: Key \(uniq_col\)=\(3\) already exists.
1491+
INSERT INTO uniq VALUES ('cat', 3);
1492+
1493+
statement ok
1494+
INSERT INTO uniq VALUES ('cat', 6);
1495+
1496+
statement error pq: new row violates row-level security policy for table "uniq"
1497+
INSERT INTO uniq VALUES ('dog', 6);
1498+
1499+
statement error pq: duplicate key value violates unique constraint "uniq_uniq_col_key"\nDETAIL: Key \(uniq_col\)=\(5\) already exists.
1500+
UPDATE uniq SET uniq_col = 5 WHERE uniq_col = 1;
1501+
1502+
statement ok
1503+
UPDATE uniq SET uniq_col = 7 WHERE uniq_col = 1;
1504+
1505+
# Ensure that any attempts to update an invisible row will be a no-op
1506+
query TI
1507+
UPDATE uniq SET uniq_col = 8 WHERE uniq_col = 5 RETURNING rls_col, uniq_col;
1508+
----
1509+
1510+
statement ok
1511+
ALTER TABLE uniq NO FORCE ROW LEVEL SECURITY;
1512+
1513+
query TI
1514+
select rls_col, uniq_col FROM uniq ORDER BY uniq_col;
1515+
----
1516+
cat 2
1517+
dog 3
1518+
cat 4
1519+
hamster 5
1520+
cat 6
1521+
cat 7
1522+
1523+
statement ok
1524+
SET ROLE root;
1525+
1526+
statement ok
1527+
DROP TABLE uniq;
1528+
1529+
statement ok
1530+
DROP USER uniq_user;
1531+
1532+
# Test to make sure that the scan to enforce foreign keys is exempt from RLS policies.
1533+
subtest fk
1534+
1535+
statement ok
1536+
CREATE TABLE parent (key INT8 NOT NULL PRIMARY KEY);
1537+
1538+
statement ok
1539+
CREATE TABLE child (
1540+
rls_col TEXT,
1541+
key INT8 NOT NULL,
1542+
CONSTRAINT fk FOREIGN KEY (key) REFERENCES parent(key) ON DELETE CASCADE
1543+
);
1544+
1545+
statement ok
1546+
CREATE USER fk_user;
1547+
1548+
statement ok
1549+
GRANT ALL ON parent TO fk_user;
1550+
1551+
statement ok
1552+
GRANT ALL ON child TO fk_user;
1553+
1554+
statement ok
1555+
ALTER TABLE parent OWNER TO fk_user;
1556+
1557+
statement ok
1558+
ALTER TABLE child OWNER TO fk_user;
1559+
1560+
statement ok
1561+
SET ROLE fk_user;
1562+
1563+
statement ok
1564+
INSERT INTO parent SELECT * FROM generate_series(1,6);
1565+
1566+
statement ok
1567+
INSERT INTO child VALUES ('bedroom', 1), ('office', 2)
1568+
1569+
# Set RLS at the parent and ensure FK still enforced.
1570+
statement ok
1571+
ALTER TABLE parent ENABLE ROW LEVEL SECURITY, FORCE ROW LEVEL SECURITY;
1572+
1573+
statement error pq: insert on table "child" violates foreign key constraint "fk"
1574+
INSERT INTO child VALUES ('hall', 7);
1575+
1576+
statement ok
1577+
INSERT INTO child VALUES ('hall', 3);
1578+
1579+
# mimic the FK lookup to show that the given RLS policies will hide the value
1580+
query I
1581+
SELECT 1 FROM parent WHERE key = 3;
1582+
----
1583+
1584+
query I
1585+
SELECT key FROM child ORDER BY key;
1586+
----
1587+
1
1588+
2
1589+
3
1590+
1591+
# Set RLS at the child and ensure FK still enforced
1592+
statement ok
1593+
ALTER TABLE child ENABLE ROW LEVEL SECURITY, FORCE ROW LEVEL SECURITY;
1594+
1595+
statement ok
1596+
CREATE POLICY ins1 ON child FOR INSERT WITH CHECK (rls_col = 'bedroom');
1597+
1598+
statement error pq: insert on table "child" violates foreign key constraint "fk"
1599+
INSERT INTO child VALUES ('bedroom', 7);
1600+
1601+
statement error pq: new row violates row-level security policy for table "child"
1602+
INSERT INTO child VALUES ('deck', 7);
1603+
1604+
statement ok
1605+
INSERT INTO child VALUES ('bedroom', 4);
1606+
1607+
# Disable RLS at the parent so that we can do a delete and have it cascade down
1608+
statement ok
1609+
ALTER TABLE parent NO FORCE ROW LEVEL SECURITY;
1610+
1611+
statement ok
1612+
DELETE FROM parent WHERE key = 1;
1613+
1614+
statement ok
1615+
CREATE POLICY sel1 ON child FOR SELECT USING (true);
1616+
1617+
query I
1618+
SELECT key FROM child ORDER BY key;
1619+
----
1620+
2
1621+
3
1622+
4
1623+
1624+
statement ok
1625+
SET ROLE root
1626+
1627+
statement ok
1628+
DROP TABLE child;
1629+
1630+
statement ok
1631+
DROP TABLE parent;
1632+
1633+
statement ok
1634+
DROP USER fk_user;
1635+
1636+
# Ensure CHECK constraints can work alongside RLS policies
1637+
subtest check_constraint
1638+
1639+
statement ok
1640+
CREATE TABLE rgb_only (col text, check (col = 'red' or col = 'green' or col = 'blue'));
1641+
1642+
statement ok
1643+
CREATE USER rgb_only_user;
1644+
1645+
statement ok
1646+
ALTER TABLE rgb_only OWNER TO rgb_only_user;
1647+
1648+
statement ok
1649+
SET ROLE rgb_only_user;
1650+
1651+
statement ok
1652+
ALTER TABLE rgb_only ENABLE ROW LEVEL SECURITY, FORCE ROW LEVEL SECURITY;
1653+
1654+
statement ok
1655+
CREATE POLICY p_sel ON rgb_only FOR SELECT USING (true);
1656+
1657+
statement ok
1658+
CREATE POLICY p_subset ON rgb_only FOR INSERT WITH CHECK (col = 'red' or col = 'brown');
1659+
1660+
statement ok
1661+
INSERT INTO rgb_only VALUES ('red')
1662+
1663+
# Allowed by policy, reject by CHECK constraint
1664+
statement error pq: failed to satisfy CHECK constraint \(\(\(col = 'red':::STRING\) OR \(col = 'green':::STRING\)\) OR \(col = 'blue':::STRING\)\)
1665+
INSERT INTO rgb_only VALUES ('brown')
1666+
1667+
# Disallowed by policy, accepted by CHECK constraint
1668+
statement error pq: new row violates row-level security policy for table "rgb_only"
1669+
INSERT INTO rgb_only VALUES ('green')
1670+
1671+
statement ok
1672+
DROP POLICY p_subset ON rgb_only;
1673+
1674+
statement ok
1675+
CREATE POLICY p_disjoint ON rgb_only FOR INSERT WITH CHECK (col = 'black');
1676+
1677+
# Disallowed by both.
1678+
statement error pq: new row violates row-level security policy for table "rgb_only"
1679+
INSERT INTO rgb_only VALUES ('blue')
1680+
1681+
query T
1682+
SELECT col FROM rgb_only ORDER BY col;
1683+
----
1684+
red
1685+
1686+
statement ok
1687+
SET ROLE root;
1688+
1689+
statement ok
1690+
DROP TABLE rgb_only;
1691+
1692+
statement ok
1693+
DROP USER rgb_only_user;
1694+
14601695
subtest truncate
14611696

14621697
statement ok

0 commit comments

Comments
 (0)