合 PG行级安全策略RLS
简介
RLS(ROW Level Security) 是PostgreSQL 9.5版本中新增特性,提供了基于行的安全策略,限制数据库用户的查看表数据权限。要知道在9.5版本之前,数据库中对用户的权限管控在表级别,例如:限制某个用户只能查询某个表。采用RLS后,不同的用户访问一个表可以看到不同的数据。
我们在一般的数据库中可能对用户的查询权限只能到表级别,例如限制某个用户只能查询哪些表。PostgreSQL从9.5版本开始支持行级别的权限管控,允许不同的用户在表上查询到不同的数据。
默认的话,表没有任何安全策略限制。这样用户根据 SQL 特权系统具有对表的访问特权,对于查询或更新来说其中所有的行都是平等的。当在一个表上启用行安全性时,所有对该表选择行或者修改行的普通访问都必须被一条 行安全性策略所允许(不过,表的拥有者通常不服从行安全性策略)。如果表上不存在安全策略,如果没有配置安全策略,所有的数据查询和更新都会禁止,但是对全表进行操作的命令,比如 TRUNCATE 和 REFERENCES 不受影响。
行安全性策略可以针对特定的命令、角色或者两者。一条策略可以被指定为适用于ALL命令,或者查询(SELECT)、 插入(INSERT)、更新(UPDATE)或者删除(DELETE)。同一个策略可分配多个角色,并且通常的角色成员关系和继承规则也适用。但是表的所有者,超级用户 (postgres) 以及加上了 BYPASSRLS 属性的角色不受安全性的限制。
只有所有者才具有启用 禁用行级安全性,给表添加策略的权限。
常见命令:
- CREATE POLICY :创建策略
- ALTER POLICY :修改策略
- DROP POLICY :删除策略
- ALTER TABLE :用于行级安全性的启用 禁用。
每个策略都有一个名字,每个表可以定义多个策略,因为策略是针对表的,所以表内的多个策略名字必须唯一,但是不同的表可以有同名的策略,当表有多个策略时,多个策略之间是 OR 的关系。
除可以通过GRANT使用 SQL 标准的 特权系统之外,表还可以具有 行安全性策略,它针对每一个用户限制哪些行可以 被普通的查询返回或者可以被数据修改命令插入、更新或删除。这种 特性也被称为行级安全性。默认情况下,表不具有 任何策略,这样用户根据 SQL 特权系统具有对表的访问特权,对于 查询或更新来说其中所有的行都是平等的。
当在一个表上启用行安全性时(使用 ALTER TABLE ... ENABLE ROW LEVEL SECURITY),所有对该表选择行或者修改行的普通访问都必须被一条 行安全性策略所允许(不过,表的拥有者通常不服从行安全性策略)。如果 表上不存在策略,将使用一条默认的否定策略,即所有的行都不可见或者不能 被修改。应用在整个表上的操作不服从行安全性,例如TRUNCATE
和 REFERENCES
。
行安全性策略可以针对特定的命令、角色或者两者。一条策略可以被指定为 适用于ALL
命令,或者SELECT
、 INSERT
、UPDATE
、或者DELETE
。 可以为一条给定策略分配多个角色,并且通常的角色成员关系和继承规则也适用。
要指定哪些行根据一条策略是可见的或者是可修改的,需要一个返回布尔结果 的表达式。对于每一行,在计算任何来自用户查询的条件或函数之前,先会计 算这个表达式(这条规则的唯一例外是leakproof
函数, 它们被保证不会泄露信息,优化器可能会选择在行安全性检查之前应用这类 函数)。使该表达式不返回true
的行将不会被处理。可以指定 独立的表达式来单独控制哪些行可见以及哪些行被允许修改。策略表达式会作 为查询的一部分运行并且带有运行该查询的用户的特权,但是安全性定义者函数 可以被用来访问对调用用户不可用的数据。
具有BYPASSRLS
属性的超级用户和角色在访问一个表时总是 可以绕过行安全性系统。表拥有者通常也能绕过行安全性,不过表拥有者 可以选择用ALTER TABLE ... FORCE ROW LEVEL SECURITY来服从行安全性。
启用和禁用行安全性以及向表增加策略是只有表拥有者具有的特权。
策略的创建可以使用CREATE POLICY命令,策略的修改 可以使用ALTER POLICY命令,而策略的删除可以使用 DROP POLICY命令。要为一个给定表启用或者禁用行 安全性,可以使用ALTER TABLE命令。
每一条策略都有名称并且可以为一个表定义多条策略。由于策略是表相 关的,一个表的每一条策略都必须有一个唯一的名称。不同的表可以拥有 相同名称的策略。
当多条策略适用于一个给定的查询时,会把它们用OR
(对宽容性策略,默认的策略类型)或者AND
(对限制性策略)组合在一起。这和给定角色拥有它作为成员的所有角色的特权的规则类似。宽容性策略和限制性策略在下文将会进一步讨论。
CREATE POLICY
CREATE POLICY — 为一个表定义一条新的行级安全性策略
大纲
1 2 3 4 5 6 | CREATE POLICY name ON table_name [ AS { PERMISSIVE | RESTRICTIVE } ] [ FOR { ALL | SELECT | INSERT | UPDATE | DELETE } ] [ TO { role_name | PUBLIC | CURRENT_USER | SESSION_USER } [, ...] ] [ USING ( using_expression ) ] [ WITH CHECK ( check_expression ) ] |
描述
CREATE POLICY
为一个表定义一条行级 安全性策略。注意为了应用已被创建的策略,在表上必须启用行级安全 性(使用ALTER TABLE ... ENABLE ROW LEVEL SECURITY
)。
一条策略授予权限以选择、插入、更新或者删除匹配相关策略表达式的行。 现有的表行会按照USING
中指定的表达式进行检查, 而将要通过INSERT
或UPDATE
创建 的新行会按照WITH CHECK
中指定的表达式进行检查。 当USING
表达式对于一个给定行返回真时,该行对用户 可见,而返回假或空时该行不可见。当一个WITH CHECK
表达式对一行返回真时,该行会被插入或更新,而如果返回假或空时会发生 一个错误。
对于INSERT
和 UPDATE
语句,在BEFORE
触发器被引发后并且在任何数据修改真正发生之前, WITH CHECK
表达式会被强制。因此, 一个BEFORE ROW
触发器可以修改要被插入的数据, 从而影响安全性策略检查的结果。WITH CHECK
表达式 在任何其他约束之前被强制。
策略名称是针对每个表的。因此,一个策略名称可以被用于很多个不同的表 并且对于不同的表呈现适合于该表的定义。
策略可以被应用于特定的命令或者特定的角色。除非特别指定,新创建的策略 的默认行为是适用于所有命令和角色。多个策略可以应用于单个命令,更多细节请见下文。表 272总结了不同类型的策略如何应用于特定的命令。
对同时具有USING
和WITH CHECK
表达式(ALL
和UPDATE
)的策略, 如果没有定义WITH CHECK
表达式,那么 USING
表达式将被用于决定哪些行可见(普通 USING
情况)以及允许哪些新行被增加( WITH CHECK
情况)。
如果为一个表启用了行级安全性但是没有适用的策略存在,将假定为一种 “默认否定”策略,这样任何行都不可见也不可更新。
参数
name
要创建的策略的名称。这必须和该表上已有的任何其他策略名称相区分。
table_name
该策略适用的表的名称(可以被模式限定)。
PERMISSIVE
指定策略被创建为宽容性策略。适用于一个给定查询的所有宽容性策略将被使用布尔“OR”操作符组合在一起。通过创建宽容性策略,管理员可以在能被访问的记录集合中进行增加。策略默认是宽容性的。
RESTRICTIVE
指定策略被创建为限制性策略。适用于一个给定查询的所有限制性策略将被使用布尔“AND”操作符组合在一起。通过创建限制性策略,管理员可以减少能被访问的记录集合,因为每一条记录都必须通过所有的限制性策略。注意在限制性策略真正能发挥作用减少访问之前,需要至少一条宽容性策略来授予对记录的访问。如果只有限制性策略存在,则没有记录能被访问。当宽容性和限制性策略混合存在时,只有当一个记录能通过至少一条宽容性策略以及所有的限制性策略时,该记录才是可访问的。
command
该策略适用的命令。合法的选项是
ALL
、SELECT
、INSERT
、UPDATE
以及DELETE
。ALL
为默认。有关这些策略如何被应用的 细节见下文。role_name
该策略适用的角色。默认是
PUBLIC
,它将把策略应用 到所有的角色。using_expression
本人提供Oracle(OCP、OCM)、MySQL(OCP)、PostgreSQL(PGCA、PGCE、PGCM)等数据库的培训和考证业务,私聊QQ646634621或微信db_bao,谢谢!