PostgreSQL 中层次结构的多个角色的行级安全性

Row-level security for multiple roles for hierarchy in PostgreSQL

我正在尝试在 Postgres 中实现行级安全性。其实我有很多角色,为了这个问题,我有四个角色:executivedirectormanagerjunior。我有一个看起来像这样的 table:

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

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

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

您可以做的一件事是为关卡定义一个枚举类型:

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,无论如何都会产生错误。

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

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

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

security_level 将成为 sec_level(rank) 的外键,您可以像以前一样比较策略中的值。您将需要额外加入查找 table,但您可以删除级别。