mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-03-13 19:57:53 +08:00
Make BYPASSRLS behave like superuser RLS bypass.
Specifically, make its effect independent from the row_security GUC, and make it affect permission checks pertinent to views the BYPASSRLS role owns. The row_security GUC thereby ceases to change successful-query behavior; it can only make a query fail with an error. Back-patch to 9.5, where BYPASSRLS was introduced.
This commit is contained in:
parent
23fc0b485d
commit
3cb0a7e75a
@ -1454,7 +1454,7 @@
|
||||
<entry><structfield>rolbypassrls</structfield></entry>
|
||||
<entry><type>bool</type></entry>
|
||||
<entry>
|
||||
Role can bypass row level security policies, see
|
||||
Role bypasses every row level security policy, see
|
||||
<xref linkend="ddl-rowsecurity"> for more information.
|
||||
</entry>
|
||||
</row>
|
||||
@ -9413,7 +9413,7 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx
|
||||
<entry><type>bool</type></entry>
|
||||
<entry></entry>
|
||||
<entry>
|
||||
User can bypass row level security policies, see
|
||||
User bypasses every row level security policy, see
|
||||
<xref linkend="ddl-rowsecurity"> for more information.
|
||||
</entry>
|
||||
</row>
|
||||
@ -9888,7 +9888,7 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx
|
||||
<entry><structfield>usebypassrls</structfield></entry>
|
||||
<entry><type>bool</type></entry>
|
||||
<entry>
|
||||
User can bypass row level security policies, see
|
||||
User bypasses every row level security policy, see
|
||||
<xref linkend="ddl-rowsecurity"> for more information.
|
||||
</entry>
|
||||
</row>
|
||||
|
@ -5591,22 +5591,15 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv;
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
This variable controls if row security policies are to be applied
|
||||
to queries which are run against tables that have row security enabled.
|
||||
The default is <literal>on</>. When set to <literal>on</>, all users,
|
||||
except superusers and the owner of the table, will have the row
|
||||
policies for the table applied to their queries. When set to
|
||||
<literal>off</>, queries will bypass row policies for the table, if
|
||||
possible, and error if not.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
For a user who is not a superuser and not the table owner to bypass
|
||||
row policies for the table, they must have the <literal>BYPASSRLS</>
|
||||
role attribute. If this is set to <literal>off</> and the user queries
|
||||
a table which has row policies enabled and the user does not have the
|
||||
right to bypass row policies then a permission denied error will be
|
||||
returned.
|
||||
This variable controls whether to raise an error in lieu of applying a
|
||||
row security policy. When set to <literal>on</>, policies apply
|
||||
normally. When set to <literal>off</>, queries fail which would
|
||||
otherwise apply at least one policy. The default is <literal>on</>.
|
||||
Change to <literal>off</> where limited row visibility could cause
|
||||
incorrect results; for example, <application>pg_dump</> makes that
|
||||
change by default. This variable has no effect on roles which bypass
|
||||
every row security policy, to wit, superusers and roles with
|
||||
the <literal>BYPASSRLS</> attribute.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
|
@ -1543,8 +1543,12 @@ REVOKE ALL ON accounts FROM PUBLIC;
|
||||
Row security policies can be specific to commands, or to roles, or to
|
||||
both. The commands available are <literal>ALL</literal>,
|
||||
<literal>SELECT</>, <literal>INSERT</>, <literal>UPDATE</>, and
|
||||
<literal>DELETE</>. Multiple roles can be assigned to a given policy
|
||||
and normal role membership and inheritance rules apply.
|
||||
<literal>DELETE</>. Multiple roles can be assigned to a given policy and
|
||||
normal role membership and inheritance rules apply. Table owners,
|
||||
superusers, and roles with the <literal>BYPASSRLS</> attribute bypass the
|
||||
row security system when querying a table. Applications that expect to
|
||||
bypass all row security through those mechanisms should
|
||||
set <xref linkend="guc-row-security"> to <literal>off</>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -1574,17 +1578,6 @@ REVOKE ALL ON accounts FROM PUBLIC;
|
||||
<xref linkend="sql-altertable"> command.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The table owners and superusers bypass the row security system when
|
||||
querying a table. Any user can request that row security be bypassed by
|
||||
setting <xref linkend="guc-row-security"> to <literal>off</literal>. If
|
||||
the user does not have privileges to bypass row security when querying a
|
||||
given table then an error will be returned instead. Other users can be
|
||||
granted the ability to bypass the row security system with
|
||||
the <literal>BYPASSRLS</literal> role attribute. This attribute can only
|
||||
be set by a superuser.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Each policy has a name and multiple policies can be defined for a
|
||||
table. As policies are table-specific, each policy for a table must
|
||||
|
@ -196,16 +196,13 @@ CREATE ROLE <replaceable class="PARAMETER">name</replaceable> [ [ WITH ] <replac
|
||||
<term><literal>NOBYPASSRLS</literal></term>
|
||||
<listitem>
|
||||
<para>
|
||||
These clauses determine whether a role is allowed to bypass row-level security (RLS)
|
||||
policies. A role having the <literal>BYPASSRLS</literal> attribute will
|
||||
be allowed to bypass row-security policies by setting
|
||||
<literal>row_security</literal> to
|
||||
<literal>OFF</literal>. <literal>NOBYPASSRLS</literal> is the default.
|
||||
These clauses determine whether a role bypasses every row-level
|
||||
security (RLS) policy. <literal>NOBYPASSRLS</literal> is the default.
|
||||
Note that pg_dump will set <literal>row_security</literal> to
|
||||
<literal>OFF</literal> by default, to ensure all contents of a table are
|
||||
dumped out. If the user running pg_dump does not have appropriate
|
||||
permissions, an error will be returned. The superuser and owner of the
|
||||
table being dumped are considered to always have the right to bypass RLS.
|
||||
table being dumped always bypass RLS.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
@ -40,10 +40,8 @@ extern int check_enable_rls(Oid relid, Oid checkAsUser, bool noError);
|
||||
* for the table and the plan cache needs to be invalidated if the environment
|
||||
* changes.
|
||||
*
|
||||
* Handle checking as another role via checkAsUser (for views, etc). Note that
|
||||
* if *not* checking as another role, the caller should pass InvalidOid rather
|
||||
* than GetUserId(). Otherwise the check for row_security = OFF is skipped, and
|
||||
* so we may falsely report that RLS is active when the user has bypassed it.
|
||||
* Handle checking as another role via checkAsUser (for views, etc). Pass
|
||||
* InvalidOid to check the current user.
|
||||
*
|
||||
* If noError is set to 'true' then we just return RLS_ENABLED instead of doing
|
||||
* an ereport() if the user has attempted to bypass RLS and they are not
|
||||
@ -78,32 +76,19 @@ check_enable_rls(Oid relid, Oid checkAsUser, bool noError)
|
||||
return RLS_NONE;
|
||||
|
||||
/*
|
||||
* Check permissions
|
||||
*
|
||||
* Table owners always bypass RLS. Note that superuser is always
|
||||
* considered an owner. Return RLS_NONE_ENV to indicate that this
|
||||
* decision depends on the environment (in this case, the user_id).
|
||||
* Table owners and BYPASSRLS users bypass RLS. Note that a superuser
|
||||
* qualifies as both. Return RLS_NONE_ENV to indicate that this decision
|
||||
* depends on the environment (in this case, the user_id).
|
||||
*/
|
||||
if (pg_class_ownercheck(relid, user_id))
|
||||
if (pg_class_ownercheck(relid, user_id) ||
|
||||
has_bypassrls_privilege(user_id))
|
||||
return RLS_NONE_ENV;
|
||||
|
||||
/*
|
||||
* If the row_security GUC is 'off', check if the user has permission to
|
||||
* bypass RLS. row_security is always considered 'on' when querying
|
||||
* through a view or other cases where checkAsUser is valid.
|
||||
*/
|
||||
if (!row_security && !checkAsUser)
|
||||
{
|
||||
if (has_bypassrls_privilege(user_id))
|
||||
/* OK to bypass */
|
||||
return RLS_NONE_ENV;
|
||||
else if (noError)
|
||||
return RLS_ENABLED;
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("insufficient privilege to bypass row security.")));
|
||||
}
|
||||
/* row_security GUC says to bypass RLS, but user lacks permission */
|
||||
if (!row_security && !noError)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("insufficient privilege to bypass row security.")));
|
||||
|
||||
/* RLS should be fully enabled for this relation. */
|
||||
return RLS_ENABLED;
|
||||
|
@ -51,7 +51,7 @@ CATALOG(pg_authid,1260) BKI_SHARED_RELATION BKI_ROWTYPE_OID(2842) BKI_SCHEMA_MAC
|
||||
bool rolcreatedb; /* allowed to create databases? */
|
||||
bool rolcanlogin; /* allowed to log in as session user? */
|
||||
bool rolreplication; /* role used for streaming replication */
|
||||
bool rolbypassrls; /* allowed to bypass row level security? */
|
||||
bool rolbypassrls; /* bypasses row level security? */
|
||||
int32 rolconnlimit; /* max connections allowed (-1=no limit) */
|
||||
|
||||
/* remaining fields may be null; use heap_getattr to read them! */
|
||||
|
@ -2584,10 +2584,15 @@ COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ','; --ok
|
||||
SET row_security TO ON;
|
||||
COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ','; --ok
|
||||
0,cfcd208495d565ef66e7dff9f98764da
|
||||
1,c4ca4238a0b923820dcc509a6f75849b
|
||||
2,c81e728d9d4c2f636f067f89cc14862c
|
||||
3,eccbc87e4b5ce2fe28308fd9f2a7baf3
|
||||
4,a87ff679a2f3e71d9181a67b7542122c
|
||||
5,e4da3b7fbbce2345d7772b0674a318d5
|
||||
6,1679091c5a880faf6fb5e6087eb1b2dc
|
||||
7,8f14e45fceea167a5a36dedd4bea2543
|
||||
8,c9f0f895fb98ab9159f51fd0297e236d
|
||||
9,45c48cce2e2d7fbdea1afc51c7c6ad26
|
||||
10,d3d9446802a44259755d38e6d163e820
|
||||
-- Check COPY TO as user without permissions. SET row_security TO OFF;
|
||||
SET SESSION AUTHORIZATION rls_regress_user2;
|
||||
@ -2627,6 +2632,7 @@ COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --ok
|
||||
1,c4ca4238a0b923820dcc509a6f75849b
|
||||
SET row_security TO ON;
|
||||
COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --ok
|
||||
1,c4ca4238a0b923820dcc509a6f75849b
|
||||
-- Check COPY TO as user without permissions. SET row_security TO OFF;
|
||||
SET SESSION AUTHORIZATION rls_regress_user2;
|
||||
SET row_security TO OFF;
|
||||
@ -2650,14 +2656,10 @@ SET row_security TO ON;
|
||||
COPY copy_t FROM STDIN; --fail - COPY FROM not supported by RLS.
|
||||
ERROR: COPY FROM not supported with row level security.
|
||||
HINT: Use direct INSERT statements instead.
|
||||
-- Check COPY TO as user with permissions and BYPASSRLS
|
||||
-- Check COPY FROM as user with permissions and BYPASSRLS
|
||||
SET SESSION AUTHORIZATION rls_regress_exempt_user;
|
||||
SET row_security TO OFF;
|
||||
COPY copy_t FROM STDIN; --ok
|
||||
SET row_security TO ON;
|
||||
COPY copy_t FROM STDIN; --fail - COPY FROM not supported by RLS.
|
||||
ERROR: COPY FROM not supported with row level security.
|
||||
HINT: Use direct INSERT statements instead.
|
||||
COPY copy_t FROM STDIN; --ok
|
||||
-- Check COPY FROM as user without permissions.
|
||||
SET SESSION AUTHORIZATION rls_regress_user2;
|
||||
SET row_security TO OFF;
|
||||
|
@ -1070,17 +1070,15 @@ COPY copy_t FROM STDIN; --fail - insufficient privilege to bypass rls.
|
||||
SET row_security TO ON;
|
||||
COPY copy_t FROM STDIN; --fail - COPY FROM not supported by RLS.
|
||||
|
||||
-- Check COPY TO as user with permissions and BYPASSRLS
|
||||
-- Check COPY FROM as user with permissions and BYPASSRLS
|
||||
SET SESSION AUTHORIZATION rls_regress_exempt_user;
|
||||
SET row_security TO OFF;
|
||||
SET row_security TO ON;
|
||||
COPY copy_t FROM STDIN; --ok
|
||||
1 abc
|
||||
2 bcd
|
||||
3 cde
|
||||
4 def
|
||||
\.
|
||||
SET row_security TO ON;
|
||||
COPY copy_t FROM STDIN; --fail - COPY FROM not supported by RLS.
|
||||
|
||||
-- Check COPY FROM as user without permissions.
|
||||
SET SESSION AUTHORIZATION rls_regress_user2;
|
||||
|
Loading…
x
Reference in New Issue
Block a user