三权分立机制
伴随着数据库的发展以及所面向业务场景的扩展,对数据库权限分离以及权限管理的细粒度划化提出了更高的要求,为了满足多样化用户的业务安全要求,openGauss数据库针对权限模型进行了更细粒度的权限划分,使得用户可以更灵活地依据实际业务进行用户权限分配和管理,除了基本系统权限和对象权限的划分外,还有一些高阶的权限管理机制用来满足客户的业务诉求,比如三权分立机制。
openGauss安装完成后会得到一个具有最高权限的超级用户。数据库超级用户的高权限意味着该用户可以做任何系统管理操作和数据管理操作,甚至可以修改数据库对象,包括接下来将要介绍的审计日志信息。对于企业管理来说, 手握超级用户权限的管理人员可以在无人知晓的情况下改变数据行为,这带来的后果是不可想象的。
在上文提到,初始化用户不允许远程登录,仅可本地登录。那么,在组织行为上由IT 部门严格监控拥有该权限的员工在本地的操作行为,就可有效避免诸如修改表中数据等“监守自盗”行为的发生。为了实际管理需要,在数据库内部就需要其他的管理员用户来管理整个系统,如果将大部分的系统管理权限都交给某一个用户来执行,实际上也是不合适的,因为这等同于超级用户。
为了很好地解决权限高度集中的问题,在openGauss系统中引入三权分立角色模型,如图所示。三权分立角色模型最关键的三个角色为安全管理员、系统管理员和审计管理员。其中,安全管理员用于创建数据管理用户;系统管理员对创建的用户进行赋权;审计管理员则审计安全管理员、系统管理员、普通用户实际的操作行为。
通过三权分立角色模型实现权限的分派,且三个管理员角色独立行使权限,相互制约制衡。使得整个系统的权限不会因为权限集中而引入安全的风险。
事实上,产品使用过程中的安全是技术本身与组织管理双重保障的结果,在系统实现三权分立模型后,需要有三个对应的产品自然人分别握有对应的账户信息,以达到真正权限分离的目的。
三权分立是对系统权限管理机制的补充,核心思想是将管理数据库对象的权限、管理用户的权限和管理审计日志的权限分离,从而避免一个管理员拥有过度集中的权利带来的高风险。通过将GUC参数enableSeparationOfDuty设置为on来打开三权分立开关。
openGauss=# select name,setting,unit,context from pg_settings where name ~ 'enableSeparationOfDuty';
name | setting | unit | context
------------------------+---------+------+------------
enableSeparationOfDuty | off | | postmaster
(1 row)
三权分立开关打开后,SYSADMIN的权限范围将缩小,不再包括允许创建用户/角色的权限,也不再包括允许查看、删除数据库审计日志的权限。SYSADMIN,CREATEROLE,AUDITADMIN三种系统权限的权限范围互相隔离,互不影响,而且一个用户仅能被赋予其中一个属性。三权分立打开后的权限范围如下:
-
列级访问控制
在一些业务场景中,数据表中的某些列存储了重要的信息,需要对用户不可见,但其他列的数据又需要用户能够查看或操作,此时就需要针对数据表的特定列做访问控制,实现针对用户的列级别的访问控制。
#创建测试数据
gsql -d postgres -r
create database testdb;
c testdb
create user test identified by 'test@123';
create user user1 identified by 'test@123';
alter database testdb owner to test;
set search_path to test;
create table tbl (id int,name varchar(20));
insert into tbl values(1,'test1'),(2,'test2'),(3,'test3');
#例1:将对表tbl的第一列(id)进行select的权限和对表tbl的第二列(name)进行update的权限授予用户user1
#赋权后用户user1有权对tbl的第一列执行select操作和对第二列执行update操作
[omm@home ~]$ gsql -d testdb -c "GRANT select(id),update(name) ON TABLE test.tbl TO user1;"
GRANT
[omm@home ~]$ gsql -d testdb -U user1 -W test@123 -c "select id from test.tbl"
ERROR: permission denied for schema test
LINE 1: select id from test.tbl
^
DETAIL: N/A
#如上因为user1没有test模式的usage权限,所以即便给他授权了模式下的表的select权限也访问不了
[omm@home ~]$ gsql -d testdb -c "GRANT usage ON schema test TO user1"
GRANT
[omm@home ~]$ gsql -d testdb -U user1 -W test@123 -c "select id from test.tbl"
id
----
1
2
3
(3 rows)
[omm@home ~]$ gsql -d testdb -U user1 -W test@123 -c "select name from test.tbl"
ERROR: permission denied for relation tbl
DETAIL: N/A
[omm@home ~]$ gsql -d testdb -U user1 -W test@123 -c "update test.tbl set name = 'haha' where id=3"
UPDATE 1
[omm@home ~]$ gsql -d testdb -U user1 -W test@123 -c "update test.tbl set id = 4 where id=3"
ERROR: permission denied for relation tbl
DETAIL: N/A
#例2:撤销用户user1对表tbl的第一列id进行select的权限
#撤销后用户user1不再具有查看表tbl的第一列id数据的权限
[omm@home ~]$ gsql -d testdb -c "REVOKE select(id) ON test.tbl FROM user1"
REVOKE
[omm@home ~]$ gsql -d testdb -U user1 -W test@123 -c "select id from test.tbl"
ERROR: permission denied for relation tbl
DETAIL: N/A
-
行级访问控制
在实际业务中还存在另外一种场景,同一张数据表,只允许用户查看满足特定条件的行数据,此时就需要将访问控制精确到数据表的行级别,使得不同用户执行相同的SQL查询、更新或删除操作,读取到的结果是不同的。
用户可以在数据表上创建行级访问控制(row level security)策略,该策略是针对特定数据库用户、特定SQL操作生效的表达式。当数据库用户访问数据表时,满足策略条件的行对用户可见,不满足条件的行对用户不可见,从而实现针对用户的行级别的访问控制。
openGauss提供SQL语句CREATE/ALTER/DROP ROW LEVEL SECURITY进行行级访问权限策略的创建/修改/删除操作:
#创建测试数据
gsql -d postgres -r
create database testdb;
c testdb
create user test identified by 'test@123';
create user mary identified by 'test@123';
create user tom identified by 'test@123';
alter database testdb owner to test;
set search_path to test;
#步骤1:创建信息表pat_info记录医院病人的个人信息:
create table pat_info(patience varchar(20),doctor varchar(20),age int);
insert into pat_info values('peter','mary',25),('bob','mary',56),('julie','tom',38)
#查询表数据
[omm@home ~]$ gsql -d testdb -U test -W test@123 -c "select * from test.pat_info"
patience | doctor | age
----------+--------+-----
peter | mary | 25
bob | mary | 56
julie | tom | 38
(3 rows)
#步骤2:创建行级访问控制策略,使得医生只能查看属于自己的病人信息:
[omm@home ~]$ gsql -d testdb -c "CREATE ROW LEVEL SECURITY POLICY rls_select ON test.pat_info FOR select USING(doctor=current_user)"
CREATE ROW LEVEL SECURITY POLICY
#步骤3:打开信息表pat_info上的行级访问控制开关
[omm@home ~]$ gsql -d testdb -c "ALTER TABLE test.pat_info ENABLE ROW LEVEL SECURITY;"
ALTER TABLE
#步骤4:将信息表pat_info的查看权限赋予所有人
[omm@home ~]$ gsql -d testdb -c "grant select on table test.pat_info to public;"
GRANT
#步骤5:Mary医生的查看结果:
[omm@home ~]$ gsql -d testdb -U mary -W test@123 -c "select * from test.pat_info"
ERROR: permission denied for schema test
LINE 1: select * from test.pat_info
^
DETAIL: N/A
[omm@home ~]$
[omm@home ~]$ gsql -d testdb -c "GRANT usage ON schema test TO mary"
GRANT
[omm@home ~]$ gsql -d testdb -U mary -W test@123 -c "select * from test.pat_info"
patience | doctor | age
----------+--------+-----
peter | mary | 25
bob | mary | 56
(2 rows)
#Tom医生的查看结果:
[omm@home ~]$ gsql -d testdb -c "GRANT usage ON schema test TO tom"
GRANT
[omm@home ~]$ gsql -d testdb -U tom -W test@123 -c "select * from test.pat_info"
- 行级访问控制
在实际业务中还存在另外一种场景,同一张数据表,只允许用户查看满足特定条件的行数据,此时就需要将访问控制精确到数据表的行级别,使得不同用户执行相同的SQL查询、更新或删除操作,读取到的结果是不同的。
用户可以在数据表上创建行级访问控制(row level security)策略,该策略是针对特定数据库用户、特定SQL操作生效的表达式。当数据库用户访问数据表时,满足策略条件的行对用户可见,不满足条件的行对用户不可见,从而实现针对用户的行级别的访问控制。
openGauss提供SQL语句CREATE/ALTER/DROP ROW LEVEL SECURITY进行行级访问权限策略的创建/修改/删除操作:
#创建测试数据
gsql -d postgres -r
create database testdb;
c testdb
create user test identified by 'test@123';
create user mary identified by 'test@123';
create user tom identified by 'test@123';
alter database testdb owner to test;
set search_path to test;
#步骤1:创建信息表pat_info记录医院病人的个人信息:
create table pat_info(patience varchar(20),doctor varchar(20),age int);
insert into pat_info values('peter','mary',25),('bob','mary',56),('julie','tom',38)
#查询表数据
[omm@home ~]$ gsql -d testdb -U test -W test@123 -c "select * from test.pat_info"
patience | doctor | age
----------+--------+-----
peter | mary | 25
bob | mary | 56
julie | tom | 38
(3 rows)
#步骤2:创建行级访问控制策略,使得医生只能查看属于自己的病人信息:
[omm@home ~]$ gsql -d testdb -c "CREATE ROW LEVEL SECURITY POLICY rls_select ON test.pat_info FOR select USING(doctor=current_user)"
CREATE ROW LEVEL SECURITY POLICY
#步骤3:打开信息表pat_info上的行级访问控制开关
[omm@home ~]$ gsql -d testdb -c "ALTER TABLE test.pat_info ENABLE ROW LEVEL SECURITY;"
ALTER TABLE
#步骤4:将信息表pat_info的查看权限赋予所有人
[omm@home ~]$ gsql -d testdb -c "grant select on table test.pat_info to public;"
GRANT
#步骤5:Mary医生的查看结果:
[omm@home ~]$ gsql -d testdb -U mary -W test@123 -c "select * from test.pat_info"
ERROR: permission denied for schema test
LINE 1: select * from test.pat_info
^
DETAIL: N/A
[omm@home ~]$
[omm@home ~]$ gsql -d testdb -c "GRANT usage ON schema test TO mary"
GRANT
[omm@home ~]$ gsql -d testdb -U mary -W test@123 -c "select * from test.pat_info"
patience | doctor | age
----------+--------+-----
peter | mary | 25
bob | mary | 56
(2 rows)
#Tom医生的查看结果:
[omm@home ~]$ gsql -d testdb -c "GRANT usage ON schema test TO tom"
GRANT
[omm@home ~]$ gsql -d testdb -U tom -W test@123 -c "select * from test.pat_info"
权限规划示例
将测试用例全部移植完成,本次移植涉及7个测试文件、全部功能接口和搜索选项、近3000行代码,针对实机进行单元测试,发现其中的不符合预期的功能接口,针对性进行调试适配,确保功能可用。最后整理测试报告TESE.md文件,列明测试用例涉及的接口和实机测试结果。
本示例以项目维度进行权限管理示例。
-
DBA拥有open Gauss实例的高权限账号,名称是dbsuperuser。
-
举例业务项目名称是oaauth,OA系统,新建schema名称是oaauth、oaauth_1。
项目中新增的资源owner账号和角色Role规划如下: