PG 数据库安全策略层次结构:

行级安全策略概述
- 行级安全策略是提供更细粒度的访问控制,比如不同用户可以看到表中不同的数据。
- 行级安全策略可以加在表上,也可以加在角色上,也可以两者都加。命令可以是 ALL、SELECT、INSERT、UPDATE 和 DELETE,同一个策略也可以赋予多个角色。
- 超级用户(postgres)以及加上了 BYPASSRLS 属性的角色不受安全性的限制。
- 每个表可以定义多个策略,因为策略是针对表的,所以表内的多个策略名字必须唯一。
- 不同的表可以有同名的策略,当表有多个策略时,多个策略之间是 OR 的关系,所有策略中任意一个为 TRUE 都通过。
行级安全策略开关
-打开/关闭行级安全策略
ALTER TABLE tab_name ENABLE/DISABLE ROW LEVEL SECURITY;
行级安全策略创建
CREATE POLICY name ON table_name
[ AS { PERMISSIVE | RESTRICTIVE } ]
[ FOR { ALL | SELECT | INSERT | UPDATE | DELETE } ]
[ TO { role_name | PUBLIC | CURRENT_ROLE | CURRENT_USER | SESSION_USER } [, ...] ]
[ USING ( using_expression ) ]
[ WITH CHECK ( check_expression ) ]
- name:同一个表上的 policy 不能重复,不同表的 policy 可以重复。
- AS,policy 的生效模式,PERMISSIVE => or,RESTRICTIVE => and,默认 PERMISSIVE。
- FOR,对哪个操作生效,默认 ALL。
- TO,对哪个 role 生效,默认 public。
- USING:对表中的已有数据进行检查的语句,可实施在 select、update、delete、all 上。
- WITH CHECK:对新数据进行检查的语句,可实施在 insert、update、all 上。
行级安全策略删除
DROP POLICY [ IF EXISTS ] name ON table_name [ CASCADE | RESTRICT ]
CASCADE | RESTRICT 这些关键词没有任何影响,因为它们不依赖于策略。
行级安全策略修改
ALTER POLICY name ON table_name RENAME TO new_name
ALTER POLICY name ON table_name
[ TO { role_name | PUBLIC | CURRENT_ROLE | CURRENT_USER | SESSION_USER } [, ...] ]
[ USING ( using_expression ) ]
[ WITH CHECK ( check_expression ) ]
行级安全策略信息查询
行级安全策略查看:
select * from pg_policy;
查看表创建的安全策略规则:
select relname,relrowsecurity,relforcerowsecurity from pg_class where relname='tab_name';
查看某个角色跳过安全策略规则:
select rolname,rolbypassrls from pg_roles where rolname='role_name';
跳过/不跳过行级安全策略
alter user role_name bypassrls/nobypassrls;
行级安全策略实践案例
1、建模式与表
CREATE SCHEMA hisinfo;
CREATE TABLE hisinfo.patient(id int, patname name, doctname name);
INSERT INTO hisinfo.patient VALUES(1,'pat0l','doctor01');
INSERT INTO hisinfo.patient VALUES(2,'pat02','doctor02');
INSERT INTO hisinfo.patient VALUES(3,'pat03','doctor03');
2、启用行级安全策略
ALTER TABLE hisinfo.patient ENABLE ROW LEVEL SECURITY;
3、建模用户
create user doctor01 password 'kingbase';
create user doctor02 password 'kingbase';
create user doctor03 password 'kingbase';
4、授权
grant usage on schema hisinfo to doctor01;
grant usage on schema hisinfo to doctor02;
grant usage on schema hisinfo to doctor03;
grant select on hisinfo.patient to doctor01;
grant select on hisinfo.patient to doctor02;
grant select on hisinfo.patient to doctor03;
5、创建行级安全策略
create policy patient_rls on hisinfo.patient using (doctname=current_user);
6、验证
psql -U doctor01 -d postgres -c "select * from hisinfo.patient;"
psql -U doctor02 -d postgres -c "select * from hisinfo.patient;"
psql -U doctor03 -d postgres -c "select * from hisinfo.patient;"
psql -U u1 -d postgres -c "select * from hisinfo.patient;"
7、bypassrls/nobypassrls 验证
psql -Uu1 -dpostgres -c "select * from hisinfo.patient;"

