访问控制

角色系统、权限模型、数据库权限详解。

访问控制决定了用户登录后可以执行哪些操作。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]