访问控制
角色系统、权限模型、数据库权限详解。
访问控制决定了用户登录后可以执行哪些操作。Pigsty 提供了一套开箱即用的角色权限模型,遵循最小权限原则。
角色系统
Pigsty 默认定义了四个业务角色和四个系统用户:
业务角色
| 角色 | 权限 | 用途 |
|---|---|---|
dbrole_readonly |
SELECT | 只读访问,用于报表、监控 |
dbrole_readwrite |
SELECT, INSERT, UPDATE, DELETE | 读写访问,用于应用程序 |
dbrole_admin |
+ CREATE, TRUNCATE | 对象管理,用于业务管理员 |
dbrole_offline |
SELECT(仅离线实例) | 受限只读,用于 ETL、分析 |
系统用户
| 用户 | 权限 | 用途 |
|---|---|---|
postgres |
SUPERUSER | 系统超级用户,仅本地访问 |
replicator |
REPLICATION | 流复制用户 |
dbuser_dba |
SUPERUSER + dbrole_admin | 数据库管理员 |
dbuser_monitor |
pg_monitor | 监控系统用户 |
角色层次
┌──────────────────┐
│ postgres │
│ (SUPERUSER) │
└────────┬─────────┘
│
┌──────────────┼──────────────┐
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌─────────┐ ┌──────────────────┐
│ dbuser_dba │ │replicator│ │ dbuser_monitor │
│ (SUPERUSER) │ │ (REPL) │ │ (pg_monitor) │
└────────┬────────┘ └─────────┘ └──────────────────┘
│
▼
┌─────────────────┐
│ dbrole_admin │
│ (CREATE, DDL) │
└────────┬────────┘
│
▼
┌─────────────────┐
│ dbrole_readwrite│
│ (INSERT, etc.) │
└────────┬────────┘
│
▼
┌─────────────────┐
│ dbrole_readonly │
│ (SELECT) │
└─────────────────┘
┌─────────────────┐
│ dbrole_offline │ (独立分支,受限访问)
│ (SELECT) │
└─────────────────┘
权限模型
对象权限
Pigsty 通过 ALTER DEFAULT PRIVILEGES 预设了对象权限:
| 对象类型 | dbrole_readonly | dbrole_readwrite | dbrole_admin |
|---|---|---|---|
| SCHEMA | USAGE | USAGE | USAGE, CREATE |
| TABLE | SELECT | SELECT, INSERT, UPDATE, DELETE | + TRUNCATE |
| SEQUENCE | SELECT | SELECT, UPDATE | + ALL |
| FUNCTION | EXECUTE | EXECUTE | EXECUTE |
数据库权限
| 权限 | 说明 |
|---|---|
| CONNECT | 允许连接到数据库 |
| CREATE | 允许在数据库中创建 Schema |
| TEMP | 允许创建临时表 |
创建业务用户
基本用户
pg_users:
- name: dbuser_app
password: 'AppUserPassword123!'
roles: [dbrole_readwrite] # 继承读写权限
pgbouncer: true # 添加到连接池
comment: 'Application user'
只读用户
pg_users:
- name: dbuser_readonly
password: 'ReadOnlyPassword123!'
roles: [dbrole_readonly]
pgbouncer: true
comment: 'Read-only user for reporting'
管理员用户
pg_users:
- name: dbuser_admin
password: 'AdminPassword123!'
roles: [dbrole_admin]
pgbouncer: true
comment: 'Business admin user'
数据库权限控制
限制数据库访问
使用 revokeconn 限制数据库连接权限:
pg_databases:
- name: secret_db
owner: dbuser_secret
revokeconn: true # 只有 owner 和管理员可连接
设置 revokeconn: true 后:
- PUBLIC 的 CONNECT 权限被撤销
- 只有 owner 和系统用户可以连接
- owner 可以授权其他用户
数据库隔离
在同一集群中隔离多个业务数据库:
pg_databases:
- name: app1_db
owner: dbuser_app1
revokeconn: true
- name: app2_db
owner: dbuser_app2
revokeconn: true
pg_users:
- name: dbuser_app1
roles: [dbrole_admin]
- name: dbuser_app2
roles: [dbrole_admin]
这样 dbuser_app1 无法访问 app2_db,反之亦然。
权限最佳实践
遵循最小权限
- 应用程序使用
dbrole_readwrite,不要使用dbrole_admin - 只有需要创建对象时才授予
dbrole_admin - 禁止应用程序使用 SUPERUSER
权限分离
| 角色 | 用户 | 职责 |
|---|---|---|
| DBA | dbuser_dba |
运维管理、紧急处理 |
| 业务管理员 | 自定义 + dbrole_admin |
Schema 变更、DDL |
| 应用程序 | 自定义 + dbrole_readwrite |
业务读写 |
| 报表系统 | 自定义 + dbrole_readonly |
只读查询 |
| ETL | 自定义 + dbrole_offline |
离线分析 |
使用角色继承
通过角色继承简化权限管理:
pg_users:
# 业务角色(不可登录)
- name: role_app1
login: false
roles: [dbrole_readwrite]
# 实际用户继承角色
- name: user_app1_prod
roles: [role_app1]
pgbouncer: true
- name: user_app1_dev
roles: [role_app1]
pgbouncer: true
行级安全(RLS)
PostgreSQL 支持行级安全策略,可实现细粒度的数据访问控制。
启用 RLS
-- 创建表
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
user_id INT,
amount DECIMAL
);
-- 启用 RLS
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
-- 创建策略:用户只能看到自己的订单
CREATE POLICY user_orders ON orders
FOR ALL
USING (user_id = current_setting('app.user_id')::INT);
配置用户
pg_users:
- name: app_user
bypassrls: false # 不允许绕过 RLS
roles: [dbrole_readwrite]