跳到内容

安全模型和注意事项

一般注意事项

虽然比密码和长期 API 令牌更安全,但 OIDC 发布并不是万能药。特别是

  • 短期 API 令牌仍然是敏感信息,不应该被泄露(理想情况下根本不应该,但肯定不应该在它们过期之前)。

  • OIDC 令牌本身是敏感信息,不应该被泄露。OIDC 令牌的有效期也很短,但成功拦截令牌的攻击者可以在其有效期内使用它来生成 API 令牌。

  • 配置可信发布者意味着信任外部状态的特定部分(例如 GitHub Actions 工作流程);该状态 **绝不能** 由不可信方控制。

总之:将您的可信发布者视为 **如同** API 令牌一样。如果您不会让用户或代码访问您的 API 令牌,那么他们也不应该能够调用您的可信发布者。

特定于提供商的注意事项

每个可信发布提供商都是自己的 OIDC 身份提供商,具有自己的安全模型和注意事项。

安全模型

GitHub Actions 对 OpenID Connect 令牌的自身安全模型有点微妙

  • 存储库中定义的任何工作流程都可以请求 OIDC 令牌,**只要它具有 id-token: write 权限**,任何受众 都可以。

  • OIDC 令牌中定义的声明与 **工作流程绑定**,这意味着在 org/repo 中的 foo.yml 中定义的工作流程 **不能冒充** 在 org/repo 中的 bar.yml 中定义的工作流程。但是,如果 foo.yml 被 **重命名** 为 bar.yml,那么 新的 bar.yml 将与旧的 bar.yml **无法区分**,除了** 反映存储库状态的声明(例如 git 引用、分支等)。

  • **一般来说**,“第三方”事件 **不能** 请求 OIDC 令牌:即使它们可以触发请求令牌的工作流程,实际的令牌检索步骤也会失败。例如:从存储库的 fork 中发出的 PR **不能** 访问“上游”存储库工作流程中的 OIDC 令牌。

  • 对此的例外是 pull_request_target 事件,它们 **从设计上来说是根本危险的**,在没有仔细考虑的情况下不应使用它们。

注意事项

  • 特别是,对于使用 GitHub Actions 进行可信发布,您 **必须**

    • 信任正确的用户名和存储库:如果您信任除您控制和信任的存储库以外的其他存储库,则该存储库可以上传到您的 PyPI 项目。

    • 信任正确的工作流程:您不应该信任每个工作流程都上传到 PyPI;相反,您应该将责任隔离到尽可能小的(和最不特权的)独立工作流程中。我们建议将此工作流程命名为 release.yml

    • 合并第三方更改到您的代码时要小心:如果您信任 release.yml,那么您必须确保对该工作流程(或在该工作流程中运行的代码)的第三方更改不是恶意的。

    • 在添加存储库贡献者、成员和管理员时要小心:默认情况下,任何可以无条件提交到您的存储库的人也可以修改您的发布工作流程,使其触发您可能不希望的事件(例如,手动 workflow_dispatch 触发器)。

    可以使用下面描述的专用环境和手动审批者来缓解这种特定风险。

  • 可信发布者注册到项目,而不是用户。这意味着从 PyPI 项目中删除用户 **不会** 删除他们可能注册的任何可信发布者,并且您应该在“停用”项目维护者时将对任何/所有可信发布者的审查作为一部分。

PyPI 提供了保护措施,使针对 OIDC 的某些攻击更加困难(例如 帐户复活攻击)。但是,与所有形式的身份验证一样,最终用户对 **正确应用** 身份验证负 **根本责任**。

除了上述要求之外,您还可以执行以下操作来“缩小”可信发布工作流程的范围

  • **使用每个作业的权限**:permissions 键可以在工作流程级别或作业级别定义;作业级别 **始终更安全**,因为它限制了接收提升的 GITHUB_TOKEN 凭据的作业数量。

  • **使用专用环境**:GitHub Actions 支持“环境”,可用于将机密隔离到特定工作流程。OIDC 发布不使用任何预配置的机密,但专用 publishdeploy 环境是一种通用的最佳实践。

    专用环境允许额外的保护措施,例如 必填审批者,可用于要求手动审批使用该环境的工作流程。

    例如,以下是 pypa/pip-auditrelease 环境如何将审查限制为维护和管理团队的成员

    Screenshot of an example configuring an environment on GitHub

  • **使用标签保护规则**:如果您使用的是基于标签的发布工作流程(例如,在推送标签时触发),那么您可以将标签创建和修改限制为维护者或更高权限(或自定义角色),以匹配您的发布模式。例如,v* 将阻止非维护者创建或修改与版本字符串(如 v1.2.3)匹配的标签。

  • **限制发布作业的范围**:您的发布作业(理想情况下)应该只有两个步骤

    1. 从 **独立的构建作业** 中检索可发布的分布文件;

    2. 使用 pypa/gh-action-pypi-publish@release/v1 发布发行版。

通过使用独立的构建作业,您可以将可以访问 OIDC 令牌的步骤数量保持在最低限度。这可以防止意外和恶意泄露。

安全模型

如果为给定的 PyPI 项目配置了可信发布者,则任何使用配置的服务帐户的服务都可以代表该身份从 Google 的身份提供商请求 OpenID Connect 令牌。该令牌可以与 PyPI API 令牌交换,该令牌具有发布到 PyPI 项目的能力。用于发布的身份可以通过指定主体来进一步限制,主体是代表发出请求的主体的 ID。

注意事项

在使用 Google Cloud 进行可信发布时,您必须信任服务帐户和 **任何使用它作为默认短暂身份的服务**。

具体来说,不建议配置 默认服务帐户,因为它们在创建时默认提供给每项服务。

安全模型

可信发布发生在 ActiveState Platform 构建基础设施中的隔离构建容器内。当用户触发一个将发布到 PyPI 的构建时,会生成一个 OIDC 令牌,并将其作为环境变量以及将要上传的发行版工件一起传递到必要的构建容器中。构建容器使用 OIDC 令牌来请求 PyPI API 令牌,然后使用它上传您的发行版。

注意事项

  • 在可信发布者中配置的用户必须是触发 ActiveState Platform 中构建的用户。该用户需要对与项目关联的 ActiveState 组织具有编辑权限。
  • ActiveState Platform 项目必须是私有的。

有关使用 ActiveState Platform 进行可信发布的更多信息,请参阅 PyPI 配置文档ActiveState Platform 文档

安全模型

  • OIDC 令牌由指定 id_tokens 关键字以及所需受众的工作流程请求。在作业运行时,令牌通过环境变量提供。
  • OIDC 令牌中定义的声明与 **组和项目绑定**,这意味着位于 orgA/repo 的存储库不能冒充位于 orgB/repo 的存储库。
  • OIDC 令牌中定义的声明与 **顶层管道绑定**,这意味着顶层管道包含的任何管道(通常是 .gitlab-ci.yml)都将能够使用信任 .gitlab-ci.yml 管道的可信发布者进行上传。
  • 特定存储库和管道的 OIDC 令牌可以由任何具有在存储库的 CI/CD 中运行该管道权限的人生成。

注意事项

  • 特别是,对于使用 GitLab CI/CD 进行可信发布,您 **必须**

    • 信任正确的命名空间和存储库:如果您信任除您控制和信任的存储库以外的其他存储库,则该存储库可以上传到您的 PyPI 项目。

    • 注意帐户复活攻击:PyPI 检查 OIDC 令牌中包含的命名空间声明(用户名或组)。但是,如果该用户名或组被删除,并且创建一个具有相同名称的新用户名或组,PyPI 仍然会识别新生成的 OIDC 令牌为有效。

    • 合并第三方更改到您的代码时要小心:如果您信任顶层管道 .gitlab-ci.yml,那么您必须确保对该文件的第三方更改不是恶意的。这尤其重要,因为 GitLab 没有提供有关请求令牌的作业的详细信息:声明中只包含顶层管道,这意味着顶层管道运行的任何作业都可以请求有效的 OIDC 令牌。

    • 在添加存储库贡献者、成员和管理员时要小心:默认情况下,任何可以无条件提交到您的存储库的人也可以修改您的发布工作流程,使其触发您可能不希望的事件(例如,手动 when: manual 规则)。

      可以使用下面描述的专用环境和手动审批者来缓解这种特定风险。

  • 可信发布者注册到项目,而不是用户。这意味着从 PyPI 项目中删除用户 **不会** 删除他们可能注册的任何可信发布者,并且您应该在“停用”项目维护者时将对任何/所有可信发布者的审查作为一部分。

除了上述要求之外,您还可以执行以下操作来“缩小”可信发布工作流程的范围

  • **使用专用环境**:GitLab CI/CD 支持“环境”,可用于将机密隔离到特定工作流程。OIDC 发布不使用任何预配置的机密,但专用 publishdeploy 环境是一种通用的最佳实践。

    专用环境允许额外的保护措施,例如 受保护的环境,可用于要求手动审批使用该环境的工作流程。

  • **使用受保护的标签**:如果您使用的是基于标签的发布工作流程(例如,在推送标签时触发),那么您可以将标签创建和修改限制为维护者或更高权限(或自定义角色),以匹配您的发布模式。例如,v* 将阻止非维护者创建或修改与版本字符串(如 v1.2.3)匹配的标签。

  • **限制发布作业的范围**:您的发布作业(理想情况下)应该只有三个步骤

    1. 从 **独立的构建作业** 中检索可发布的分布文件;

    2. 将 OIDC 令牌交换为 PyPI API 令牌;

    3. 使用 twine 和 API 令牌发布发行版。

通过使用独立的构建作业,您可以将可以访问 OIDC 令牌的步骤数量保持在最低限度。这可以防止意外和恶意泄露。