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

rsl1atfo  于 2023-01-30  发布在  PostgreSQL
关注(0)|答案(1)|浏览(169)

我的数据库中有2个用户,一个是"强"用户,一个是"弱"用户。我只想为其中一个用户(弱用户)应用RLS策略。这意味着,当强用户查询表时,它应该获取所有行。但当弱用户查询表时,将应用该策略,它将只返回允许的行。
我已经创建了一个表,并将RLS策略只应用于弱用户。但即使在使用强用户查询时,该策略也会执行,并阻止我获取所有行。我使用的是PostgreSQL版本11.4。
下面是我创建策略的方式(我使用另一个第3个用户创建了策略,该用户既是管理员,也是表的所有者)

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) |

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

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的查询也没有返回任何内容。
我错过了什么?
这是预期行为吗?
有人能解释一下吗?

yiytaume

yiytaume1#

在使用ALTER TABLE account_test ENABLE ROW LEVEL SECURITY对表启用RLS时,将对所有用户使用default-deny all策略。
在表上启用[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(对于限制策略)组合这些策略。这类似于给定角色具有其所属的所有角色的权限的规则。下面将进一步讨论允许策略与限制策略。

相关问题