本页面适用于平台管理员和运维人员,以及希望最大限度地降低舰队中与身份相同性相关的风险的安全工程师。
在阅读本页面之前,请确保您熟悉关于舰队工作负载身份联合中的概念。
术语
本页面使用以下术语:
- Workload Identity Federation for GKE:一项可为单个 Google Cloud 项目中的 GKE 工作负载提供身份的功能。
- 舰队工作负载身份联合:一项功能,可将 Workload Identity Federation for GKE 扩展到整个舰队中的工作负载,包括 Google Cloud外部和多个项目中的工作负载。
- 工作负载身份池:一种以与 Identity and Access Management (IAM) 兼容的格式向工作负载提供身份的实体。每个集群都是工作负载身份池中的身份提供方。
舰队中的身份相同性
工作负载身份池是一种实体,可为工作负载提供 IAM 在对请求进行身份验证和授权时可以使用的身份格式。借助 Workload Identity Federation for GKE,每个项目默认都有一个固定的 Google 管理的工作负载身份池,该池是该项目独有的。
借助舰队工作负载身份联合,舰队宿主项目的 Google 管理的工作负载身份池是您注册到舰队的所有集群的默认工作负载身份池,无论这些集群位于其他项目中还是其他云端。您可以选择性地为特定集群设置自行管理的工作负载身份池,以供集群使用,而不是使用默认池。
在舰队工作负载身份联合和适用于 GKE 的工作负载身份联合中,您都可以使用 IAM 允许政策向集群中的实体(例如 Kubernetes ServiceAccount 或 Pod)授予对特定 Google Cloud资源的访问权限。在允许政策中,您可以使用 IAM 可读取的命名语法(即主账号标识符)来引用这些实体。主账号标识符包含集群使用的工作负载身份池的名称,以及用于选择集群中特定实体的其他信息。例如,以下主账号标识符会选择命名空间中的 Kubernetes ServiceAccount:
principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/WORKLOAD_IDENTITY_POOL_NAME/subject/ns/NAMESPACE/sa/SERVICEACCOUNT
在此示例中,以下字段包含有关主账号的信息:
PROJECT_NUMBER
:舰队宿主项目的编号。WORKLOAD_IDENTITY_POOL_NAME
:工作负载身份池的名称。NAMESPACE
:命名空间的名称。SERVICEACCOUNT
:Kubernetes ServiceAccount 的名称。
对 Google Cloud API 的请求通过使用集群生成的短期有效的 OAuth 2.0 访问令牌进行身份验证。这些访问令牌包含创建请求的实体的主账号标识符。IAM 使用主账号标识符来确保允许政策授权实体执行所请求的操作。
身份相同性对多租户舰队的影响
主账号标识符会导致身份相同,这意味着环境中与特定主账号标识符匹配的任何实体都会被 IAM 视为同一实体。对于单项目 Workload Identity Federation for GKE,身份相同性适用于该项目中共享同一主账号标识符的所有实体。不过,借助舰队工作负载身份联合,这种身份相同性会应用于整个舰队中共享同一主账号标识符的所有实体,而无论集群项目如何。
例如,对于上一部分中的主账号标识符,使用同一服务账号、同一命名空间和同一工作负载身份池的 Pod 发出的请求会获得相同的主账号标识符,而无论集群或项目如何。
如果您的舰队仅在舰队宿主项目中运行集群,则身份相同性影响与 Workload Identity Federation for GKE 相同。不过,如果您的舰队包含在其他项目中运行的集群,则这种身份相同性会扩展到舰队中的所有已注册集群。
舰队身份相同性的复杂性示例
以下示例场景描述了在实现舰队工作负载身份联合时可能会出现的潜在身份相同性复杂情况。每个场景都为您提供了可能的缓解措施,这些措施可能有助于您应对这些复杂情况。
注册了所有集群且具有相同工作负载身份池的单项目舰队
请考虑以下舰队配置:
- 舰队的所有成员集群都在舰队宿主项目中。
- 项目中的所有集群都是舰队的成员。
- 所有集群都使用相同的工作负载身份池。
在此场景中,舰队的所有成员集群都在舰队宿主项目中,并且该项目中的所有集群都是舰队的成员。
如舰队的身份相同性影响部分所述,在此场景中使用舰队级工作负载身份联合与使用Workload Identity Federation for GKE相同,并且没有额外的风险。
注册了部分集群且具有相同工作负载身份池的单项目舰队
请考虑以下舰队配置:
- 该舰队包含两个集群,这两个集群都在舰队宿主项目中运行。
- 舰队宿主项目包含不是舰队成员的第三个集群。
- 不是舰队成员的集群也已启用Workload Identity Federation for GKE。
- 项目中的所有集群都使用相同的工作负载身份池
在此配置中,您在一个集群中向实体授予的任何角色都适用于项目中与该主账号标识符匹配的其他实体。这可能会导致意外地向不属于舰队的实体授予权限。例如,向选择命名空间中特定服务账号的主账号标识符授予角色具有以下影响:
- 在舰队成员集群中,在指定命名空间中运行并使用指定服务账号的工作负载共享访问权限。
- 在第三个非成员集群中运行的工作负载(使用相同的命名空间和服务账号名称)也会获得相同的访问权限。
以下建议可能有助于解决此复杂性问题:
- 配置舰队成员集群以使用自行管理的工作负载身份池(预览版)。这样可确保舰队成员集群中的实体与非成员集群中的实体具有不同的主账号标识符。如需了解详情,请参阅从混合信任舰队工作负载向 Google Cloud API 进行身份验证。
创建专用舰队宿主项目,并使用组织政策来防止专用舰队宿主项目运行集群。这样可以将舰队级工作负载身份池信任网域与 GKE 项目级信任网域分隔开。只有已注册的集群才能共享舰队范围的工作负载身份池。
这些建议适用于 Google Cloud 上的集群和关联集群。
注册了部分集群且具有相同工作负载身份池的多项目舰队
请考虑以下舰队配置:
- 相应舰队包含在两个 Google Cloud项目中运行的成员集群:
project-1
和project-2
。 project-1
是队列宿主项目。project-1
中的所有集群都是舰队成员。project-2
包含一个舰队成员集群和一个未注册的集群。project-1
中的所有集群都使用项目的 Google 管理的工作负载身份池,这也是默认的舰队级工作负载身份池。project-2
中的舰队成员集群使用舰队范围的工作负载身份池。
在此场景中,您授予舰队宿主项目中实体的任何权限也适用于来自 project-2
的成员集群中的实体,因为它们都共享同一个工作负载身份池。
为了尝试解决这种复杂性,请创建一个专用 Google Cloud 项目 Google Cloud 作为舰队宿主项目。project-1
和 project-2
中的舰队成员集群随后会默认共享专用项目的工作负载身份池。然后,您可以在主账号标识符中使用 project-1
的工作负载身份池,向 project-1
中的集群授予项目级访问权限。
防止创建类似身份
在舰队中实现身份相同性需要您谨慎实施访问权限控制,以防止有意或无意地创建类似身份。例如,假设您向命名空间中使用特定 ServiceAccount 的所有 Pod 授予访问权限。如果有人在其他舰队成员集群中创建了该命名空间和 ServiceAccount,则该集群中的 Pod 会获得相同的访问权限。
为减少出现此问题的几率,请使用授权机制,仅允许一组受信任的用户创建、更新或删除命名空间和 Kubernetes 服务账号。
对于 IAM,以下权限可提供此访问权限:
container.namespaces.*
container.serviceAccounts.*
对于 Kubernetes 基于角色的访问权限控制 (RBAC),以下 ClusterRole 示例配置了与这些 Kubernetes 资源互动的特殊访问权限:
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: namespace-admin rules: - apiGroups: [""] resources: ["namespaces"] verbs: ["create","delete","update","patch"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: serviceaccount-admin rules: - apiGroups: [""] resources: ["serviceaccounts"] verbs: ["create","delete","update","patch","impersonate"]