身份认证
HBA 规则、密码策略、证书认证详解。
身份认证是安全的第一道防线,确保只有合法用户才能访问数据库。Pigsty 支持多种认证方式,并通过 HBA(Host-Based Authentication)规则进行精细控制。
HBA 规则
HBA 规则决定了"谁可以从哪里用什么方式连接"。
规则结构
pg_hba_rules:
- user: '<用户>' # 用户名或角色,支持 + 前缀表示角色成员
db: '<数据库>' # 数据库名,all 表示所有
addr: '<地址>' # 来源地址,支持别名
auth: '<方法>' # 认证方法
title: '<说明>' # 规则说明(可选)
地址别名
| 别名 | 含义 |
|---|---|
local |
本地 Unix Socket |
localhost |
127.0.0.1/32 |
intra |
内网 CIDR(由 pg_intranet 定义) |
infra |
基础设施节点 IP |
world |
0.0.0.0/0(所有地址) |
认证方法别名
| 别名 | 实际方法 | 说明 |
|---|---|---|
deny |
reject |
拒绝连接 |
pwd |
scram-sha-256 |
密码认证 |
ssl |
scram-sha-256 + hostssl |
SSL + 密码 |
cert |
cert |
客户端证书 |
trust |
trust |
无条件信任(不推荐) |
ident/peer |
ident/peer |
OS 用户映射 |
默认规则
pg_default_hba_rules:
# dbsu 本地免密访问
- {user: '${dbsu}', db: all, addr: local, auth: ident}
- {user: '${dbsu}', db: replication, addr: local, auth: ident}
# 复制用户
- {user: '${repl}', db: replication, addr: localhost, auth: pwd}
- {user: '${repl}', db: replication, addr: intra, auth: pwd}
# 监控用户
- {user: '${monitor}', db: all, addr: localhost, auth: pwd}
- {user: '${monitor}', db: all, addr: infra, auth: pwd}
# 管理员(强制 SSL)
- {user: '${admin}', db: all, addr: infra, auth: ssl}
- {user: '${admin}', db: all, addr: world, auth: ssl}
# 业务用户
- {user: '+dbrole_readonly', db: all, addr: localhost, auth: pwd}
- {user: '+dbrole_readonly', db: all, addr: intra, auth: pwd}
- {user: '+dbrole_offline', db: all, addr: intra, auth: pwd}
密码策略
密码加密
Pigsty 默认使用 SCRAM-SHA-256,这是 PostgreSQL 支持的最安全的密码哈希算法:
pg_pwd_enc: scram-sha-256
密码存储
密码可以在配置中使用明文或哈希值:
pg_users:
# 明文密码(部署时自动加密)
- name: dbuser_app
password: 'MySecurePassword123!'
# 已加密的哈希值
- name: dbuser_app
password: 'SCRAM-SHA-256$4096:xxx...'
密码强度检查
启用 passwordcheck 扩展强制密码复杂度:
pg_libs: 'passwordcheck, pg_stat_statements, auto_explain'
或使用功能更丰富的 credcheck 扩展:
pg_extensions:
- credcheck
密码有效期
设置用户密码过期时间:
pg_users:
- name: temp_user
password: 'xxx'
expire_in: 30 # 30 天后过期
- name: contract_user
password: 'xxx'
expire_at: '2024-12-31' # 指定日期过期
证书认证
证书认证提供比密码更强的安全性,可实现双因素认证。
工作原理
- 客户端持有由 CA 签发的证书
- 证书的 CN(Common Name)字段对应数据库用户名
- 服务器验证证书有效性并提取用户名
配置步骤
第一步:签发客户端证书
# 使用 Pigsty 提供的脚本签发证书
./cert.yml -e cn=dbuser_app
证书生成在 files/pki/misc/dbuser_app.{key,crt}。
第二步:配置 HBA 规则
pg_hba_rules:
- user: dbuser_app
db: all
addr: world
auth: cert
title: 'App user with certificate'
第三步:客户端使用证书连接
psql "host=pg-test port=5432 dbname=app \
sslmode=verify-full \
sslcert=dbuser_app.crt \
sslkey=dbuser_app.key \
sslrootcert=ca.crt"
双因素认证
结合密码和证书实现双因素认证:
pg_hba_rules:
# 需要证书 + 密码
- user: secure_user
db: all
addr: world
auth: cert
# 在 PostgreSQL 中还需要配置 clientcert=verify-full
客户端需要同时提供:
- 有效的客户端证书
- 正确的密码
登录失败处理
日志记录
PostgreSQL 默认记录认证失败:
LOG: connection received: host=192.168.1.100 port=45678
FATAL: password authentication failed for user "hacker"
告警配置
配置 VictoriaMetrics 告警规则监控认证失败。
自动封禁(可选)
可配合 fail2ban 自动封禁频繁失败的 IP:
# /etc/fail2ban/jail.local
[postgresql]
enabled = true
filter = postgresql
action = iptables[name=PostgreSQL, port=5432, protocol=tcp]
logpath = /pg/log/postgres/postgresql-*.log
maxretry = 5
bantime = 3600
认证故障排查
常见问题
问题:FATAL: no pg_hba.conf entry for host
原因:没有匹配的 HBA 规则
解决:检查 pg_hba.conf 并添加适当的规则
问题:FATAL: password authentication failed
原因:密码错误或用户不存在
解决:验证用户名和密码
问题:FATAL: certificate authentication failed
原因:证书无效或 CN 不匹配
解决:检查证书有效期和 CN 字段
调试命令
# 查看当前 HBA 规则
psql -c "SELECT * FROM pg_hba_file_rules;"
# 查看用户信息
psql -c "SELECT usename, valuntil FROM pg_user;"
# 测试连接
psql "host=xxx port=5432 dbname=xxx user=xxx" -c "SELECT 1;"