服务身份

每个 Cloud Run 修订版本或作业都与一个服务账号相关联。Google Cloud 客户端库会自动使用此服务账号向 Google Cloud API 进行身份验证。服务代码可连接的 Google Cloud API 示例包括 Cloud Storage、Firestore、Cloud SQL、Pub/Sub 或 Cloud Tasks。

如果您未指定服务账号,Cloud Run 会将修订版本或作业关联到默认服务账号,默认服务账号具有跨所有 Google Cloud API 的广泛权限。Google 建议使用基于服务的身份并授予选择性权限。

默认服务账号简介

默认情况下,Cloud Run 修订版本和作业以 Compute Engine 默认服务账号身份执行。Compute Engine 默认服务账号具有 Project Editor IAM 角色,该角色可授予对 Google Cloud 项目中所有资源的读取和写入权限。

虽然这可能方便,而不是使用默认服务账号,但 Google 建议您创建具有最精细的权限的用户管理服务账号,并将该服务账号指定为 Cloud Run 服务或作业的身份。本文档介绍如何使用 Cloud Run 配置每项服务的身份。

使用每项服务的身份

Google 建议您为每个 Cloud Run 服务或作业分配一个用户管理的服务账号,而不是使用默认服务账号,从而为该服务提供专用身份。通过用户管理的服务账号,您可以使用 Identity and Access Management 授予一组最低权限来控制访问权限。

Google Cloud CLIGoogle Cloud 客户端库会自动检测它们何时在 Google Cloud 上运行并使用当前 Cloud Run 修订版本的运行时服务账号。这意味着,如果您的代码使用 gcloud CLI 或官方 Google Cloud 客户端库,它将自动检测 Cloud Run 服务的运行时服务账号并进行身份验证。此策略称为应用默认凭据,支持跨多个环境移植代码。

分配每个服务的身份时涉及两个方面:

分配用户管理的服务账号所需的权限

如需使用用户管理的服务账号部署 Cloud Run 服务,您必须拥有模拟该服务账号的权限 (iam.serviceAccounts.actAs)。此权限可通过 roles/iam.serviceAccountUser IAM 角色授予。所有主账号(例如用户、服务账号)必须具有用户管理的服务账号此权限,才能将 Cloud Run 服务部署为用户管理的服务账号。

您可以使用 Google Cloud 控制台、API (YAML) 或使用 gcloud CLI 授予此权限,如下所示:

gcloud iam service-accounts add-iam-policy-binding "SERVICE_ACCOUNT_EMAIL" \
    --member "PRINCIPAL" \
    --role "roles/iam.serviceAccountUser"

您需要将其中的:

  • SERVICE_ACCOUNT_EMAIL 替换为服务账号电子邮件地址,例如 PROJECT_NUMBER-compute@developer.gserviceaccount.com
  • PRINCIPAL 替换为要为其添加绑定的主账号。请使用格式 user:email,例如 user:test-user@gmail.com

如需了解如何授予权限,请参阅授予、更改和撤消对资源的访问权限

使用用户管理的服务账号部署新服务

如果您还没有用户管理的服务账号,请先创建一个服务账号

您可以在创建新服务部署新修订版本时使用 Google Cloud 控制台、gcloud CLI 或 API (YAML) 设置 Cloud Run 服务的账号:

控制台

  1. 在 Google Cloud 控制台中,前往 Cloud Run:

    转到 Cloud Run

  2. 如果您是要配置一个新服务来作为部署目标,请点击创建服务。如果您要配置现有服务,请点击该服务,然后点击修改和部署新的修订版本

  3. 如果您要配置新服务,请根据需要填写初始服务设置页面,然后点击容器、网络、安全性以展开服务配置页面。

  4. 点击安全标签。

    图片

    • 点击服务账号下拉菜单,然后选择所需的服务账号。
  5. 点击创建部署

gcloud

您可以使用以下命令更新现有服务以拥有新的运行时服务账号:

gcloud run services update SERVICE --service-account SERVICE_ACCOUNT

替换:

  • SERVICE 替换为您的服务名称。
  • SERVICE_ACCOUNT 替换为与新身份关联的服务账号:此值是服务账号的电子邮件地址,例如 example@myproject.iam.gserviceaccount.com

您还可以在部署期间使用以下命令设置服务账号:

gcloud run deploy --image IMAGE_URL --service-account SERVICE_ACCOUNT

您需要将其中的:

  • IMAGE_URL 替换为对容器映像的引用,例如 us-docker.pkg.dev/cloudrun/container/hello:latest。 如果您使用 Artifact Registry,则必须已经创建制品库 REPO_NAME。网址的形状为 LOCATION-docker.pkg.dev/PROJECT_ID/REPO_NAME/PATH:TAG
  • SERVICE_ACCOUNT 替换为与新身份关联的服务账号:此值是服务账号的电子邮件地址,例如 example@myservice.iam.gserviceaccount.com

YAML

您可以使用 gcloud run services describe --format export 命令下载并查看现有服务配置,该命令会生成清理后的 YAML 格式的结果。然后按照后续说明修改字段,最后使用 gcloud run services replace 命令上传修改后的 YAML。请务必严格按照说明修改字段。

  1. 要查看和下载配置,请运行以下命令:

    gcloud run services describe SERVICE --format export > service.yaml
  2. 更新 serviceAccountName: 特性:

    apiVersion: serving.knative.dev/v1
    kind: Service
    metadata:
      name: SERVICE
    spec:
      template:
        spec:
          serviceAccountName: SERVICE_ACCOUNT

    替换

    • SERVICE 替换为您的 Cloud Run 服务的名称。
    • SERVICE_ACCOUNT 替换为与新身份关联的服务账号:此值是服务账号的电子邮件地址,例如 example@myproject.iam.gserviceaccount.com
  3. 使用以下命令将服务替换为其新配置:

    gcloud run services replace service.yaml

Terraform

如需了解如何应用或移除 Terraform 配置,请参阅基本 Terraform 命令

如需创建服务账号,请将以下资源添加到现有 main.tf 文件中:

resource "google_service_account" "cloudrun_service_identity" {
  account_id = "my-service-account"
}

创建或更新 Cloud Run 服务并添加服务账号:

resource "google_cloud_run_v2_service" "default" {
  name     = "cloud-run-srv"
  location = "us-central1"

  template {
    containers {
      image = "us-docker.pkg.dev/cloudrun/container/hello"
    }
    service_account = google_service_account.cloudrun_service_identity.email
  }
}

使用其他项目中的服务账号

您还可以使用与 Cloud Run 服务位于不同 Google Cloud 项目中的用户管理的服务账号。如果该服务账号和 Cloud Run 服务位于不同的项目中:

  • 包含该服务账号的项目要求将组织政策 iam.disableCrossProjectServiceAccountUsage 在文件夹级层设置为 false 或未实施,或从项目级层设置继承该配置。默认情况下,该设置为 true

  • 服务账号要求 roles/iam.serviceAccountTokenCreator 具有部署项目服务代理的角色成员资格:

    service-PROJECT_NUMBER@serverless-robot-prod.iam.gserviceaccount.com
    

    其中,PROJECT_NUMBER 是项目的编号。

  • 该服务账号要求对执行部署操作的身份(用户或自动化)具有 roles/iam.serviceAccountUser 的角色成员资格。

您可以将角色成员资格直接应用于服务账号资源,也可以从资源层次结构中的更高级层继承。

用户管理的服务账号操作 Cloud Run 所需的权限

如果 Cloud Run 服务不访问 Google Cloud 的任何其他部分,则其服务账号不需要被授予任何角色或权限

从 Google Cloud 控制台创建新的服务账号时,可选的“向此服务账号授予对项目的访问权限”步骤适用于所需的任何其他访问权限。例如,一项 Cloud Run 服务可能会调用另一项专用 Cloud Run 服务,或者它可能会访问 Cloud SQL 数据库,这两种情况都需要特定的 IAM 角色。如需了解详情,请参阅有关管理访问权限的文档。

使用元数据服务器提取 ID 和访问令牌

如果您的 Cloud Run 服务的代码使用 Google Cloud 客户端库,则该库会自动获取访问令牌,以便使用该服务的运行时服务账号对代码的请求进行身份验证。

如果您改用自己的自定义代码,则可以使用元数据服务器手动提取访问令牌和 ID 令牌。注意,您无法直接从本地机器查询此服务器,因为元数据服务器仅适用于在 Google Cloud 上运行的工作负载。

您可以使用元数据服务器提取的两种类型的令牌如下所示:

如需提取令牌,请选择以下选项之一:

访问令牌

例如,如果要创建 Pub/Sub 主题,请使用 projects.topics.create 方法。

  1. 使用计算元数据服务器来提取访问令牌

    curl "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token" \
        --header "Metadata-Flavor: Google"
    

    此端点会返回一个带有 access_token 属性的 JSON 响应。

  2. 在 HTTP/协议请求中,您必须使用 Authorization 标头中的访问令牌对请求进行身份验证:

    PUT https://pubsub.googleapis.com/v1/projects/PROJECT_ID/topics/TOPIC_ID
    Authorization: Bearer ACCESS_TOKEN
    

    其中:

    • PROJECT_ID 是项目 ID。
    • TOPIC_ID 是主题 ID。
    • ACCESS_TOKEN 是您在上一步中提取的访问令牌。

    响应:

    {
        "name": "projects/PROJECT_ID/topics/TOPIC_ID"
    }
    

ID 令牌

使用计算元数据服务器提取具有特定目标设备的身份令牌

curl "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience=AUDIENCE" \
    --header "Metadata-Flavor: Google"

其中,AUDIENCE 是请求的 JWT 目标设备。

对于 Cloud Run 服务,受众群体应该是您要调用的服务的网址或为该服务配置的自定义受众群体(例如自定义网域)。

https://service.domain.com

对于其他资源,则可能是受 IAP 保护的资源的 OAuth 客户端 ID:

1234567890.apps.googleusercontent.com

获取创建专用服务账号的建议

Recommender 服务会自动提供使用最低必需权限创建专用服务账号的建议。

后续步骤

了解如何管理对服务的访问权限,或如何向服务对开发者、服务和最终用户进行安全身份验证

对于使用服务身份来最大程度降低安全风险的应用的端到端演示,请按照《教程:保护 Cloud Run 服务安全》执行操作。