南大通用GBase 8c提供安全权限机制、行级访问控制等数据库安全功能,本文简述下这些安全功能的语法使用。
(1)默认权限机制
数据库对象创建后,进行对象创建的用户就是该对象的所有者。数据库安装后的默认情况下,未开启三权分立,数据库系统管理员具有与对象所有者相同的权限。也就是说对象创建后,默认只有对象所有者或者系统管理员可以查询、修改和销毁对象,以及通过GRANT 将对象的权限授予其他用户。为使其他用户能够使用对象,必须向用户或包含该用户的角色授予必要的权限。
GBase 8c 支持以下的权限:SELECT、INSERT、UPDATE、DELETE、TRUNCATE、 REFERENCES、CREATE、CONNECT、EXECUTE、USAGE、ALTER、DROP、COMMENT、 INDEX 和 VACUUM。不同的权限与不同的对象类型关联。
要撤消已经授予的权限,可以使用 REVOKE。对象所有者的权限(例如 ALTER、DROP、COMMENT、INDEX、VACUUM、GRANT 和 REVOKE) 是隐式拥有的,即只要拥有对象就可以执行对象所有者的这些隐式权限。对象所有者可以撤消自己的普通权限,例如,使表对自己以及其他人只读,系统管理员用户除外。
系统表和系统视图要么只对系统管理员可见,要么对所有用户可见。标识了需要系统管理员权限的系统表和视图只有系统管理员可以查询。
数据库提供对象隔离的特性,对象隔离特性开启时,用户只能查看有权限访问的对象 (表、视图、字段、函数),系统管理员不受影响。
(2)用户权限设置
- 给用户直接授予某对象的权限,请使用 GRANT。
将 Schema 中的表或者视图对象授权给其他用户或角色时,需要将表或视图所属 Schema的 USAGE 权限同时授予该用户或角色。否则用户或角色将只能看到这些对象的名称, 并不能实际进行对象访问。
例如,下面示例将 Schema tpcds 的权限赋给用户 joe 后,将表 tpcds.web_returns 的 select权限赋给用户 joe。
GRANT USAGE ON SCHEMA tpcds TO joe;
GRANT SELECT ON TABLE tpcds.web_returns to joe;
- 给用户指定角色,使用户继承角色所拥有的对象权限
a、创建角色。例如,新建一个角色 lily,同时给角色指定系统权限 CREATEDB:
postgres=# CREATE ROLE lily WITH CREATEDB PASSWORD "test;123";
b、给角色赋予对象权限,请使用GRANT。 例如,将模式 tpcds 的权限赋给角色 lily 后,将表 tpcds.web_returns 的 select 权限赋给角色 lily。
postgres=# GRANT USAGE ON SCHEMA tpcds TO lily;
postgres=# GRANT SELECT ON TABLE tpcds.web_returns to lily;
c、将角色的权限赋予用户。
postgres=# GRANT lily to joe;
d、当将角色的权限赋予用户时,角色的属性并不会传递到用户。
e、回收用户权限,请使用 REVOKE。
(3)行级访问控制
行级访问控制特性将数据库访问控制精确到数据表行级别,使数据库达到行级访问控制的能力。不同用户执行相同的 SQL 查询操作,读取到的结果是不同的。 用户可以在数据表创建行访问控制(Row Level Security)策略,该策略是指针对特定数据库用户、特定 SQL 操作生效的表达式。当数据库用户对数据表访问时,若 SQL 满足数据表特定的 Row Level Security 策略,在查询优化阶段将满足条件的表达式,按照属性(PERMISSIVE | RESTRICTIVE)类型,通过 AND 或 OR 方式拼接,应用到执行计划上。 行级访问控制的目的是控制表中行级数据可见性,通过在数据表上预定义 Filter,在查询优化阶段将满足条件的表达式应用到执行计划上,影响最终的执行结果。当前受影响的SQL 语句包括 SELECT,UPDATE,DELETE。
示例:某表中汇总了不同用户的数据,但是不同用户只能查看自身相关的数据信息, 不能查看其他用户的数据信息。
--创建用户 alice, bob, peter
postgres=# CREATE USER alice PASSWORD ‘test;123’;
postgres=# CREATE USER bob PASSWORD 'test;123';
postgres=# CREATE USER peter PASSWORD 'test;123';
--创建表 all_data,包含不同用户数据信息
postgres=# CREATE TABLE all_data(id int, role varchar(100), data varchar(100));
--向数据表插入数据
postgres=# INSERT INTO all_data VALUES(1, 'alice', 'alice data');
postgres=# INSERT INTO all_data VALUES(2, 'bob', 'bob data');
postgres=# INSERT INTO all_data VALUES(3, 'peter', 'peter data');
--将表 all_data 的读取权限赋予 alice,bob 和 peter 用户
postgres=# GRANT SELECT ON all_data TO alice, bob, peter;
--打开行访问控制策略开关
postgres=# ALTER TABLE all_data ENABLE ROW LEVEL SECURITY;
--创建行访问控制策略,当前用户只能查看用户自身的数据
postgres=# CREATE ROW LEVEL SECURITY POLICY all_data_rls ON all_data USING(role = CURRENT_USER);
--查看表详细信息
postgres=# \d+ all_data
Table "public.all_data"
Column |
Type| Modifiers | Storage | Stats target | Description
--------+------------------------+-----------+----------+--------------+-------------
USING (((role)::name = "current_user"())) Has OIDs: no
Location Nodes: ALL DATANODES
Options: orientation=row, compression=no, enable_rowsecurity=true
--切换至用户 alice,执行 SQL"SELECT * FROM public.all_data"
postgres=# \q
gsql -d postgres -p 5432 -U alice
postgres=> SELECT * FROM public.all_data;
id | role | data
----+-------+------------
1 | alice | alice data (1 row)
postgres=> EXPLAIN(COSTS OFF) SELECT * FROM public.all_data;
QUERY PLAN
----------------------------------------------------------------
Streaming (type: GATHER) Node/s: All datanodes
-> Seq Scan on all_data
Filter: ((role)::name = 'alice'::name)
Notice: This query is influenced by row level security feature (5 rows)
--切换至用户 peter,执行 SQL"SELECT * FROM public.all_data"
postgres=# \q
gsql -d postgres -p 5432 -U peter
postgres=> SELECT * FROM public.all_data;
id | role | data
----+-------+------------
3 | peter | peter data (1 row)
gbase=> EXPLAIN(COSTS OFF) SELECT * FROM public.all_data;
QUERY PLAN
----------------------------------------------------------------
Streaming (type: GATHER) Node/s: All datanodes
-> Seq Scan on all_data
Filter: ((role)::name = 'peter'::name)
Notice: This query is influenced by row level security feature (5 rows)
注意事项
PG_STATISTIC系统表和PG_STATISTIC_EXT系统表存储了统计对象的一些敏感信息,如高频值 MCV。若创建行级访问控制后,将这两张系统表的查询权限授予普通用户,则普通用户仍然可以通过访问这两张系统表,得到统计对象里的这些信息。