【问题标题】:Row-level security for multiple roles for hierarchy in PostgreSQLPostgreSQL 中层次结构的多个角色的行级安全性
【发布时间】:2019-11-25 09:14:54
【问题描述】:

我正在尝试在 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 连接到数据库并选择表时,该角色只能看到security_level 列中具有executive 的行。我想做的是启用行级安全性,以便更高安全性角色可以看到与其安全级别匹配的行以及具有较低安全权限的行。层次结构如下所示:

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

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

【问题讨论】:

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


    【解决方案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) 的外键,您可以像以前一样比较策略中的值。您将需要与查找表进行额外连接,但您可以删除级别。

    【讨论】:

    • 我收到第一个解决方案的错误:ERROR: operator does not exist: text >= sec_level HINT: No operator matches the given name and argument types. You might need to add explicit type casts.
    • 您要么必须明确转换为sec_level,要么按照我的建议将列的类型更改为sec_level
    猜你喜欢
    • 2017-08-07
    • 2019-12-09
    • 2013-11-18
    • 2012-06-16
    • 1970-01-01
    • 2012-07-11
    • 2015-02-15
    • 2010-11-19
    • 2016-10-29
    相关资源
    最近更新 更多