1.用户权限分类
MogDB数据库用户权限可以分为三类:系统权限,对象权限和行级访问控制权限。
系统权限
系统权限又称为用户属性,包括以下权限。
| 系统权限 | 缺省值 | 描述 |
|---|---|---|
| INHERIT / NOINHERIT | INHERIT | 角色是否具有继承角色的权限。 |
| CREATEROLE / NOCREATEROLE | NOCREATEROLE | 角色是否可以创建其他的角色。 |
| CREATEDB / NOCREATEDB | NOCREATEDB | 角色是否可以创建数据库。 |
| LOGIN / NOLOGIN | CREAT USER 命令缺省为LOGIN;CREATE ROLE 命令缺省为NOLOGIN。 | 角色是否可以登录数据库。 |
| REPLICATION / NOREPLICATION | NOREPLICATION | 角色是否允许流复制或设置系统为备份模式。 |
| AUDITADMIN / NOAUDITADMIN | NOAUDITADMIN | 角色是否为审计管理员。 |
| SYSADMIN / NOSYSADMIN | NOSYSADMIN | 角色是否为系统管理员。 |
| USEFT / NOUSEFT | NOUSEFT | 角色是否可以操作外表。 |
| MONADMIN / NOMONADMIN | NOMONADMIN | 角色是否为监控管理员。 |
| OPRADMIN / NOOPRADMIN | NOOPRADMIN | 角色是否为运维管理员。 |
| POLADMIN / NOPOLADMIN | NOPOLADMIN | 角色是否为安全策略管理员。 |
对象权限
数据库对象(表和视图、指定字段、数据库、函数、模式、表空间等)的相关权限。
数据库中的对象权限如下:
| 对象权限 | 说明 |
|---|---|
| ALTER | 允许用户修改指定对象的属性,但不包括修改对象的所有者和修改对象所在的模式。 |
| COMMENT | 允许用户定义或修改指定对象的注释。 |
| CONNECT | 允许用户连接到指定的数据库。 |
| CREATE | 对于数据库,允许在数据库里创建新的模式。对于模式,允许在模式中创建新的对象。如果要重命名一个对象,用户除了必须是该对象的所有者外,还必须拥有该对象所在模式的CREATE权限。对于表空间,允许在表空间中创建表,允许在创建数据库和模式的时候把该表空间指定为缺省表空间。 |
| DELETE | 允许执行DELETE命令删除指定表中的数据。通常,delete命令也需要select权限来查询出哪些行需要删除。 |
| DROP | 允许用户删除指定的对象。 |
| EXECUTE | 允许使用指定的函数,以及利用这些函数实现的操作符。 |
| INDEX | 允许用户在指定表上创建索引,并管理指定表上的索引,还允许用户对指定表执行REINDEX和CLUSTER操作。 |
| INSERT | 允许对指定的表执行INSERT命令。 |
| REFERENCES | 创建一个外键约束,必须拥有参考表和被参考表的REFERENCES权限。 |
| SELECT | 允许对指定的表、视图、序列执行SELECT命令,update或delete时也需要对应字段上的select权限。 |
| TRUNCATE | 允许执行TRUNCATE语句删除指定表中的所有记录。 |
| UPDATE | 允许对声明的表中任意字段执行UPDATE命令。通常,update命令也需要select权限来查询出哪些行需要更新。SELECT…FORUPDATE和SELECT…FORSHARE除了需要SELECT权限外,还需要UPDATE权限。 |
| USAGE | 对于过程语言,允许用户在创建函数的时候指定过程语言。对于模式,USAGE允许访问包含在指定模式中的对象,若没有该权限,则只能看到这些对象的名称。对于序列,USAGE允许使用nextval函数。对于DataSource对象,USAGE是指访问权限,也是可赋予的所有权限,即USAGE与ALLPRIVILEGES等价。 |
| TEMPORARY/TEMP | 允许创建临时表。 |
| TRIGGER | 允许在指定表上创建触发器。 |
| VACUUM | 允许用户对指定的表执行ANALYZE和VACUUM操作。 |
各对象支持的权限列表如下:
| 对象名称 | 权限列表 |
|---|---|
| TABLE | SELECT/INSERT/UPDATE/DELETE/TRUNCATE/REFERENCES/ALTER/DROP/COMMENT/INDEX/VACUUM/TRIGGER |
| TABLE_COLUMN | SELECT/INSERT/UPDATE/REFERENCES/COMMENT |
| DATABASE | CREATE/CONNECT/TEMPORARY/TEMP/ALTER/DROP/COMMENT |
| DOMAIN | USAGE |
| FOREIGN DATA WRAPPER | USAGE |
| FOREIGN SERVER | USAGE/ALTER/DROP/COMMENT |
| FUNCTION | EXECUTE/ALTER/DROP/COMMENT |
| LANGUAGE | USAGE |
| LARGE OBJECT | SELECT/UPDATE |
| SCHEMA | CREATE/USAGE/ALTER/DROP/COMMENT |
| TABLESPACE | CREATE/ALTER/DROP/COMMENT |
| TYPE | USAGE/ALTER/DROP/COMMENT |
| DATA SOURCE | USAGE |
行级访问控制权限
行级访问控制特性将数据库访问控制精确到数据表行级别。不同用户执行相同的SQL查询操作,读取到的结果是不同的。
2.系统权限分配与回收
系统权限一般通过CREATE/ALTER ROLE语法来指定。其中,SYSADMIN权限可以通过GRANT/REVOKE ALL PRIVILEGE授予或撤销。但系统权限无法通过ROLE和USER的权限被继承,也无法授予PUBLIC。
例2.1:赋予用户系统管理员权限
语法:
ALTER USER user_name [ [ WITH ] option [ … ] ];
where option can be:
{CREATEDB | NOCREATEDB}
| {CREATEROLE | NOCREATEROLE}
| {INHERIT | NOINHERIT}
| {AUDITADMIN | NOAUDITADMIN}
| {SYSADMIN | NOSYSADMIN}
| {MONADMIN | NOMONADMIN}
| {OPRADMIN | NOOPRADMIN}
| {POLADMIN | NOPOLADMIN}
| {USEFT | NOUSEFT}
| {LOGIN | NOLOGIN}
| {REPLICATION | NOREPLICATION}
| {INDEPENDENT | NOINDEPENDENT}
| {VCADMIN | NOVCADMIN}
| {PERSISTENCE | NOPERSISTENCE}
| CONNECTION LIMIT connlimit
| [ ENCRYPTED | UNENCRYPTED ] PASSWORD { ‘password’ [ EXPIRED ] | DISABLE | EXPIRED }
| [ ENCRYPTED | UNENCRYPTED ] IDENTIFIED BY { ‘password’ [ REPLACE ‘old_password’ | EXPIRED ] | DISABLE }
| VALID BEGIN ‘timestamp’
| VALID UNTIL ‘timestamp’
| RESOURCE POOL ‘respool’
| USER GROUP ‘groupuser’
| PERM SPACE ‘spacelimit’
| TEMP SPACE ‘tmpspacelimit’
| SPILL SPACE ‘spillspacelimit’
| NODE GROUP logic_cluster_name
| ACCOUNT { LOCK | UNLOCK }
| PGUSER
gsql工具中,查看alter user命令语法
\help alter user
给用户赋予系统管理员权限
ALTER USER enmo WITH SYSADMIN;
或
GRANT ALL PRIVILEGE TO enmo;
例2.2:解锁/锁定用户
语法:参考例2.1
解锁用户
ALTER USER enmo ACCOUNT UNLOCK;
锁定用户
ALTER USER enmo ACCOUNT LOCK;
3.对象权限分配与回收
数据库系统管理员可以给任何角色或用户授予/撤销任何权限。拥有CREATEROLE权限的角色可以赋予或者撤销任何非系统管理员角色的权限。
3.1对象权限分配与回收
GRANT/REVOKE命令用户数据库对象授予/回收。
任何角色或用户都将拥有通过GRANT直接赋予的权限和所属的权限,再加上PUBLIC的权限。
例3.1.1:给用户赋予单张表的查询权限
首先赋予用户表的查询权限:
语法:GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | ALTER | DROP | COMMENT | INDEX | VACUUM } [, …] | ALL [ PRIVILEGES ] } ON { [ TABLE ] table_name [, …] | ALL TABLES IN SCHEMA schema_name [, …] } TO { [ GROUP ] role_name | PUBLIC } [, …] [ WITH GRANT OPTION ];
GRANT SELECT ON all_data IN SCHEMA enmo TO alice, bob, peter;
为了让用户成功的查询不属于它自己的sechma下的表,除了要执行上面语句赋予该用户对表的查询权限以外,还需要赋予该用户使用表所属shema的使用权限:
语法:GRANT { { CREATE | USAGE | ALTER | DROP | COMMENT } [, …] | ALL [ PRIVILEGES ] } ON SCHEMA schema_name [, …] TO { [ GROUP ] role_name | PUBLIC } [, …] [ WITH GRANT OPTION ];
GRANT USAGE ON SCHEMA enmo TO alice, bob, peter;
如果不具有表所属schema的usage权限,用户在查询表数据时会报错:
enmo=> select * from enmo.all_data;
ERROR: permission denied for schema enmo
例3.1.2:给用户赋予某个schema下所有表的查询权限
将模式A的usage权限赋给用户B
语法:参考例3.1.1
GRANT USAGE ON SCHEMA A TO B;
将模式A下所有表的select权限赋给用户B
语法:参考例3.1.1
GRANT SELECT ON ALL TABLES IN SCHEMA A TO B;
3.2public权限
任何角色或用户都将拥有通过GRANT直接赋予的权限和所属的权限,再加上PUBLIC的权限。
默认public具有以下权限:数据库的CONNECT权限和CREATE TEMP TABLE权限、函数的EXECUTE特权、语言和数据类型(包括域)的USAGE特权。
要撤销或重新授予用户和角色对PUBLIC的权限,可通过在GRANT和REVOKE指定关键字PUBLIC实现。
例3.2.1: 撤销public执行某个schema下执行存储过程权限
语法:REVOKE [ GRANT OPTION FOR ]
{ { EXECUTE | ALTER | DROP | COMMENT } [, …] | ALL [ PRIVILEGES ] }
ON { FUNCTION {function_name ( [ {[ argmode ] [ arg_name ] arg_type} [, …] ] )} [, …]
| ALL FUNCTIONS IN SCHEMA schema_name [, …] }
FROM { [ GROUP ] role_name | PUBLIC } [, …]
[ CASCADE | RESTRICT ];
REVOKE EXECUTE ON ALL FUNCTIONS IN SCHEMA enmo FROM PUBLIC;
3.3WITH GRANT OPTION
如果声明了WITH GRANT OPTION,则被授权的用户也可以将此权限赋予他人,否则就不能授权给他人。这个选项不能赋予PUBLIC。
例3.3.1:赋给用户表的select权限,并允许该用户将此权限赋予他人
语法:参考例3.1.1
GRANT SELECT ON all_data IN SCHEMA enmo TO alice WITH GRANT OPTION;
3.4对象默认权限
对象的所有者缺省具有该对象上的所有权限,出于安全考虑所有者可以舍弃部分权限,但ALTER、DROP、COMMENT、INDEX、VACUUM以及对象的可再授予权限属于所有者固有的权限,隐式拥有。
对象创建时初始的默认权限可以使用ALTER DEFAULT PRIVILEGES命令修改。
例3.4.1:设置用户A将来创建的表的查询权限默认赋给用户B
语法:ALTER DEFAULT PRIVILEGES [ FOR { ROLE | USER } target_role [, …] ] [ IN SCHEMA schema_name [, …] ] abbreviated_grant_or_revoke;
where abbreviated_grant_or_revoke can be:
grant_on_tables_clause | grant_on_functions_clause | grant_on_types_clause | revoke_on_tables_clause | revoke_on_functions_clause | revoke_on_types_clause
where grant_on_tables_clause can be:
GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | ALTER | DROP | COMMENT | INDEX | VACUUM } [, …] | ALL [ PRIVILEGES ] } ON TABLES TO { [ GROUP ] role_name | PUBLIC } [, …] [ WITH GRANT OPTION ]
ALTER DEFAULT PRIVILEGES FOR USER A GRANT SELECT ON TABLES TO B;
3.5角色权限的分配与回收
将一个角色或用户的权限授予一个或多个其他角色或用户。在这种情况下,每个角色或用户都可视为拥有一个或多个数据库权限的集合。
当声明了WITH ADMIN OPTION,被授权的用户可以将该权限再次授予其他角色或用户,以及撤销所有由该角色或用户继承到的权限。当授权的角色或用户发生变更或被撤销时,所有继承该角色或用户权限的用户拥有的权限都会随之发生变更。
例3.5.1:将角色A权限赋予B
语法:GRANT role_name [, …] TO role_name [, …] [ WITH ADMIN OPTION ];
GRANT A TO B;
4.行级访问控制权限设置
行级访问控制的目的是控制表中行级数据可见性。用户可以在数据表创建行访问控制(Row Level Security)策略,该策略是指针对特定数据库用户、特定SQL操作生效的表达式。当数据库用户对数据表访问时,若SQL满足数据表特定的Row Level Security策略,在查询优化阶段将满足条件的表达式,按照属性(PERMISSIVE | RESTRICTIVE)类型,通过OR|AND方式拼接,应用到执行计划上,影响最终的执行结果。当前受影响的SQL语句包括SELECT,UPDATE,DELETE。
4.1开启表的行级访问策略
语法:ALTER TABLE [ IF EXISTS ] { table_name [*] | ONLY table_name | ONLY ( table_name )} ENABLE ROW LEVEL SECURITY;
ALTER TABLE all_data ENABLE ROW LEVEL SECURITY;
4.2关闭表的行级访问策略
语法:ALTER TABLE [ IF EXISTS ] { table_name [*] | ONLY table_name | ONLY ( table_name )} DISABLE ROW LEVEL SECURITY;
ALTER TABLE all_data DISABLE ROW LEVEL SECURITY;
4.3创建行级访问控制策略
语法:CREATE [ ROW LEVEL SECURITY ] POLICY policy_name ON table_name [ AS { PERMISSIVE | RESTRICTIVE } ] [ FOR { ALL | SELECT | UPDATE | DELETE } ] [ TO { role_name | PUBLIC } [, ...] ] USING ( using_expression )
CREATE ROW LEVEL SECURITY POLICY all_data_rls ON all_data USING(role = CURRENT_USER);
4.4删除行级访问控制策略
语法:DROP [ ROW LEVEL SECURITY ] POLICY [ IF EXISTS ] policy_name ON table_name [ CASCADE | RESTRICT ]
DROP ROW LEVEL SECURITY POLICY all_data_rls ON all_data;
4.5修改行级访问控制策略名称
语法:ALTER [ ROW LEVEL SECURITY ] POLICY [ IF EXISTS ] policy_name ON table_name RENAME TO new_policy_name;
ALTER ROW LEVEL SECURITY POLICY all_data_rls ON all_data RENAME TO all_data_new_rls;
4.6修改行级访问控制策略影响用户
语法:ALTER [ ROW LEVEL SECURITY ] POLICY policy_name ON table_name [ TO { role_name | PUBLIC } [, …] ] [ USING ( using_expression ) ];
ALTER ROW LEVEL SECURITY POLICY all_data_new_rls ON all_data TO alice, bob;
4.7查询数据库中表的行级访问策略
select *from PG_RLSPOLICIES;
4.8测试
a.创建行级访问控制策略,并验证策略生效
enmo=> select * from enmo.all_data;
id | role | data
----+-------+------------
1 | alice | alice data
2 | bob | bob data
3 | peter | peter data
(3 rows)
enmo=> \d+ all_data
Table "enmo.all_data"
Column | Type | Modifiers | Storage | Stats target | Description
--------+------------------------+-----------+----------+--------------+-------------
id | integer | | plain | |
role | character varying(100) | | extended | |
data | character varying(100) | | extended | |
Has OIDs: no
Options: orientation=row, compression=no
enmo=> --打开行访问控制策略开关
enmo=> ALTER TABLE all_data ENABLE ROW LEVEL SECURITY;
ALTER TABLE
enmo=> --创建行访问控制策略,当前用户只能查看用户自身的数据
enmo=> CREATE ROW LEVEL SECURITY POLICY all_data_rls ON all_data USING(role = CURRENT_USER);
CREATE ROW LEVEL SECURITY POLICY
enmo=> \d+ all_data
Table "enmo.all_data"
Column | Type | Modifiers | Storage | Stats target | Description
--------+------------------------+-----------+----------+--------------+-------------
id | integer | | plain | |
role | character varying(100) | | extended | |
data | character varying(100) | | extended | |
Row Level Security Policies:
POLICY "all_data_rls" FOR ALL
TO public
USING (((role)::name = "current_user"()))
Has OIDs: no
Options: orientation=row, compression=no, enable_rowsecurity=true
enmo=> select *from PG_RLSPOLICIES;
-[ RECORD 1 ]----+----------------------------------
schemaname | enmo
tablename | all_data
policyname | all_data_rls
policypermissive | PERMISSIVE
policyroles | {public}
policycmd | ALL
policyqual | ((role)::name = "current_user"())
enmo=>--行级访问策略对表的所有者无效
enmo=> select * from enmo.all_data;
id | role | data
----+-------+------------
1 | alice | alice data
2 | bob | bob data
3 | peter | peter data
(3 rows)
enmo=> \c - alice
Password for user alice:
Non-SSL connection (SSL connection is recommended when requiring high-security)
You are now connected to database "enmo" as user "alice".
enmo=>--用户alice只能访问到role='alice'的数据行
enmo=> select *from enmo.all_data;
id | role | data
----+-------+------------
1 | alice | alice data
(1 row)
enmo=>--用户alice对表enmo.all_data的insert操作未受行级访问控制影响
enmo=> INSERT INTO enmo.all_data VALUES(4, 'ogdb', 'ogdb data');
INSERT 0 1
enmo=> SELECT * FROM enmo.all_data;
id | role | data
----+-------+------------
1 | alice | alice data
(1 row)
enmo=> \conninfo
You are connected to database "enmo" as user "enmo" via socket in "/opt/OpenGauass/tmp" at port "15400".
enmo=> SELECT * FROM enmo.all_data;
id | role | data
----+-------+------------
1 | alice | alice data
2 | bob | bob data
3 | peter | peter data
4 | ogdb | ogdb data
(4 rows)
enmo=>--用户alice对表enmo.all_data的update操作只能修改role='alice'的数据行
enmo=> update enmo.all_data set id=id+10;
UPDATE 1
enmo=> EXPLAIN(COSTS OFF) update enmo.all_data set id=id+10;
QUERY PLAN
----------------------------------------------------------------
Update on all_data
-> Seq Scan on all_data
Filter: ((role)::name = 'alice'::name)
Notice: This query is influenced by row level security feature
(4 rows)
enmo=> SELECT * FROM enmo.all_data;
id | role | data
----+-------+------------
11 | alice | alice data
(1 row)
enmo=> \conninfo
You are connected to database "enmo" as user "enmo" via socket in "/opt/OpenGauss/tmp" at port "15400".
enmo=> SELECT * FROM enmo.all_data;
id | role | data
----+-------+------------
2 | bob | bob data
3 | peter | peter data
4 | ogdb | ogdb data
11 | alice | alice data
(4 rows)
enmo=>--用户alice对表enmo.all_data的delete操作只能删除role='alice'的数据行
enmo=> delete from enmo.all_data;
DELETE 1
enmo=> EXPLAIN(COSTS OFF) delete from enmo.all_data;
QUERY PLAN
----------------------------------------------------------------
Delete on all_data
-> Seq Scan on all_data
Filter: ((role)::name = 'alice'::name)
Notice: This query is influenced by row level security feature
(4 rows)
enmo=> SELECT * FROM enmo.all_data;
id | role | data
----+------+------
(0 rows)
enmo=> \conninfo
You are connected to database "enmo" as user "enmo" via socket in "/opt/OpenGauss/tmp" at port "15400".
enmo=> SELECT * FROM enmo.all_data;
id | role | data
----+-------+------------
2 | bob | bob data
3 | peter | peter data
4 | ogdb | ogdb data
(3 rows)
enmo=> --用户bob只能访问到role='bob'的数据行
enmo=> \c - bob
Password for user bob:
Non-SSL connection (SSL connection is recommended when requiring high-security)
You are now connected to database "enmo" as user "bob".
enmo=> SELECT * FROM enmo.all_data;
id | role | data
----+------+----------
2 | bob | bob data
(1 row)
enmo=> EXPLAIN(COSTS OFF) SELECT * FROM enmo.all_data;
QUERY PLAN
----------------------------------------------------------------
Seq Scan on all_data
Filter: ((role)::name = 'bob'::name)
Notice: This query is influenced by row level security feature
(3 rows)
enmo=>--行级访问策略对数据库初始化用户无效
enmo=# \c - ogdb
Non-SSL connection (SSL connection is recommended when requiring high-security)
You are now connected to database "enmo" as user "ogdb".
enmo=# select *from enmo.all_data;
id | role | data
----+-------+------------
1 | alice | alice data
2 | bob | bob data
3 | peter | peter data
(3 rows)
enmo=#
b.修改行级访问控制策略名称,并设置仅对alice用户生效
enmo=> ALTER ROW LEVEL SECURITY POLICY all_data_rls ON all_data RENAME TO all_data_new_rls;
ALTER ROW LEVEL SECURITY POLICY
enmo=> ALTER ROW LEVEL SECURITY POLICY all_data_new_rls ON all_data TO alice;
ALTER ROW LEVEL SECURITY POLICY
enmo=> select *from PG_RLSPOLICIES;
-[ RECORD 1 ]----+----------------------------------
schemaname | enmo
tablename | all_data
policyname | all_data_new_rls
policypermissive | PERMISSIVE
policyroles | {alice}
policycmd | ALL
policyqual | ((role)::name = "current_user"())
enmo=> \c - alice
Password for user alice:
Non-SSL connection (SSL connection is recommended when requiring high-security)
You are now connected to database "enmo" as user "alice".
enmo=>--用户alice只能访问到role='alice'的数据行
enmo=> SELECT * FROM enmo.all_data;
id | role | data
----+-------+------------
1 | alice | alice data
(1 row)
enmo=> \c - bob
Password for user bob:
Non-SSL connection (SSL connection is recommended when requiring high-security)
You are now connected to database "enmo" as user "bob".
enmo=> --行级访问策略对用户bob无效
enmo=> SELECT * FROM enmo.all_data;
id | role | data
----+-------+------------
1 | alice | alice data
2 | bob | bob data
3 | peter | peter data
(3 rows)
enmo=>
c.对表禁用行级访问控制后,行级访问控制策略失效
enmo=> \conninfo
You are connected to database "enmo" as user "enmo" via socket in "/opt/OpenGauss/tmp" at port "15400".
enmo=> ALTER TABLE all_data DISABLE ROW LEVEL SECURITY;
ALTER TABLE
enmo=> \x
Expanded display is on.
enmo=> select *from PG_RLSPOLICIES;
-[ RECORD 1 ]----+----------------------------------
schemaname | enmo
tablename | all_data
policyname | all_data_new_rls
policypermissive | PERMISSIVE
policyroles | {alice}
policycmd | ALL
policyqual | ((role)::name = "current_user"())
enmo=> \dt+ all_data
List of relations
-[ RECORD 1 ]---------------------------------
Schema | enmo
Name | all_data
Type | table
Owner | enmo
Size | 8192 bytes
Storage | {orientation=row,compression=no}
Description |
enmo=> SELECT * FROM enmo.all_data;
id | role | data
----+-------+------------
2 | bob | bob data
3 | peter | peter data
4 | ogdb | ogdb data
1 | alice | alice data
(4 rows)
enmo=> \c - alice
Password for user alice:
Non-SSL connection (SSL connection is recommended when requiring high-security)
You are now connected to database "enmo" as user "alice".
enmo=>--行级访问控制策略未对alice用户生效
enmo=> SELECT * FROM enmo.all_data;
id | role | data
----+-------+------------
2 | bob | bob data
3 | peter | peter data
4 | ogdb | ogdb data
1 | alice | alice data
(4 rows)
enmo=> EXPLAIN(COSTS OFF) SELECT * FROM enmo.all_data;
QUERY PLAN
----------------------
Seq Scan on all_data
(1 row)
enmo=>




