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

Commit ff27fcf

Browse files
committed
Fix relcache for policies, and doc updates
Andres pointed out that there was an extra ';' in equalPolicies, which made me realize that my prior testing with CLOBBER_CACHE_ALWAYS was insufficient (it didn't always catch the issue, just most of the time). Thanks to that, a different issue was discovered, specifically in equalRSDescs. This change corrects eqaulRSDescs to return 'true' once all policies have been confirmed logically identical. After stepping through both functions to ensure correct behavior, I ran this for about 12 hours of CLOBBER_CACHE_ALWAYS runs of the regression tests with no failures. In addition, correct a few typos in the documentation which were pointed out by Thom Brown (thanks!) and improve the policy documentation further by adding a flushed out usage example based on a unix passwd file. Lastly, clean up a few comments in the regression tests and pg_dump.h.
1 parent 07d46a8 commit ff27fcf

File tree

7 files changed

+127
-18
lines changed

7 files changed

+127
-18
lines changed

doc/src/sgml/ddl.sgml

Lines changed: 110 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1615,7 +1615,7 @@ REVOKE ALL ON accounts FROM PUBLIC;
16151615
and foreign key references, will bypass row security to ensure that
16161616
data integrity is maintained. Care must be taken when developing
16171617
schemas and row level policies to avoid a "covert channel" leak of
1618-
information through these referntial integrity checks.
1618+
information through these referential integrity checks.
16191619
</para>
16201620

16211621
<para>
@@ -1674,6 +1674,115 @@ CREATE POLICY user_policy ON users
16741674
normal privileges system.
16751675
</para>
16761676

1677+
<para>
1678+
Below is a larger example of how this feature can be used in
1679+
production environments, based on a unix password file.
1680+
</para>
1681+
1682+
<programlisting>
1683+
-- Simple passwd-file based example
1684+
CREATE TABLE passwd (
1685+
username text UNIQUE NOT NULL,
1686+
pwhash text,
1687+
uid int PRIMARY KEY,
1688+
gid int NOT NULL,
1689+
real_name text NOT NULL,
1690+
home_phone text,
1691+
extra_info text,
1692+
home_dir text NOT NULL,
1693+
shell text NOT NULL
1694+
);
1695+
1696+
CREATE ROLE admin; -- Administrator
1697+
CREATE ROLE bob; -- Normal user
1698+
CREATE ROLE alice; -- Normal user
1699+
1700+
-- Populate the table
1701+
INSERT INTO passwd VALUES
1702+
('admin','xxx',0,0,'Admin','111-222-3333',null,'/root','/bin/dash');
1703+
INSERT INTO passwd VALUES
1704+
('bob','xxx',1,1,'Bob','123-456-7890',null,'/home/bob','/bin/zsh');
1705+
INSERT INTO passwd VALUES
1706+
('alice','xxx',2,1,'Alice','098-765-4321',null,'/home/alice','/bin/zsh');
1707+
1708+
-- Be sure to enable row level security on the table
1709+
ALTER TABLE passwd ENABLE ROW LEVEL SECURITY;
1710+
1711+
-- Create policies
1712+
-- Administrator can see all rows and add any rows
1713+
CREATE POLICY admin_all ON passwd TO admin USING (true) WITH CHECK (true);
1714+
-- Normal users can view all rows
1715+
CREATE POLICY all_view ON passwd FOR SELECT USING (true);
1716+
-- Normal users can update their own records, but
1717+
-- limit which shells a normal user is allowed to set
1718+
CREATE POLICY user_mod ON passwd FOR UPDATE
1719+
USING (current_user = username)
1720+
WITH CHECK (
1721+
current_user = username AND
1722+
shell IN ('/bin/bash','/bin/sh','/bin/dash','/bin/zsh','/bin/tcsh')
1723+
);
1724+
1725+
-- Allow admin all normal rights
1726+
GRANT SELECT, INSERT, UPDATE, DELETE ON passwd TO admin;
1727+
-- Users only get select access on public columns
1728+
GRANT SELECT
1729+
(username, uid, gid, real_name, home_phone, extra_info, home_dir, shell)
1730+
ON passwd TO public;
1731+
-- Allow users to update certain columns
1732+
GRANT UPDATE
1733+
(pwhash, real_name, home_phone, extra_info, shell)
1734+
ON passwd TO public;
1735+
</programlisting>
1736+
1737+
<para>
1738+
As with any security settings, it's important to test and ensure that
1739+
the system is behaving as expected. Using the example above, this
1740+
demonstrates that the permission system is working properly.
1741+
</para>
1742+
1743+
<programlisting>
1744+
-- admin can view all rows and fields
1745+
postgres=> set role admin;
1746+
SET
1747+
postgres=> table passwd;
1748+
username | pwhash | uid | gid | real_name | home_phone | extra_info | home_dir | shell
1749+
----------+--------+-----+-----+-----------+--------------+------------+-------------+-----------
1750+
admin | xxx | 0 | 0 | Admin | 111-222-3333 | | /root | /bin/dash
1751+
bob | xxx | 1 | 1 | Bob | 123-456-7890 | | /home/bob | /bin/zsh
1752+
alice | xxx | 2 | 1 | Alice | 098-765-4321 | | /home/alice | /bin/zsh
1753+
(3 rows)
1754+
1755+
-- Test what Alice is able to do
1756+
postgres=> set role alice;
1757+
SET
1758+
postgres=> table passwd;
1759+
ERROR: permission denied for relation passwd
1760+
postgres=> select username,real_name,home_phone,extra_info,home_dir,shell from passwd;
1761+
username | real_name | home_phone | extra_info | home_dir | shell
1762+
----------+-----------+--------------+------------+-------------+-----------
1763+
admin | Admin | 111-222-3333 | | /root | /bin/dash
1764+
bob | Bob | 123-456-7890 | | /home/bob | /bin/zsh
1765+
alice | Alice | 098-765-4321 | | /home/alice | /bin/zsh
1766+
(3 rows)
1767+
1768+
postgres=> update passwd set username = 'joe';
1769+
ERROR: permission denied for relation passwd
1770+
-- Allowed to change her own real_name, but no others
1771+
postgres=> update passwd set real_name = 'Alice Doe';
1772+
UPDATE 1
1773+
postgres=> update passwd set real_name = 'John Doe' where username = 'admin';
1774+
UPDATE 0
1775+
postgres=> update passwd set shell = '/bin/xx';
1776+
ERROR: new row violates WITH CHECK OPTION for "passwd"
1777+
postgres=> delete from passwd;
1778+
ERROR: permission denied for relation passwd
1779+
postgres=> insert into passwd (username) values ('xxx');
1780+
ERROR: permission denied for relation passwd
1781+
-- Alice can change her own password
1782+
postgres=> update passwd set pwhash = 'abc';
1783+
UPDATE 1
1784+
</programlisting>
1785+
16771786
</sect1>
16781787

16791788
<sect1 id="ddl-schemas">

doc/src/sgml/ref/alter_policy.sgml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ ALTER POLICY <replaceable class="parameter">name</replaceable> ON <replaceable c
9494
security-barrier qualification to queries which use the table
9595
automatically. If multiple policies are being applied for a given
9696
table then they are all combined and added using OR. The USING
97-
expression applies to records which are being retrived from the table.
97+
expression applies to records which are being retrieved from the table.
9898
</para>
9999
</listitem>
100100
</varlistentry>

doc/src/sgml/ref/create_policy.sgml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ CREATE POLICY <replaceable class="parameter">name</replaceable> ON <replaceable
8181
referenced table. These issues can be addressed by carefully crafting
8282
policies which prevent users from being able to insert, delete, or update
8383
records at all which might possibly indicate a value they are not otherwise
84-
able to see, or by using generated values (eg: surrogate keys) instead.
84+
able to see, or by using generated values (e.g.: surrogate keys) instead.
8585
</para>
8686

8787
<para>
@@ -218,7 +218,7 @@ CREATE POLICY <replaceable class="parameter">name</replaceable> ON <replaceable
218218
records from the relation which pass the <literal>SELECT</literal>
219219
policy will be returned, even if other records exist in the relation.
220220
The <literal>SELECT</literal> policy only accepts the USING expression
221-
as it only ever applies in cases where records are being retrived from
221+
as it only ever applies in cases where records are being retrieved from
222222
the relation.
223223
</para>
224224
</listitem>
@@ -272,7 +272,7 @@ CREATE POLICY <replaceable class="parameter">name</replaceable> ON <replaceable
272272
for the <literal>DELETE</literal>, and rows which are not visible
273273
through the <literal>SELECT</literal> policy may be deleted if they
274274
pass the <literal>DELETE</literal> USING policy. The
275-
<literal>DELETE</literal> policy only accept the USING expression as
275+
<literal>DELETE</literal> policy only accepts the USING expression as
276276
it only ever applies in cases where records are being extracted from
277277
the relation for deletion.
278278
</para>

src/backend/utils/cache/relcache.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -868,7 +868,7 @@ equalPolicy(RowSecurityPolicy *policy1, RowSecurityPolicy *policy2)
868868
return false;
869869
if (policy1->cmd != policy2->cmd)
870870
return false;
871-
if (policy1->hassublinks != policy2->hassublinks);
871+
if (policy1->hassublinks != policy2->hassublinks)
872872
return false;
873873
if (strcmp(policy1->policy_name,policy2->policy_name) != 0)
874874
return false;
@@ -926,7 +926,7 @@ equalRSDesc(RowSecurityDesc *rsdesc1, RowSecurityDesc *rsdesc2)
926926
return false;
927927
}
928928

929-
return false;
929+
return true;
930930
}
931931

932932
/*

src/bin/pg_dump/pg_dump.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ typedef struct _tableInfo
246246
bool hasindex; /* does it have any indexes? */
247247
bool hasrules; /* does it have any rules? */
248248
bool hastriggers; /* does it have any triggers? */
249-
bool rowsec; /* does it have any row-security policy? */
249+
bool rowsec; /* is row-security enabled? */
250250
bool hasoids; /* does it have OIDs? */
251251
uint32 frozenxid; /* for restore frozen xid */
252252
uint32 minmxid; /* for restore min multi xid */

src/test/regress/expected/rowsecurity.out

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ INSERT INTO document VALUES
6969
( 7, 33, 2, 'rls_regress_user2', 'great technology book'),
7070
( 8, 44, 1, 'rls_regress_user2', 'great manga');
7171
ALTER TABLE document ENABLE ROW LEVEL SECURITY;
72-
-- user's security level must be higher that or equal to document's
72+
-- user's security level must be higher than or equal to document's
7373
CREATE POLICY p1 ON document
7474
USING (dlevel <= (SELECT seclv FROM uaccount WHERE pguser = current_user));
7575
-- viewpoint from rls_regress_user1
@@ -280,7 +280,7 @@ SELECT * FROM document d FULL OUTER JOIN category c on d.cid = c.cid;
280280
DELETE FROM category WHERE cid = 33; -- fails with FK violation
281281
ERROR: update or delete on table "category" violates foreign key constraint "document_cid_fkey" on table "document"
282282
DETAIL: Key (cid)=(33) is still referenced from table "document".
283-
-- cannot insert FK referencing invisible PK
283+
-- can insert FK referencing invisible PK
284284
SET SESSION AUTHORIZATION rls_regress_user2;
285285
SELECT * FROM document d FULL OUTER JOIN category c on d.cid = c.cid;
286286
did | cid | dlevel | dauthor | dtitle | cid | cname
@@ -301,7 +301,7 @@ SELECT * FROM document WHERE did = 8; -- and confirm we can't see it
301301
-----+-----+--------+---------+--------
302302
(0 rows)
303303

304-
-- database superuser cannot bypass RLS policy when enabled
304+
-- database superuser does bypass RLS policy when enabled
305305
RESET SESSION AUTHORIZATION;
306306
SET row_security TO ON;
307307
SELECT * FROM document;
@@ -327,7 +327,7 @@ SELECT * FROM category;
327327
44 | manga
328328
(4 rows)
329329

330-
-- database superuser cannot bypass RLS policy when FORCE enabled.
330+
-- database superuser does not bypass RLS policy when FORCE enabled.
331331
RESET SESSION AUTHORIZATION;
332332
SET row_security TO FORCE;
333333
SELECT * FROM document;
@@ -340,7 +340,7 @@ SELECT * FROM category;
340340
-----+-------
341341
(0 rows)
342342

343-
-- database superuser can bypass RLS policy when disabled
343+
-- database superuser does bypass RLS policy when disabled
344344
RESET SESSION AUTHORIZATION;
345345
SET row_security TO OFF;
346346
SELECT * FROM document;

src/test/regress/sql/rowsecurity.sql

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ INSERT INTO document VALUES
8484

8585
ALTER TABLE document ENABLE ROW LEVEL SECURITY;
8686

87-
-- user's security level must be higher that or equal to document's
87+
-- user's security level must be higher than or equal to document's
8888
CREATE POLICY p1 ON document
8989
USING (dlevel <= (SELECT seclv FROM uaccount WHERE pguser = current_user));
9090

@@ -136,7 +136,7 @@ SET SESSION AUTHORIZATION rls_regress_user1;
136136
SELECT * FROM document d FULL OUTER JOIN category c on d.cid = c.cid;
137137
DELETE FROM category WHERE cid = 33; -- fails with FK violation
138138

139-
-- cannot insert FK referencing invisible PK
139+
-- can insert FK referencing invisible PK
140140
SET SESSION AUTHORIZATION rls_regress_user2;
141141
SELECT * FROM document d FULL OUTER JOIN category c on d.cid = c.cid;
142142
INSERT INTO document VALUES (10, 33, 1, current_user, 'hoge');
@@ -146,19 +146,19 @@ SET SESSION AUTHORIZATION rls_regress_user1;
146146
INSERT INTO document VALUES (8, 44, 1, 'rls_regress_user1', 'my third manga'); -- Must fail with unique violation, revealing presence of did we can't see
147147
SELECT * FROM document WHERE did = 8; -- and confirm we can't see it
148148

149-
-- database superuser cannot bypass RLS policy when enabled
149+
-- database superuser does bypass RLS policy when enabled
150150
RESET SESSION AUTHORIZATION;
151151
SET row_security TO ON;
152152
SELECT * FROM document;
153153
SELECT * FROM category;
154154

155-
-- database superuser cannot bypass RLS policy when FORCE enabled.
155+
-- database superuser does not bypass RLS policy when FORCE enabled.
156156
RESET SESSION AUTHORIZATION;
157157
SET row_security TO FORCE;
158158
SELECT * FROM document;
159159
SELECT * FROM category;
160160

161-
-- database superuser can bypass RLS policy when disabled
161+
-- database superuser does bypass RLS policy when disabled
162162
RESET SESSION AUTHORIZATION;
163163
SET row_security TO OFF;
164164
SELECT * FROM document;

0 commit comments

Comments
 (0)