安全模型及注意事项
Trusted Publishing 的主要设计目的是为 PyPI 上传统上使用的长期 API 令牌提供更安全的替代方案。
近年来,窃取 API 令牌等凭证已成为网络攻击的主要手段之一。其原因在于凭证管理本身就十分复杂且风险重重。可信发布机制通过使用短期令牌而非长期令牌来降低这种风险。短期令牌无需存储,因此更不容易丢失、泄露到日志中或被恶意软件窃取。此外,即使短期令牌泄露,攻击者也只有很短的时间窗口来利用泄露的令牌,从而最大限度地减少潜在损失。
然而,了解可信发布机制无法涵盖的风险类型仍然十分重要。您应该将可信发布机制视为保护软件包安全众多工具之一。
一般性考虑
-
可信发布使用有效期较短的 API 令牌,这些令牌会在授权它们的 OIDC 流程完成后不超过 15 分钟过期。与普通的 API 身份验证一样,可信发布并不保证代码的安全性或其作者的可信度。
-
可信发布机制无法解决软件包在构建之前或之后是否被修改过的问题。而认证机制可以解决这些风险。
-
有效期较短的 API 令牌是敏感信息,必须防止被盗或泄露。
-
OIDC 令牌本身也是敏感信息,必须防止被盗或泄露。OIDC 令牌有效期很短,但攻击者如果成功拦截到令牌,就可以利用它生成 API 令牌,直到令牌过期为止。
-
配置可信发布者意味着信任身份提供商 (IdP),例如 GitHub Actions。可信发布依赖于该 IdP 及其授权用户的完整性。实际上,这意味着可信发布用户必须保护并维护其注册为可信发布者的 CI/CD 工作流,因为这些工作流中的任何漏洞都可能等同于凭证泄露。
总之:将您的受信任发布者视为API 令牌。如果您不会允许用户或代码访问您的 API 令牌,那么他们也不应该能够调用您的受信任发布者。
提供者特定考虑因素
每个可信发布提供商都是其自身的 OIDC 身份提供商,拥有其自身的安全模型和注意事项。
安全模型
GitHub Actions自身针对OpenID Connect令牌的安全模型有点微妙:
-
只要拥有相应的权限,存储库中定义的任何工作流都可以向任何受众请求 OIDC 令牌 。
id-token: write -
OIDC令牌中定义的声明与工作流绑定
foo.yml,这意味着在`<workflow_name> `中定义的工作流org/repo不能冒充bar.yml在`<workflow_name>`中 定义的工作流org/repo。但是,如果foo.yml将 `<workflow_name>`重命名为`<workflow_name>bar.yml`,则新的bar.yml令牌与旧的令牌将无法区分,bar.yml除了反映存储库状态的声明(例如git引用、分支等)。 -
一般来说,“第三方”事件无法请求 OIDC 令牌:即使它们可以触发请求令牌的工作流,实际的令牌获取步骤也会失败。例如:从仓库的分支提交的 PR无法访问“上游”仓库工作流中的 OIDC 令牌。
-
但活动是个例外,活动从本质上来说
pull_request_target就 具有危险性,不应在没有仔细考虑的情况下使用。
考虑因素
-
特别是对于使用 GitHub Actions 的可信发布功能,您 必须:
-
信任正确的用户名和存储库:如果您信任的存储库不是您控制和信任的存储库,则该存储库可以上传到您的 PyPI 项目。
-
信任正确的流程:你不应该信任每个上传到 PyPI 的流程;相反,你应该将责任限定在尽可能小(权限最低)的独立流程中。我们建议给这个流程命名
release.yml。 -
将第三方更改合并到您的代码时要小心:如果您信任某个第三方
release.yml,那么您必须确保对该工作流(或在该工作流中运行的代码)的第三方更改不是恶意的。 -
添加存储库贡献者、成员和管理员时要小心:默认情况下,任何可以无条件提交到您的存储库的人也可以修改您的发布工作流程,使其在您不希望发生的事件(例如,手动
workflow_dispatch触发)时触发。
如下所述,使用带有人工审批人的专用环境可以降低这种特殊风险。
-
-
受信任的发布者是注册到项目而非用户名下的。这意味着从 PyPI 项目中移除用户并不会移除他们可能注册的任何受信任的发布者,因此,在项目维护者“离职”时,您应该审核所有受信任的发布者。
PyPI 采取了保护措施,使针对 OIDC 的某些攻击(例如账户复活攻击)更加困难。然而,与所有形式的身份验证一样,最终用户仍需对正确应用这些措施负根本责任。
除了上述要求之外,您还可以执行以下操作来“缩小”可信发布工作流程的范围:
-
使用按作业权限:
permissions密钥可以在工作流级别或作业级别定义;作业级别始终更安全, 因为它限制了获得高级凭据的作业数量GITHUB_TOKEN。 -
使用专用环境:GitHub Actions 支持“环境”,可用于将密钥隔离到特定工作流。OIDC 发布不使用任何预配置的密钥,但使用专用
publish环境deploy是一种通用的最佳实践。专用环境允许添加额外的保护措施,例如 要求审核人员进行人工审核,这可以用于要求使用该环境的工作流程必须经过人工批准。
例如,以下示例展示了如何
pypa/pip-audit将release审核权限限制在维护和管理团队成员范围内:
-
使用标签保护规则:如果您使用基于标签的发布工作流程(例如,根据推送的标签触发发布),则可以将标签的创建和修改权限限制为维护者及更高级别权限(或自定义角色),且仅限符合您发布模式的标签。例如,
v*这将阻止非维护者创建或修改与版本字符串匹配的标签,例如v1.2.3。 -
限制你的出版工作范围:你的出版工作(理想情况下)应该只有两个步骤:
-
从单独的构建作业中检索可发布的发行文件;
-
使用以下命令发布分发包
pypa/gh-action-pypi-publish@release/v1。
-
通过使用单独的构建作业,您可以将访问 OIDC 令牌的步骤数量控制在最低限度。这可以防止意外泄露和恶意泄露。
安全模型
如果为某个 PyPI 项目配置了受信任的发布者,则任何使用该已配置服务帐号的服务都可以代表该帐号向 Google 的身份提供商请求 OpenID Connect 令牌。该令牌可以交换为 PyPI API 令牌,从而能够向该 PyPI 项目发布内容。用于发布的身份还可以通过指定主题(代表发出请求的主体的 ID)进行进一步限制。
考虑因素
将可信发布与 Google Cloud 结合使用时,您必须信任服务帐号以及使用该帐号作为默认临时身份的任何服务。
具体来说,不建议配置默认服务帐户,因为创建每个服务时都会默认提供这些帐户。
安全模型
可信发布是在 ActiveState 平台构建基础架构中一个独立的构建容器内进行的。当用户触发构建并计划发布到 PyPI 时,系统会生成一个 OIDC 令牌,并将其作为环境变量传递给相应的构建容器,同时还会上传发布版本。构建容器会使用该 OIDC 令牌请求 PyPI API 令牌,然后使用该令牌上传发布版本。
考虑因素
- 在受信任发布者中配置的用户必须是触发 ActiveState 平台构建的用户。该用户需要拥有与项目关联的 ActiveState 组织中的编辑权限。
- ActiveState平台项目必须是私有的。
有关使用 ActiveState 平台进行可信发布的更多信息,请参阅PyPI 配置文档和ActiveState 平台文档。
安全模型
- 工作流会通过指定关键字和目标受众来请求 OIDC 令牌
id_tokens。作业运行时,令牌会通过环境变量提供。 - OIDC 令牌中定义的声明与组和项目绑定,这意味着位于 orgA/repo 的存储库不能冒充位于 orgB/repo 的存储库。
- OIDC 令牌中定义的声明与顶级管道绑定,这意味着顶级管道(通常是
.gitlab-ci.yml)中包含的任何管道都可以使用信任该.gitlab-ci.yml管道的受信任发布者进行上传。 - 任何有权在存储库的 CI/CD 中运行该流水线的人都可以生成特定存储库和流水线的 OIDC 令牌。
考虑因素
-
特别是对于使用 GitLab CI/CD 的可信发布,您 必须:
-
信任正确的命名空间和存储库:如果您信任的存储库不是您控制和信任的存储库,则该存储库可以上传到您的 PyPI 项目。
-
请注意防范账号复活攻击:PyPI 会检查 OIDC 令牌中包含的命名空间声明(用户名或组)。但是,如果该用户名或组被删除,并且创建了一个同名的新用户名或组,PyPI 仍然会将新用户名或组生成的 OIDC 令牌识别为有效。
-
合并第三方对代码的更改时务必谨慎:如果您信任顶层流水线
.gitlab-ci.yml,则必须确保对该文件所做的第三方更改并非恶意更改。这一点尤为重要,因为 GitLab 不会提供关于哪个作业请求了令牌的详细信息:声明中仅包含顶层流水线,这意味着由顶层流水线运行的任何作业都可以请求有效的 OIDC 令牌。 -
添加存储库贡献者、成员和管理员时要小心:默认情况下,任何可以无条件提交到您的存储库的人也可以修改您的发布工作流程,使其在您不希望发生的事件(例如,手动
when: manual规则)上触发。如下所述,使用带有人工审批人的专用环境可以降低这种特殊风险。
-
-
受信任的发布者是注册到项目而非用户名下的。这意味着从 PyPI 项目中移除用户并不会移除他们可能注册的任何受信任的发布者,因此,在项目维护者“离职”时,您应该审核所有受信任的发布者。
除了上述要求之外,您还可以执行以下操作来“缩小”可信发布工作流程的范围:
-
使用专用环境:GitLab CI/CD 支持“环境”,可用于将密钥隔离到特定工作流程。OIDC 发布不使用任何预配置的密钥,但使用专用
publish环境deploy是一种通用的最佳实践。专用环境允许额外的保护措施,例如 受保护的环境,可以要求对使用该环境的工作流进行手动批准。
-
使用受保护的标签:如果您使用基于标签的发布工作流程(例如,根据推送的标签触发),则可以将标签的创建和修改权限限制为维护者及更高级别用户(或自定义角色),且仅限符合您发布模式的标签。例如,
v*这将阻止非维护者创建或修改与版本字符串匹配的标签,例如v1.2.3。 -
限制你的出版工作范围:你的出版工作(理想情况下)应该只有两个步骤:
-
从单独的构建作业中检索可发布的发行文件;
-
使用 发布分发
twine,该 处理 OIDC 交换。
-
通过使用单独的构建作业,您可以将访问 OIDC 令牌的步骤数量控制在最低限度。这可以防止意外泄露和恶意泄露。