这是本节的多页打印视图。
点击此处打印.
返回本页常规视图.
安全合规
Pigsty 以安全即代码的方式管理认证、授权、加密、审计与备份恢复,并提供从默认配置到生产加固的清晰路径。
数据库通常是信息系统中最敏感的组件:它保存着最有价值的数据,也因此是攻击与故障后果最严重的地方。
数据库安全并不是某个可以一键开启的功能,而是一系列问题的答案之和:谁能连进来?连进来能做什么?流量会不会被窃听?操作有没有留痕?数据坏了、丢了、被删了,还能不能恢复?
Pigsty 把这些问题的答案沉淀为一套 开箱即用的安全基线,并用 声明式配置 的方式加以管理:
HBA 规则、角色与权限、证书与加密、备份与审计策略,全部以 参数 的形式在 配置清单 中声明,由幂等剧本渲染落地。
这种 安全即代码(Security as Code)的做法本身就是一项重要的安全实践:安全策略可以被版本控制、评审与回溯,配置清单为多实例环境提供统一基线。
当审计者问“谁能访问这个数据库”时,可以先从一份可读的 YAML 声明出发,再用实际生成的 HBA 与数据库授权验证它是否已经生效。
安全即代码
在传统运维中,安全配置散落在各个角落:某台服务器上的 pg_hba.conf,某位 DBA 手工执行过的 GRANT 语句,某次应急时临时放开的防火墙规则。
时间一长,文档与实际状态容易出现偏差,也很难快速确认各实例正在使用哪一版规则。
Pigsty 的做法不同:安全策略是集群定义的一部分,与集群的其他属性写在一起。
pg-meta:
hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
vars:
pg_cluster: pg-meta
pg_users: # 谁可以登录:账号、角色与过期时间
- { name: dbuser_app ,password: '<独立随机口令>' ,roles: [dbrole_readwrite] ,expire_in: 365 }
pg_databases: # 数据库及其隔离策略
- { name: app ,owner: dbuser_app ,revokeconn: true }
pg_hba_rules: # 谁能从哪里、以何种方式连接
- { user: dbuser_app ,db: app ,addr: 10.1.0.0/16 ,auth: ssl ,order: 50 ,title: 'app access via ssl' }
用户、权限、HBA 规则以声明的方式描述,剧本负责把它们幂等地应用到集群的每个实例上:
新加入的实例可以沿用同一套策略,git 提交历史也可以记录安全配置的变更。手工执行的 GRANT、运行时参数修改和节点文件变更仍可能造成漂移,因此生产环境还需要定期核对实际状态。
默认安全基线
合理的默认值可以减少遗漏。以下能力在 Pigsty 默认配置下即处于启用状态:
有所取舍的加固项
默认配置面向运行在受信内网中的部署,一部分安全能力需要显式启用 —— 它们或有性能与兼容性代价,或需要用户提供额外的决策:
安全加固模板 ha/safe 将 TLS、证书认证、密码检查和备份加密等配置组合在一起,
并配合面向一致性优先业务的 CRIT 参数模板 给出一份可直接修改的示例。模板中的公开凭据、审计扩展与故障模型仍需逐项确认。
完整的升级路径见 安全模型。
本章内容
| 章节 | 回答的问题 |
|---|
| 安全模型 | 信任的根在哪里?防线有几道?如何从默认基线逐步加固? |
| 身份认证 | 谁能连进来?如何证明身份?HBA 规则如何声明与生效? |
| 访问控制 | 连进来之后能做什么?最小权限如何成为默认行为? |
| 加密通信 | 流量如何加密?证书由谁签发、如何分发与轮换? |
| 数据安全 | 数据如何保证完整、可恢复、保密、可追溯? |
| 合规实践 | 如何把安全能力映射到等保与 SOC 2 的控制要求? |
相关话题
概念层之外,以下页面提供操作层面的安全内容:
1 - 安全模型
Pigsty 的信任边界与纵深防御体系:管理节点作为高信任控制面,从默认基线逐步完成生产加固。
在讨论具体的安全特性之前,值得先回答两个更基本的问题:信任的根在哪里,以及 防线有几道。
前者决定了你应该重点保护什么,后者决定了当某一道防线失守时,你还剩下什么。
信任边界
Pigsty 是一套基于 Ansible 的声明式部署系统,它的信任模型与其他控制平面系统类似:管理节点 就是控制平面,也是整个部署中最需要保护的节点。
| 角色 | 掌握的资产与权限 |
|---|
| 管理节点(Admin Node) | 配置清单 pigsty.yml(通常包含系统与业务凭据)、CA 私钥、对所有节点的 SSH 管理权限 |
| INFRA 节点 | 监控告警、DNS、Nginx 入口、软件仓库 |
| 数据库节点 | 数据库实例、本地 dbsu、受限 sudo |
| 客户端 | 数据库凭据或客户端证书,经服务端口、HBA 与认证进入 |
这些角色掌握的能力不同,并不是简单的线性等级。其中三份资产尤其关键:
- 配置清单
pigsty.yml:包含所有组件的密码与凭证。应当严格控制管理节点与配置仓库(如果使用 git 管理)的访问权限。 - CA 私钥
files/pki/ca/ca.key:整个部署的信任锚点,持有它就可以签发任意受信证书。文件权限为 0600,存放于 0700 的目录中,建议离线备份。 - 管理用户的 SSH 私钥:管理节点通过 SSH 免密 sudo 管理所有纳管节点,这份私钥等价于所有节点的 root 权限。
Pigsty 的 安全策略 对此有明确表述:需要管理节点访问权限、或已持有 pigsty.yml 与 CA 私钥才能实施的攻击,不被视作安全漏洞 ——
这些是设计上的高信任控制面,必须以相应的等级加以保护。
七道防线
纵深防御不依赖某一项机制独立解决所有问题,而是让不同控制相互补充。
Pigsty 的安全能力可以归纳为七道防线:
| # | 防线 | 机制 | 详见 |
|---|
| 1 | 网络边界 | 防火墙分区、监听地址收敛、统一入口 | 本页下文 |
| 2 | 传输加密 | 本地 CA、组件间 TLS | 加密通信 |
| 3 | 身份认证 | HBA 规则集、SCRAM 密码、客户端证书 | 身份认证 |
| 4 | 访问控制 | 角色体系、默认权限、数据库隔离 | 访问控制 |
| 5 | 主机安全 | SELinux、受限 sudo、专用系统用户 | 本页下文 |
| 6 | 数据安全 | 校验和、备份与加密、PITR、防误删 | 数据安全 |
| 7 | 审计追溯 | DDL 与连接日志、审计扩展、集中日志 | 数据安全 |
其中第 2、3、4、6、7 道防线各有专门章节展开,这里补充说明网络与主机两道防线。
网络边界
Pigsty 在节点置备时默认启用防火墙(node_firewall_mode 默认为 zone 模式),按操作系统使用 firewalld 或 ufw 实现:
内网网段(10.0.0.0/8、172.16.0.0/12、192.168.0.0/16,由 node_firewall_intranet 定义)加入信任区,
公网侧仅放行 node_firewall_public_port 声明的端口,默认为 22(SSH)、80、443(Web)。
默认演示配置 pigsty.yml 中额外放行了 5432 端口以便本地体验,生产部署通常应当移除。确需直接接入数据库时,应通过安全组、防火墙与 HBA 将来源限制到明确网段。
数据库默认监听所有地址(pg_listen:0.0.0.0),实际访问范围由监听地址、防火墙与 HBA 共同决定。对于要求更严格的场景,可以将监听收敛到特定地址:
pg_listen: '${ip},${vip},${lo}' # 仅监听主机 IP、集群 VIP 与本地环回地址
默认防火墙不会直接向公网开放 Grafana、VictoriaMetrics 等 Web 基础设施,外部访问通常经由 Nginx 门户 反向代理接入;
数据库流量则通过 HAProxy 提供的 服务 端口接入。入口越少,越容易加固,也越容易审计。
主机安全
主机层的核心原则:每个系统用户只拥有完成本职工作所需的最小权限。
- 数据库超级用户
postgres(pg_dbsu)默认 不设密码,只能通过本地 ident 认证登录数据库,无法远程以超级用户身份进入。
它的 sudo 权限由 pg_dbsu_sudo 控制,默认为 limit 模式:仅允许免密执行数据库相关服务的 systemctl 操作与日志查看,而不是完整的 root 权限。 - 管理用户(
node_admin_username,默认 dba)供运维人员与剧本使用,默认拥有免密 sudo(nopass);
安全敏感的环境可通过 node_admin_sudo 改为 all(sudo 需输入密码)或 limit(限制命令集)。 - SELinux 由
node_selinux_mode 控制,默认为 permissive 模式:记录违规行为但不阻断,为切换到 enforcing 强制模式积累基线。
Pigsty 不接管 SSH 服务端配置:禁用口令登录、限制 root 远程登录等操作系统级加固不在剧本管理范围内,应当纳入您自己的主机安全基线。
加固梯度
安全水位的提升不必一步到位。Pigsty 提供了一条清晰的升级路径,每一档都建立在前一档之上:
第一档:默认基线。开箱即用的安全能力包括 SCRAM 密码、数据校验和、本地 CA 与组件证书、分层 HBA、四层角色模型、默认备份和防火墙分区。
它适合受信内网中的开发、测试与验证环境;生产部署还需要继续检查凭据、网络边界和客户端验证。
第二档:随机凭证。默认密码是公开写在文档里的,任何暴露于网络的部署都必须更换。在生成配置时加上 -g 选项,可以随机化配置向导识别的内置参数和示例凭据:
./configure -g # --generate:随机化向导识别的默认凭据
该选项不会替换 pgBackRest 的 cipher_pass、ha/safe 中的全部 MinIO 示例凭据,也不会处理用户自定义值。完整范围见 默认凭证清单。
第三档:策略加固(ha/safe 模板)。配置模板 conf/ha/safe.yml 将多项安全配置组合为一份可以继续定制的参考:
- TLS 与证书认证:主要 TCP HBA 规则使用
ssl,公网管理员使用客户端证书;PgBouncer 启用 require,Patroni API 启用 HTTPS。本地 ident 与部分 localhost 口令规则仍然保留。 - 密码策略:显式预加载
passwordcheck,并为内置用户声明 expire_in;模板中的示例口令仍需在部署前检查和替换。 - 攻击面收敛:监听地址收敛至
${ip},${vip},${lo},监控与管理账号从公网访问连接池被显式拒绝。 - 备份加密:pgBackRest 使用 MinIO 仓库并启用 AES-256-CBC;
pgBR.${pg_cluster} 是可预测的示例值,必须替换。 - 安全扩展:安装
passwordcheck、credcheck、pgaudit、pgsodium、anonymizer 等安全相关扩展;安装不等于预加载、创建或配置。
第四档:内核加固(crit.yml 参数模板)。safe 模板默认为集群指定了面向核心业务的 CRIT 参数模板,它相对通用的 oltp 模板:
- 强制启用数据校验和,不受
pg_checksum 参数影响; - 启用严格同步复制(
synchronous_mode_strict),没有可用同步副本时阻塞需要同步确认的写入; - 记录连接与断开事件;PostgreSQL 18 还会区分连接接收、认证与授权阶段;
- 将 watchdog 配置为
automatic,仅在系统存在可用设备时启用。
严格同步模式以不丢失已确认事务为目标,但仍依赖 synchronous_commit、同步副本状态和故障切换条件;RPO 需要通过目标拓扑上的故障演练验证。
也可以不使用完整模板,只挑选需要的加固项,声明在集群或全局参数中:
pg-meta:
hosts:
10.10.10.10: { pg_seq: 1 , pg_role: primary }
10.10.10.11: { pg_seq: 2 , pg_role: replica }
10.10.10.12: { pg_seq: 3 , pg_role: replica }
vars:
pg_cluster: pg-meta
pg_conf: crit.yml # 使用 crit 内核参数模板
patroni_ssl_enabled: true # Patroni API 启用 HTTPS
pgbouncer_sslmode: require # Pgbouncer 强制 TLS
pg_listen: '${ip},${vip},${lo}' # 监听地址收敛
pg_libs: '$libdir/passwordcheck, pg_stat_statements, auto_explain' # 密码强度检查
接下来
2 - 身份认证
Pigsty 以声明式方式管理 PostgreSQL 与 PgBouncer 的 HBA 规则,配合 SCRAM 密码与客户端证书,回答“谁能连进来、如何证明身份”。
PostgreSQL 使用 pg_hba.conf 进行 基于主机的认证(Host-Based Authentication):谁(用户)、从哪里(来源地址)、访问什么(数据库)、需要以何种方式证明身份(认证方法)。
这套机制足够强大,但在集群环境中手工维护的成本很高:主库与从库可能需要不同规则,配置文件又分布在每个实例的数据目录中。
如果缺少统一声明和刷新流程,各实例的规则很容易发生漂移。
Pigsty 的答案与 声明式配置 一脉相承:HBA 规则是配置清单的一部分,由剧本统一渲染与下发。
HBA 即代码
集群的 HBA 规则由两组参数拼接而成:全局默认规则 pg_default_hba_rules 与集群自定义规则 pg_hba_rules;
PgBouncer 连接池 另有独立的两组对应参数(pgb_default_hba_rules 与 pgb_hba_rules)。
每条规则可以用两种形式书写。别名形式 是推荐的方式,一条规则一行,语义一目了然:
pg_hba_rules:
- { user: dbuser_app ,db: app ,addr: 10.1.0.0/16 ,auth: ssl ,order: 50 ,title: 'app user access via ssl' }
原始形式 则直接给出 pg_hba.conf 的原文,用于表达别名覆盖不了的特殊规则。
除了四要素之外,规则还有两个控制字段:
order:渲染顺序。HBA 按“先匹配先生效”的原则工作,顺序即优先级。约定 0-99 保留给用户的高优先级规则,100-999 是默认规则集,未指定 order 的规则排在最后。role:实例角色过滤。common 与 default 规则对所有实例生效;primary、replica、offline、standby、delayed 规则仅在对应角色的实例上启用;
role: offline 的规则还会额外下发给标记了 pg_offline_query 的实例。同一份声明渲染到不同实例,得到的是各自角色对应的规则 —— 主从差异不再需要手工维护。
修改声明后,使用封装好的脚本应用变更,规则会被重新渲染并重载生效:
bin/pgsql-hba pg-meta # 重新渲染并应用 pg-meta 集群的 HBA 规则
pg_hba_rules 用于追加规则,不会自动收窄范围更宽的默认规则。需要建立更严格的边界时,应同时审查 pg_default_hba_rules,并在变更后检查各实例实际生成的 pg_hba.conf。
地址与认证别名
别名形式的价值在于把常见场景抽象为语义化的词汇。addr 字段的别名展开为具体的地址块:
| 别名 | 展开为 | 含义 |
|---|
local | Unix Socket | 仅本地套接字 |
localhost | Unix Socket、127.0.0.1/32 与 ::1/128 | 本机 |
admin | <admin_ip>/32 | 管理节点 |
infra | 各 INFRA 节点的 /32 地址 | 基础设施节点 |
cluster | 集群各成员的 /32 地址 | 集群内部 |
intra | 10.0.0.0/8、172.16.0.0/12、192.168.0.0/16 | 内网网段,可通过 node_firewall_intranet 定制 |
world | 0.0.0.0/0 与 ::/0 | 任意地址 |
| CIDR 地址 | 原样保留 | 自定义网段 |
auth 字段的别名决定认证方法,以及是否强制 TLS 连接:
| 别名 | 认证方法 | 说明 |
|---|
deny | reject | 显式拒绝 |
trust | trust | 无条件放行,慎用 |
pwd | scram-sha-256 或 md5 | 依 pg_pwd_enc 而定,默认 SCRAM |
sha | scram-sha-256 | 强制 SCRAM |
md5 | md5 | 兼容旧客户端 |
ssl | hostssl 与密码认证 | 密码认证,且必须走 TLS |
ssl-sha | hostssl 与 scram-sha-256 | TLS 与强制 SCRAM |
cert | hostssl 与 cert | 客户端证书认证 |
ident、os | ident(PgBouncer 中为 peer) | 操作系统用户映射 |
peer | peer | 本地操作系统用户 |
用户字段支持四个占位符,渲染时替换为实际用户名:${dbsu}(超级用户)、${repl}(复制用户)、${monitor}(监控用户)、${admin}(管理用户);
+role 前缀表示匹配该角色的所有成员。
这里还要区分两件事:auth: ssl 只要求连接使用 TLS,并不要求客户端验证服务端身份。安全敏感的客户端还应使用 sslmode=verify-full 和可信 CA,详见 加密通信。
默认规则解读
Pigsty 的默认 HBA 规则集体现了一个简单的原则:来源越远,要求越严。以下是 PostgreSQL 侧的默认规则(源码原文):
pg_default_hba_rules: # postgres default host-based authentication rules, order by `order`
- {user: '${dbsu}' ,db: all ,addr: local ,auth: ident ,title: 'dbsu access via local os user ident' ,order: 100}
- {user: '${dbsu}' ,db: replication ,addr: local ,auth: ident ,title: 'dbsu replication from local os ident' ,order: 150}
- {user: '${repl}' ,db: replication ,addr: localhost ,auth: pwd ,title: 'replicator replication from localhost',order: 200}
- {user: '${repl}' ,db: replication ,addr: intra ,auth: pwd ,title: 'replicator replication from intranet' ,order: 250}
- {user: '${repl}' ,db: postgres ,addr: intra ,auth: pwd ,title: 'replicator postgres db from intranet' ,order: 300}
- {user: '${monitor}' ,db: all ,addr: localhost ,auth: pwd ,title: 'monitor from localhost with password' ,order: 350}
- {user: '${monitor}' ,db: all ,addr: infra ,auth: pwd ,title: 'monitor from infra host with password',order: 400}
- {user: '${admin}' ,db: all ,addr: infra ,auth: ssl ,title: 'admin @ infra nodes with pwd & ssl' ,order: 450}
- {user: '${admin}' ,db: all ,addr: world ,auth: ssl ,title: 'admin @ everywhere with ssl & pwd' ,order: 500}
- {user: '+dbrole_readonly',db: all ,addr: localhost ,auth: pwd ,title: 'pgbouncer read/write via local socket',order: 550}
- {user: '+dbrole_readonly',db: all ,addr: intra ,auth: pwd ,title: 'read/write biz user via password' ,order: 600}
- {user: '+dbrole_offline' ,db: all ,addr: intra ,auth: pwd ,title: 'allow etl offline tasks from intranet',order: 650}
逐层来看:
- 本地最受信任:超级用户
postgres 只能通过本地 Unix Socket 以 ident 方式进入 —— 不需要密码,但也无法在远程使用。这就是为什么 dbsu 默认不设密码:不存在可以被窃取的口令。 - 内网次之:复制与业务账号在内网使用 SCRAM 口令认证;监控和管理用户的远程访问主要面向 INFRA 节点。
- 公网最严:默认只有管理员可以从任意地址访问,且必须同时提供口令与 TLS 连接。
PgBouncer 侧的默认规则更保守一层:监控与管理账号从公网访问连接池会被显式 deny,业务用户则限定在本机与内网。
需要特别说明,默认 +dbrole_offline 规则没有设置 role,因此会应用到所有实例。要把离线用户限制到 pg_role: offline 或设置了 pg_offline_query: true 的实例,必须在对应 HBA 规则上显式增加 role: offline。
这份默认规则集是“可用性优先”的取舍:业务账号在内网使用口令认证即可接入。
ha/safe 模板将主要 TCP 规则改为 ssl,管理员从非内网位置访问必须持有客户端证书(cert);本地 ident 与部分 localhost 口令规则仍然保留。
密码策略
Pigsty 默认使用 PostgreSQL 官方推荐的 scram-sha-256 算法存储密码(pg_pwd_enc),仅在需要兼容老旧客户端时才应降级为 md5。
密码处理链路会在执行 ALTER USER ... PASSWORD 前临时关闭语句日志(SET log_statement TO 'none'),避免口令进入 PostgreSQL 日志。
但明文口令仍会出现在配置清单中,渲染后的用户 SQL 也会以 0640 权限写入 /pg/tmp/pg-user-<name>.sql;相关任务没有完整使用 Ansible no_log。因此应限制管理节点、配置仓库和自动化输出的访问,并避免对含凭据任务使用 --diff。
密码强度默认不做强制,需要时可以预加载 passwordcheck 扩展,或使用规则更丰富的 credcheck 扩展:
pg_libs: '$libdir/passwordcheck, pg_stat_statements, auto_explain' # 拒绝弱密码
ha/safe 模板显式设置了上述 pg_libs;单独选择 CRIT 参数模板不会自动加载 passwordcheck。
账号有效期通过用户定义中的 expire_in(自创建起天数)或 expire_at(截止日期)声明,配合组织的密码轮换制度使用:
pg_users:
- { name: dbuser_app ,password: '<独立随机口令>' ,roles: [dbrole_readwrite] ,expire_in: 365 }
证书认证
口令终究可能被钓鱼、复用或撞库。对管理员这样的高权限账号,可以在 HBA 中使用 auth: cert 要求 客户端证书认证:
客户端必须持有由本地 CA 签发、CN 与数据库用户名一致的证书才能建立连接。在 HBA 仅接受 cert 的前提下,单独泄露口令不足以通过认证。
使用内置的 cert.yml 剧本签发客户端证书:
./cert.yml -e cn=dbuser_dba # 为 dbuser_dba 签发客户端证书,默认有效期 20 年
./cert.yml -e cn=dbuser_dba -e expire=365d # 或指定较短的有效期
签发的证书位于 files/pki/misc/<cn>.key 与 files/pki/misc/<cn>.crt。客户端私钥应通过受控渠道交付;客户端仍需使用 verify-full 验证数据库服务端,证书体系详见 加密通信。
连接池与组件 API
数据库本体之外,还有两类入口需要认证:
PgBouncer 连接池 使用独立的 HBA 规则集与用户列表。默认关闭 pgbouncer_auth_query,此时只有声明了 pgbouncer: true 的用户才会进入 userlist.txt 并通过连接池认证;启用动态认证查询后,应重新评估可登录用户范围。
Patroni REST API 承载高可用控制指令(重启、切换、重载配置),写操作要求 HTTP Basic 认证(patroni_username 与 patroni_password),
且来源受地址白名单限制;启用 patroni_ssl_enabled 后 API 全程走 HTTPS。
Grafana、HAProxy 管理界面、MinIO、etcd 等组件的凭证同样在配置清单中声明,完整清单与修改方式见 合规实践。
接下来
3 - 访问控制
Pigsty 内置四层角色模型与默认权限模板,将最小权限原则落实为可声明、可复用的集群配置。
认证 回答“你是谁”,授权回答“你能做什么”。
权限失控很少是因为缺少机制 —— PostgreSQL 的 GRANT 与 REVOKE 足够精细。问题在于缺少一套被默认执行的约定:
业务上线时直接把账号设为属主;临时排障授予超级用户后没有及时回收;新表创建后遗漏授权,最终在生产环境触发权限错误。
Pigsty 提供了一套开箱即用的基础访问控制模型作为起点:四层角色、默认权限与数据库隔离。
它减少了逐库手工授权,但仍需要部署方按业务边界分配角色,并定期核对实际权限。

角色体系
Pigsty 默认创建四个 业务角色 —— 它们不可登录,作为权限组使用:
| 角色 | 属性 | 继承 | 用途 |
|---|
dbrole_readonly | NOLOGIN | - | 全局只读访问 |
dbrole_readwrite | NOLOGIN | dbrole_readonly | 全局读写(DML),业务账号的默认选择 |
dbrole_admin | NOLOGIN | dbrole_readwrite、pg_monitor | 对象创建(DDL),管理与发布流程使用 |
dbrole_offline | NOLOGIN | - | 独立只读角色,可配合 HBA 限制到离线实例 |
以及四个 系统用户,各自只承担一种职责:
| 用户 | 属性 | 用途 |
|---|
postgres | SUPERUSER | 数据库超级用户:不设密码,仅限本地 ident 登录 |
replicator | REPLICATION | 流复制与备份,附带 pg_monitor 与只读权限 |
dbuser_dba | SUPERUSER | 日常管理用户,继承 dbrole_admin |
dbuser_monitor | - | 监控用户,仅持有 pg_monitor 与只读权限 |
业务账号通过 roles 字段挂载到角色组上,权限随继承而来:
pg_users:
- { name: dbuser_app ,password: '...' ,roles: [dbrole_readwrite] } # 常规业务账号
- { name: dbuser_report ,password: '...' ,roles: [dbrole_readonly] } # 报表只读账号
- { name: dbuser_etl ,password: '...' ,roles: [dbrole_offline] } # 离线 ETL 账号
角色体系本身也是声明的一部分(pg_default_roles),可以定制。
该参数是一份完整列表;调整时应保留所需的系统用户与默认角色,并同步检查 HBA、默认权限和脚本中的角色引用。
默认权限
角色解决了“权限授予谁”,还剩下另一半问题:新创建的对象如何自动获得正确的权限?
PostgreSQL 的原生答案是 ALTER DEFAULT PRIVILEGES。Pigsty 通过 pg_default_privileges 将其声明化:
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
只读角色获得查询与执行权限,读写角色叠加 DML,管理角色再增加对象管理所需的 DDL 辅助权限。
所有权约定
默认权限机制有一个经常被忽略的前提:它只对配置了默认权限的对象创建者生效。Pigsty 会为以下身份配置默认权限:
- 数据库系统用户
pg_dbsu,默认为 postgres; - 管理用户
pg_admin_username,默认为 dbuser_dba; dbrole_admin;- 每个在
pg_databases 中声明的数据库属主。
应用 DDL 通常应使用声明的数据库属主;平台级管理与发布操作可以使用 dbuser_dba,或先 SET ROLE dbrole_admin。由其他用户直接创建的对象不会自动进入这套默认权限体系,除非另行为该用户配置 ALTER DEFAULT PRIVILEGES。
这不是 Pigsty 的限制,而是 PostgreSQL 默认权限机制本身的工作方式:默认权限跟随对象创建者,而不是数据库或会话中的登录用户名自动传播。
数据库隔离
默认情况下,PostgreSQL 向 PUBLIC 授予数据库 CONNECT 权限。只要 HBA 同时允许连接,可登录用户就可能进入并不属于自己的数据库;多业务共享集群时尤其需要收敛这一默认值。
在数据库定义中声明 revokeconn,即可回收公共连接权限:
pg_databases:
- { name: app_a ,owner: dbuser_a ,revokeconn: true }
- { name: app_b ,owner: dbuser_b ,revokeconn: true }
启用后,该数据库上 PUBLIC 的 CONNECT 权限被撤销,只显式授予复制、监控、管理用户与数据库属主 ——
属主获得带 GRANT OPTION 的连接权限,可以自行决定向谁开放访问。在没有其他角色继承或额外授权的前提下,app_a 的账号将无法连接 app_b。
与之配套,集群初始化时还会回收数据库与 public 模式上 PUBLIC 的 CREATE 权限:
REVOKE CREATE ON DATABASE app FROM PUBLIC;
REVOKE CREATE ON SCHEMA public FROM PUBLIC;
普通用户不再能在公共数据库或模式中随意创建对象,从而降低不安全 search_path 与对象覆盖带来的风险。
PostgreSQL 15 起已经收紧 public 模式的默认 CREATE 权限;Pigsty 将这项边界统一应用到所有受支持的大版本上。
离线角色与实例隔离
dbrole_offline 的设计用途,是为 ETL、报表和个人查询提供一组独立的只读权限。但角色本身只控制对象权限,并不会自动限制用户连接到哪类实例。
当前默认 HBA 中,+dbrole_offline 的内网规则没有设置 role,因此会应用到所有实例。要把它限制到 pg_role: offline 的专用实例,或标记了 pg_offline_query: true 的普通从库,需要在完整的 pg_default_hba_rules 列表中修改这一条规则:
pg_default_hba_rules:
# 复制并保留其他默认规则,仅修改离线角色这一条
- { user: '+dbrole_offline', db: all, addr: intra, auth: pwd, role: offline, order: 650,
title: 'allow offline users on offline instances' }
定义 pg_default_hba_rules 会替换整组默认值,不能只保留示例中的一条。只有当 HBA 已按实例角色过滤,且用户没有同时继承其他可登录角色时,这类高消耗查询才会被限制到离线实例。资源隔离还应配合 独立服务入口、连接数和查询资源控制。
数据库之外
最小权限原则同样贯彻到主机层面:
- 超级用户
postgres 不设密码,只能本地 ident 登录;其 sudo 权限默认限制在数据库相关服务的启停与日志查看(pg_dbsu_sudo:limit)。 - 监控用户
dbuser_monitor 默认持有 pg_monitor、只读角色与专用 monitor 模式权限,不具备业务表写权限。 - 复制用户
replicator 被显式授予备份恢复所需的目录函数执行权限,而不是笼统的超级用户。
接下来
4 - 加密通信
Pigsty 内置自签名 CA,为受管组件签发证书并分发信任,提供统一的 TLS 基础设施。
TLS 可以提供三类保护:传输加密、服务端身份验证与 客户端身份验证。这三项能力需要分别配置:启用服务端 TLS 并不等于客户端已经验证了服务端身份,也不等于服务端要求客户端证书。
TLS 的主要运维成本不在加密算法本身,而在证书的签发、分发、信任与轮换。缺少统一管理时,内网服务往往只启用加密,却跳过证书验证,或者干脆继续使用明文连接。
Pigsty 的做法是把 PKI 也纳入声明式管理:部署时自动创建本地自签名 CA,为受管组件签发证书并分发信任,让 TLS 在部署完成后即可使用。
本地 CA
首次执行部署时,Pigsty 会在 管理节点 上检查并按需创建 CA:
| 文件 | 说明 | 权限 |
|---|
files/pki/ca/ca.key | CA 私钥:整个部署的信任根,务必妥善保管 | 0600(目录 0700) |
files/pki/ca/ca.crt | CA 根证书:可以自由分发 | 0644 |
- CA 的行为由
ca_create 控制:CA 文件已存在则原样复用(幂等),不存在则新建;
设为 false 时若找不到 CA 文件,部署会直接报错中止,防止意外生成新的信任根。 - CA 证书的 CN 由
ca_cn 指定,默认 pigsty-ca;密钥为 RSA 4096 位。 - 有效期:CA 根证书 100 年,组件证书默认 20 年(
cert_validity:7300d)。
面向浏览器的 Nginx 证书是例外,当前默认有效期为 397 天。
较长的默认有效期用于降低私有基础设施的初始维护成本,并不意味着生产环境无需轮换。组织已有证书策略时,应缩短有效期,并建立到期监控和换证流程。
信任分发
签发证书只是一半,另一半是让每个 节点 信任这些证书。节点纳入管理时,Pigsty 将 CA 证书分发到所有节点的 /etc/pki/ca.crt,并链接进操作系统信任链:
- EL 系(RHEL、Rocky、Alma):链接至
/etc/pki/ca-trust/source/anchors/ 并执行 update-ca-trust - Debian、Ubuntu:链接至
/usr/local/share/ca-certificates/ 并执行 update-ca-certificates
此后,使用操作系统信任库的客户端(例如 curl)可以验证 Pigsty CA 签发的证书。
CA 证书还会发布到 Nginx 门户 的站点根目录(ca.crt),供浏览器与外部客户端下载安装。
PostgreSQL 的 libpq 客户端需要单独说明:它默认使用 ~/.postgresql/root.crt,默认 sslmode 为 prefer,不会直接使用操作系统信任库验证服务端身份。
客户端验证服务端
安全敏感的 PostgreSQL 客户端应使用 sslmode=verify-full,并指定 Pigsty CA:
psql "host=pg-meta dbname=postgres user=dbuser_dba sslmode=verify-full sslrootcert=/etc/pki/ca.crt"
verify-full 会同时验证证书链与连接主机名,因此客户端使用的 DNS 名称或 IP 地址必须出现在服务端证书的 SAN 中。外部客户端需要先安装 ca.crt,或通过 sslrootcert 指定 CA 文件。
证书矩阵
本地 CA 为下列组件签发证书,构成统一的信任链:
表中的“加密状态”一列如实反映了默认配置的取舍:
- 部署时启用:PostgreSQL 服务端可以接受 SSL 连接,etcd 的客户端与对等通信使用 TLS。
- 默认加密:MinIO(备份流量)与 Nginx(Web 流量)默认启用 HTTPS。
- 默认关闭,按需启用:Patroni REST API 与 PgBouncer 的 TLS 默认关闭,证书已经就位,可以通过相应参数开启;
ha/safe 模板中两者均默认开启。
还有一层需要分清的区别:服务端支持 SSL 不等于强制客户端使用 SSL,更不等于客户端验证了服务端身份。
是否强制加密由 HBA 规则 决定(auth: ssl 或 cert);是否验证服务端则由客户端的 sslmode 与信任配置决定。默认规则仅对任意来源的管理员连接强制 TLS,safe 模板将主要 TCP 规则改为 ssl 或 cert,但仍保留本地 ident 与部分 localhost 口令规则。
客户端证书
内置剧本 cert.yml 用于签发客户端证书。证书的 CN 对应数据库用户名,供 HBA 的 cert 认证方式使用:
./cert.yml -e cn=dbuser_dba # 为 dbuser_dba 签发客户端证书,默认有效期 20 年
./cert.yml -e cn=dbuser_dba -e expire=365d # 或指定更短的有效期
签发结果位于 files/pki/misc/<cn>.key 与 files/pki/misc/<cn>.crt。客户端私钥应通过受控渠道交付,并设置为仅对应用户可读。客户端证书解决服务端对客户端身份的验证,客户端仍需使用 verify-full 验证数据库服务端。
使用企业 CA
如果组织已有 PKI 体系,可以让 Pigsty 改用您的 CA(或由企业根 CA 签出的中间 CA)签发证书:把证书与私钥放到指定位置即可,剧本检测到已有 CA 后不会重新生成:
files/pki/ca/ca.key # 您的 CA 私钥(或中间 CA 私钥)
files/pki/ca/ca.crt # 对应的 CA 证书
同时建议设置 ca_create: false:这样当文件缺失时部署会显式失败,避免意外创建新的自签名 CA,破坏既有的信任链。
密钥保护与轮换
- CA 私钥只存在于管理节点上。它与
pigsty.yml 一起构成部署中信任等级最高的资产(参见 信任边界),建议离线备份。 - CA 私钥一旦泄露,需要建立新的信任根并重新签发全部组件与客户端证书。执行前应规划新旧 CA 的信任过渡,避免一次性中断所有连接。
- 组件证书的签发源保存在管理节点的
files/pki/<component>/,节点上的证书只是部署副本。仅删除节点上的证书会重新复制原证书,不会触发重新签发。轮换时应更新或删除管理节点上的对应证书源,再执行相关剧本,并按组件要求重载或滚动重启。
接下来
- 🔑 身份认证:用 HBA 决定谁必须走 SSL 与证书
- 🔒 数据安全:静态数据与备份的加密
- ✅ 合规实践:证书管理的合规证据
5 - 数据安全
使用校验和、备份与 PITR、加密和审计日志保护 PostgreSQL 数据的完整性、可恢复性、保密性与可追溯性。
网络边界、身份认证 和 权限控制 用于降低事件发生的概率;当硬件损坏、口令泄露或误操作已经发生时,还需要依靠数据层机制控制影响并完成恢复。
数据安全要回答四个问题:数据是 完整 的吗?丢了能 恢复 吗?被拿走了会 泄密 吗?发生了什么能 查清 吗?
完整性
磁盘坏块、内存位翻转、存储固件缺陷,都可能造成 静默数据损坏:数据坏了,但没有任何报错。
Pigsty 默认启用页级数据校验和(pg_checksum:true),
集群初始化时以 data-checksums 建库,PostgreSQL 会在页面写入时计算校验和,并在读取时检查页面损坏。
页校验和主要发现存储介质、I/O 路径或写入后发生的页面损坏,不能检测所有内存错误、逻辑错误或应用写入的错误数据,也不能替代备份。
CRIT 参数模板 更进一步:校验和强制启用,不受参数影响;
同时启用 严格同步复制(synchronous_mode_strict),在没有可用同步副本时阻塞需要同步确认的写入。
该模式以不丢失已确认事务为目标,但仍依赖客户端没有降低 synchronous_commit、同步副本正常参与提交,以及故障切换只选择包含所需 WAL 的节点。RPO 需要通过目标拓扑上的故障演练验证。
可恢复性
副本主要处理节点故障,备份则处理误删除、逻辑错误、集群损坏和更大范围的灾难。
高可用 可以缩短主库故障造成的中断,但如果有人误删了数据,复制也会把误操作同步到其他副本。备份因此无可替代。
Pigsty 默认启用 pgBackRest(pgbackrest_enabled):
基础备份加上持续归档的 WAL,构成 时间点恢复(PITR)能力,可以将集群恢复到备份与 WAL 保留窗口内的目标时刻。
备份仓库由 pgbackrest_method 选择:
| 仓库 | 位置 | 默认保留策略 | 加密 |
|---|
local(默认) | 本地 /pg/backup 目录 | 最近 2 份全量备份 | 无 |
minio | MinIO 或 S3 对象存储 | 14 天 | AES-256-CBC |
对于防误删场景,还有两项辅助机制:
备份的存在不等于恢复的能力。恢复演练应当成为例行工作:原理与决策见 时间点恢复,配置与操作见 PGSQL 备份恢复。
保密性
静态数据的保密性分三层展开:
备份加密。MinIO 备份仓库默认启用 AES-256-CBC 加密,但默认加密口令(pgBackRest)是公开的,生产环境必须修改。
ha/safe 模板按集群名称区分加密口令:
pgbackrest_repo:
minio:
cipher_type: aes-256-cbc
cipher_pass: 'pgBR.${pg_cluster}' # 示例值,部署前必须替换
pgBR.${pg_cluster} 是可预测的示例值,configure -g 也不会替换它。生产环境应使用独立随机口令,并与备份分开保存;口令丢失会导致备份无法恢复。
本地备份仓库默认不加密。加密可以降低备份文件被单独复制或介质被盗时的泄露风险,但如果密钥与备份位于同一主机,保护效果仍会受到限制。
传输加密。备份上传 MinIO 走 HTTPS,PostgreSQL 客户端与流复制可以通过 HBA 强制 SSL。客户端还应验证服务端证书,详见 加密通信。
静态加密。PostgreSQL 上游内核目前没有通用的内置透明数据加密(TDE),Pigsty 提供两条现实路径:
使用 Percona PostgreSQL 内核的 pg_tde 扩展实现表级透明加密(参见 pgtde 配置模板);
或使用 pgsodium、pgcrypto、anonymizer 等 安全扩展 在列级实现加密与脱敏 —— safe 模板已预装这一类扩展。
此外,全盘加密(LUKS、dm-crypt)在操作系统层解决介质被盗问题,与数据库层方案互补。
审计与追溯
出了问题,要能回答“谁在什么时候做了什么”。Pigsty 的日志审计分层递进:
默认基线:所有 DDL 语句被记录(log_statement: ddl),执行超过 100ms 的查询被记录(log_min_duration_statement: 100),
PostgreSQL 18 及以上版本还会记录连接授权事件。
CRIT 模板:记录连接与断开事件(log_connections 与 log_disconnections);PostgreSQL 18 还会区分连接接收、认证与授权阶段。
pgaudit 扩展:需要语句级的细粒度审计(对象级读写、按角色审计)时,安装 pgaudit 并加入 pg_libs 预加载。
safe 模板已预装该扩展,加载与审计策略需按需求显式声明。
启用 INFRA 日志组件并完成 Vector 配置后,PostgreSQL 日志会汇入 VictoriaLogs 集中存储(默认保留 15 天,可按合规要求调整)。
日志和指标为安全事件的检索、告警与回溯提供输入,但事件判定、响应和证据保全仍需要配套流程。
接下来
6 - 合规实践
合规是配置、流程与证据的组合:上线加固清单、等保与 SOC 2 控制点映射、供应链完整性与漏洞响应机制。
合规不是一个可以购买的产品,而是一种需要持续证明的状态。它由三部分组成:
- 配置:安全能力是否启用 —— 这部分由 Pigsty 直接提供;
- 流程:权限审批、变更管理、恢复演练等制度 —— 需要组织自行建立;
- 证据:能证明前两者持续有效的记录 —— Pigsty 的 配置清单、运行日志和 监控系统 可以提供其中一部分。
本页从上线前的加固清单开始,给出 Pigsty 安全能力与常见合规框架的映射关系。
这些映射用于方案设计和差距分析,不构成等保测评结论、SOC 2 审计意见或法律建议。
默认凭证清单
Pigsty 的默认凭证公开写在文档与源码中,仅供演示与本地开发使用。任何生产部署或暴露于网络的部署,上线前必须修改所有适用的默认值:
| 范围 | 默认值示例 | configure -g |
|---|
| Grafana 管理员与只读用户 | pigsty、DBUser.Viewer | 是 |
| HAProxy 管理界面 | pigsty | 是 |
| PostgreSQL 管理、监控、复制用户 | DBUser.DBA、DBUser.Monitor、DBUser.Replicator | 是 |
| Patroni REST API | Patroni.API | 是 |
| etcd root | Etcd.Root | 是 |
| MinIO root | S3User.MinIO | 是 |
| MinIO 备份与示例业务用户 | S3User.Backup、S3User.Meta、S3User.Data | 是 |
| 示例数据库用户 | DBUser.Meta、DBUser.Supa、Vibe.Coding | 是 |
| pgBackRest 加密口令 | cipher_pass: pgBackRest | 否 |
ha/safe 中的 MinIO 用户与 pgBR.${pg_cluster} | 模板示例值 | 否 |
| 用户自行添加的凭据 | 自定义值 | 否 |
生成配置时可以使用 -g,随机化配置向导识别的内置参数和示例字符串:
./configure -g # 生成配置清单,并随机化向导识别的默认凭据
配置向导会把生成的密码输出到终端,因此终端记录和自动化日志也应按敏感信息保护。生成完成后还要检查配置文件,单独替换 pgBackRest cipher_pass、ha/safe 中未覆盖的 MinIO 示例值和自定义凭据。
上线加固清单
部署前:
部署后:
周期性:
合规证据
声明式配置为合规审计提供了稳定的证据入口,但还需要保留运行时状态,证明配置已经应用并持续有效。
| 证据 | 来源 |
|---|
| 安全配置基线及其变更历史 | pigsty.yml 配置清单与 Git 提交记录 |
| 访问控制矩阵 | pg_default_roles、pg_users 与 pg_hba_rules 声明 |
| 实际生效的认证规则 | 各实例渲染出的 pg_hba.conf,用于与声明比较并发现漂移 |
| 实际用户与权限 | PostgreSQL 系统目录、数据库 ACL、\du+ 与 \ddp+ |
| 操作与连接日志 | PostgreSQL 日志(DDL、慢查询、连接),VictoriaLogs 集中留存 |
| 备份记录 | pgBackRest 备份信息与监控面板 |
| 安全事件与告警记录 | 监控系统告警历史 |
| 证书清单 | files/pki/ 目录与各组件部署证书 |
等保三级映射
《GB/T 22239-2019》三级要求中“安全计算环境”部分与 Pigsty 能力的对应关系:
| 控制要求 | Pigsty 能力 | 需要补充 |
|---|
| 身份鉴别唯一性 | 独立账号体系,SCRAM-SHA-256 密码存储 | 账号实名管理制度 |
| 口令复杂度与定期更换 | passwordcheck、credcheck 扩展,expire_in 账号过期 | 启用扩展;轮换制度 |
| 登录失败处理 | 可借助 credcheck 等扩展实现 | 按需启用与配置 |
| 访问控制与最小权限 | 四层角色模型、默认权限与数据库隔离 | 权限审批流程 |
| 安全审计 | DDL、连接、慢查询日志,pgaudit,集中日志留存 | CRIT 模板或手工启用连接日志;留存周期按要求调整 |
| 通信保密性 | 本地 CA 与 TLS,HBA 强制 ssl 或 cert | 强制 TLS、客户端 verify-full 与证书轮换 |
| 数据完整性 | 页级校验和(默认启用),严格同步复制(CRIT) | 存储保护、故障模型与演练 |
| 数据保密性 | 备份 AES 加密,TDE 与列级加密路径 | 按需启用 |
| 数据备份恢复 | pgBackRest、PITR 与远端仓库(MinIO) | 恢复演练制度 |
| 剩余信息保护 | - | 介质销毁与擦除流程 |
等保还包括安全物理环境、安全通信网络、安全管理制度等部分,超出数据库发行版的能力范畴:
Pigsty 可以支持“安全计算环境”中与数据库相关的部分技术控制,机房、网络设备与管理制度仍需在整体方案中补足。
SOC 2 映射
SOC 2 信任服务准则(TSC)中与数据库直接相关的部分控制点:
| 控制点 | Pigsty 能力 | 需要补充 |
|---|
| CC6.1 逻辑访问安全 | HBA、RBAC、默认权限与数据库隔离 | 权限设计、审批与定期复核 |
| CC6.2 用户注册与授权 | 声明式用户、角色和有效期 | 入职、变更、离职和身份核验流程 |
| CC6.3 访问变更与撤销 | pg_users、角色调整、REVOKE 与到期时间 | 工单、授权批准和及时回收证据 |
| CC6.6 外部边界威胁 | 防火墙、监听地址、HBA 与管理入口限制 | 网络架构、边界设备和持续验证 |
| CC6.7 信息传输与移动 | TLS、客户端验证与备份加密 | 数据导出、介质和第三方传输策略 |
| CC7.2 系统监控 | Victoria 可观测性栈,数千项指标与告警 | 告警响应流程 |
| CC7.3 事件追溯 | 集中日志,审计扩展 | 日志审查流程 |
| A1.2 可用性与恢复 | 高可用 与 PITR | 演练记录与 RTO、RPO 目标 |
供应链与漏洞响应
合规审查越来越关注软件供应链,Pigsty 在分发与响应侧提供以下保障:
包完整性:Pigsty 软件仓库(repo.pigsty.io、repo.pigsty.cc)中的 RPM、DEB 包经 GPG 签名,
公钥指纹为 9592 A7BC 7A68 2E73 3337 6E09 E793 5D8D B9BD 8B20(B9BD8B20),可在信任前核验。但部署时写入的仓库定义以及 INFRA 节点 上的本地仓库,默认不强制逐包签名验证;生产环境应检查包管理器的仓库信任与验签设置。
漏洞响应:安全问题通过 GitHub 私有漏洞报告或邮件渠道私下披露(参见 SECURITY.md),
项目目标是在 3 个工作日内确认、7 天内给出初步评估。
版本支持:安全修复随最新稳定版发布,保持升级是获得安全修复的方式;需要长期锁定版本的用户,可通过 订阅服务 获得延长支持。
接下来