PostgreSQL中多个角色的行级安全性

时间:2019-07-16 15:18:57

标签: postgresql postgresql-11 row-level-security

我正在尝试在Postgres中实现行级安全性。实际上,我有很多角色,但是出于这个问题的考虑,有四个角色:executivedirectormanagerjunior。我有一张看起来像这样的桌子:

SELECT * FROM ex_schema.residence; --as superuser

  primary_key  |   residence   | security_level
------------------+---------------+--------------
             5 | Time-Share    | executive
             1 | Single-Family | junior
             2 | Multi-Family  | director
             4 | Condominium   | manager
             6 | Modular       | junior
             3 | Townhouse     | director

我编写了一个启用行级安全性的策略,如下所示:

CREATE POLICY residence_policy
ON ex_schema.residence
FOR ALL
USING (security_level = CURRENT_USER)
WITH CHECK (primary_key IS NOT NULL AND security_level = CURRENT_USER);

如预期的那样,当executive连接到数据库并选择表时,该角色只会看到executive列中具有security_level的行。我想做的是启用行级安全性,以便更高安全性的角色可以看到与其安全级别相匹配的行以及具有较低安全性特权的行。层次结构如下所示:

ROW ACCESS PER ROLE
executive: executive, director, manager, junior
director: director, manager, junior
manager: manager, junior
junior: junior 

我想知道如何实现这种类型的行级策略,以便特定角色可以访问多种类型的安全级别。更改security_level列结构和数据类型具有灵活性。

1 个答案:

答案 0 :(得分:1)

您可以做的一件事就是为您的级别定义一个枚举类型:

CREATE TYPE sec_level AS ENUM
   ('junior', 'manager', 'director', 'executive');

然后,您可以在security_level列中使用该类型,并将策略写为

CREATE POLICY residence_policy ON ex_schema.residence
   FOR ALL
   USING (security_level >= CURRENT_USER::sec_level);

无需检查主键是否为NULL,无论如何都会产生错误。

仅当您知道这些级别不会更改,尤其是不会删除任何级别时,才使用枚举类型。

或者,您可以使用查找表:

CREATE TABLE sec_level
   name text PRIMARY KEY,
   rank double precision UNIQUE NOT NULL
);

security_level将成为sec_level(rank)的外键,您可以像以前一样比较策略中的值。您将需要与查找表进行额外的连接,但是您可以删除级别。