使用工作负载身份联合的最佳实践

借助工作负载身份联合,在 Google Cloud 外部运行的应用可以使用来自外部身份提供方的凭据来模拟服务账号。

通过使用工作负载身份联合,您可以让应用使用外部环境提供的身份验证机制并替换服务账号密钥,从而提高安全性。

要安全地使用工作负载身份联合,您必须以保护您免受以下威胁的方式对其进行配置:

  • 欺骗:不法分子可能会试图欺骗用户的身份,以获得未经授权的 Google Cloud 资源访问权限。
  • 提升权限:不法分子可能会利用工作负载身份联合来访问他们原本无权访问的资源。
  • 不可否认性:不法分子可能会使用外部凭据来隐藏其身份和操作,这使得难以将操作追溯到他们。

本指南介绍了确定何时使用工作负载身份联合的最佳实践,以及如何以有助于您最大限度地降低风险的方式对其进行配置。

何时使用工作负载身份联合

将工作负载身份联合用于有权访问环境凭据的应用

在 Google Cloud 以外的云服务商上运行的应用通常有权访问环境凭据。这些是应用无需执行任何额外身份验证即可获取的凭据。例如:

如果环境凭据是 OpenID Connect (OIDC) 令牌、SAML 断言或 AWS 凭据,您可以配置工作负载身份联合,让应用交换这些凭据以获取短期 Google 访问令牌。如果环境凭据使用其他格式,您可以先将其交换为 OIDC 令牌或 SAML 断言,然后将它们用于工作负载身份联合。

每当应用需要访问 Google Cloud 并且有权访问环境凭据时,请使用工作负载身份联合。

使用额外的令牌交换来使用工作负载身份联合不支持的环境凭据

在某些情况下,应用可以访问环境凭据,但工作负载身份联合不支持凭据类型。在这些情况下,请检查额外的令牌交换是否允许您将环境凭据转换为可用于工作负载身份联合的凭据类型。

例如,如果您的应用在 Active Directory 环境中运行,则可访问 Kerberos 凭据。如果您的环境中有支持集成 Windows 身份验证的身份提供方(如 Active Directory Federation Services (AD FS)),则可以使用这些 Kerberos 凭据向身份提供方进行身份验证并获取使用 JWT 格式的 OAuth 访问令牌。使用此访问令牌和工作负载身份联合,您可以让应用执行第二次令牌交换以获取短期有效的 Google 凭据。

链接令牌交换会增加复杂性并可能引入其他依赖项,但您无需管理和保护服务账号密钥。

使用工作负载身份联合减少需要轮替的凭据数量

与 OpenID 或 SAML 身份提供方集成的应用通常使用客户端密钥(或不同形式的密钥)向身份提供方进行身份验证。通常,此密钥存储为应用配置的一部分。如需允许此类应用访问 Google Cloud,您必须在以下各项之间做出选择:

  1. 创建服务账号密钥并将其与其他密钥一起存储。
  2. 使用现有身份提供方颁发的令牌,并使用工作负载身份联合将其交换为 Google 凭据。

第一个选项需要两个密钥,但第二个选项只需要一个密钥。减少密钥数量可以帮助您简化密钥轮替,进而改善安全性。

防范仿冒威胁

工作负载身份池不包含任何身份或用户账号,因此它与 Cloud Identity 等用户目录不同。相反,工作负载身份池表示一个可显示来自外部身份提供方的身份的视图,以便将其用作 IAM 主账号。

根据您配置工作负载身份池及其提供方的方式,同一外部身份可能表示为多个不同的 IAM 主账号,或者多个外部身份可以映射到同一 IAM 主账号。这种歧义可能会让不法分子趁机发起欺骗攻击。

以下部分介绍了帮助您避免歧义映射并降低欺骗威胁风险的最佳实践。

与 GitHub 或其他多租户身份提供方联合时使用属性条件

工作负载身份联合不会维护用户账号目录;而是会实现基于声明的身份:因此,如果两个令牌由同一身份提供方 (IdP) 颁发且其声明映射到同一 google.subject 值,则系统会假定这两个令牌用于标识同一用户。如需了解哪个 IdP 颁发了令牌,工作负载身份联合会检查并验证令牌的颁发者网址。

某些提供方(例如 GitHub 和 Terraform Cloud)在其所有租户中使用单个颁发者网址。对于这些提供方,颁发者网址标识所有 GitHub 或 Terraform Cloud 组织,而不是特定的 GitHub 或 Terraform Cloud 组织。

使用这些身份提供方时,让工作负载身份联合检查令牌的颁发者网址以确保令牌来自可信来源且其声明可信任是不够的。我们建议您配置工作负载身份联合属性条件,以检查令牌是否来自可信租户,或者是否来自可信组织(如果是 GitHub 或 Terraform Cloud)。

如需了解详情,请参阅配置属性条件

使用专用项目管理工作负载身份池和提供方

您可以使用单个专用项目来管理工作负载身份池和提供方,而不是跨多个项目管理工作负载身份池和提供方。使用专用项目可帮助您:

  • 确保仅将可信的身份提供方用于工作负载身份联合。
  • 集中控制对工作负载身份池和提供方配置的访问。
  • 在所有项目和应用中应用一致的特性映射和条件。

您可以使用组织政策限制条件来实施使用专用项目来管理工作负载身份池和提供方的规则。

使用组织政策限制条件来禁止在其他项目中创建工作负载身份池提供方

有权创建工作负载身份池提供方的用户可以创建工作负载身份池和提供方,这些工作负载池和提供方可能与您在专用项目中管理的工作负载池和提供方无关。

您可以使用 constraints/iam.workloadIdentityPoolProviders 组织政策限制条件并将规则设置为拒绝全部,以防止创建新的工作负载身份池提供方。

默认情况下,在组织层次结构的根目录下应用这些限制,以拒绝创建新的工作负载身份池提供方。通过应用允许某些可信 AWS 账号或 OIDC 提供方的政策限制条件,为您希望允许管理工作负载身份池和提供方的项目创建例外。

每个工作负载身份池使用单个提供方以避免主题冲突

借助工作负载身份联合,您可以为每个工作负载身份池创建多个提供方。如果身份由多个提供方管理,但您希望隐藏在 Google Cloud 上运行的工作负载中的这种复杂性,则使用多个提供方会非常有效。

使用多个提供方会带来主题冲突的风险,即一个提供方的 google.subject 的特性映射返回与另一个提供方的特性映射相同的值。此类冲突的结果是多个外部身份映射到同一 IAM 主账号,导致外部身份在 Cloud Audit Logs 中无法区分。

为避免主题冲突,请为每个工作负载身份池使用单个提供方。如果您需要与多个提供方联合,请创建多个工作负载身份池,每个池均使用单个工作负载身份提供方。

避免与同一身份提供方联合两次

通过创建使用同一配置或类似配置的多个工作负载身份池提供方,您可以多次与同一身份提供方联合。如果这些提供方属于同一工作负载身份池,则此类配置可能会导致主题冲突。如果提供方属于不同的工作负载身份池,则不会发生主题冲突,并且同一外部身份将表示为不同的 IAM 主账号。

将单个外部身份映射到多个 IAM 主账号会使分析特定外部身份有权访问的资源变得更加困难。这种歧义还会增加尝试撤消访问权限的风险:管理员可能会撤消一个主账号的访问权限,但可能不知道另一个主账号存在,从而无意中导致外部身份保留访问权限。

为最大程度地降低歧义的风险,请避免多次与同一身份提供方联合。请改为创建单个工作负载身份池和提供方,并使用特性映射和条件来确保它可用于需要访问 Google Cloud 资源的所有外部身份。

保护身份提供方的 OIDC 元数据端点

当您与 OpenID Connect 提供方联合时,工作负载身份联合会定期从身份提供方下载 OIDC 元数据。工作负载身份联合使用 IdP 的元数据和 JSON Web 密钥集 (JWKS) 验证令牌。

为了确保真实性,使用 TLS 来保护与身份提供方的通信。如果您的提供方部署在终止 TLS 的负载均衡器或反向代理后面,则 TLS 连接可确保负载均衡器或反向代理的真实性,但不能保证实际身份提供方的真实性。

不法分子可能能够通过启动中间人 (MITM) 攻击来利用此设置,在该攻击中,他们会重新配置负载均衡器,使其将 JWKS 请求传递给提供不同密钥集的恶意端点。交换 JWKS 可让不法分子签署工作负载身份联合认为有效的令牌,并可能允许他们伪造其他用户的身份。

为了防止 JWKS 交换,请确保您的 IdP 以保护其免受 MITM 攻击的方式部署。

使用工作负载身份池提供方的网址作为目标对象

当您与 OpenID Connect 提供方联合时,工作负载身份联合会验证令牌(在 aud 声明中编码)的目标对象是否与提供方允许的目标对象设置相匹配。同样,当您与 SAML 提供方联合时,工作负载身份联合会检查 SAML 断言是否指定了与预期目标对象匹配的目标对象限制

默认情况下,工作负载身份联合要求目标对象与唯一标识工作负载身份池提供方的网址 https://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID 匹配。要求令牌和断言使用此网址作为目标对象有助于降低混淆代理攻击的风险。在此类攻击中,不法分子向工作负载身份联合提供令牌或 SAML 断言,该断言并非用于工作负载身份联合,而是用于其他 API。

要求令牌或断言包含目标工作负载身份池提供方的网址可帮助您确保客户端只能使用专门为工作负载身份联合颁发的令牌和断言。

在特性映射中使用不可变特性

授予外部身份模拟服务账号的权限,您需要创建按主题、群组或自定义属性引用外部身份的 IAM 绑定。外部身份的主题、组和自定义特性派生自外部身份提供方在令牌交换期间传递给工作负载身份联合的特性。

某些身份提供方允许用户更改一些自己的特性。例如,用户可以修改其电子邮件地址或别名。如果您的 IAM 绑定引用可修改的特性,则用户可能会修改其用户配置文件,而意外失去对某些资源的访问权限。更糟糕的情况是,不法分子可能有意修改他们的用户属性以匹配现有的 IAM 绑定,从而获得未经授权的资源访问权限。

为了防范这种欺骗威胁,请将特性映射限制为用户无法修改或根本无法修改的特性。

在特性映射中使用不可重复使用的特性

如果您授予外部身份来模拟服务账号并随后删除外部身份提供方中的用户,则该服务账号的 IAM 绑定将保持不变。

如果您日后向外部身份提供方添加新用户,并且该用户与先前删除的用户共享某些特性(例如,同一电子邮件地址),则新旧用户的工作负载将无法区分身份联合。因此,仅用于引用旧用户的 IAM 绑定可能也适用于新用户。

为了防止产生这种歧义,请使用完全依赖于无法随时间重复使用的特性的特性映射,例如唯一用户 ID。

如果您的公司政策允许重复使用电子邮件地址等特性,请避免在特性映射中使用这些特性,并改用其他保证在时间上唯一的特性。

不允许修改特性映射

工作负载身份联合使用特性映射来选择外部身份提供商提供的哪些特性应该嵌入到 STS 令牌中,以及特性名称应如何进行转换。配置特性映射是在外部身份提供商与 Google Cloud 之间设置信任关系的关键步骤。

特性映射对于使用工作负载身份联合的安全性也至关重要:如果您已许可联合主账号或主账号集模拟服务账号,然后您又更改了特性映射,则您可以更改哪些用户有权访问该服务账号。

修改特性映射需要 iam.googleapis.com/workloadIdentityPoolProviders.update 权限。具有此权限的角色包括:

  • Owner (roles/owner)
  • IAM Workload Identity Pool Admin (roles/iam.workloadIdentityPoolAdmin)

如果不法分子有权修改特性映射,则他们可能可以更改映射规则,导致其仿冒身份并获取对服务账号的访问权限。为防止此类恶意修改,请确保只有少数管理用户有权修改特性映射。

请考虑创建一个用于管理工作负载身份池的专用 Google Cloud 项目,这有助于限制在资源层次结构的更高级层向用户意外授予其中一个角色的风险。

请勿依赖于不稳定或非权威的特性

身份提供商使用特性来传达有关经过身份验证的用户的信息。身份提供商通常保证某些特性具有权威性,但其他特性并不具有权威性。例如,外部身份提供商可能会在 OIDC 令牌中嵌入用户名和用户 ID。这两个特性可唯一标识用户,并且看似可以互换。但是,外部身份提供商可能保证用户 ID 稳定且权威,但允许更改用户名。

如果特性映射依赖于不稳定或不具有权威性的特性,则不法分子可能可以通过修改外部身份提供商中的用户个人资料来仿冒其身份。例如,他们可能将其用户名更改为近期在外部身份提供商中删除的用户的用户名,但仍有权访问 Google Cloud 上的服务账号。

为防范此类仿冒攻击,请确保特性映射仅依赖于外部身份提供商保证其稳定且具有权威特性的特性。

防范不可否认的威胁

每当您发现影响 Google Cloud 中某项资源的可疑活动时,Cloud Audit Logs 是非常重要的信息来源,可帮助您了解该活动发生的时间以及参与的用户。

使用工作负载身份联合时,应用会模拟服务账号。在 Cloud Audit Logs 中,应用执行的任何活动均归因于模拟的服务账号。要重建导致活动的完整事件链,您必须能够将 Cloud Audit Logs 与身份提供方的日志相关联,以便您可以找出涉及哪个外部身份以及执行活动的原因。

本部分介绍最佳实践,可帮助您保留不可否的审核跟踪记录。

为 IAM API 启用数据访问日志

为了帮助您识别和了解服务账号模拟场景,Cloud Engine 等服务在 Cloud Audit Logs 中包含 serviceAccountDelegationInfo 部分。如果应用使用工作负载身份联合,本部分包括用于模拟服务账号的主账号的主题

并非所有服务都在 Cloud Audit Logs 中包含模拟详细信息。为了帮助维护不可否认的审核跟踪,您还必须通过为 Security Token Service APIIdentity and Access Management API 启用数据访问日志来记录所有模拟事件。为包含用于工作负载身份联合的工作负载身份池或服务账号的所有云项目启用这些日志。

通过启用这些日志,您可以确保每当应用使用工作负载身份联合来交换外部凭据模拟服务账号时,都会向 Cloud Audit Logs 添加一个条目。

使用唯一的主题映射

Cloud Audit Logs 条目的 serviceAccountDelegationInfo 部分中使用的主要主题由您的工作负载身份池提供方的 google.subject 属性映射确定。

当您发现可疑活动并需要找出涉及的外部身份时,您必须能够根据相应的 google.subject 值查找外部身份。

同样,当外部身份遭到破解,并且您需要确定该身份是否用于访问 Google Cloud 资源时,您必须能够找到与外部身份对应的 Cloud Audit Logs 条目。

为工作负载身份池提供方定义特性映射时,请为 google.subject 选择唯一的映射,以便:

  • 外部身份仅映射到一个 google.subject 值。
  • google.subject 值仅映射到一个外部身份。
  • 您可以根据外部身份的 google.subject 值查询外部身份。

使用满足这些唯一性条件的特性映射有助于确保您可以按 google.subject 值查找外部身份,反之亦然。

防范提升权限威胁

如需在使用工作负载身份联合时应用最小权限原则,您必须执行以下操作:

  • 限制可以模拟服务账号的外部身份的数量
  • 限制服务账号可以访问的资源

过于宽松的配置可能会导致不法分子使用外部身份升级其权限并访问不应访问的资源。

以下部分提供了可帮助您防范权限升级威胁的最佳实践。

使用与您需要访问的资源位于同一项目中的服务账号

当客户端通过使用客户端库REST API 来使用工作负载身份联合时,它遵循一个三个步骤:

  1. 从受信任的身份提供商获取凭据。
  2. 用凭据从 Security Token Service 交换令牌。
  3. 使用 Security Token Service 中的令牌模拟服务账号并获取短期有效的 Google 访问令牌。

最后,使用与您需要访问的资源位于同一项目中的服务账号。使用在同一项目中管理的服务账号可以帮助您应用更严格的访问权限,并让您更轻松地确定何时不再需要该服务账号。

为每个应用使用专用的服务账号

如果您有多个应用使用工作负载身份联合来访问同一项目中的资源,请为每个应用创建一个专用服务账号。使用特定于应用的服务账号仅授予对每个应用所需资源的访问权限,从而帮助您避免过度授权。

避免向池中的所有成员授予访问权限

在外部身份模拟服务账号之前,您必须向其授予服务账号的 roles/iam.workloadIdentityUser 角色。授予此角色时,请避免将其授予工作负载身份池的所有成员。而是将该角色授予特定的外部身份或符合特定条件的身份。

最初,需要访问 Google Cloud 资源的外部用户数量可能很少。因此,工作负载身份池的特性条件和身份提供方配置可能仅允许少数外部身份使用工作负载身份联合。

当您以后将新工作负载添加到 Google Cloud 时,可能需要修改身份提供方配置或工作负载身份池的特性条件,以便允许其他外部身份。

通过仅将 roles/iam.workloadIdentityUser 角色授予特定外部身份,您可以确保安全地增加工作负载身份池,而不会无意中授予超出需求的外部身份模拟访问权限。

后续步骤