]> begriffs open source - ai-pg/blob - full-docs/txt/ddl-rowsecurity.txt
Convert HTML docs to more streamlined TXT
[ai-pg] / full-docs / txt / ddl-rowsecurity.txt
1
2 5.9. Row Security Policies #
3
4    In addition to the SQL-standard privilege system available through
5    GRANT, tables can have row security policies that restrict, on a
6    per-user basis, which rows can be returned by normal queries or
7    inserted, updated, or deleted by data modification commands. This
8    feature is also known as Row-Level Security. By default, tables do not
9    have any policies, so that if a user has access privileges to a table
10    according to the SQL privilege system, all rows within it are equally
11    available for querying or updating.
12
13    When row security is enabled on a table (with ALTER TABLE ... ENABLE
14    ROW LEVEL SECURITY), all normal access to the table for selecting rows
15    or modifying rows must be allowed by a row security policy. (However,
16    the table's owner is typically not subject to row security policies.)
17    If no policy exists for the table, a default-deny policy is used,
18    meaning that no rows are visible or can be modified. Operations that
19    apply to the whole table, such as TRUNCATE and REFERENCES, are not
20    subject to row security.
21
22    Row security policies can be specific to commands, or to roles, or to
23    both. A policy can be specified to apply to ALL commands, or to SELECT,
24    INSERT, UPDATE, or DELETE. Multiple roles can be assigned to a given
25    policy, and normal role membership and inheritance rules apply.
26
27    To specify which rows are visible or modifiable according to a policy,
28    an expression is required that returns a Boolean result. This
29    expression will be evaluated for each row prior to any conditions or
30    functions coming from the user's query. (The only exceptions to this
31    rule are leakproof functions, which are guaranteed to not leak
32    information; the optimizer may choose to apply such functions ahead of
33    the row-security check.) Rows for which the expression does not return
34    true will not be processed. Separate expressions may be specified to
35    provide independent control over the rows which are visible and the
36    rows which are allowed to be modified. Policy expressions are run as
37    part of the query and with the privileges of the user running the
38    query, although security-definer functions can be used to access data
39    not available to the calling user.
40
41    Superusers and roles with the BYPASSRLS attribute always bypass the row
42    security system when accessing a table. Table owners normally bypass
43    row security as well, though a table owner can choose to be subject to
44    row security with ALTER TABLE ... FORCE ROW LEVEL SECURITY.
45
46    Enabling and disabling row security, as well as adding policies to a
47    table, is always the privilege of the table owner only.
48
49    Policies are created using the CREATE POLICY command, altered using the
50    ALTER POLICY command, and dropped using the DROP POLICY command. To
51    enable and disable row security for a given table, use the ALTER TABLE
52    command.
53
54    Each policy has a name and multiple policies can be defined for a
55    table. As policies are table-specific, each policy for a table must
56    have a unique name. Different tables may have policies with the same
57    name.
58
59    When multiple policies apply to a given query, they are combined using
60    either OR (for permissive policies, which are the default) or using AND
61    (for restrictive policies). The OR behavior is similar to the rule that
62    a given role has the privileges of all roles that they are a member of.
63    Permissive vs. restrictive policies are discussed further below.
64
65    As a simple example, here is how to create a policy on the account
66    relation to allow only members of the managers role to access rows, and
67    only rows of their accounts:
68 CREATE TABLE accounts (manager text, company text, contact_email text);
69
70 ALTER TABLE accounts ENABLE ROW LEVEL SECURITY;
71
72 CREATE POLICY account_managers ON accounts TO managers
73     USING (manager = current_user);
74
75    The policy above implicitly provides a WITH CHECK clause identical to
76    its USING clause, so that the constraint applies both to rows selected
77    by a command (so a manager cannot SELECT, UPDATE, or DELETE existing
78    rows belonging to a different manager) and to rows modified by a
79    command (so rows belonging to a different manager cannot be created via
80    INSERT or UPDATE).
81
82    If no role is specified, or the special user name PUBLIC is used, then
83    the policy applies to all users on the system. To allow all users to
84    access only their own row in a users table, a simple policy can be
85    used:
86 CREATE POLICY user_policy ON users
87     USING (user_name = current_user);
88
89    This works similarly to the previous example.
90
91    To use a different policy for rows that are being added to the table
92    compared to those rows that are visible, multiple policies can be
93    combined. This pair of policies would allow all users to view all rows
94    in the users table, but only modify their own:
95 CREATE POLICY user_sel_policy ON users
96     FOR SELECT
97     USING (true);
98 CREATE POLICY user_mod_policy ON users
99     USING (user_name = current_user);
100
101    In a SELECT command, these two policies are combined using OR, with the
102    net effect being that all rows can be selected. In other command types,
103    only the second policy applies, so that the effects are the same as
104    before.
105
106    Row security can also be disabled with the ALTER TABLE command.
107    Disabling row security does not remove any policies that are defined on
108    the table; they are simply ignored. Then all rows in the table are
109    visible and modifiable, subject to the standard SQL privileges system.
110
111    Below is a larger example of how this feature can be used in production
112    environments. The table passwd emulates a Unix password file:
113 -- Simple passwd-file based example
114 CREATE TABLE passwd (
115   user_name             text UNIQUE NOT NULL,
116   pwhash                text,
117   uid                   int  PRIMARY KEY,
118   gid                   int  NOT NULL,
119   real_name             text NOT NULL,
120   home_phone            text,
121   extra_info            text,
122   home_dir              text NOT NULL,
123   shell                 text NOT NULL
124 );
125
126 CREATE ROLE admin;  -- Administrator
127 CREATE ROLE bob;    -- Normal user
128 CREATE ROLE alice;  -- Normal user
129
130 -- Populate the table
131 INSERT INTO passwd VALUES
132   ('admin','xxx',0,0,'Admin','111-222-3333',null,'/root','/bin/dash');
133 INSERT INTO passwd VALUES
134   ('bob','xxx',1,1,'Bob','123-456-7890',null,'/home/bob','/bin/zsh');
135 INSERT INTO passwd VALUES
136   ('alice','xxx',2,1,'Alice','098-765-4321',null,'/home/alice','/bin/zsh');
137
138 -- Be sure to enable row-level security on the table
139 ALTER TABLE passwd ENABLE ROW LEVEL SECURITY;
140
141 -- Create policies
142 -- Administrator can see all rows and add any rows
143 CREATE POLICY admin_all ON passwd TO admin USING (true) WITH CHECK (true);
144 -- Normal users can view all rows
145 CREATE POLICY all_view ON passwd FOR SELECT USING (true);
146 -- Normal users can update their own records, but
147 -- limit which shells a normal user is allowed to set
148 CREATE POLICY user_mod ON passwd FOR UPDATE
149   USING (current_user = user_name)
150   WITH CHECK (
151     current_user = user_name AND
152     shell IN ('/bin/bash','/bin/sh','/bin/dash','/bin/zsh','/bin/tcsh')
153   );
154
155 -- Allow admin all normal rights
156 GRANT SELECT, INSERT, UPDATE, DELETE ON passwd TO admin;
157 -- Users only get select access on public columns
158 GRANT SELECT
159   (user_name, uid, gid, real_name, home_phone, extra_info, home_dir, shell)
160   ON passwd TO public;
161 -- Allow users to update certain columns
162 GRANT UPDATE
163   (pwhash, real_name, home_phone, extra_info, shell)
164   ON passwd TO public;
165
166    As with any security settings, it's important to test and ensure that
167    the system is behaving as expected. Using the example above, this
168    demonstrates that the permission system is working properly.
169 -- admin can view all rows and fields
170 postgres=> set role admin;
171 SET
172 postgres=> table passwd;
173  user_name | pwhash | uid | gid | real_name |  home_phone  | extra_info | home_d
174 ir    |   shell
175 -----------+--------+-----+-----+-----------+--------------+------------+-------
176 ------+-----------
177  admin     | xxx    |   0 |   0 | Admin     | 111-222-3333 |            | /root
178       | /bin/dash
179  bob       | xxx    |   1 |   1 | Bob       | 123-456-7890 |            | /home/
180 bob   | /bin/zsh
181  alice     | xxx    |   2 |   1 | Alice     | 098-765-4321 |            | /home/
182 alice | /bin/zsh
183 (3 rows)
184
185 -- Test what Alice is able to do
186 postgres=> set role alice;
187 SET
188 postgres=> table passwd;
189 ERROR:  permission denied for table passwd
190 postgres=> select user_name,real_name,home_phone,extra_info,home_dir,shell from
191 passwd;
192  user_name | real_name |  home_phone  | extra_info | home_dir    |   shell
193 -----------+-----------+--------------+------------+-------------+-----------
194  admin     | Admin     | 111-222-3333 |            | /root       | /bin/dash
195  bob       | Bob       | 123-456-7890 |            | /home/bob   | /bin/zsh
196  alice     | Alice     | 098-765-4321 |            | /home/alice | /bin/zsh
197 (3 rows)
198
199 postgres=> update passwd set user_name = 'joe';
200 ERROR:  permission denied for table passwd
201 -- Alice is allowed to change her own real_name, but no others
202 postgres=> update passwd set real_name = 'Alice Doe';
203 UPDATE 1
204 postgres=> update passwd set real_name = 'John Doe' where user_name = 'admin';
205 UPDATE 0
206 postgres=> update passwd set shell = '/bin/xx';
207 ERROR:  new row violates WITH CHECK OPTION for "passwd"
208 postgres=> delete from passwd;
209 ERROR:  permission denied for table passwd
210 postgres=> insert into passwd (user_name) values ('xxx');
211 ERROR:  permission denied for table passwd
212 -- Alice can change her own password; RLS silently prevents updating other rows
213 postgres=> update passwd set pwhash = 'abc';
214 UPDATE 1
215
216    All of the policies constructed thus far have been permissive policies,
217    meaning that when multiple policies are applied they are combined using
218    the “OR” Boolean operator. While permissive policies can be constructed
219    to only allow access to rows in the intended cases, it can be simpler
220    to combine permissive policies with restrictive policies (which the
221    records must pass and which are combined using the “AND” Boolean
222    operator). Building on the example above, we add a restrictive policy
223    to require the administrator to be connected over a local Unix socket
224    to access the records of the passwd table:
225 CREATE POLICY admin_local_only ON passwd AS RESTRICTIVE TO admin
226     USING (pg_catalog.inet_client_addr() IS NULL);
227
228    We can then see that an administrator connecting over a network will
229    not see any records, due to the restrictive policy:
230 => SELECT current_user;
231  current_user
232 --------------
233  admin
234 (1 row)
235
236 => select inet_client_addr();
237  inet_client_addr
238 ------------------
239  127.0.0.1
240 (1 row)
241
242 => TABLE passwd;
243  user_name | pwhash | uid | gid | real_name | home_phone | extra_info | home_dir
244  | shell
245 -----------+--------+-----+-----+-----------+------------+------------+---------
246 -+-------
247 (0 rows)
248
249 => UPDATE passwd set pwhash = NULL;
250 UPDATE 0
251
252    Referential integrity checks, such as unique or primary key constraints
253    and foreign key references, always bypass row security to ensure that
254    data integrity is maintained. Care must be taken when developing
255    schemas and row level policies to avoid “covert channel” leaks of
256    information through such referential integrity checks.
257
258    In some contexts it is important to be sure that row security is not
259    being applied. For example, when taking a backup, it could be
260    disastrous if row security silently caused some rows to be omitted from
261    the backup. In such a situation, you can set the row_security
262    configuration parameter to off. This does not in itself bypass row
263    security; what it does is throw an error if any query's results would
264    get filtered by a policy. The reason for the error can then be
265    investigated and fixed.
266
267    In the examples above, the policy expressions consider only the current
268    values in the row to be accessed or updated. This is the simplest and
269    best-performing case; when possible, it's best to design row security
270    applications to work this way. If it is necessary to consult other rows
271    or other tables to make a policy decision, that can be accomplished
272    using sub-SELECTs, or functions that contain SELECTs, in the policy
273    expressions. Be aware however that such accesses can create race
274    conditions that could allow information leakage if care is not taken.
275    As an example, consider the following table design:
276 -- definition of privilege groups
277 CREATE TABLE groups (group_id int PRIMARY KEY,
278                      group_name text NOT NULL);
279
280 INSERT INTO groups VALUES
281   (1, 'low'),
282   (2, 'medium'),
283   (5, 'high');
284
285 GRANT ALL ON groups TO alice;  -- alice is the administrator
286 GRANT SELECT ON groups TO public;
287
288 -- definition of users' privilege levels
289 CREATE TABLE users (user_name text PRIMARY KEY,
290                     group_id int NOT NULL REFERENCES groups);
291
292 INSERT INTO users VALUES
293   ('alice', 5),
294   ('bob', 2),
295   ('mallory', 2);
296
297 GRANT ALL ON users TO alice;
298 GRANT SELECT ON users TO public;
299
300 -- table holding the information to be protected
301 CREATE TABLE information (info text,
302                           group_id int NOT NULL REFERENCES groups);
303
304 INSERT INTO information VALUES
305   ('barely secret', 1),
306   ('slightly secret', 2),
307   ('very secret', 5);
308
309 ALTER TABLE information ENABLE ROW LEVEL SECURITY;
310
311 -- a row should be visible to/updatable by users whose security group_id is
312 -- greater than or equal to the row's group_id
313 CREATE POLICY fp_s ON information FOR SELECT
314   USING (group_id <= (SELECT group_id FROM users WHERE user_name = current_user)
315 );
316 CREATE POLICY fp_u ON information FOR UPDATE
317   USING (group_id <= (SELECT group_id FROM users WHERE user_name = current_user)
318 );
319
320 -- we rely only on RLS to protect the information table
321 GRANT ALL ON information TO public;
322
323    Now suppose that alice wishes to change the “slightly secret”
324    information, but decides that mallory should not be trusted with the
325    new content of that row, so she does:
326 BEGIN;
327 UPDATE users SET group_id = 1 WHERE user_name = 'mallory';
328 UPDATE information SET info = 'secret from mallory' WHERE group_id = 2;
329 COMMIT;
330
331    That looks safe; there is no window wherein mallory should be able to
332    see the “secret from mallory” string. However, there is a race
333    condition here. If mallory is concurrently doing, say,
334 SELECT * FROM information WHERE group_id = 2 FOR UPDATE;
335
336    and her transaction is in READ COMMITTED mode, it is possible for her
337    to see “secret from mallory”. That happens if her transaction reaches
338    the information row just after alice's does. It blocks waiting for
339    alice's transaction to commit, then fetches the updated row contents
340    thanks to the FOR UPDATE clause. However, it does not fetch an updated
341    row for the implicit SELECT from users, because that sub-SELECT did not
342    have FOR UPDATE; instead the users row is read with the snapshot taken
343    at the start of the query. Therefore, the policy expression tests the
344    old value of mallory's privilege level and allows her to see the
345    updated row.
346
347    There are several ways around this problem. One simple answer is to use
348    SELECT ... FOR SHARE in sub-SELECTs in row security policies. However,
349    that requires granting UPDATE privilege on the referenced table (here
350    users) to the affected users, which might be undesirable. (But another
351    row security policy could be applied to prevent them from actually
352    exercising that privilege; or the sub-SELECT could be embedded into a
353    security definer function.) Also, heavy concurrent use of row share
354    locks on the referenced table could pose a performance problem,
355    especially if updates of it are frequent. Another solution, practical
356    if updates of the referenced table are infrequent, is to take an ACCESS
357    EXCLUSIVE lock on the referenced table when updating it, so that no
358    concurrent transactions could be examining old row values. Or one could
359    just wait for all concurrent transactions to end after committing an
360    update of the referenced table and before making changes that rely on
361    the new security situation.
362
363    For additional details see CREATE POLICY and ALTER TABLE.