备份:修复 OpenBao Raft snapshot 与机器身份 #11

Open
opened 2026-09-09 18:47:25 +00:00 by panxiao81 · 0 comments
Owner

优先级

暂缓。当前优先实现 Kubernetes GitOps;本问题不阻塞 Flux bootstrap,但在扩大 OpenBao 依赖或取消其他恢复路径前必须完成。

已确认现状

2026-09-09 对 bao1 做了只读核查及一次手动触发:

  • openbao-snapshot.timer 已加载、enabled 且 active,每天 02:00 UTC 触发
  • /etc/openbao/snapshot.token 存在且为 root-only
  • /var/backups/openbao 存在,但没有任何 snapshot
  • live 脚本曾使用 https://127.0.0.1:8200,因证书没有 IP SAN 而持续失败
  • 已从现有 main 重跑 snapshots 标签,脚本现使用 https://bao.ad.ddupan.top:8200,TLS 问题已消除
  • 再次触发后 API 返回 403
  • snapshot token 自查询失败,确认已失效或过期

当前没有可用 Raft snapshot。VM 备份状态尚未纳入本 ticket 的已验证事实。

根因

现有任务只检查 token 文件是否存在,不验证 token 是否有效。token 是 period=768h 的 orphan periodic token,但 snapshot 脚本从不执行 renew-self,因此文件仍在而凭据已过期。

身份模型决策

不要把人类 OIDC 管理员 token 存给 systemd。需要在实施前选择并记录以下一种机器身份:

方案 A:受限 periodic service token

  • OIDC 管理员仅在 bootstrap/轮换时临时签发
  • token 为 orphan、service 类型,仅绑定 snapshot policy
  • root-only 保存
  • 每次 snapshot 前 renew-self
  • 自动检测失效并明确告警,不静默依赖文件存在

方案 B:AppRole

  • systemd 使用受限 role_id/secret_id 登录
  • 每次获取短期 snapshot token
  • 设计 secret_id 的保存、轮换、TTL/使用次数及恢复流程

优先评估方案 A;实现简单,但必须承认 snapshot 权限可以导出全部 Bao 数据,属于高价值凭据。

后续工作

  1. 通过 PR 完成机器身份设计与 IaC
  2. 使用一次性 OIDC 管理员会话完成首次 token/角色 bootstrap;管理员 token 不落盘
  3. 手动生成 snapshot,并记录文件大小、权限和 SHA-256,不输出内容
  4. 验证下一次定时执行和续租
  5. 将 snapshot 加密复制到 VM 之外
  6. 在隔离环境执行一次 restore + unseal 演练
  7. 为 timer/service 失败加入监控告警

验收标准

  • 连续至少两次定时 snapshot 成功
  • 后台任务不保存 OIDC 管理员 token
  • snapshot 凭据仅拥有所需最小权限
  • snapshot 有至少一份异机加密副本
  • restore 演练成功,并使用已有的 PGP/YubiKey 恢复路径完成 unseal

已知密钥恢复条件

PGP 私钥已有独立备份;PGP 加密后的 unseal key 密文可以长期保存。解密后的 unseal key 明文不得提交 Git 或写入 ticket。

## 优先级 暂缓。当前优先实现 Kubernetes GitOps;本问题不阻塞 Flux bootstrap,但在扩大 OpenBao 依赖或取消其他恢复路径前必须完成。 ## 已确认现状 2026-09-09 对 bao1 做了只读核查及一次手动触发: - openbao-snapshot.timer 已加载、enabled 且 active,每天 02:00 UTC 触发 - /etc/openbao/snapshot.token 存在且为 root-only - /var/backups/openbao 存在,但没有任何 snapshot - live 脚本曾使用 https://127.0.0.1:8200,因证书没有 IP SAN 而持续失败 - 已从现有 main 重跑 snapshots 标签,脚本现使用 https://bao.ad.ddupan.top:8200,TLS 问题已消除 - 再次触发后 API 返回 403 - snapshot token 自查询失败,确认已失效或过期 当前没有可用 Raft snapshot。VM 备份状态尚未纳入本 ticket 的已验证事实。 ## 根因 现有任务只检查 token 文件是否存在,不验证 token 是否有效。token 是 period=768h 的 orphan periodic token,但 snapshot 脚本从不执行 renew-self,因此文件仍在而凭据已过期。 ## 身份模型决策 不要把人类 OIDC 管理员 token 存给 systemd。需要在实施前选择并记录以下一种机器身份: ### 方案 A:受限 periodic service token - OIDC 管理员仅在 bootstrap/轮换时临时签发 - token 为 orphan、service 类型,仅绑定 snapshot policy - root-only 保存 - 每次 snapshot 前 renew-self - 自动检测失效并明确告警,不静默依赖文件存在 ### 方案 B:AppRole - systemd 使用受限 role_id/secret_id 登录 - 每次获取短期 snapshot token - 设计 secret_id 的保存、轮换、TTL/使用次数及恢复流程 优先评估方案 A;实现简单,但必须承认 snapshot 权限可以导出全部 Bao 数据,属于高价值凭据。 ## 后续工作 1. 通过 PR 完成机器身份设计与 IaC 2. 使用一次性 OIDC 管理员会话完成首次 token/角色 bootstrap;管理员 token 不落盘 3. 手动生成 snapshot,并记录文件大小、权限和 SHA-256,不输出内容 4. 验证下一次定时执行和续租 5. 将 snapshot 加密复制到 VM 之外 6. 在隔离环境执行一次 restore + unseal 演练 7. 为 timer/service 失败加入监控告警 ## 验收标准 - 连续至少两次定时 snapshot 成功 - 后台任务不保存 OIDC 管理员 token - snapshot 凭据仅拥有所需最小权限 - snapshot 有至少一份异机加密副本 - restore 演练成功,并使用已有的 PGP/YubiKey 恢复路径完成 unseal ## 已知密钥恢复条件 PGP 私钥已有独立备份;PGP 加密后的 unseal key 密文可以长期保存。解密后的 unseal key 明文不得提交 Git 或写入 ticket。
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: panxiao81/homelab-infra#11