轮换前先盘点哪些东西?
我会先开一张表,不急着改 GitHub 后台。
| 字段 | 示例 | 为什么要写 |
|---|---|---|
| secret 名称 | CLOUDFLARE_API_TOKEN | 后面比对 workflow |
| 使用范围 | production / staging | 决定放 repository 还是 environment |
| 供应商 | Cloudflare / Stripe / Supabase | 知道去哪里撤销旧密钥 |
| 权限 | deploy、read-only、billing | 判断能不能降权 |
| owner | 谁能重建 | 防止只有一个人会操作 |
| 轮换窗口 | 2026-03-04 10:00 UTC | 出问题能查时间线 |
GitHub 官方文档支持 repository、environment 和 organization secrets。小 SaaS 团队最容易犯的错,是把生产和测试共用一个仓库级 secret。这样 staging workflow 一旦被误触发,也能拿到生产权限。
我的规则是:生产部署、支付、数据库写权限,一律放 production environment;测试环境放 staging;只读通知类 token 才考虑 repository secret。
environments 怎么拆?
先建三个 environment:preview、staging、production。
preview:只允许读权限,给 PR 预览用。staging:允许写测试资源,禁止碰生产数据库。production:加 required reviewers,至少一人批准。
GitHub environments 可以把 secrets 和部署保护规则绑在一起。这样不是每个 workflow 都能直接碰生产。独立开发者一个人做项目时,也建议保留 production environment,因为三个月后你会忘记某个 workflow 的触发条件。
如果你的部署链路依赖 Cloudflare Pages、Workers 或 R2,生产 token 只给对应资源的最小权限,不要用账号级全权限 token。轮换密钥不是形式主义,顺手降权才是收益。
轮换清单怎么执行
按这个顺序走,少出事故:
- 冻结部署窗口:至少 30 分钟内不要合并大 PR。
- 导出当前 workflow 列表:确认哪些 job 读取了目标 secret。
- 在供应商后台创建新密钥:权限按最小化设置。
- 在 GitHub environment 写入新值:不要改错环境。
- 跑 staging workflow:验证构建、迁移、部署、回调。
- 跑 production smoke workflow:只做最小验证。
- 撤销旧密钥:在供应商后台删除或禁用。
- 查 audit log:确认没有异常成员和规则变更。
- 记录结果:写 owner、时间、旧密钥撤销状态。
我不建议把所有供应商密钥同一天轮换。Cloudflare、Stripe、数据库、邮件、AI API 分批做,每批之间留 15-30 分钟观察窗口。一次改完看起来效率高,失败时定位很痛苦。
审计日志看什么
轮换当天至少看这几类:
| 信号 | 正常情况 | 需要追查 |
|---|---|---|
| secret 更新 | 只有指定 owner 操作 | 多人重复修改同一 secret |
| environment 规则 | required reviewers 未变 | 审批规则被临时关闭 |
| workflow 触发 | 轮换相关 workflow | 奇怪分支触发生产部署 |
| 成员权限 | 无新增 admin | 临时 admin 未回收 |
| 第三方 App | 无新增授权 | 未知 App 读取仓库 |
GitHub 的 audit log 对组织很有用,但前提是你知道自己要找什么。不要只搜「secret」,还要看 environment、repo permission、workflow dispatch、GitHub App 相关记录。
远程团队避免轮换当天掉线
轮换当天最怕的是:人在机场或酒店 Wi-Fi,GitHub、Cloudflare、Stripe 后台来回跳,2FA 又在另一台设备上。我的做法很土:提前一天确认 2FA 设备、电源、备用网络和供应商登录状态。
如果团队成员分布在不同国家,至少让执行人和审批人都能稳定打开 GitHub、Cloudflare、Stripe 后台。需要跨平台处理部署时,可以准备一条海外服务跑 GitHub Actions / Cloudflare 的稳定线路,避免轮换窗口里因为后台连接不稳而误判为权限问题。
注意,这不是让网络替代权限管理。权限、审计和最小化才是正事;稳定访问只是降低操作噪音。
回滚设计
不要把回滚写成「恢复旧 secret」。更稳的设计是两段式:
- 新密钥上线后,旧密钥保留 30-60 分钟但不再写入 GitHub。
- 如果生产 smoke test 失败,判断是 secret 值错误、权限不足、供应商限制,还是 workflow 读错环境。
- 只有确认新密钥无法快速修复,才把旧密钥重新写回 environment。
- 回滚后也要记录原因,并重新安排轮换,不要让旧密钥无限期复活。
Stripe、Cloudflare、数据库这类关键密钥,回滚窗口要短。你保留旧密钥越久,泄露面就越大。
轮换后的收尾检查
我会做五件小事:
- 搜 workflow 里有没有硬编码 token。
- 检查 PR 预览有没有拿到生产 secret。
- 确认旧密钥在供应商后台已经撤销。
- 给 secret owner 发一条完成记录。
- 把下一次轮换日期放进团队日历。
真正成熟的密钥管理,不是某次轮换做得多漂亮,而是下次轮换不用重新想流程。