创建短期有效的服务帐号凭据

本页面介绍了如何为服务帐号创建短期有效凭据来模拟其身份。

服务帐号可以使用短期有效凭据来验证对 Google Cloud API 和其他非 Google API 的调用。短期有效凭据的生命周期有限,持续时间仅为几个小时或更短。如果您需要为信任的服务帐号授予对资源的有限访问权限,则短期有效服务帐号凭据会很有用。与服务帐号密钥等长期有效凭据相比,短期有效凭据还可以降低风险。

支持的凭据类型包括 OAuth 2.0 访问令牌、OpenID Connect ID 令牌、自签名 JSON Web 令牌 (JWT) 和自签名二进制对象 (blob)。最常用的凭据类型是 OAuth 2.0 访问令牌OpenID Connect (OIDC) ID 令牌。以下是一些示例场景:

  • OAuth 2.0 访问令牌:OAuth 2.0 访问令牌可用于对服务帐号到 Google Cloud API 的访问进行身份验证。请考虑以下示例用例:为了获得对项目的提升权限,服务管理员可以创建属于某个服务帐号的 OAuth 2.0 访问令牌,以模拟该服务帐号来调用 Google Cloud API。该令牌的生命周期很短,因此提升的权限是临时性的。使用短期有效的令牌有助于您在身份和资源中实现最小权限原则。当生产环境中出现紧急情况,服务管理员需要使用临时提升的授权来进行调试时,此令牌也非常有用。

  • OIDC ID 令牌:OIDC ID 令牌可用于向接受 OpenID Connect 的服务验证服务帐号的身份。 请考虑以下示例用例:通过创建属于某个服务帐号的 OIDC ID 令牌,在 Google Cloud 上运行的服务可以向第三方云服务提供程序上部署的其他服务(例如数据流水线作业)验证自己的身份。如果目标服务配置了 OIDC,则身份验证会成功。

准备工作

创建服务帐号

首先,请创建一个新的服务帐号

授予必要权限

调用者可以使用两种不同的流程为服务帐号创建短期有效凭据。每种流程都需要具备相应权限:

  • 直接请求:调用者被验证为 Google 帐号或服务帐号,并直接发出创建短期有效凭据的请求。此流程涉及两种身份:调用者以及为其创建凭据的服务帐号。
  • 委托请求:与直接请求流程一样,调用者被验证为 Google 帐号或服务帐号,但会将请求委托给委托链中的一个或多个服务帐号。在此流程中,多个服务帐号会充当原始调用者与为其创建凭据的服务帐号之间的中介。委托链中的每个服务帐号都必须具有传递请求所需的权限。

    当项目包含多个层级的权限有限的服务帐号,且每个层级都配置为对特定资源执行特定或有限的功能时,此流程很有用。例如,一个服务帐号仅被授予对 Cloud Storage 资源的权限,另一个服务帐号仅被授予对 Compute Engine 资源的权限,等等。如需成功跨多个服务帐号委托请求,必须在委托链中列出每个服务帐号。

直接请求权限

如本页面上的授予必要权限所述,直接请求仅涉及两种身份:调用者以及为其创建凭据的服务帐号。在此流程中,请考虑使用以下身份:

  • 服务帐号 1 (sa-1):发出短期有效凭据请求的调用者。
  • 服务帐号 2 (sa-2):为其创建凭据的权限有限的帐号。

如需授予 sa-1 创建短期有效凭据的权限,请在 sa-2 上为其授予 Service Account Token Creator 角色 (roles/iam.serviceAccountTokenCreator)。这是一个将服务帐号视为资源而非身份的示例:必须授予 sa-1sa-2 签发凭据的权限。如需详细了解如何将服务帐号视为身份或资源,请参阅服务帐号权限

以下步骤使用 REST API 来授予所需的权限,但您也可以使用 Cloud Console 或 gcloud 命令行工具进行授权。

API

首先,请阅读 sa-2 的 IAM 政策

serviceAccounts.getIamPolicy 方法可获取服务帐号的 IAM 政策。

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

  • project-id:您的 Google Cloud 项目 ID。
  • 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"
      ]
    }
  ]
}

最后,写入更新后的政策

serviceAccounts.setIamPolicy 方法为服务帐号设置更新后的 IAM 政策。

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

  • project-id:您的 Google Cloud 项目 ID。
  • 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
}

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

响应中包含更新后的政策。

委托请求权限

如本页面上的授予必要权限所述,委托请求涉及的身份超过两种:调用者、委托链中的一个或多个服务帐号,以及当前的服务帐号。在此流程中,请考虑使用以下身份:

  • 服务帐号 1 (sa-1):发出短期有效凭据请求的调用者。
  • 服务帐号 2 (sa-2):中间服务帐号,将初始请求委托给 sa-3
  • 服务帐号 3 (sa-3):为其创建凭据的权限有限的帐号。

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

在此特定示例中,必须在 sa-2 上授予 sa-1 Service Account Token Creator 角色 (roles/iam.serviceAccountTokenCreator)。这是一个将服务帐号视为资源而非身份的示例:必须授予 sa-1sa-2 委托访问权限的权限。如需详细了解如何将服务帐号视为身份或资源,请参阅服务帐号权限

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

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

以下步骤使用 REST API 来授予所需的权限,但您也可以使用 Cloud Console 或 gcloud 命令行工具进行授权。

API

首先,请获取 sa-2(中间服务帐号)的 IAM 政策

serviceAccounts.getIamPolicy 方法可获取服务帐号的 IAM 政策。

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

  • project-id:您的 Google Cloud 项目 ID。
  • 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 方法为服务帐号设置更新后的 IAM 政策。

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

  • project-id:您的 Google Cloud 项目 ID。
  • 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(为其创建凭据的服务帐号)的 IAM 政策

serviceAccounts.getIamPolicy 方法可获取服务帐号的 IAM 政策。

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

  • project-id:您的 Google Cloud 项目 ID。
  • 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 方法为服务帐号设置更新后的 IAM 政策。

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

  • project-id:您的 Google Cloud 项目 ID。
  • 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 访问令牌。

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

HTTP 方法和网址:

POST https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/sa-name@project-id.iam.gserviceaccount.com:generateAccessToken

请求 JSON 正文:

{
  "delegates": [
    delegates
  ],
  "scope": [
    scopes
  ],
  "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 方法为服务帐号生成 OpenID Connect ID 令牌。

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

  • sa-name:您要为其创建令牌的服务帐号的名称。
  • project-id:您的 Google Cloud 项目 ID。
  • delegates:如果您使用的是委托请求流程,请参阅本页面上的指定委托链。如果您使用的是没有委托的直接请求流程,请在请求正文中省略 delegates 字段。

HTTP 方法和网址:

POST https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/sa-name@project-id.iam.gserviceaccount.com:generateIdToken

请求 JSON 正文:

{
  "delegates": [
    delegates
  ],
  "audience": "sa-name@project-id.iam.gserviceaccount.com",
  "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。
  • 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。
    • 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/account-email-or-unique-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"
      ]
    }
    

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