针对特定用户的 PostgreSQL RLS 策略未按预期工作并适用于所有用户

Posted

技术标签:

【中文标题】针对特定用户的 PostgreSQL RLS 策略未按预期工作并适用于所有用户【英文标题】:PostgreSQL RLS policy to specific user is not working as expected and applies to all users 【发布时间】:2020-03-03 14:03:53 【问题描述】:

我的数据库中有 2 个用户,一个是“强”,一个是“弱”。 我只想为其中一个弱用户应用 RLS 策略。 这意味着,当强用户查询表时,它应该获取所有行。但是当弱用户查询该表时,该策略将被应用,它只会返回允许的行。

我创建了一个表,并将 RLS 策略仅应用于弱用户。 但即使在使用强用户进行查询时,也会执行该策略并阻止我获取所有行。 我使用的是 PostgreSQL 版本 11.4。

这是我创建策略的方式(我已经与另一个第三个用户创建了策略,该用户是管理员和表的所有者)

CREATE TABLE account_test
(
    id bigserial not null,
    description varchar(200),
    tenant_id UUID not null
);
ALTER TABLE account_test ENABLE ROW LEVEL SECURITY;
CREATE POLICY tenant_policy ON account_test TO weak_user
                        USING (tenant_id = current_setting('rls.tenant_id')::uuid);

account=# select * from pg_policies;

 schemaname |  tablename   |  policyname   | permissive |     roles     | cmd |                             qual                             | with_check
------------+--------------+---------------+------------+---------------+-----+--------------------------------------------------------------+------------
 account    | account_test | tenant_policy | PERMISSIVE | **weak_user**   | ALL | (tenant_id = (current_setting('rls.tenant_id'::text))::uuid) |

现在,使用管理员用户插入和选择始终有效,因为它是所有者:

insert into account_test (description, tenant_id) VALUES ('desc111', '11111111-c929-462e-ade4-074c81643191');
select * from account_test;  

这里没问题,所有行都返回了。

当尝试使用weak_user 登录并选择时,我没有得到预期的行:

select * from account_test; 
-- returns 0 rows as expected (weak_user).

如果我设置了参数,则应用策略并且我按预期获取数据:

select set_config('rls.tenant_id', '11111111-c929-462e-ade4-074c81643191',true);
select * from account_test; 
-- returns 1 row as expected

现在,当我使用strong_user 登录并执行select * from account_test 查询时,我希望返回所有行,因为策略仅适用于weak_user。 但是,我得到与weak_user 相同的行为,并且没有行返回。 使用 set_config 的查询也不返回任何内容。

我错过了什么?

这是预期的行为吗?

谁能解释一下?

【问题讨论】:

【参考方案1】:

当您在具有ALTER TABLE account_test ENABLE ROW LEVEL SECURITY 的表上启用 RLS 时,所有用户都会使用默认拒绝所有策略。

在表上启用 [RLS] 时,行安全策略必须允许对表进行所有正常访问以选择行或修改行。 (但是,表的所有者通常不受行安全策略的约束。)如果表不存在策略,则使用默认拒绝策略,这意味着没有行可见或可以修改。

– https://www.postgresql.org/docs/current/ddl-rowsecurity.html

每个策略都有一个名称,并且可以为一个表定义多个策略。由于策略是特定于表的,因此表的每个策略都必须具有唯一的名称。不同的表可能有同名的策略。

为了让strong_user 能够访问,您需要添加另一个规则,例如

CREATE POLICY tenant_policy ON account_test TO strong_user USING (true);

当多个策略应用于给定查询时,它们会使用 OR(对于默认的许可策略)或 AND(对于限制性策略)进行组合。这类似于给定角色拥有其所属的所有角色的权限的规则。下文将进一步讨论许可政策与限制政策。

【讨论】:

感谢@Gajus 提供详细且解释清楚的答案。

以上是关于针对特定用户的 PostgreSQL RLS 策略未按预期工作并适用于所有用户的主要内容,如果未能解决你的问题,请参考以下文章

[译] PostgreSQL 行安全性策略

postgresql的安装与基础语法

postgresql的安装与基础语法

[译] PostgreSQL 行安全性策略

通过将安全视图分配给角色并提供针对多个条件的过滤器,在 Snowflake 上实现行级安全性 (RLS)

如何实现对亚马逊 Redshift 的原始 sql 访问的行级安全性 (RLS)?