文章目录
openGauss数据库权限管理模型
由于数据库中存储着大量重要数据和各类敏感信息,并且为持有不同权限的合法用户提供数据共享服务,这就要求数据库具备完善的安全防御机制来抵抗来自内部和外部的恶意攻击,以保障数据不丢失、隐私不泄露以及数据不被篡改等。当前openGauss数据库已经构建了纵深防御的安全体系,保障数据库在应用中的安全。完善的权限管理机制可以有效阻断恶意用户的越权操作。本文将重点介绍openGauss数据库的权限管理机制。
基础权限控制模型
常见的权限控制模型有三种:基于策略的访问控制模型,基于角色的访问控制模型以及基于会话和角色的访问控制模型。openGauss数据库采用基于角色的权限访问控制模型,利用角色来组织和管理权限,能够大大简化对权限的授权管理。借助角色机制,当给一组权限相同的用户授权时,只需将权限授予角色,再将角色授予这组用户即可,不需要对用户逐一授权。而且利用角色权限分离可以很好地控制不同用户拥有不同的权限,相互制约达到平衡。
伴随着数据库的发展以及所面向业务场景的扩展,对数据库权限分离以及权限管理的细粒度划化提出了更高的要求,为了满足多样化用户的业务安全要求,openGauss数据库针对权限模型进行了更细粒度的权限划分,使得用户可以更灵活地依据实际业务进行用户权限分配和管理。
openGauss数据库权限层级
在openGauss数据库系统的对象布局逻辑结构中,每个实例下允许创建多个数据库(database),每个数据库下允许创建多个模式(schema),每个模式下允许创建多个对象,比如表、函数、视图、索引等,每个表又可以依据行和列两个维度进行衡量,从而形成如下的逻辑层级:
依据上述逻辑分布构建如下图所示的openGauss数据库的权限体系,每一层都有自己的权限控制。
比如用户想要成功查看数据表某一行的数据,那么他需要具备能够登录数据库(LOGIN)这一系统权限,表所在数据库的连接权限(CONNECT),表所在模式的使用权限(USAGE)和数据表本身的查看权限(SELECT),同时还要满足对这一行数据的行级访问控制条件(row level security)。
openGauss数据库权限分类
在openGauss数据库中,用户和角色是基本相同的概念,唯一的区别是在创建角色的时默认没有LOGIN权限,也不会自动创建同名的模式。也就是说一个拥有LOGIN权限的角色可以被认为是一个用户。在以下的介绍中我们统一通过用户(USER)来连接、访问数据库以及执行SQL,通过角色(ROLE)来组织和管理权限。我们通过将不同的权限打包成角色授予用户,使得用户获得该角色中的所有权限。同时通过改变角色的权限,该角色所包含的所有成员的权限也会被自动修改。
在openGauss数据库系统中权限分为两种:系统权限和对象权限。
-
系统权限是指系统规定用户使用数据库的权限,比如登录数据库、创建数据库、创建用户/角色、创建安全策略等。
-
对象权限是指在数据库、模式、表、视图、函数等数据库对象上执行特殊动作的权限,不同的对象类型与不同的权限相关联,比如数据库的连接权限,表的查看、更新、插入等权限,函数的执行权限等。基于特定的对象来描述对象权限才是有意义的。
系统权限
系统权限又称用户属性,具有特定属性的用户会获得指定属性所对应的权限。系统权限无法通过角色(ROLE)被继承。在创建用户或角色时可以通过SQL语句CREATE ROLE/USER指定用户具有某些属性,或者通过ALTER ROLE/USER的方式给用户/角色添加用户属性或取消用户属性。
openGauss数据库支持如下系统权限的授予和回收:
系统权限 | 权限范围 |
---|---|
SYSADMIN | 允许用户创建数据库,创建表空间 允许用户创建用户/角色 允许用户查看、删除审计日志 允许用户查看其它用户的数据 |
MONADMIN | 允许用户对系统模式dbe_perf及该模式下的监控视图或函数进行查看和权限管理 |
OPRADMIN | 允许用户使用Roach工具执行数据库备份和恢复 |
POLADMIN | 允许用户创建资源标签、创建动态数据脱敏策略和统一审计策略 |
AUDITADMIN | 允许用户查看、删除审计日志 |
CREATEDB | 允许用户创建数据库 |
USEFT | 允许用户创建外表 |
CREATEROLE | 允许用户创建用户/角色 |
INHERIT | 允许用户继承所在组的角色的权限 |
LOGIN | 允许用户登录数据库 |
REPLICATION | 允许用户执行流复制相关操作 |
openGauss提供SQL语句CREATE/ALTER ROLE/USER实现系统权限的授予和回收,示例如下:
#例1:创建角色role1,同时授予role1创建数据库的权限
openGauss=# CREATE ROLE role1 WITH CREATEDB password 'openGauss@2021';
CREATE ROLE
#例2:授予角色role1监控管理员的权限,同时取消创建数据库的权限
openGauss=# ALTER ROLE role1 WITH MONADMIN NOCREATEDB;
ALTER ROLE
#例3:查看系统表pg_authid或系统视图pg_roles获取角色role1的相关信息
openGauss=# SELECT rolname,rolcreatedb,rolmonitoradmin FROM pg_authid WHERE rolname= 'role1';
rolname | rolcreatedb | rolmonitoradmin
---------+-------------+-----------------
role1 | f | t
(1 row)
对象权限
对象所有者缺省具有该对象上的所有操作权限,比如修改、删除对象的权限,查看对象的权限,将对象的操作权限授予其他用户,或撤销已经授予的操作权限等。其中对象的ALTER、 DROP、COMMENT、INDEX、VACUUM以及对象的可再授予权限属于所有者固有的权限,隐式拥有。但对象所有者可以撤消自己的普通权限,例如,使表对自己以及其他人都只可读。
对象权限可以通过角色(ROLE)被继承,这样方便用户将这些单个的权限打包成一个角色进行权限管理。openGauss数据库针对每一类数据库对象支持如下对象权限:
对象 | 权限 | 权限说明 |
---|---|---|
TABLESPACE | CREATE | 允许用户在指定的表空间中创建表 |
ALTER | 允许用户对指定的表空间执行ALTER语句修改属性 | |
DROP | 允许用户删除指定的表空间 | |
COMMENT | 允许用户对指定的表空间定义或修改注释 | |
DATABASE | CONNECT | 允许用户连接到指定的数据库 |
TEMP | 允许用户在指定的数据库中创建临时表 | |
CREATE | 允许用户在指定的数据库里创建模式 | |
ALTER | 允许用户对指定的数据库执行ALTER语句修改属性 | |
DROP | 允许用户删除指定的数据库 | |
COMMENT | 允许用户对指定的数据库定义或修改注释 | |
SCHEMA | CREATE | 允许用户在指定的模式中创建新的对象 |
USAGE | 允许用户访问包含在指定模式内的对象 | |
ALTER | 允许用户对指定的模式执行ALTER语句修改属性 | |
DROP | 允许用户删除指定的模式 | |
COMMENT | 允许用户对指定的模式定义或修改注释 | |
FUNCTION | EXECUTE | 允许用户使用指定的函数 |
ALTER | 允许用户对指定的函数执行ALTER语句修改属性 | |
DROP | 允许用户删除指定的函数 | |
COMMENT | 允许用户对指定的函数定义或修改注释 | |
TABLE | INSERT | 允许用户对指定的表执行INSERT语句插入数据 |
DELETE | 允许用户对指定的表执行DELETE语句删除表中数据 | |
UPDATE | 允许用户对指定的表执行UPDATE语句 | |
SELECT | 允许用户对指定的表执行SELECT语句 | |
TRUNCATE | 允许用户执行TRUNCATE语句删除指定表中的所有记录 | |
REFERENCES | 允许用户对指定的表创建一个外键约束 | |
TRIGGER | 允许用户在指定的表上创建触发器 | |
ALTER | 允许用户对指定的表执行ALTER语句修改属性 | |
DROP | 允许用户删除指定的表 | |
COMMENT | 允许用户对指定的表定义或修改注释 | |
INDEX | 允许用户在指定表上创建索引,并管理指定表上的索引 | |
VACUUM | 允许用户对指定的表执行ANALYZE和VACUUM操作 |
openGauss提供SQL语句GRANT/REVOKE实现对象权限的授予和回收:
#创建测试数据
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 tbl1 (id int);
insert into tbl1 values(1),(2),(3);
#例1:将对表tbl1进行select的权限以及将select再赋权的权限授予用户user1,
#赋权后用户user1有权对tbl执行select操作且user1有权限将select权限再赋予其他用户
[omm@home ~]$ gsql -d testdb -c "GRANT select ON TABLE test.tbl1 TO user1 WITH GRANT OPTION"
GRANT
[omm@home ~]$ gsql -d testdb -U user1 -W test@123 -c "select * from test.tbl1"
ERROR: permission denied for schema test
LINE 1: select * from test.tbl1
^
DETAIL: N/A
#如上因为user1没有test模式的usage权限,所以即便给他授权了模式下的表的select权限也访问不了
gsql -d testdb -c "GRANT usage ON schema test TO user1"
[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 * from test.tbl1"
id
----
1
2
3
(3 rows)
#此时user1没有对表alter、drop的权限
[omm@home ~]$ gsql -d testdb -U user1 -W test@123 -c "drop table test.tbl1"
ERROR: permission denied for relation tbl1
DETAIL: N/A
[omm@home ~]$ gsql -d testdb -U user1 -W test@123 -c "alter table test.tbl1 add column name text"
ERROR: permission denied for relation tbl1
DETAIL: N/A
#例2:将对表tbl1进行alter和drop的权限赋给用户user1
#赋权后用户user1有权对tbl1进行修改(ALTER)和删除(DROP)操作
[omm@home ~]$ gsql -d testdb -c "GRANT alter, drop ON TABLE test.tbl1 TO user1;"
GRANT
[omm@home ~]$ gsql -d testdb -U user1 -W test@123 -c "alter table test.tbl1 add column name text"
ALTER TABLE
[omm@home ~]$
#例3:撤销用户user1对表tbl进行select的权限
[omm@home ~]$ gsql -d testdb -U user1 -W test@123 -c "select * from test.tbl1"
id | name
----+------
1 |
2 |
3 |
(3 rows)
[omm@home ~]$ gsql -d testdb -c "REVOKE select ON test.tbl1 FROM user1"
REVOKE
#撤销后用户user1对tbl进行select操作会报错:
[omm@home ~]$ gsql -d testdb -U user1 -W test@123 -c "select * from test.tbl1"
ERROR: permission denied for relation tbl1
DETAIL: N/A
用户权限集合
依据openGauss数据库的权限管理机制,一个用户真正拥有的权限是以下几类权限的并集:
在实际的业务应用中,建议客户依据权限最小化原则配置所需要的权限账户,在满足业务诉求的基础上赋予用户最少的权限。
openGauss数据库权限演进
openGauss数据库提供了一系列系统权限和对象权限,用户可以依据实际业务将权限组装成角色使用。但随着openGauss数据库在各种应用场景下的用户反馈,未来openGauss数据库还会提供一系列的内置角色,将实际应用中经常使用的权限组合打包成内置角色,用户可以直接使用内置角色来进行权限管理。
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三种系统权限的权限范围互相隔离,互不影响,而且一个用户仅能被赋予其中一个属性。
三权分立打开后的权限范围如下:
系统权限 | 权限范围 |
---|---|
SYSADMIN | 允许用户创建数据库,创建表空间 |
CREATEROLE | 允许用户创建用户/角色 |
AUDITADMIN | 允许用户查看、删除审计日志 |
列级访问控制
在一些业务场景中,数据表中的某些列存储了重要的信息,需要对用户不可见,但其他列的数据又需要用户能够查看或操作,此时就需要针对数据表的特定列做访问控制,实现针对用户的列级别的访问控制。
openGauss提供SQL语句GRANT/REVOKE实现针对列对象的权限授予和回收:
#创建测试数据
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"
参考资料
https://blog.youkuaiyun.com/weixin_53596073/article/details/123474217