组的行级安全性或使组可以访问行

Posted

技术标签:

【中文标题】组的行级安全性或使组可以访问行【英文标题】:Row level security for groups or Making rows accebile to groups 【发布时间】:2018-12-26 07:23:43 【问题描述】:

我希望只有组成员可以访问表中的行。我通过以下方法创建用户并将他们添加到组中,

CREATE USER abc LOGIN PASSWORD 'securedpassword1';
CREATE USER xyz LOGIN PASSWORD 'securedpassword2';

ALTER GROUP permanent ADD USER abc;

然后,我编写的策略使其只有当前用户可以访问。但我需要整个小组才能访问它。

CREATE TABLE table_Workers
(
    worID INT
    ,worName CHARACTER VARYING
    ,pgUser CHARACTER VARYING
);
INSERT INTO table_Workers VALUES 
(1,'Jason','abc'),(2,'Roy','abc'),(3,'Johny','abc')
,(4,'Jane','xyz'),(5,'Kane','xyz'),(6,'Stuart','xyz');


CREATE POLICY policy_employee_user ON table_Workers FOR ALL
TO PUBLIC USING (pgUser = current_user);

ALTER TABLE table_Workers ENABLE ROW LEVEL SECURITY;

pgUser 命名可以访问该行的用户。我希望用 pgRole 替换列 pgUser,其中提到了组的名称,其成员可以访问该特定行。任何提示或方法都可以使整个组都可以访问行。

【问题讨论】:

不确定语法,但可能是using (pg_has_role(current_user, 'permanent')) pgUser 这里是提到可以访问该行的用户名的列。如果 current_user 和 pgUser 都具有相同的值,则可以访问行。现在有一个名为 pgRole 或 pgGroup 的列。我想用它来检查当前用户是否在 pgGroup 列中提到的那个组中。因此用户可以访问相应的行。这样不同的用户可以访问他们需要的不同行。 您在问题中包含了表 table_workers 的完整 create table 语句(edit 您的问题在 cmets 中邮政编码)。但看来你应该可以使用pg_has_role(pguser, pgrole)然后 好的。我已经相应地编辑了这个问题。但如果我使用列 pgRole,我必须删除列 pgUser。我希望你的意思是pg_has_role(current_user, pgrole) 这里。 pgRole 将有两个组,包括“永久”和“临时” 感谢您的及时回复。我提到我需要将pgUser 列替换为pgRole。将输入组名的位置。我的目标是让这些组的成员能够访问相应的行。 【参考方案1】:

这似乎有效:

CREATE TABLE workers
(
    worid   int,
    worname text,
    pgrole text[]
);

INSERT INTO workers 
VALUES 
  (1,'Jason','group1'),
  (2,'Roy','group1,group2'),
  (3,'Johny','group1');

CREATE POLICY policy_employee_user ON workers FOR ALL
TO PUBLIC 
   USING ( (select count(*) 
            from unnest(pgrole) r 
            where pg_has_role(current_user, r, 'MEMBER')) > 0 );

ALTER TABLE workers ENABLE ROW LEVEL SECURITY;

【讨论】:

太棒了!非常感谢。这就像一颗宝石。虽然我不了解策略命令中的完整逻辑,但它正在工作。我需要花一些时间来正确理解它。 人员信息,当然我们需要在这里创建具有适当用户的群组group 1group 2。然后 grant selectinsert 相应组的权限。【参考方案2】:
db=# create table rls(i int);
CREATE TABLE
Time: 189.439 ms
db=# alter table rls enable row level security ;
ALTER TABLE
Time: 12.725 ms
db=# insert into rls values(1);
INSERT 0 1
Time: 13.241 ms
db=# create user member;
CREATE ROLE
Time: 11.882 ms
db=# create role rls_r;
CREATE ROLE
Time: 9.378 ms
db=# grant rls_r to member ;
GRANT ROLE
Time: 5.704 ms
db=# CREATE POLICY p ON rls FOR ALL TO PUBLIC USING ((select count(*)=1 from pg_auth_members where member = current_user::regrole));
CREATE POLICY
Time: 32.471 ms

现在检查:

db=# set role ro ;
SET
Time: 0.350 ms
db=> select * from rls;
 i
---
(0 rows)

Time: 9.801 ms
db=> set role member;
SET
Time: 0.494 ms
db=> select * from rls;
 i
---
 1
(1 row)

Time: 0.694 ms

似乎有效...

为什么会有这样的规定?

当你 du role 时,记住 Member of 在 psql 中带有数组?.. 所以只是:

MacBook-Air:~ vao$ psql db -E
Timing is on.
Pager usage is off.
psql (9.6.1)
Type "help" for help.

db=# \du ro
********* QUERY **********
SELECT r.rolname, r.rolsuper, r.rolinherit,
  r.rolcreaterole, r.rolcreatedb, r.rolcanlogin,
  r.rolconnlimit, r.rolvaliduntil,
  ARRAY(SELECT b.rolname
        FROM pg_catalog.pg_auth_members m
        JOIN pg_catalog.pg_roles b ON (m.roleid = b.oid)
        WHERE m.member = r.oid) as memberof
, r.rolreplication
, r.rolbypas-s-rls
FROM pg_catalog.pg_roles r
WHERE r.rolname ~ '^(ro)$'
ORDER BY 1;
**************************

            List of roles
 Role name |  Attributes  | Member of
-----------+--------------+-----------
 ro        | Cannot login | 

然后您会看到所需的查询

【讨论】:

感谢您的回答。我需要来自不同组的用户能够访问他们各自的行。因此,我在表中有一个单独的列,它将具有可以访问它的组的名称。将用户组与该列的值进行比较。如果组的名称与该组的成员可以访问的名称相同。我无法比较您建议的政策中的该组列。这是我觉得可以按特定组定义特定行的可访问性的唯一方法。

以上是关于组的行级安全性或使组可以访问行的主要内容,如果未能解决你的问题,请参考以下文章

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

SQL Server 数据库中使用扩展属性的动态行级安全性

使用 MS SQL 的 JAX-RS 中的行级安全性

SQL Server 2019 中 Polybase 外部表的行级安全性可能吗?

Postgres 规范化表上的行级安全性

[译] PostgreSQL 行安全性策略