访问控制
Categories:
权限控制很重要,但很多用户做不好。因此 Pigsty 提供了一套开箱即用的精简访问控制模型,为您的集群安全性提供一个兜底。
角色系统
Pigsty 默认的角色系统包含四个默认角色和四个默认用户:
角色名称 | 属性 | 所属 | 描述 |
---|---|---|---|
dbrole_readonly |
NOLOGIN |
角色:全局只读访问 | |
dbrole_readwrite |
NOLOGIN |
dbrole_readonly | 角色:全局读写访问 |
dbrole_admin |
NOLOGIN |
pg_monitor,dbrole_readwrite | 角色:管理员/对象创建 |
dbrole_offline |
NOLOGIN |
角色:受限的只读访问 | |
postgres |
SUPERUSER |
系统超级用户 | |
replicator |
REPLICATION |
pg_monitor,dbrole_readonly | 系统复制用户 |
dbuser_dba |
SUPERUSER |
dbrole_admin | pgsql 管理用户 |
dbuser_monitor |
pg_monitor | pgsql 监控用户 |
这些角色与用户的详细定义如下所示:
pg_default_roles: # 全局默认的角色与系统用户
- { name: dbrole_readonly ,login: false ,comment: role for global read-only access }
- { name: dbrole_offline ,login: false ,comment: role for restricted read-only access }
- { name: dbrole_readwrite ,login: false ,roles: [dbrole_readonly] ,comment: role for global read-write access }
- { name: dbrole_admin ,login: false ,roles: [pg_monitor, dbrole_readwrite] ,comment: role for object creation }
- { name: postgres ,superuser: true ,comment: system superuser }
- { name: replicator ,replication: true ,roles: [pg_monitor, dbrole_readonly] ,comment: system replicator }
- { name: dbuser_dba ,superuser: true ,roles: [dbrole_admin] ,pgbouncer: true ,pool_mode: session, pool_connlimit: 16 ,comment: pgsql admin user }
- { name: dbuser_monitor ,roles: [pg_monitor] ,pgbouncer: true ,parameters: {log_min_duration_statement: 1000 } ,pool_mode: session ,pool_connlimit: 8 ,comment: pgsql monitor user }
默认角色
Pigsty 中有四个默认角色:
- 业务只读 (
dbrole_readonly
): 用于全局只读访问的角色。如果别的业务想要此库只读访问权限,可以使用此角色。 - 业务读写 (
dbrole_readwrite
): 用于全局读写访问的角色,主属业务使用的生产账号应当具有数据库读写权限 - 业务管理员 (
dbrole_admin
): 拥有DDL权限的角色,通常用于业务管理员,或者需要在应用中建表的场景(比如各种业务软件) - 离线只读访问 (
dbrole_offline
): 受限的只读访问角色(只能访问 offline 实例,通常是个人用户,ETL工具账号)
默认角色在 pg_default_roles
中定义,除非您确实知道自己在干什么,建议不要更改默认角色的名称。
- { name: dbrole_readonly , login: false , comment: role for global read-only access } # 生产环境的只读角色
- { name: dbrole_offline , login: false , comment: role for restricted read-only access (offline instance) } # 受限的只读角色
- { name: dbrole_readwrite , login: false , roles: [dbrole_readonly], comment: role for global read-write access } # 生产环境的读写角色
- { name: dbrole_admin , login: false , roles: [pg_monitor, dbrole_readwrite] , comment: role for object creation } # 生产环境的 DDL 更改角色
默认用户
Pigsty 也有四个默认用户(系统用户):
- 超级用户 (
postgres
),集群的所有者和创建者,与操作系统 dbsu 名称相同。 - 复制用户 (
replicator
),用于主-从复制的系统用户。 - 监控用户 (
dbuser_monitor
),用于监控数据库和连接池指标的用户。 - 管理用户 (
dbuser_dba
),执行日常操作和数据库更改的管理员用户。
这4个默认用户的用户名/密码通过4对专用参数进行定义,并在很多地方引用:
pg_dbsu
:操作系统 dbsu 名称,默认为 postgres,最好不要更改它pg_dbsu_password
:dbsu 密码,默认为空字符串意味着不设置 dbsu 密码,最好不要设置。pg_replication_username
:postgres 复制用户名,默认为replicator
pg_replication_password
:postgres 复制密码,默认为DBUser.Replicator
pg_admin_username
:postgres 管理员用户名,默认为dbuser_dba
pg_admin_password
:postgres 管理员密码的明文,默认为DBUser.DBA
pg_monitor_username
:postgres 监控用户名,默认为dbuser_monitor
pg_monitor_password
:postgres 监控密码,默认为DBUser.Monitor
在生产部署中记得更改这些密码,不要使用默认值!
pg_dbsu: postgres # 数据库超级用户名,这个用户名建议不要修改。
pg_dbsu_password: '' # 数据库超级用户密码,这个密码建议留空!禁止dbsu密码登陆。
pg_replication_username: replicator # 系统复制用户名
pg_replication_password: DBUser.Replicator # 系统复制密码,请务必修改此密码!
pg_monitor_username: dbuser_monitor # 系统监控用户名
pg_monitor_password: DBUser.Monitor # 系统监控密码,请务必修改此密码!
pg_admin_username: dbuser_dba # 系统管理用户名
pg_admin_password: DBUser.DBA # 系统管理密码,请务必修改此密码!
如果您修改默认用户的参数,在 pg_default_roles
中修改相应的角色定义即可:
- { name: postgres ,superuser: true ,comment: system superuser }
- { name: replicator ,replication: true ,roles: [pg_monitor, dbrole_readonly] ,comment: system replicator }
- { name: dbuser_dba ,superuser: true ,roles: [dbrole_admin] ,pgbouncer: true ,pool_mode: session, pool_connlimit: 16 , comment: pgsql admin user }
- { name: dbuser_monitor ,roles: [pg_monitor, dbrole_readonly] ,pgbouncer: true ,parameters: {log_min_duration_statement: 1000 } ,pool_mode: session ,pool_connlimit: 8 ,comment: pgsql monitor user }
权限系统
Pigsty 拥有一套开箱即用的权限模型,该模型与默认角色一起配合工作。
- 所有用户都可以访问所有模式。
- 只读用户(
dbrole_readonly
)可以从所有表中读取数据。(SELECT,EXECUTE) - 读写用户(
dbrole_readwrite
)可以向所有表中写入数据并运行 DML。(INSERT,UPDATE,DELETE)。 - 管理员用户(
dbrole_admin
)可以创建对象并运行 DDL(CREATE,USAGE,TRUNCATE,REFERENCES,TRIGGER)。 - 离线用户(
dbrole_offline
)类似只读用户,但访问受到限制,只允许访问离线实例(pg_role = 'offline'
或pg_offline_query = true
) - 由管理员用户创建的对象将具有正确的权限。
- 所有数据库上都配置了默认权限,包括模板数据库。
- 数据库连接权限由数据库定义管理。
- 默认撤销
PUBLIC
在数据库和public
模式下的CREATE
权限。
对象权限
数据库中新建对象的默认权限由参数 pg_default_privileges
所控制:
- GRANT USAGE ON SCHEMAS TO dbrole_readonly
- GRANT SELECT ON TABLES TO dbrole_readonly
- GRANT SELECT ON SEQUENCES TO dbrole_readonly
- GRANT EXECUTE ON FUNCTIONS TO dbrole_readonly
- GRANT USAGE ON SCHEMAS TO dbrole_offline
- GRANT SELECT ON TABLES TO dbrole_offline
- GRANT SELECT ON SEQUENCES TO dbrole_offline
- GRANT EXECUTE ON FUNCTIONS TO dbrole_offline
- GRANT INSERT ON TABLES TO dbrole_readwrite
- GRANT UPDATE ON TABLES TO dbrole_readwrite
- GRANT DELETE ON TABLES TO dbrole_readwrite
- GRANT USAGE ON SEQUENCES TO dbrole_readwrite
- GRANT UPDATE ON SEQUENCES TO dbrole_readwrite
- GRANT TRUNCATE ON TABLES TO dbrole_admin
- GRANT REFERENCES ON TABLES TO dbrole_admin
- GRANT TRIGGER ON TABLES TO dbrole_admin
- GRANT CREATE ON SCHEMAS TO dbrole_admin
由管理员新创建的对象,默认将会上述权限。使用 \ddp+
可以查看这些默认权限:
类型 | 访问权限 |
---|---|
函数 | =X |
dbrole_readonly=X | |
dbrole_offline=X | |
dbrole_admin=X | |
模式 | dbrole_readonly=U |
dbrole_offline=U | |
dbrole_admin=UC | |
序列号 | dbrole_readonly=r |
dbrole_offline=r | |
dbrole_readwrite=wU | |
dbrole_admin=rwU | |
表 | dbrole_readonly=r |
dbrole_offline=r | |
dbrole_readwrite=awd | |
dbrole_admin=arwdDxt |
默认权限
SQL 语句 ALTER DEFAULT PRIVILEGES
允许您设置将来创建的对象的权限。 它不会影响已经存在对象的权限,也不会影响非管理员用户创建的对象。
在 Pigsty 中,默认权限针对三个角色进行定义:
{% for priv in pg_default_privileges %}
ALTER DEFAULT PRIVILEGES FOR ROLE {{ pg_dbsu }} {{ priv }};
{% endfor %}
{% for priv in pg_default_privileges %}
ALTER DEFAULT PRIVILEGES FOR ROLE {{ pg_admin_username }} {{ priv }};
{% endfor %}
-- 对于其他业务管理员而言,它们应当在执行 DDL 前执行 SET ROLE dbrole_admin,从而使用对应的默认权限配置。
{% for priv in pg_default_privileges %}
ALTER DEFAULT PRIVILEGES FOR ROLE "dbrole_admin" {{ priv }};
{% endfor %}
这些内容将会被 PG集群初始化模板 pg-init-template.sql
所使用,在集群初始化的过程中渲染并输出至 /pg/tmp/pg-init-template.sql
。
该命令会在 template1
与 postgres
数据库中执行,新创建的数据库会通过模板 template1
继承这些默认权限配置。
也就是说,为了维持正确的对象权限,您必须用管理员用户来执行 DDL,它们可以是:
{{ pg_dbsu }}
,默认为postgres
{{ pg_admin_username }}
,默认为dbuser_dba
- 授予了
dbrole_admin
角色的业务管理员用户(通过SET ROLE
切换为dbrole_admin
身份)。
使用 postgres
作为全局对象所有者是明智的。如果您希望以业务管理员用户身份创建对象,创建之前必须使用 SET ROLE dbrole_admin
来维护正确的权限。
当然,您也可以在数据库中通过 ALTER DEFAULT PRIVILEGE FOR ROLE <some_biz_admin> XXX
来显式对业务管理员授予默认权限。
数据库权限
在 Pigsty 中,数据库(Database)层面的权限在数据库定义中被涵盖。
数据库有三个级别的权限:CONNECT
、CREATE
、TEMP
,以及一个特殊的’权限’:OWNERSHIP
。
- name: meta # 必选,`name` 是数据库定义中唯一的必选字段
owner: postgres # 可选,数据库所有者,默认为 postgres
allowconn: true # 可选,是否允许连接,默认为 true。显式设置 false 将完全禁止连接到此数据库
revokeconn: false # 可选,撤销公共连接权限。默认为 false,设置为 true 时,属主和管理员之外用户的 CONNECT 权限会被回收
- 如果
owner
参数存在,它作为数据库属主,替代默认的{{ pg_dbsu }}
(通常也就是postgres
) - 如果
revokeconn
为false
,所有用户都有数据库的CONNECT
权限,这是默认的行为。 - 如果显式设置了
revokeconn
为true
:- 数据库的
CONNECT
权限将从PUBLIC
中撤销:普通用户无法连接上此数据库 CONNECT
权限将被显式授予{{ pg_replication_username }}
、{{ pg_monitor_username }}
和{{ pg_admin_username }}
CONNECT
权限将GRANT OPTION
被授予数据库属主,数据库属主用户可以自行授权其他用户连接权限。
- 数据库的
revokeconn
选项可用于在同一个集群间隔离跨数据库访问,您可以为每个数据库创建不同的业务用户作为属主,并为它们设置revokeconn
选项。
示例:数据库隔离
pg-infra:
hosts:
10.10.10.40: { pg_seq: 1, pg_role: primary }
10.10.10.41: { pg_seq: 2, pg_role: replica , pg_offline_query: true }
vars:
pg_cluster: pg-infra
pg_users:
- { name: dbuser_confluence, password: mc2iohos , pgbouncer: true, roles: [ dbrole_admin ] }
- { name: dbuser_gitlab, password: sdf23g22sfdd , pgbouncer: true, roles: [ dbrole_readwrite ] }
- { name: dbuser_jira, password: sdpijfsfdsfdfs , pgbouncer: true, roles: [ dbrole_admin ] }
pg_databases:
- { name: confluence , revokeconn: true, owner: dbuser_confluence , connlimit: 100 }
- { name: gitlab , revokeconn: true, owner: dbuser_gitlab, connlimit: 100 }
- { name: jira , revokeconn: true, owner: dbuser_jira , connlimit: 100 }
CREATE权限
出于安全考虑,Pigsty 默认从 PUBLIC
撤销数据库上的 CREATE
权限,从 PostgreSQL 15 开始这也是默认行为。
数据库属主总是可以根据实际需要,来自行调整 CREATE 权限。