使用可信发布消除长期凭证

概述

在软件供应链安全领域,保护用于向包仓库(如 PyPI、npm、RubyGems)发布软件的凭证至关重要。传统的长期凭证(如 API 密钥、密码)一旦泄露,攻击者便可以长期、隐蔽地发起恶意包发布攻击,严重威胁整个生态系统的安全。可信发布 机制正是为了应对此问题而提出的,它通过使用短暂、自动化的凭证,取代长期的人工密钥,从根本上减少了凭证被盗用和滥用的风险,是提升软件供应链韧性的一个关键实践。

核心概念

可信发布的核心思想是消除长期存储的静态凭证,并引入一种基于身份和工作负载的动态认证流程。其关键组成部分包括:

  • 短期凭证:发布过程使用的认证令牌具有极短的有效期(例如几分钟),仅在需要时即时生成,用后即焚。这极大地缩小了凭证被盗后可被利用的时间窗口。
  • OIDC 与身份提供者:可信发布通常与 OpenID Connect 协议深度集成。CI/CD 工作负载(如 GitHub Actions、GitLab CI)本身可以由一个可信的身份提供者(如 GitHub)进行认证。该工作负载会获取一个代表其身份的 OIDC 令牌。
  • 信任链:包仓库(如 PyPI)预先配置为信任特定的身份提供者和发布环境(例如特定的 GitHub 仓库和分支)。当 CI/CD 工作负载请求发布时,它会出示其 OIDC 令牌。仓库验证该令牌的签发者、仓库身份、分支等信息是否与预设策略匹配。如果匹配,则自动授予一个一次性的、具有发布权限的短期凭证。
  • 供应链攻击防御:该机制的主要目标是防御供应链攻击,特别是攻击者通过窃取或泄露长期凭证来注入恶意代码的场景。即使 CI 环境或开发者机器被入侵,攻击者也无法获得可长期使用的发布密钥。

实践

以在 PyPI 上为一个 Python 项目配置可信发布为例,典型的实践步骤包括:

  1. 项目端配置:在包仓库(如 PyPI)的项目设置中,进入“发布”或“API 令牌”部分,创建一个新的“可信发布”配置。
  2. 声明信任源:在配置中明确指定允许发布的身份提供者(GitHub)及其具体来源,通常需要填写:
    • 发布者名称:https://token.actions.githubusercontent.com
    • 仓库所有者/名称:你的GitHub用户名/你的仓库名
    • 工作流文件名:例如 publish.yml
    • 环境(可选):可以进一步限定只有特定环境(如 production)的工作流可以触发发布。
  3. CI/CD 工作流配置:在项目的 CI/CD 工作流文件(如 .github/workflows/publish.yml)中,移除所有静态的 API 密钥。相反,配置工作流在发布步骤中请求一个 OIDC 令牌,并使用该令牌进行认证。
  4. 自动化发布:当代码推送到受保护的分支(如 main)且工作流被触发时,CI 系统会自动向包仓库请求发布。仓库验证请求来自已授权的 CI 环境,签发短期凭证,完成安全发布。

这种模式已被 PyPI、npm、RubyGems 等主流包生态系统采纳和支持。

SRE 要点

  • 与可靠性的关联:采用可信发布提升了软件交付管道的可靠性。它消除了因长期凭证过期、轮换不及时或意外泄露导致的发布中断风险。发布流程变得更安全、更可预测。
  • 最佳实践与常见反模式:
    • 最佳实践:为所有软件包启用可信发布,并严格配置信任策略(例如,限定到特定的 main 分支和 production 环境);将此作为默认发布方式,而非例外。
    • 反模式:继续在 CI/CD 环境变量或代码仓库中存储长期 API 密钥;为“方便”而放宽信任策略,允许任意分支或工作流发布。
  • 可观测性与事件响应:包仓库应记录所有基于可信发布的发布事件,包括请求来源(仓库、工作流、分支)。这些日志对于审计和检测异常发布行为(例如,一个未预期的分支尝试发布)至关重要,可作为 SIEM 或安全监控系统的数据源。
  • 相关指标:虽然没有直接的 SLO/SLI,但可以将“百分比的发布使用可信发布机制完成”作为一个重要的运营指标来跟踪迁移进度和采用率。目标应是 100%。
  • 秘密管理:可信发布是 秘密管理 的一个演进和增强。它通过彻底消除某些长期秘密的需求,简化了整体安全模型。SRE 团队应将其视为强化供应链安全的标准工具。

通过采纳可信发布,团队能够有效缓解一个重大类别的供应链风险,将安全重心从“保护静态秘密”转移到“验证自动化工作负载的身份”这一更现代、更可靠的基础上。