使用和管理服务帐号的最佳做法

服务帐号代表非人类用户。它们旨在用于工作负载(例如自定义应用)在没有最终用户参与的情况下访问资源或执行操作的场景。

服务帐号与普通用户帐号存在以下区别:

  • 服务帐号没有密码,不能用于基于浏览器的登录。
  • 服务帐号作为属于 Google Cloud 项目的资源创建和管理。相比之下,用户在 Cloud Identity 或 Google Workspace 帐号中进行管理。
  • 这些帐号专用于 Google Cloud。相比之下,在 Cloud Identity 或 Google Workspace 中管理的用户可跨多个 Google 产品和服务开展工作。

本指南介绍管理、使用和保护服务帐号的最佳做法。

选择何时使用服务帐号

服务帐号可用于许多不同用途,但并不总是最佳选择。以下部分提供了有关何时应使用服务帐号以及何时应避免使用服务账号的指导。

在无人参与场景下使用服务帐号

并非所有应用都会与人类用户交互,而是可能会在无人参与情况下在后台运行。无人参与的应用包括批量作业、调度从队列读取的消息的工作器进程或资源监控代理。

每当无人参与的应用需要访问资源(例如 Cloud Storage 存储分区)时,该应用必须代表自己执行操作,而不是代表任何最终用户。如需代表自己执行操作,应用需要自己的身份,它与任何最终用户身份无关。

如需为应用提供其自己的身份,请为该应用创建服务帐号,并为服务帐号授予该应用需要访问的资源的访问权限。通过允许应用使用自己的服务帐号,您可以帮助确保应用无需用户交互即可运行。此外,还要确保任何由应用发起的资源访问都可归因于同一个应用。

使用服务帐号在主帐号之间进行转换

与最终用户交互的应用可以使用 Google 登录对这些用户进行身份验证,但这并非强制要求这样做:相反,应用可以依赖于第三方身份提供商,也可以实现自定义身份验证方案来对用户进行身份验证。

如果应用使用第三方或自定义身份并需要访问某个资源(如 BigQuery 数据集或 Cloud Storage 存储桶),则必须在主帐号之间进行转换。由于 Google Cloud API 无法识别第三方或自定义身份,因此应用无法将最终用户的身份传播到 BigQuery 或 Cloud Storage。相反,应用必须使用其他 Google 身份执行访问。

如需让应用在主帐号之间转换,请为应用创建服务帐号,并为其授予应用需要访问的资源的访问权限。每当应用需要访问 Google Cloud 资源时,请确保最终用户先经过身份验证,然后允许其使用服务帐号访问该资源。

主帐号之间的转换可能会限制受影响 Google Cloud 资源的 Cloud Audit Logs 的实用性:由于应用使用服务帐号访问资源,因此 Cloud Audit Logs 可能不会明确指示是否代表特定最终用户执行操作。为帮助确保不可否认性,请扩展您的应用,使其每当在主帐号之间进行转换时都写入自定义日志记录。这样,您可以追溯触发资源访问的最终用户。

应用可能需要敏感或个人用户数据的访问权限。此类数据示例包括用户的邮箱或日历、存储在云端硬盘中的文档或包含敏感数据的 BigQuery 数据集。

如果应用执行无人参与的后台任务(例如编制索引或数据泄露防护 (DLP) 扫描),或者最终用户未使用 Google 身份进行身份验证,则使用服务帐号访问用户数据是合适的做法。在应用代表最终用户执行操作的所有其他场景中,最好避免使用服务帐号。

使用 OAuth 同意流程请求最终用户的同意,而不是使用服务帐号访问用户数据(可能执行主帐号转换)。然后,让应用以最终用户的身份进行操作。使用 OAuth(而非服务帐号)有助于确保:

  • 用户可以查看将授予应用对哪些资源的访问权限,并且可以明确表示或拒绝同意。
  • 用户可以随时在我的帐号页面上撤消同意。
  • 您无需拥有一个可以不受限制地访问所有用户数据的服务帐号。

通过允许应用使用最终用户凭据,您可以延迟对 Google Cloud API 的权限检查。这种方法限制了因编码错误(混淆代理问题)而导致意外公开用户不应有权访问的数据的风险。

在开发过程中请勿使用服务帐号

在日常工作中,您可能会使用 gcloud 命令行工具、gsutilterraform 等工具。请勿使用服务帐号运行这些工具。您应该通过运行 gcloud auth login(对于 gcloud 工具和 gsutil)或 gcloud auth application-default login(对于 terraform 和其他第三方工具)来允许这些工具使用您的凭据。

您可以使用类似的方法来开发和调试计划在 Google Cloud 上部署的应用。部署后,应用可能需要服务帐号,但如果您在本地工作站上运行该应用,则可以让它使用您的个人凭据。

为了帮助确保应用同时支持个人凭据和服务帐号凭据,请使用 Cloud 客户端库自动查找凭据

使用服务帐号

用户向 Google Cloud 进行身份验证的典型方法是使用用户名和密码登录,或使用单点登录 (SSO)。服务帐号没有密码,也无法使用 SSO。服务帐号支持一组不同的身份验证方法。以下部分介绍了选择身份验证方法的最佳做法。

如何使用服务帐号

尽量使用关联的服务帐号

如需允许部署在 Google Cloud 上的应用使用服务帐号,请将服务帐号关联到底层计算资源。通过关联服务帐号,您可以允许应用获取服务帐号的令牌,并使用这些令牌来访问 Google Cloud API 和资源。

如需获取应用中的访问令牌,请使用客户端库(如果可能)。客户端库会自动检测应用是否在关联服务帐号的计算资源上运行。

如果使用客户端库不切实际,请对应用进行调整,以便以编程方式从元数据服务器获取令牌。支持访问元数据服务器的计算资源包括:

如需查看允许您关联服务帐号的计算资源的完整列表,请参阅管理服务帐号模拟

使用 Workload Identity 将服务帐号关联到 Kubernetes pod

如果您使用 Google Kubernetes Engine,则可能会在一个 GKE 集群上同时运行不同应用。各个应用需要访问的资源和 API 可能不同。

如果您将服务帐号关联到 GKE 集群或其某个节点池,则默认情况下,该集群或节点池上运行的所有 pod 都可以模拟服务帐号。在不同应用之间共享一个服务帐号会导致很难为该服务帐号分配一组正确的权限:

  • 如果您只授予所有应用需要的资源的访问权限,则某些应用可能会因为缺少特定资源的访问权限而无法正常运行。
  • 如果您授予任何特定应用需要的所有资源的访问权限,则您可能会过度授予访问权限。

如需管理 GKE 环境中的资源的访问权限,更好的方法是使用 Workload Identity:

  1. 请勿将服务帐号关联到 GKE 集群或节点池。
  2. 为需要 Google API 或资源的访问权限的每个 Kubernetes pod 创建一个专用服务帐号。
  3. 为需要 Google API 或资源的访问权限的每个 Kubernetes pod 创建一个 Kubernetes 服务帐号,并将其关联到 pod。
  4. 使用 Workload Identity 在服务帐号及其对应的 Kubernetes 服务帐号之间创建映射。

使用工作负载身份联合来允许在本地或在其他云提供商上运行的应用使用服务帐号

如果您的应用在本地或其他云服务商上运行,您无法将服务帐号关联到底层计算资源。但是,应用可能有权访问特定于环境的凭据,例如:

  • AWS 临时凭据
  • Azure Active Directory 访问令牌
  • 由本地身份提供商(例如 Active Directory Federation Services (AD FS) 或 KeyCloak)签发的 OpenID 访问令牌或 ID 令牌

如果您的应用有权访问其中一个凭据并需要访问 Google Cloud API 或资源,请使用工作负载身份联合

借助工作负载身份联合,您可以在 Google Cloud 项目与外部身份提供商之间创建单向信任关系。建立信任后,应用便可使用受信任的身份提供商签发的凭据,按照以下三步流程来模拟服务帐号:

  1. 从可信的身份提供商获取凭据,例如 OpenID Connect ID 令牌。
  2. 使用 Security Token Service (STS) API 将凭据换成短期有效的 Google STS 令牌。
  3. 使用 STS 令牌向 IAM Service Account Credentials API 进行身份验证,并获取服务帐号的短期有效的 Google 访问令牌。

通过使用工作负载身份联合,您可以让应用使用外部环境提供的身份验证机制,并且无需存储和管理服务帐号密钥。

使用 IAM Credentials API 代理凭据

有些应用仅在特定时间或在特定情况下需要特定资源的访问权限。例如:

  • 应用在启动期间可能需要配置数据的访问权限,但初始化后可能会不需要此访问权限。
  • 监管者应用可能会定期启动后台作业,其中每个作业都有不同的访问权限要求。

在这种情况下,使用单个服务帐号并授予其对所有资源的访问权限违反了最小权限原则:在任何时间点,应用拥有访问权限的资源数量都可能超过实际所需的。

为帮助确保应用的不同部分仅有权访问所需的资源,请使用 IAM Credentials API 代理短期有效的凭据:

  • 为应用或用例的每个部分创建专用服务帐号,并只授予服务帐号对必要资源的访问权限。
  • 创建另一个充当监管者的服务帐号。向监管者服务帐号授予其他服务帐号的 Service Account Token Creator 角色,以便它可以为这些服务帐号请求短期访问令牌。
  • 拆分应用,使应用的一部分充当令牌代理,并且仅让应用的这一部分使用监管者服务帐号。
  • 使用令牌代理向应用的其他部分签发短期有效的服务帐号。

如果没有可行的替代方案,请使用服务帐号密钥

有时,您可能会遇到无法关联服务帐号,并且使用 Workload Identity工作负载身份联合不是可行方法的情况。例如,您的某个本地应用可能需要 Google Cloud 资源的访问权限,但您的本地身份提供商与 OpenID Connect 不兼容,因此无法用于工作负载身份联合。

如果其他身份验证方法不可行,请为该应用创建服务帐号密钥。借助服务帐号密钥,应用可以以服务帐号身份进行身份验证,这类似于用户可使用用户名和密码进行身份验证的方式。服务帐号密钥是一种 Secret 类型,必须免遭未经授权的访问。建议将其存储在安全的位置(例如密钥保险柜),并经常进行轮替。

管理服务帐号

服务帐号与普通用户帐号的区别不仅在于使用方法,还在于管理方法。以下部分提供了管理服务帐号的最佳做法。

将服务帐号作为资源管理

常规用户帐号通常根据组织的“joiner-mover-leaver”流程进行管理:员工加入时,系统会为他们创建新的用户帐号。当员工调动部门时,其用户帐号会更新。当员工离开公司时,他们的用户帐号会被暂停或删除。

相比之下,服务帐号不与任何特定员工关联。而是最好将服务帐号视为资源(属于其他资源或是其他资源的一部分),例如特定虚拟机实例或应用。

要有效地管理服务帐号,请不要孤立地看待服务帐号,而应在其关联资源的背景中进行考量,并将服务帐号及其关联资源作为一个整体进行管理:对服务帐号及其关联资源应用相同的进程、相同的生命周期和相同的安全级别,并使用相同的工具进行管理。

创建单一用途的服务帐号

在多个应用之间共享一个服务帐号可能会导致服务帐号的管理复杂化:

  • 这些应用可能有不同的生命周期。如果应用被停用,您可能不清楚服务帐号是否可停用,以及是否仍需要服务帐号。
  • 随着时间的推移,应用的访问权限要求可能会有所不同。如果应用使用同一个服务帐号,您可能需要向服务帐号授予越来越多的资源的访问权限,导致增加总体风险。
  • Cloud Audit Logs 包含执行更改或访问数据的服务帐号的名称,但不会显示使用该服务帐号的应用的名称。如果多个应用共享一个服务帐号,您可能无法将活动追溯到正确的应用。

为了避免这些问题,请为每个应用创建专用服务帐号,并避免使用默认服务帐号

遵循命名和文档惯例

为了帮助跟踪服务与应用或资源之间的关联,请在创建新的服务帐号时遵循命名惯例:

  • 为服务帐号电子邮件地址添加一个前缀,以标识该帐号的使用方式。例如:
    • vm-,表示挂接到虚拟机实例的服务帐号。
    • wi-,表示 Workload Identity 使用的服务帐号。
    • wif-,表示工作负载身份联合使用的服务帐号。
    • onprem-,表示本地应用使用的服务帐号。
  • 如果虚拟机运行差旅费用应用,则在服务帐号电子邮件地址中嵌入该应用的名称,例如 vm-travelexpenses@
  • 使用说明字段添加联系人、指向相关文档的链接或其他说明。

请勿在服务帐号的电子邮件地址中嵌入敏感信息或字词。

识别并停用未使用的服务帐号

如果不再使用某服务帐号,请停用该服务帐号。通过停用未使用的服务帐号,可以降低服务帐号因不法分子水平扩散或权限提升而被滥用的风险。

对于与特定资源(如虚拟机实例)关联的单一用途的服务帐号,请在停用或删除关联资源后,立即停用该服务帐号。

对于用于多种用途或跨多个资源共享的服务帐号,要确定服务帐号是否仍在使用则更为困难。在这些情况下,请使用以下方法:

停用未使用的服务帐号,然后再将其删除

如果您删除一个服务帐号,然后创建具有相同名称的新服务帐号,系统会为新服务帐号分配不同的身份。因此,原始 IAM 绑定不会应用于新服务帐号。相反,如果停用并重新启用服务帐号,所有的 IAM 绑定保持不变。

为避免意外丢失 IAM 绑定,最好不要立即删除服务帐号。如果不再需要某个服务帐号,请在过一段时间后再删除。

切勿删除默认服务帐号,例如 App EngineCompute Engine 默认服务帐号。这些服务帐号只能通过停用并重新启用相应 API 来重新创建,这可能会破坏您现有的部署。如果您不使用默认服务帐号,停用它们即可。

后续步骤