账号权限体系
PostgreSQL 的权限管理模型,是一种典型的 RBAC(基于角色的权限控制)的实现。其将用户、角色、权限通过此模型管理起来。
PostgreSQL 中的“用户”概念和“角色”概念实际是等同的,唯一的区别在于“用户”拥有 login 权限,而“角色”拥有 nologin 权限。
PostgreSQL 的权限可以分为两类,“系统权限”和“数据库对象权限”。PostgreSQL 通过角色来进行权限管理,角色可以拥有系统权限和数据库对象权限。并且也可以作为一组权限集合,授予给其他的角色或者用户。
可以通过授予角色/用户相应的系统权限和对象权限来对数据库进行管理。
系统权限
系统权限是指可以执行特定数据库操作的权限。PostgreSQL 中使用“角色属性(Role Attributes)” 和“默认角色(Default Roles)”两种方式来管理系统权限。
角色属性
角色属性可以在 CREATE ROLE 时指定,或者通过 ALTER ROLE 来修改。角色属性保存在 pg_authid 系统表中。
CREATE ROLE 语法如下:
CREATE ROLE name [ [ WITH ] option [ ... ] ]where option can be:SUPERUSER | NOSUPERUSER| CREATEDB | NOCREATEDB| CREATEROLE | NOCREATEROLE| INHERIT | NOINHERIT| LOGIN | NOLOGIN| REPLICATION | NOREPLICATION| BYPASSRLS | NOBYPASSRLS| CONNECTION LIMIT connlimit| [ ENCRYPTED ] PASSWORD 'password' | PASSWORD NULL| VALID UNTIL 'timestamp'| IN ROLE role_name [, ...]| IN GROUP role_name [, ...]| ROLE role_name [, ...]| ADMIN role_name [, ...]| USER role_name [, ...]| SYSID uid
其中 superuser 角色属性可以绕过所有的权限检查,执行数据库的任何操作,是数据库中的最高权限。superuser 权限类似于 Linux 操作系统 root 权限。
注意:
应安全要求,腾讯云数据库 PostgreSQL 关闭了 superuser 权限的使用。但因为部分操作必须要求 superuser 进行,所以云数据库 PostgreSQL 提供了 tencentdb_superuser 角色,请参见 用户与权限操作。
默认角色
PostgreSQL 提供了一组默认角色,这些角色提供对某些通常需要特权功能和信息的访问。管理员可以将这些角色授予其他用户或角色,使这些用户可以访问指定的功能和信息。下表列举了 PostgreSQL 11 中支持的 默认角色。
角色 | 允许的操作 |
pg_execute_server_program | 允许通过部分能够执行操作语句的函数或者功能去执行相应的操作系统语句。 |
pg_monitor | 读取和执行与监控相关的函数或视图的权限,这个角色包含 pg_read_all_settings、 pg_read_all_stats 和 pg_stat_scan_tables。 |
pg_read_all_settings | 读取所有配置信息,包括部分 superuser 才能看到的信息。 |
pg_read_all_stats | 阅读所有 pg_stat_* 视图并使用各种与统计相关的扩展,包括部分 superuser 才可见的信息。 |
pg_read_server_files | 允许通过 copy 或者文件访问的函数读取数据库所在服务器的一些拥有权限的文件。 |
pg_signal_backend | 可以通过向后端发出指令使某一个会话启动或者停止。 |
pg_stat_scan_tables | 执行可能需要长时间锁定表(ACCESS SHARE 锁)的监控功能。 |
pg_write_server_files | 允许通过 copy 或者文件访问的函数写入数据库所在服务器的一些拥有权限的文件。 |
public | 隐藏角色,代表所有人,如果赋予一个权限给 public,那么所有角色就拥有了此权限。有一些对象是有赋予给 public 角色默认权限的。 |
数据库对象权限
数据库对象权限使用 ACL(Access Control List)进行控制。下表给出了 PostgreSQL 中所有的数据库对象权限及其缩写。
权限 | 缩写 | 支持的对象 |
SELECT | r (“read”) | LARGE OBJECT、SEQUENCE、TABLE (and table-like objects)、table column |
INSERT | a (“append”) | TABLE、table column |
UPDATE | w (“write”) | LARGE OBJECT、SEQUENCE、TABLE、table column |
DELETE | d | TABLE |
TRUNCATE | D | TABLE |
REFERENCES | x | TABLE、table column |
TRIGGER | t | TABLE |
CREATE | C | DATABASE、SCHEMA、TABLESPACE |
CONNECT | c | DATABASE |
TEMPORARY | T | DATABASE |
EXECUTE | X | FUNCTION、PROCEDURE |
USAGE | U | DOMAIN、FOREIGN DATA WRAPPER、FOREIGN SERVER、LANGUAGE、SCHEMA、SEQUENCE、TYPE |
下表中列出了每一种对象拥有的权限以及通过 psql 查询权限命令:
对象类型 | 所有权限 | 默认角色 Pubilc 的权限 | psql 查看权限的命令 |
DATABASE | CTc | Tc | \\l |
DOMAIN | U | U | \\dD+ |
FUNCTION or PROCEDURE | X | X | \\df+ |
FOREIGN DATA WRAPPER | U | none | \\dew+ |
FOREIGN SERVER | U | none | \\des+ |
LANGUAGE | U | U | \\dL+ |
LARGE OBJECT | rw | none | - |
SCHEMA | UC | none | \\dn+ |
SEQUENCE | rwU | none | \\dp |
TABLE (and table-like objects) | arwdDxt | none | \\dp |
Table column | arwx | none | \\dp |
TABLESPACE | C | none | \\db+ |
TYPE | U | U | \\dT+ |
PostgreSQL 中使用 aclitem 来表示一个具体的数据库对象上的权限。对于 database 和 schema,aclitem 存储在 pg_database.datacl 和 pg_namespace.nspacl 中,对于 table,view 等其他数据库对象,pg_class.relacl 中保存了 aclitem 的一个 list。对于列级别的权限,aclitem 将保存在 pg_attribute.attacl 中。
例如,normal_user=a*r/test1 表示 normal_user 这个用户对于当前数据库对象拥有 INSERT和 SELECT 权限,其中 INSERT 权限带有 with grant option,表示可以授权其他用户该权限。最后的 /test1 表示这条 aclitem 权限是 test1 授予的。
postgres=# \\dpAccess privilegesSchema | Name | Type | Access privileges | Column privileges | Policies--------+------+-------+-------------------+-------------------+----------public | t1 | table | test1=arwdDxt/test1 | |(1 rows)postgres=# grant select on t1 to normal_user;GRANTpostgres=# grant insert on t1 to normal_user with grant option;GRANTpostgres=# grant update on t1 to public;GRANTpostgres=# grant select (a) on t1 to test2;GRANTpostgres=# \\dpAccess privilegesSchema | Name | Type | Access privileges | Column privileges | Policies--------+------+-------+-----------------------+-------------------+----------public | t1 | table | test1=arwdDxt/test1 +| a: +|| | | normal_user=a*r/test1+| test2=r/test1 || | | =w/test1 | |(1 rows)-- =w/test1 表示 test1 授予了 public 角色 UPDATE 权限