OIDC 短时凭证如何取代长期密钥

1 人参与

我以前干过一件现在想起来有点后怕的事:把生产环境的访问密钥直接放进 CI 的仓库 secrets 里,job 级 env 一配,然后心安理得,毕竟构建日志里它显示成三个星号。

后来我才想明白,掩码做的是日志字符串替换,它降低的是密钥出现在日志里的概率,完全不改变进程能读到密钥这个事实。job 级 env 对那个 job 的每个 step 都可见,包括只是装依赖、跑测试、调用第三方 Action 的那些 step——一次 set -x、一次崩溃时的环境转储,就能把它带出去。更别提那些在目标仓库上下文里运行、又 checkout 了 PR 代码的工作流,外部贡献者根本不用碰受保护分支,代码就能拿到这些变量。这条路径比"日志泄露密钥"可怕得多。

我为什么最后被 OIDC 说服

原理其实一句话:流水线不再拿着长期密码去敲云的门,而是让云相信"这次任务确实是这个仓库、这个分支跑出来的",然后现场发一张几小时后过期的临时令牌。密钥从"一份存放在某处、必须被保管和轮换的东西",变成了"跑起来那一刻才存在的东西"。没有长期密钥可以泄露,也就没有长期密钥需要轮换——这一点对我这种记性差的人太友好了。

但 OIDC 好用不代表配一下就行。真正决定安全边界的是信任策略写得多窄:限定到具体的仓库、分支、environment,而不是"任何来自这个 CI 平台的请求"。写得松,等于把长期密钥的风险换了个包装。

迁移顺序,我是这么走的

先盘账:列出所有持有生产或类生产凭证的 job,标出触发条件和这些密钥的静态有效期。这一步通常比我预想的长,侧枝很多。

然后缩小注入范围:把 job 级 env 下沉到真正需要它的那一个 step,别顺手传给会打印环境的脚本。

接着换短时凭证:云上走 OIDC,数据库和第三方 API 如果没有 OIDC 能力,至少改成按 job 领取、有效期以小时计。

最后才轮换和吊销旧密钥,而且一定要确认没有遗留调用方。

回退我建议做成双轨而不是一键回滚:新旧两套凭证并行一段时间,旧密钥保留但缩短有效期、加上审批。这样出问题时能立刻降级,而不是在事故现场临时决定要不要把安全控制整个关掉。

日志脱敏当然还要做,但我现在把它当成降低可见性的手段,而不是访问控制。这两件事混为一谈,是我交过的最贵的一笔学费。

参与讨论

1 条评论
  • HanaBlush

    我们之前也把密钥全塞任务环境变量,现在想想后怕