From af44cbd5ecd7e1db0ae4bce75c8f1bce14b1d6db Mon Sep 17 00:00:00 2001 From: Dean Rasheed Date: Wed, 27 Sep 2017 17:16:15 +0100 Subject: [PATCH] Improve the CREATE POLICY documentation. Provide a correct description of how multiple policies are combined, clarify when SELECT permissions are required, mention SELECT FOR UPDATE/SHARE, and do some other more minor tidying up. Reviewed by Stephen Frost Discussion: https://postgr.es/m/CAEZATCVrxyYbOFU8XbGHicz%2BmXPYzw%3DhfNL2XTphDt-53TomQQ%40mail.gmail.com Back-patch to 9.5. --- doc/src/sgml/ref/create_policy.sgml | 206 ++++++++++++++++++---------- 1 file changed, 134 insertions(+), 72 deletions(-) diff --git a/doc/src/sgml/ref/create_policy.sgml b/doc/src/sgml/ref/create_policy.sgml index c0dfe1ea4b..70df22c059 100644 --- a/doc/src/sgml/ref/create_policy.sgml +++ b/doc/src/sgml/ref/create_policy.sgml @@ -73,20 +73,17 @@ CREATE POLICY name ON Policies can be applied for specific commands or for specific roles. The default for newly created policies is that they apply for all commands and - roles, unless otherwise specified. If multiple policies apply to a given - statement, they will be combined using OR (although ON CONFLICT DO - UPDATE and INSERT policies are not combined in this way, but - rather enforced as noted at each stage of ON CONFLICT execution). + roles, unless otherwise specified. - For commands that can have both USING - and WITH CHECK policies (ALL + For policies that can have both USING + and WITH CHECK expressions (ALL and UPDATE), if no WITH CHECK - policy is defined, then the USING policy will be used - both for which rows are visible (normal USING case) - and for which rows will be allowed to be added (WITH - CHECK case). + expression is defined, then the USING expression will be + used both to determine which rows are visible (normal + USING case) and which new rows will be allowed to be + added (WITH CHECK case). @@ -144,6 +141,16 @@ CREATE POLICY name ON + + + Note that there needs to be at least one permissive policy to grant + access to records before restrictive policies can be usefully used to + reduce that access. If only restrictive policies exist, then no records + will be accessible. When a mix of permissive and restrictive policies + are present, a record is only accessible if at least one of the + permissive policies passes, in addition to all the restrictive + policies. + @@ -210,7 +217,7 @@ CREATE POLICY name ON - + Per-Command Policies @@ -223,8 +230,7 @@ CREATE POLICY name ON ALL policy exists and more specific policies exist, then both the ALL policy and the more - specific policy (or policies) will be combined using - OR, as usual for overlapping policies. + specific policy (or policies) will be applied. Additionally, ALL policies will be applied to both the selection side of a query and the modification side, using the USING expression for both cases if only @@ -293,11 +299,12 @@ CREATE POLICY name ON Using UPDATE for a policy means that it will apply - to UPDATE commands (or auxiliary ON - CONFLICT DO UPDATE clauses of INSERT - commands). Since UPDATE involves pulling an - existing record and then making changes to some portion (but - possibly not all) of the record, UPDATE + to UPDATE, SELECT FOR UPDATE + and SELECT FOR SHARE commands, as well as + auxiliary ON CONFLICT DO UPDATE clauses of + INSERT commands. Since UPDATE + involves pulling an existing record and replacing it with a new + modified record, UPDATE policies accept both a USING expression and a WITH CHECK expression. The USING expression determines which records @@ -306,22 +313,6 @@ CREATE POLICY name ON - - When an UPDATE command is used with a - WHERE clause or a RETURNING - clause, SELECT rights are also required on the - relation being updated and the appropriate SELECT - and ALL policies will be combined (using OR for any - overlapping SELECT related policies found) with the - USING clause of the UPDATE policy - using AND. Therefore, in order for a user to be able to - UPDATE specific rows, the user must have access - to the row(s) through a SELECT - or ALL policy and the row(s) must pass - the UPDATE policy's USING - expression. - - Any rows whose updated values do not pass the WITH CHECK expression will cause an error, and the @@ -331,21 +322,33 @@ CREATE POLICY name ON - Note, however, that INSERT with ON CONFLICT - DO UPDATE requires that an UPDATE policy - USING expression always be enforced as a - WITH CHECK expression. This - UPDATE policy must always pass when the - UPDATE path is taken. Any existing row that - necessitates that the UPDATE path be taken must - pass the (UPDATE or ALL) - USING qualifications (combined using OR), which - are always enforced as WITH CHECK - options in this context. (The UPDATE path will - never be silently avoided; an error will be thrown - instead.) Finally, the final row appended to the relation must pass - any WITH CHECK options that a conventional - UPDATE is required to pass. + Typically an UPDATE command also needs to read + data from columns in the relation being updated (e.g., in a + WHERE clause or a RETURNING + clause, or in an expression on the right hand side of the + SET clause). In this case, + SELECT rights are also required on the relation + being updated, and the appropriate SELECT or + ALL policies will be applied in addition to + the UPDATE policies. Thus the user must have + access to the row(s) being updated through a SELECT + or ALL policy in addition to being granted + permission to update the row(s) via an UPDATE + or ALL policy. + + + + When an INSERT command has an auxiliary + ON CONFLICT DO UPDATE clause, if the + UPDATE path is taken, the row to be updated is + first checked against the USING expressions of + any UPDATE policies, and then the new updated row + is checked against the WITH CHECK expressions. + Note, however, that unlike a standalone UPDATE + command, if the existing row does not pass the + USING expressions, an error will be thrown (the + UPDATE path will never be silently + avoided). @@ -364,19 +367,18 @@ CREATE POLICY name ON - When a DELETE command is used with a - WHERE clause or a RETURNING - clause, SELECT rights are also required on the - relation being updated and the appropriate SELECT - and ALL policies will be combined (using OR for any - overlapping SELECT related policies found) with the - USING clause of the DELETE policy - using AND. Therefore, in order for a user to be able to - DELETE specific rows, the user must have access - to the row(s) through a SELECT - or ALL policy and the row(s) must pass - the DELETE policy's USING - expression. + In most cases a DELETE command also needs to read + data from columns in the relation that it is deleting from (e.g., + in a WHERE clause or a + RETURNING clause). In this case, + SELECT rights are also required on the relation, + and the appropriate SELECT or + ALL policies will be applied in addition to + the DELETE policies. Thus the user must have + access to the row(s) being deleted through a SELECT + or ALL policy in addition to being granted + permission to delete the row(s) via a DELETE or + ALL policy. @@ -390,6 +392,76 @@ CREATE POLICY name ON + + + Application of Multiple Policies + + + When multiple policies of different command types apply to the same command + (for example, SELECT and UPDATE + policies applied to an UPDATE command), then the user + must have both types of permissions (for example, permission to select rows + from the relation as well as permission to update them). Thus the + expressions for one type of policy are combined with the expressions for + the other type of policy using the AND operator. + + + + When multiple policies of the same command type apply to the same command, + then there must be at least one PERMISSIVE policy + granting access to the relation, and all of the + RESTRICTIVE policies must pass. Thus all the + PERMISSIVE policy expressions are combined using + OR, all the RESTRICTIVE policy + expressions are combined using AND, and the results are + combined using AND. If there are no + PERMISSIVE policies, then access is denied. + + + + Note that, for the purposes of combining multiple policies, + ALL policies are treated as having the same type as + whichever other type of policy is being applied. + + + + For example, in an UPDATE command requiring both + SELECT and UPDATE permissions, if + there are multiple applicable policies of each type, they will be combined + as follows: + + +expression from RESTRICTIVE SELECT/ALL policy 1 +AND +expression from RESTRICTIVE SELECT/ALL policy 2 +AND +... +AND +( + expression from PERMISSIVE SELECT/ALL policy 1 + OR + expression from PERMISSIVE SELECT/ALL policy 2 + OR + ... +) +AND +expression from RESTRICTIVE UPDATE/ALL policy 1 +AND +expression from RESTRICTIVE UPDATE/ALL policy 2 +AND +... +AND +( + expression from PERMISSIVE UPDATE/ALL policy 1 + OR + expression from PERMISSIVE UPDATE/ALL policy 2 + OR + ... +) + + + + @@ -418,16 +490,6 @@ CREATE POLICY name ON - - Note that there needs to be at least one permissive policy to grant - access to records before restrictive policies can be usefully used to - reduce that access. If only restrictive policies exist, then no records - will be accessible. When a mix of permissive and restrictive policies - are present, a record is only accessible if at least one of the - permissive policies passes, in addition to all the restrictive - policies. - - Generally, the system will enforce filter conditions imposed using security policies prior to qualifications that appear in user queries, -- 2.40.0