文章目录
- [PostgreSQL 密码算法从 md5 迁移至 scram-sha-256 的影响分析与升级方案](#PostgreSQL 密码算法从 md5 迁移至 scram-sha-256 的影响分析与升级方案)
-
- [场景 1](#场景 1)
- 场景2
PostgreSQL 密码算法从 md5 迁移至 scram-sha-256 的影响分析与升级方案
场景 1
分析:
| 阶段 | password_encryption |
pg_hba.conf 认证方式 | 存储的密码哈希 | 是否正常 |
|---|---|---|---|---|
| PG 15.13 | 未设置(PG15 默认 scram-sha-256) |
md5 |
SCRAM-SHA-256 | 正常:md5 认证方式允许同时验证 md5 和 SCRAM-SHA-256 哈希 |
| PG 15.18 | md5 |
md5 |
SCRAM-SHA-256(未变) | 正常:password_encryption 只影响新设置的密码,不会回溯重加密已有密码 |
| 改为 scram-sha-256 | scram-sha-256 |
scram-sha256 |
SCRAM-SHA-256(未变) | 正常:哈希本身就是 SCRAM-SHA-256,认证方式匹配 |
关键原理:
-
password_encryption仅影响后续通过ALTER USER / CREATE USER设置的密码,不会自动重加密已有密码 -
pg_hba.conf 中
md5认证方式(PG 10+)实际是"md5 或 scram-sha-256 均可",会根据pg_authid中存储的哈希前缀自动选择 -
改为
scram-sha256后,只有 SCRAM-SHA-256 哈希能通过认证------当前 postgres 用户的哈希恰好已是 SCRAM-SHA-256,所以不受影响
等级保护合规风险:
| 风险点 | 说明 |
|---|---|
| 其他用户可能是 md5 哈希 | 如果库中存在 md5 前缀的哈希(SELECT rolname, rolpassword FROM pg_authid WHERE rolpassword LIKE 'md5%'),改为 scram-sha256 后这些用户将无法登录 |
| 需强制重置所有 md5 密码 | 合规要求:所有密码必须用 scram-sha-256 存储。需逐个 ALTER USER xxx PASSWORD '新密码' 重置 |
建议操作:
sql
-- 1. 检查是否有 md5 哈希的用户
SELECT rolname, rolpassword FROM pg_authid
WHERE rolpassword LIKE 'md5%' AND rolcanlogin = true;
-- 2. 对每个 md5 用户重置密码(重置后自动用当前 password_encryption=scram-sha-256 加密)
ALTER USER xxx PASSWORD '<新密码>';
-- 3. 验证全部为 scram-sha-256
SELECT rolname, rolpassword FROM pg_authid
WHERE rolpassword IS NOT NULL AND rolcanlogin = true;
场景2
环境比较新, 比如环境是 D007及之后的版本(多数局点), 最开始 password_encryption 就是 md5,且 pg_hba.conf 中auth_type 也是 md5 假设现在要将该需求合入 D013 中(将 password_encryption 改为 scram-sha256, 将 pg_hba.conf 中 auth_type 改为 scram-sha256, 同时期望存储的密码也是 scram-sha-256 加密的), 则 对于从 D007升级到 D013 的环境, 需要关注 password_encryption 的 变动导致 postgres 等用户登陆的影响 有啥需要额外做的 以实现该需求吗? 这是个经典的 PG 密码算法迁移问题。从 D007(md5)升级到 D013(scram-sha-256),必须额外做密码迁移,否则所有用户登录失败。
核心矛盾
plaintext
D007 现状:
password_encryption = md5
pg_hba.conf auth_type = md5
pg_authid 中存储: md5xxxxxxxxxxxx(md5 哈希前缀)
D013 目标:
password_encryption = scram-sha-256
pg_hba.conf auth_type = scram-sha256
要求 pg_authid 中存储: SCRAM-SHA-256$...(SCRAM 哈希前缀)
关键 :scram-sha256 认证方式只接受 SCRAM-SHA-256 哈希 ,md5 哈希的用户直接登录失败 。且 md5 哈希不可逆,无法转换为 SCRAM-SHA-256,必须用明文重新设置。
必须额外做的事
1. 升级脚本:重置所有可登录用户的密码
sql
-- 升级前:检查受影响用户(密码以 md5 开头的可登录用户)
SELECT rolname, rolpassword
FROM pg_authid
WHERE rolpassword LIKE 'md5%' AND rolcanlogin = true;
对已知明文密码的系统账户(postgres、replication 用户等),直接重置:
sql
-- 先确保 password_encryption 已改为 scram-sha-256(影响新设置的密码用 SCRAM 加密)
-- 在 postgresql.conf 中: password_encryption = scram-sha-256
-- 执行 pg_ctl reload 或 SELECT pg_reload_conf();
-- 重置系统账户密码(用原明文重新设置,存储自动变为 SCRAM-SHA-256)
ALTER USER postgres PASSWORD '<系统管理员密码>';
ALTER USER replicator PASSWORD '<复制用户密码>';
-- ... 其他已知密码的系统账户
2. 对于未知密码的业务用户
有三种策略,按安全要求选择:
| 策略 | 做法 | 优点 | 缺点 |
|---|---|---|---|
| A. 强制重置 | 升级后业务用户首次登录强制改密码 | 最安全,合规 | 影响业务,需协调 |
| B. 临时兼容 | pg_hba.conf 中先保留 md5,逐步迁移 |
零业务中断 | 过渡期不合规 |
| C. 预先收集 | 升级前从应用配置中提取所有数据库连接密码,升级脚本中统一重置 | 一次性完成 | 需要梳理所有应用密码配置 |
推荐策略 C(最实用):
python
# 升级脚本伪代码
# 1. 从应用配置文件中提取所有数据库连接密码
# 2. 在 PG 中统一重置
known_passwords = {
"postgres": "<系统管理员密码>",
"app_user1": "<从应用配置提取>",
"app_user2": "<从应用配置提取>",
# ...
}
for user, pwd in known_passwords.items():
execute_sql(f"ALTER USER {user} PASSWORD '{pwd}';")
3. 完整升级流程(推荐)
plaintext
阶段1:密码迁移(pg_hba.conf 仍为 md5,保证兼容)
① 修改 password_encryption = scram-sha-256
② pg_ctl reload
③ 执行密码重置脚本(ALTER USER ... PASSWORD '明文')
④ 验证:SELECT rolname, rolpassword FROM pg_authid
WHERE rolpassword LIKE 'md5%' AND rolcanlogin = true;
→ 期望结果为空(所有用户已迁移到 SCRAM-SHA-256)
阶段2:切换认证方式
⑤ 修改 pg_hba.conf: md5 → scram-sha256
⑥ pg_ctl reload(或 restart)
⑦ 验证登录:psql -U postgres -d postgres
阶段3:验证
⑧ 业务应用连接验证
⑨ 复制连接验证(如适用)
风险清单
| 风险 | 影响 | 应对 |
|---|---|---|
| 遗漏用户 --- 未重置密码的用户升级后无法登录 | 业务中断 | 升级前完整扫描 pg_authid,确保无 md5 哈希残留 |
| 复制槽用户 --- replication 用户密码未同步修改 | 主从复制断开 | 升级脚本中包含 replication 用户,同步修改 primary_conninfo |
| 应用硬编码 md5 --- 某些旧驱动/中间件只支持 md5 认证 | 连接失败 | 确认所有客户端驱动版本 ≥ PG 10(均支持 SCRAM-SHA-256) |
| 回滚 --- 升级失败需回滚到 D007 | 密码哈希不可逆 | 回滚前备份 pg_authid,回滚时用 ALTER USER 恢复 md5 密码 |
升级脚本模板
bash
#!/bin/bash
# D007 → D013 密码算法迁移脚本
PG_USER="postgres"
PG_HOST="127.0.0.1"
PG_PORT="5432"
echo "=== 阶段1:检查待迁移用户 ==="
MD5_USERS=$(psql -U $PG_USER -h $PG_HOST -p $PG_PORT -t -Ac \
"SELECT rolname FROM pg_authid WHERE rolpassword LIKE 'md5%' AND rolcanlogin = true")
if [ -z "$MD5_USERS" ]; then
echo "无 md5 用户,无需迁移"
else
echo "待迁移用户: $MD5_USERS"
echo "FATAL: 存在 md5 用户,必须先重置密码!"
exit 1
fi
echo "=== 阶段2:重置系统账户密码 ==="
# password_encryption 已在 postgresql.conf 中设为 scram-sha-256
psql -U $PG_USER -h $PG_HOST -p $PG_PORT -c \
"ALTER USER postgres PASSWORD '<系统管理员密码>';"
# ... 其他用户
echo "=== 阶段3:验证迁移结果 ==="
REMAINING=$(psql -U $PG_USER -h $PG_HOST -p $PG_PORT -t -Ac \
"SELECT count(*) FROM pg_authid WHERE rolpassword LIKE 'md5%' AND rolcanlogin = true")
echo "剩余 md5 用户数: $REMAINING"
if [ "$REMAINING" -ne 0 ]; then
echo "FATAL: 仍有用户未迁移!"
exit 1
fi
echo "=== 阶段4:切换 pg_hba.conf ==="
# 修改 pg_hba.conf: md5 → scram-sha256
sed -i 's/\bmd5\b/scram-sha256/g' $PGDATA/pg_hba.conf
pg_ctl reload
echo "=== 迁移完成 ==="
总结 :额外必须做的是用明文重置所有 md5 用户的密码,仅改配置文件不够------存储的 md5 哈希不会自动变成 SCRAM-SHA-256