为多个服务账号创建短期有效凭据

本页面介绍如何根据服务账号的委托链为服务账号创建短期有效凭据。当您需要发出一系列令牌生成调用以获取具有完成任务所需权限的令牌时,可以使用此方法。

获取短期有效凭据后,您可以使用它来模拟服务账号

如果可以通过单个令牌生成调用生成具有所需权限的令牌,则应直接为该服务账号创建短期有效凭据

关于创建短期有效凭据

根据您创建的令牌类型,您可以使用短期有效凭据来验证对 Google API、第三方 API 或需要 ID 令牌的应用的调用。短期有效凭据的生命周期有限,持续时间仅为几个小时或更短,不会自动刷新。如果您需要为信任的服务账号授予对资源的有限访问权限,则短期有效服务账号凭据会很有用。与服务账号密钥等长期有效凭据相比,短期有效凭据还可以降低风险。

您可以为服务账号创建以下类型的短期有效凭据:

  • OAuth 2.0 访问令牌

    大多数 Google API 都接受使用访问令牌进行身份验证。为服务账号生成访问令牌时,访问令牌没有刷新令牌,这意味着当令牌过期时,您必须重复令牌创建过程来生成新的令牌。

    如需了解详情,请参阅访问令牌

  • OpenID Connect (OIDC) ID 令牌

    ID 令牌遵循 OpenID Connect (OIDC) 规范。只有少量服务和应用接受 ID 令牌。

    如需了解详情,请参阅 ID 令牌对 Cloud Run 或 Cloud Functions 上托管的应用的身份验证

  • 自签名 JSON 网络令牌 (JWT)

    您可以使用自签名 JWT 向某些 Google API 进行身份验证,而无需从授权服务器获取访问令牌。使用 API Gateway 部署的 API 需要使用这些令牌。

  • 自签名二进制 blob

    当您需要安全地传输任意二进制数据时,自签名 blob 非常有用,通常可用于进行身份验证。

委托请求流程

委托请求流程使您可以使用单个请求链接多个直接请求,而无需按顺序发出多个直接请求。在此流程中,对服务账号凭据的请求会委托给委托链中的一个或多个服务账号,然后再为最终服务账号生成凭据。生成的凭据仅代表最终服务账号,而不代表委托链中的中间服务账号。

委托链中的每个服务账号都必须具有链中下一个服务账号所需的权限,以便它可以传递请求。

如果某个服务账号提供了您需要的所有权限,则您应使用从一个服务账号创建短期有效凭据中介绍的更简单的流程。

准备工作

  • Enable the IAM and Service Account Credentials APIs.

    Enable the APIs

  • 了解 IAM 服务账号

  • 按照快速入门中的步骤启用结算功能和 IAM API(如果尚未启用)。

  • 确定您将在委托链中使用的服务账号。

    如有需要,您可以创建新的服务账号并将其添加到委托链中。

提供所需权限

委托请求涉及两个以上的身份:调用方、委托链中的一个或多个服务账号,以及创建的凭据所适用的服务账号。在此流程中,请考虑使用以下身份:

  • 服务账号 1 (SA_1):发出短期有效凭据请求的调用者。
  • 服务账号 2 (SA_2):中间服务账号,将初始请求委托给 SA_3。此账号仅传递请求,不会向 SA_1SA_3 提供任何额外的访问权限。
  • 服务账号 3 (SA_3):为其创建凭据的权限有限的账号。

如需允许委托,则每个账号必须向委托链中的前一个账号授予 Service Account Token Creator 角色 (roles/iam.serviceAccountTokenCreator)。

在此特定示例中,必须在 SA_2 上授予 SA_1 Service Account Token Creator 角色 (roles/iam.serviceAccountTokenCreator)。以下是将 SA_2 服务账号视为资源的示例:当您在 SA_2 上授予角色时,您更新其允许政策的方式与更新任何其他资源的方式相同。

在此示例流程中,只有一个中间服务账号。要通过多个服务账号委托访问权限,您还必须将此角色分配给委托链中的任何其他服务账号。

接下来,您还必须在 SA_3 上授予 SA_2 Service Account Token Creator 角色 (roles/iam.serviceAccountTokenCreator)。这样,SA_2 就能为 SA_3 创建短期有效凭据。

以下步骤使用 REST API 授予该角色。但是,您也可以使用 Google Cloud 控制台或 gcloud CLI

API

首先,请获取 SA_2(中间服务账号)的允许政策

serviceAccounts.getIamPolicy 方法可获取服务账号的允许政策。

在使用任何请求数据之前,请先进行以下替换:

  • PROJECT_ID:您的 Google Cloud 项目 ID。项目 ID 是字母数字字符串,例如 my-project
  • SA_2:服务账号 2 的名称。
  • POLICY_VERSION:要返回的政策版本。请求应指定最新的政策版本,即政策版本 3。如需了解详情,请参阅在获取政策时指定政策版本

HTTP 方法和网址:

POST https://iam.googleapis.com/v1/projects/PROJECT_ID/serviceAccounts/SA_2@PROJECT_ID.iam.gserviceaccount.com:getIamPolicy

请求 JSON 正文:

{
  "options": {
    "requestedPolicyVersion": POLICY_VERSION
  }
}

如需发送您的请求,请展开以下选项之一:

您应该收到类似以下内容的 JSON 响应:

{
  "version": 1,
  "etag": "BwWKmjvelug=",
  "bindings": [
    {
      "role": "roles/serviceAccountAdmin",
      "members": [
        "user:admin@example.com"
      ]
    }
  ]
}

如果您尚未将角色授予服务账号,则响应将只包含 etag 值。请在下一步中添加该 etag 值。

接下来,请修改允许政策以授予 SA_1 Service Account Token Creator 角色 (roles/iam.serviceAccountTokenCreator)。

例如,如需修改上一步中的示例响应,请添加以下内容:

{
  "version": 1,
  "etag": "BwWKmjvelug=",
  "bindings": [
    {
      "role": "roles/serviceAccountAdmin",
      "members": [
        "user:admin@example.com"
      ]
    },
    {
      "role": "roles/iam.serviceAccountTokenCreator",
      "members": [
        "serviceAccount:SA_1@PROJECT_ID.iam.gserviceaccount.com"
      ]
    }
  ]
}

然后,请写入 SA_2 的更新允许政策

serviceAccounts.setIamPolicy 方法会为服务账号设置更新后的允许政策。

在使用任何请求数据之前,请先进行以下替换:

  • PROJECT_ID:您的 Google Cloud 项目 ID。项目 ID 是字母数字字符串,例如 my-project
  • SA_2:服务账号 2 的名称。
  • POLICY:您要设置的政策的 JSON 格式。如需详细了解政策的格式,请参阅政策参考

    例如,要设置上一步中显示的允许政策,请将 POLICY 替换为以下内容:

    {
      "version": 1,
      "etag": "BwWKmjvelug=",
      "bindings": [
        {
          "role": "roles/serviceAccountAdmin",
          "members": [
            "user:admin@example.com"
          ]
        },
        {
          "role": "roles/iam.serviceAccountTokenCreator",
          "members": [
            "serviceAccount:SA_1@PROJECT_ID.iam.gserviceaccount.com"
          ]
        }
      ]
    }
    

HTTP 方法和网址:

POST https://iam.googleapis.com/v1/projects/PROJECT_ID/serviceAccounts/SA_2@PROJECT_ID.iam.gserviceaccount.com:setIamPolicy

请求 JSON 正文:

{
  "policy": POLICY
}

如需发送您的请求,请展开以下选项之一:

响应包含更新后的允许政策。

现在,请获取 SA_3(为其创建凭据的服务账号)的允许政策

serviceAccounts.getIamPolicy 方法可获取服务账号的允许政策。

在使用任何请求数据之前,请先进行以下替换:

  • PROJECT_ID:您的 Google Cloud 项目 ID。项目 ID 是字母数字字符串,例如 my-project
  • SA_3:服务账号 3 的名称。
  • POLICY_VERSION:要返回的政策版本。请求应指定最新的政策版本,即政策版本 3。如需了解详情,请参阅在获取政策时指定政策版本

HTTP 方法和网址:

POST https://iam.googleapis.com/v1/projects/PROJECT_ID/serviceAccounts/SA_3@PROJECT_ID.iam.gserviceaccount.com:getIamPolicy

请求 JSON 正文:

{
  "options": {
    "requestedPolicyVersion": POLICY_VERSION
  }
}

如需发送您的请求,请展开以下选项之一:

您应该收到类似以下内容的 JSON 响应:

{
  "version": 1,
  "etag": "BwWKmjvelug=",
  "bindings": [
    {
      "role": "roles/serviceAccountAdmin",
      "members": [
        "user:admin@example.com"
      ]
    }
  ]
}

如果您尚未将角色分配给服务账号,则响应将只包含 etag 值。请在下一步中添加该 etag 值。

接下来,请修改允许政策以授予 SA_2 Service Account Token Creator 角色 (roles/iam.serviceAccountTokenCreator)。

例如,如需修改上一步中的示例响应,请添加以下内容:

{
  "version": 1,
  "etag": "BwWKmjvelug=",
  "bindings": [
    {
      "role": "roles/serviceAccountAdmin",
      "members": [
        "user:admin@example.com"
      ]
    },
    {
      "role": "roles/iam.serviceAccountTokenCreator",
      "members": [
        "serviceAccount:SA_2@PROJECT_ID.iam.gserviceaccount.com"
      ]
    }
  ]
}

最后,写入更新后的允许政策

serviceAccounts.setIamPolicy 方法会为服务账号设置更新后的允许政策。

在使用任何请求数据之前,请先进行以下替换:

  • PROJECT_ID:您的 Google Cloud 项目 ID。项目 ID 是字母数字字符串,例如 my-project
  • SA_3:服务账号 3 的名称。
  • POLICY:您要设置的政策的 JSON 格式。如需详细了解政策的格式,请参阅政策参考

    例如,要设置上一步中显示的允许政策,请将 POLICY 替换为以下内容:

    {
      "version": 1,
      "etag": "BwWKmjvelug=",
      "bindings": [
        {
          "role": "roles/serviceAccountAdmin",
          "members": [
            "user:admin@example.com"
          ]
        },
        {
          "role": "roles/iam.serviceAccountTokenCreator",
          "members": [
            "serviceAccount:SA_2@PROJECT_ID.iam.gserviceaccount.com"
          ]
        }
      ]
    }
    

HTTP 方法和网址:

POST https://iam.googleapis.com/v1/projects/PROJECT_ID/serviceAccounts/SA_3@PROJECT_ID.iam.gserviceaccount.com:setIamPolicy

请求 JSON 正文:

{
  "policy": POLICY
}

如需发送您的请求,请展开以下选项之一:

响应包含更新后的允许政策。

请求短期有效凭据

为每种身份授予适当的角色后,您便可以请求所需服务账号的短期有效凭据。系统支持以下几种凭据类型:

如需了解如何为这些请求指定委托链,请参阅本页面上的指定委托链部分。

生成 OAuth 2.0 访问令牌

默认情况下,OAuth 2.0 访问令牌的有效期最长为 1 小时(3600 秒)。不过,您可以将这些令牌的最长生命周期延长至 12 小时(43200 秒)。为此,请确定需要延长令牌有效期的服务账号,然后将这些服务账号添加到组织政策中(该政策包含 constraints/iam.allowServiceAccountCredentialLifetimeExtension 列表限制条件)。随后,您在为这些服务账号创建令牌时,可以指定最长为 43200 秒的生命周期。

如需为服务账号生成 OAuth 2.0 访问令牌,请执行以下操作:

API

Service Account Credentials API 的 serviceAccounts.generateAccessToken 方法为服务账号生成 OAuth 2.0 访问令牌。

在使用任何请求数据之前,请先进行以下替换:

  • SA_NAME:您要为其创建令牌的服务账号的名称。
  • PROJECT_ID:您的 Google Cloud 项目 ID。项目 ID 是字母数字字符串,例如 my-project
  • DELEGATES:如果您使用的是委托请求流程,请参阅本页面上的指定委托链。如果您使用的是没有委托的直接请求流程,请在请求正文中省略 delegates 字段。
  • LIFETIME:访问令牌到期前的时间量(以秒为单位)。例如 300s

    默认情况下,令牌的最长生命周期为 1 小时(3600 秒)。如需将这些令牌的最长生命周期延长至 12 小时(43200 秒),请将服务账号添加到组织政策中(该政策包含 constraints/iam.allowServiceAccountCredentialLifetimeExtension 列表限制条件)。

HTTP 方法和网址:

POST https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/SA_NAME@PROJECT_ID.iam.gserviceaccount.com:generateAccessToken

请求 JSON 正文:

{
  "delegates": [
    DELEGATES
  ],
  "scope": [
    "https://www.googleapis.com/auth/cloud-platform"
  ],
  "lifetime": "LIFETIME"
}

如需发送您的请求,请展开以下选项之一:

如果 generateAccessToken 请求成功,响应正文会包含一个 OAuth 2.0 访问令牌和一个到期时间。然后,便可以使用 accessToken 代表服务账号验证请求,直至到达 expireTime 时限:

{
  "accessToken": "eyJ0eXAi...NiJ9",
  "expireTime": "2020-04-07T15:01:23.045123456Z"
}

生成 OpenID Connect ID 令牌

OpenID Connect ID 令牌的有效期为 1 小时(3600 秒)。如需为服务账号生成 ID 令牌,请执行以下操作:

API

Service Account Credentials API 的 serviceAccounts.generateIdToken 方法为服务账号生成 OIDC ID 令牌。

在使用任何请求数据之前,请先进行以下替换:

  • PRIV_SA:为其创建短期令牌的具有权限的服务账号的电子邮件地址。
  • AUDIENCE_NAME:令牌的受众群体,通常是令牌将用于访问的应用或服务的网址。

HTTP 方法和网址:

POST https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/PRIV_SA:generateIdToken

请求 JSON 正文:

{
  "audience": "AUDIENCE_NAME",
  "includeEmail": "true"
}

如需发送您的请求,请展开以下选项之一:

如果 generateId 请求成功,则响应正文会包含一个有效期为 1 小时的 ID 令牌。然后,便可以使用 token 代表服务账号验证请求:

{
  "token": "eyJ0eXAi...NiJ9"
}

创建自签名 JSON Web 令牌 (JWT)

自签名 JSON Web 令牌 (JWT) 在各种场景中都很有用,例如:

  • 按照 Google 的身份验证指南中的说明验证对 Google API 的调用。
  • 在 Google Cloud 或非 Google 服务(例如 App Engine 应用)之间安全地进行通信。在此场景中,一个应用可对一个令牌签名,而在进行身份验证时,该令牌可以由另一个应用进行验证。
  • 通过签署包含有关用户、账号或设备的任意声明的 JWT,将服务账号视为身份提供方。

如需为服务账号生成自签名 JWT,请执行以下操作:

API

Service Account Credentials API 的 serviceAccounts.signJwt 方法使用服务账号的系统管理私钥来对 JWT 进行签名。

在使用任何请求数据之前,请先进行以下替换:

  • SA_NAME:您要为其创建令牌的服务账号的名称。
  • PROJECT_ID:您的 Google Cloud 项目 ID。项目 ID 是字母数字字符串,例如 my-project
  • DELEGATES:如果您使用的是委托请求流程,请参阅本页面上的指定委托链。如果您使用的是没有委托的直接请求流程,请在请求正文中省略 delegates 字段。
  • JWT_PAYLOAD:需要签名的 JWT 载荷,它是一个包含 JWT 声明集的 JSON 对象。包含您所需用例必需的且满足您要调用的服务验证要求必需的声明。如果您要调用 Google API,请参阅 Google 的身份验证指南了解声明要求。

    exp(到期时间)声明不得超过未来 12 小时。如果您要调用 Google API,则 exp 声明必须设置为不超过未来 1 小时。

    以下示例载荷包含调用 Google API 的声明,其中 EXP 是表示到期时间的整数时间戳:

    { \"iss\": \"SA_NAME@PROJECT_ID.iam.gserviceaccount.com\", \"sub\": \"SA_NAME@PROJECT_ID.iam.gserviceaccount.com\", \"aud\": \"https://firestore.googleapis.com/\", \"iat\": 1529350000, \"exp\": EXP }

HTTP 方法和网址:

POST https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/SA_NAME@PROJECT_ID.iam.gserviceaccount.com:signJwt

请求 JSON 正文:

{
  "delegates": [
    DELEGATES
  ],
  "payload": "JWT_PAYLOAD"
}

如需发送您的请求,请展开以下选项之一:

如果 signJwt 请求成功,则响应正文会包含已签名的 JWT 以及用于签署 JWT 的签名密钥 ID。您可以将 signedJwt 值用作不记名令牌,以代表服务账号直接验证请求。令牌在请求中指定的到期时间内有效:

{
  "keyId": "42ba1e...fc0a",
  "signedJwt": "eyJ0eXAi...NiJ9"
}

创建自签名 blob

当您需要安全地传输任意二进制数据时,自签名 blob 非常有用,通常可用于进行身份验证。例如,如果要使用自定义协议/令牌类型(而不是 JWT),您可以将该数据包含在已签署的 blob 中,以供下游服务使用。

如需为服务账号生成自签名 blob,请执行以下操作:

API

Service Account Credentials API 的 serviceAccounts.signBlob 方法使用服务账号的系统管理私钥来对 blob 进行签名。

在使用任何请求数据之前,请先进行以下替换:

  • SA_NAME:您要为其创建令牌的服务账号的名称。
  • PROJECT_ID:您的 Google Cloud 项目 ID。项目 ID 是字母数字字符串,例如 my-project
  • DELEGATES:如果您使用的是委托请求流程,请参阅本页面上的指定委托链。如果您使用的是没有委托的直接请求流程,请在请求正文中省略 delegates 字段。
  • BLOB_PAYLOAD:Base64 编码的字节串。例如,VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wZWQgb3ZlciB0aGUgbGF6eSBkb2cu

HTTP 方法和网址:

POST https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/SA_NAME@PROJECT_ID.iam.gserviceaccount.com:signBlob

请求 JSON 正文:

{
  "delegates": [
    DELEGATES
  ],
  "payload": "BLOB_PAYLOAD"
}

如需发送您的请求,请展开以下选项之一:

如果 signBlob 请求成功,则响应正文会包含已签名的 blob 以及用于签署 blob 的签名密钥 ID。您可以将 signedBlob 值用作不记名令牌,以代表服务账号直接验证请求。在服务账号的系统管理私钥到期之前,该令牌有效。此密钥的 ID 是响应中 keyId 字段的值。

{
  "keyId": "42ba1e...fc0a",
  "signedBlob": "eyJ0eXAi...NiJ9"
}

指定委托链

使用委托请求流程创建短期服务账号凭据时,每个 API 的请求正文都必须以正确的顺序按以下格式指定服务账号委托链:

projects/-/serviceAccounts/SA_ID

SA_ID 替换为服务账号的唯一数字 ID 或服务账号的电子邮件地址。

例如,在从 SA_1(调用者)流向 SA_2(受委托账号)到 SA_3(受委托账号)再到 SA_4 的委托链中,delegates[] 字段将按以下顺序包含 SA_2SA_3

{
  "delegates": [
    "projects/-/serviceAccounts/SA_2@PROJECT_ID.iam.gserviceaccount.com",
    "projects/-/serviceAccounts/SA_3@PROJECT_ID.iam.gserviceaccount.com"
  ]
}

调用者以及为其创建凭据的服务账号不包含在委托链中。