我正在尝试在Postgres中实现行级安全性。实际上,我有很多角色,但是出于这个问题的考虑,有四个角色:executive
,director
,manager
和junior
。我有一张看起来像这样的桌子:
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列结构和数据类型具有灵活性。
答案 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)
的外键,您可以像以前一样比较策略中的值。您将需要与查找表进行额外的连接,但是您可以删除级别。