使用身份联合获取短期凭据

使用集合让一切井井有条 根据您的偏好保存内容并对其进行分类。

本指南介绍了如何通过以下过程使用工作负载身份池和提供商获取短期凭据:

  1. 从受信任的身份提供商获取凭据。
  2. 用凭据从 Security Token Service 交换令牌。
  3. 使用 Security Token Service 中的令牌模拟服务帐号并获取短期 Google 访问令牌。

使用短期有效的 Google 访问令牌,您可以访问服务帐号有权访问的任何 Google Cloud 资源。

准备工作

  1. 启用 IAM, Security Token Service, and Service Account Credentials API。

    启用 API

  2. 通过创建工作负载身份池和提供方与外部身份提供方联合。

  3. 创建您希望外部身份模拟的服务帐号

  4. 向服务帐号授予对您希望外部身份访问的资源的访问权限

授予外部身份模拟服务帐号的权限

如需允许外部身份模拟服务帐号,您必须向其授予服务帐号的 Workload Identity User 角色 (roles/iam.workloadIdentityUser)。您可以向特定外部身份或多个外部身份授予该角色:

  • 对于特定的外部身份,请编写一个检查 google.subject 特性的特性条件。
  • 对于一组外部身份,编写一个检查 google.groups 特性或自定义属性 attribute.NAME 的特性条件。
  • 对于工作负载身份池中的所有外部身份,您不使用特性条件。

控制台

  1. 在 Google Cloud 控制台中,转到 Workload Identity 池页面。

    转到“工作负载身份池”

  2. 找到要更新的工作负载身份池,然后点击它。

  3. 点击 授予访问权限

  4. 服务帐号下拉列表中,选择外部身份将模拟的服务帐号。

  5. 选择池中的哪些身份可以模拟服务帐号:

    • 如需仅允许工作负载身份池的特定身份来模拟服务帐号,请选择仅限与过滤条件匹配的身份

      属性名称下拉列表中,选择要过滤的属性。

      特性值字段中,输入特性的预期值。

      例如,如果您使用特性映射 google.subject=assertion.sub,请将特性名称设置为 subject特性值 设置为外部身份提供商颁发的令牌中 sub 声明的值。

    • 要允许工作负载身份池的所有外部身份模拟服务帐号,请选择池中的所有身份

  6. 点击保存

  7. 点击关闭

gcloud

  1. 为外部身份创建标识符:

    • 特定的外部身份:

      principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/subject/SUBJECT
      
    • 一组外部身份:

      principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/group/GROUP
      
    • 具有特定属性的所有外部身份:

      principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/attribute.ATTRIBUTE_NAME/ATTRIBUTE_VALUE
      
    • 工作负载身份池中的所有外部身份:

      principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/*
      

    替换以下值:

    • PROJECT_NUMBER:包含工作负载身份池的项目编号
    • POOL_ID:工作负载身份池的池 ID
    • SUBJECT已映射google.subject 的特性的预期值
    • GROUP已映射google.groups 的特性的预期值
    • ATTRIBUTE_NAME特性映射中的自定义特性的名称

    要获取当前项目的项目编号,您可以使用以下命令:

    gcloud projects describe $(gcloud config get-value core/project) --format=value\(projectNumber\)
    
  2. 将 Workload Identity User 角色 (roles/iam.workloadIdentityUser) 授予给服务帐号的主帐号:

    gcloud iam service-accounts add-iam-policy-binding SERVICE_ACCOUNT_EMAIL \
        --role=roles/iam.workloadIdentityUser \
        --member="MEMBER_ID"
    

    替换以下值:

    • SERVICE_ACCOUNT_EMAIL:服务帐号的电子邮件地址
    • MEMBER_ID:您在上一步中标识的成员标识符

使用客户端库、gcloud CLI 或 Terraform 进行身份验证

Cloud 客户端库、gcloud CLI 和 Terraform 可以自动获取外部凭据,并使用这些凭据来模拟服务帐号。如要让库和工具完成此过程,您必须提供凭据配置文件。此文件定义了以下内容:

  • 从何处获取外部凭据
  • 要使用的工作负载身份池和提供商
  • 需要模拟的服务帐号

客户端库使用凭据配置文件的方式取决于您的外部身份提供商:

AWS

客户端库会自动从 EC2 实例元数据获取临时凭据。

Azure

客户端库会自动从 Azure 实例元数据服务 (IMDS) 获取访问令牌。

GitHub Actions

由于获取 GitHub ID 令牌所需的参数因工作流执行而异,因此您无法在 GitHub Actions 工作流中使用静态凭据配置文件。

使用 google-github-actions/auth 操作在工作流执行期间自动生成凭据配置文件。然后,客户端库和工具(例如 terraform)可以使用此凭据配置文件自动获取 Google 凭据。

OIDC

客户端库会从本地文件、HTTP 网址或本地可执行文件获取凭据:

  • 文件来源凭据:令牌从文件加载。其他进程在旧令牌到期前,必须使用新 OIDC 令牌刷新此文件。例如,如果令牌的有效期为 1 小时,您必须在 1 小时之前刷新该文件。
  • 网址来源的凭据:使用响应 HTTP GET 请求的端点从本地服务器加载令牌。响应必须是 OIDC ID 令牌(采用纯文本或 JSON 格式)。
  • 可执行凭据:令牌从本地可执行文件加载。可执行文件必须以 JSON 格式将未过期的有效 OIDC ID 令牌提供给 stdout:

    {
      "version": 1,
      "success": true,
      "token_type": "urn:ietf:params:oauth:token-type:id_token",
      "id_token": "HEADER.PAYLOAD.SIGNATURE",
      "expiration_time": 1620499962
    }
    
    如需获得成功的响应,必须提供这些字段,但 expiration_time 除外。仅当在凭据配置中指定了输出文件时,才需要 expiration_time 字段。

    如果发生错误,可执行文件必须按以下 JSON 格式提供给 stdout:

    {
      "version": 1,
      "success": false,
      "code": "401",
      "message": "Caller not authorized."
    }
    
    这些字段都是错误响应的必填字段。引发相应的错误时,客户端库将使用这些代码和消息字段。

    响应格式字段摘要:

    • version:JSON 输出的版本;目前仅支持版本 1。
    • success:响应的状态。如果为 true,则响应必须包含第三方令牌、令牌类型和过期时间。此外,可执行文件必须以退出代码 0 退出。如果为 false,则响应必须包含错误代码和消息字段,并以非零值退出。
    • token_type:第三方主题令牌类型。支持的值包括 urn:ietf:params:oauth:token-type:id_tokenurn:ietf:params:oauth:token-type:jwt
    • id_token:第三方 OIDC 令牌。
    • expiration_time:OIDC 令牌到期时间(与 UNIX 计时原点之间相隔的秒数)。
    • code:错误代码字符串。
    • message:错误消息。

    运行可执行文件时,客户端库将填充以下环境变量:

    • GOOGLE_EXTERNAL_ACCOUNT_AUDIENCE:凭据配置中的目标对象字段。始终存在。
    • GOOGLE_EXTERNAL_ACCOUNT_TOKEN_TYPE:预期的主题令牌类型。始终存在。
    • GOOGLE_EXTERNAL_ACCOUNT_IMPERSONATED_EMAIL:服务帐号电子邮件地址。仅当使用服务帐号模拟时存在。
    • GOOGLE_EXTERNAL_ACCOUNT_OUTPUT_FILE:凭据配置中的输出文件位置。仅当在凭据配置中指定了该位置时存在。

    可执行文件可以使用这些环境变量来避免对这些值进行硬编码。

    如需使用客户端库启用此凭据溯源方法,必须将 GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES 环境变量设置为 1

OIDC (AD FS)

客户端库可以从本地文件或 HTTP 网址获取凭据,但不支持直接集成 Windows 身份验证 (IWA)。如需获取已登录用户的访问令牌并将其存储在本地文件中,请使用以下 PowerShell 命令:

(Invoke-RestMethod `
    -Uri "https://ADFS_DOMAIN/adfs/oauth2/token/" `
    -Method POST `
    -Body @{
        client_id = 'CLIENT_ID'
        grant_type = 'client_credentials'
        scope = 'openid'
        resource = 'RELYING_PARTY_ID'
        use_windows_client_authentication = 'true'
        } `
    -UseDefaultCredentials).access_token | Out-File -Encoding ASCII TOKEN_FILEPATH

替换以下值:

  • ADFS_DOMAIN:AD FS 服务器场的公共域名。
  • CLIENT_ID:AD FS 中应用注册的客户端 ID。
  • RELYING_PARTY_ID:在 AD FS 中为工作负载身份池创建 Web API 应用时使用的信赖方标识符。
  • TOKEN_FILEPATH:用于保存 AD FS 令牌的临时文件的路径。确保将文件存储在只有授权用户才能读取文件内容的位置。

由于短期有效的 Google 凭据仅在有限的时间内有效(默认为 1 小时),因此必须定期重新运行此命令。

SAML

客户端库会从本地文件、HTTP 网址或本地可执行文件获取凭据:

  • 文件来源凭据:从文件加载的断言。其他进程必须在旧断言到期前使用 base64 编码的新 SAML 断言刷新此文件。例如,如果断言的有效期为 1 小时,您必须在 1 小时之前刷新该文件。
  • 网址来源的凭据:使用响应 HTTP GET 请求的端点从本地服务器加载断言。响应必须是 base64 编码的 SAML 断言或包含 base64 编码的 SAML 断言的 JSON。
  • 可执行文件来源的凭据:从本地可执行文件加载断言。可执行文件必须以 JSON 格式将未过期的有效 SAML 断言提供给 stdout:

    {
      "version": 1,
      "success": true,
      "token_type": "urn:ietf:params:oauth:token-type:saml2",
      "saml_response": "...",
      "expiration_time": 1620499962
    }
    
    如需获得成功的响应,必须提供这些字段,但 expiration_time 除外。仅当在凭据配置中指定了输出文件时,才需要 expiration_time 字段。

    如果发生错误,可执行文件必须按以下 JSON 格式提供给 stdout:

    {
      "version": 1,
      "success": false,
      "code": "401",
      "message": "Caller not authorized."
    }
    
    这些字段都是错误响应的必填字段。引发相应的错误时,客户端库将使用这些代码和消息字段。

    响应格式字段摘要:

    • version:JSON 输出的版本;目前仅支持版本 1。
    • success:响应的状态。如果为 true,则响应必须包含第三方令牌、令牌类型和过期时间。此外,可执行文件必须以退出代码 0 退出。如果为 false,则响应必须包含错误代码和消息字段,并以非零值退出。
    • token_type:第三方主题令牌类型。必须为 urn:ietf:params:oauth:token-type:saml2
    • saml_response:第三方 SAML 响应。
    • expiration_time:第三方 SAML 响应的到期时间(与 Unix 计时原点之间相隔的秒数)。
    • code:错误代码字符串。
    • message:错误消息。

    运行可执行文件时,客户端库将填充以下环境变量: * GOOGLE_EXTERNAL_ACCOUNT_AUDIENCE:凭据配置中的目标对象字段。始终存在。 * GOOGLE_EXTERNAL_ACCOUNT_TOKEN_TYPE:预期的主题令牌类型。始终存在。 * GOOGLE_EXTERNAL_ACCOUNT_IMPERSONATED_EMAIL:服务帐号电子邮件地址。仅当使用服务帐号模拟时存在。 * GOOGLE_EXTERNAL_ACCOUNT_OUTPUT_FILE:凭据配置中的输出文件位置。仅当在凭据配置中指定了该位置时存在。

    可执行文件可以使用这些环境变量来避免对这些值进行硬编码。

    如需使用客户端库启用此凭据溯源方法,必须将 GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES 环境变量设置为 1

以下步骤可让客户端库或 Terraform 使用工作负载身份联合进行身份验证:

  1. 创建凭据配置文件:

    控制台

    在 Google Cloud 控制台中下载凭据配置文件:

    1. 在 Google Cloud 控制台中,转到 Workload Identity 池页面。

      转到“工作负载身份池”

    2. 找到包含您要使用的身份提供商的工作负载身份池,然后点击它。

    3. 选择关联的服务帐号

    4. 找到您要使用的服务帐号,然后点击 下载

    5. 配置您的应用对话框中,选择将模拟服务帐号的外部身份的提供商。

    6. 请提供以下额外设置:

      AWS

      无需进行其他设置。

      Azure

      资源路径:Azure 应用的应用 ID URI

      OIDC

      OIDC 令牌路径:要从中获取凭据的本地文件路径或网址。

      格式类型:从中检索 ID 令牌的文件或网址响应的格式。

      主题令牌字段名称:响应中包含令牌的字段(如果格式类型为 json)。

      SAML

      SAML 断言路径:要从中获取凭据的本地文件路径或网址。

      格式类型:从中检索断言的文件或网址响应的格式。

      断言字段名称:响应中包含断言的字段(如果格式类型为 json)。

    7. 选择 下载配置以下载凭据配置文件,然后点击关闭

    gcloud

    使用 gcloud iam workload-identity-pools create-cred-config 创建凭据配置文件:

    AWS

    创建凭据配置文件,让库从 EC2 实例元数据中获取访问令牌:

    gcloud iam workload-identity-pools create-cred-config \
        projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID \
        --service-account=SERVICE_ACCOUNT_EMAIL \
        --service-account-token-lifetime-seconds=SERVICE_ACCOUNT_TOKEN_LIFETIME \
        --aws \
        --output-file=FILEPATH.json
    

    替换以下值:

    • PROJECT_NUMBER:包含工作负载身份池的项目的编号
    • POOL_ID:工作负载身份池的 ID
    • PROVIDER_ID:工作负载身份池提供方的 ID
    • SERVICE_ACCOUNT_EMAIL:服务帐号的电子邮件地址
    • SERVICE_ACCOUNT_TOKEN_LIFETIME:服务帐号访问令牌的有效时长(以秒为单位);如果未提供,则默认为 1 小时。如果需要超过一小时的有效时长,则必须在强制执行 constraints/iam.allowServiceAccountCredentialLifetimeExtension 限制条件的组织政策中将该服务帐号添加为允许值。
    • FILEPATH:用于保存配置的文件

    如果您使用的是 AWS IMDSv2,则需要向 gcloud iam workload-identity-pools create-cred-config 命令添加一个额外的标志 --enable-imdsv2

    gcloud iam workload-identity-pools create-cred-config \
        projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID \
        --service-account=SERVICE_ACCOUNT_EMAIL \
        --aws \
        --enable-imdsv2 \
        --output-file=FILEPATH.json
    

    Azure

    创建凭据配置文件,让库从 Azure Instance Metadata Service (IMDS) 获取访问令牌:

    gcloud iam workload-identity-pools create-cred-config \
        projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID \
        --service-account=SERVICE_ACCOUNT_EMAIL \
        --service-account-token-lifetime-seconds=SERVICE_ACCOUNT_TOKEN_LIFETIME \
        --azure \
        --app-id-uri APPLICATION_ID_URI \
        --output-file=FILEPATH.json
    

    替换以下值:

    • PROJECT_NUMBER:包含工作负载身份池的项目的编号
    • POOL_ID:工作负载身份池的 ID
    • PROVIDER_ID:工作负载身份池提供方的 ID
    • SERVICE_ACCOUNT_EMAIL:服务帐号的电子邮件地址
    • SERVICE_ACCOUNT_TOKEN_LIFETIME:服务帐号访问令牌的有效时长(以秒为单位);如果未提供,则默认为 1 小时。如果需要超过一小时的有效时长,则必须在强制执行 constraints/iam.allowServiceAccountCredentialLifetimeExtension 限制条件的组织政策中将该服务帐号添加为允许值。
    • APPLICATION_ID_URI:Azure 应用的应用 ID URI
    • FILEPATH:用于保存配置的文件

    OIDC

    如需使用文件溯源凭据,请使用 --credential-source-file 标志:

    gcloud iam workload-identity-pools create-cred-config \
        projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID \
        --service-account=SERVICE_ACCOUNT_EMAIL \
        --service-account-token-lifetime-seconds=SERVICE_ACCOUNT_TOKEN_LIFETIME \
        --output-file=FILEPATH.json \
        --credential-source-file=TOKEN_FILEPATH \
        --credential-source-type=SOURCE_TYPE \
        --credential-source-field-name=FIELD_NAME
    

    替换以下值:

    • PROJECT_NUMBER:包含工作负载身份池的项目的编号
    • POOL_ID:工作负载身份池的 ID
    • PROVIDER_ID:工作负载身份池提供方的 ID
    • SERVICE_ACCOUNT_EMAIL:服务帐号的电子邮件地址
    • SERVICE_ACCOUNT_TOKEN_LIFETIME:服务帐号访问令牌的有效时长(以秒为单位);如果未提供,则默认为 1 小时。如果需要超过一小时的有效时长,则必须在强制执行 constraints/iam.allowServiceAccountCredentialLifetimeExtension 限制条件的组织政策中将该服务帐号添加为允许值。
    • FILEPATH:用于保存配置的文件
    • TOKEN_FILEPATH:存储 OIDC ID 令牌的路径
    • SOURCE_TYPE:OIDC ID 令牌文件的格式,设置为 text(默认)或 json
    • FIELD_NAME:包含令牌的文本文件中的字段(如果 SOURCE_TYPEjson

    如需使用网址来源的凭据,请使用 --credential-source-url 标志:

    gcloud iam workload-identity-pools create-cred-config \
        projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID \
        --service-account=SERVICE_ACCOUNT_EMAIL \
        --service-account-token-lifetime-seconds=SERVICE_ACCOUNT_TOKEN_LIFETIME \
        --output-file=FILEPATH.json \
        --credential-source-url="TOKEN_URL" \
        --credential-source-headers="KEY_1=VALUE_1,KEY_2=VALUE_2" \
        --credential-source-type=SOURCE_TYPE \
        --credential-source-field-name=FIELD_NAME
    

    替换以下值:

    • PROJECT_NUMBER:包含工作负载身份池的项目的编号
    • POOL_ID:工作负载身份池的 ID
    • PROVIDER_ID:工作负载身份池提供方的 ID
    • SERVICE_ACCOUNT_EMAIL:服务帐号的电子邮件地址
    • SERVICE_ACCOUNT_TOKEN_LIFETIME:服务帐号访问令牌的有效时长(以秒为单位);如果未提供,则默认为 1 小时。如果需要超过一小时的有效时长,则必须在强制执行 constraints/iam.allowServiceAccountCredentialLifetimeExtension 限制条件的组织政策中将该服务帐号添加为允许值。
    • FILEPATH:用于保存配置的文件
    • TOKEN_URL:要从中检索 OIDC ID 令牌的网址
    • KEY_nVALUE_n:要添加到对 TOKEN_URL 的 HTTP 请求中的自定义标头
    • SOURCE_TYPE:OIDC ID 令牌文件的格式,设置为 text(默认)或 json
    • FIELD_NAME:包含令牌的文本文件中的字段(如果 SOURCE_TYPEjson

    如需使用可执行文件来源的凭据,请使用 --executable-command 标志:

    gcloud iam workload-identity-pools create-cred-config \
        projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID \
        --service-account=SERVICE_ACCOUNT_EMAIL \
        --service-account-token-lifetime-seconds=SERVICE_ACCOUNT_TOKEN_LIFETIME \
        --output-file=FILEPATH.json \
        --executable-command=EXECUTABLE_COMMAND \
        --executable-timeout-millis=EXECUTABLE_TIMEOUT \
        --executable-output-file=EXECUTABLE_OUTPUT_FILE
    

    替换以下值:

    • PROJECT_NUMBER:包含工作负载身份池的项目的编号
    • POOL_ID:工作负载身份池的 ID
    • PROVIDER_ID:工作负载身份池提供方的 ID
    • SERVICE_ACCOUNT_EMAIL:服务帐号的电子邮件地址
    • SERVICE_ACCOUNT_TOKEN_LIFETIME:服务帐号访问令牌的有效时长(以秒为单位);如果未提供,则默认为 1 小时。如果需要超过一小时的有效时长,则必须在强制执行 constraints/iam.allowServiceAccountCredentialLifetimeExtension 限制条件的组织政策中将该服务帐号添加为允许值。
    • FILEPATH:用于保存配置的文件
    • EXECUTABLE_COMMAND:要运行来检索 OIDC ID 令牌的完整命令(包括参数)(例如 --executable-command="/path/to/command --foo=bar")。
    • EXECUTABLE_TIMEOUT:等待可执行文件运行的可选时长(以毫秒为单位),默认为 30 秒
    • EXECUTABLE_OUTPUT_FILE:此文件路径指向由可执行文件生成的 3PI 凭据。这对于缓存凭据很有用。通过指定此路径,身份验证库将首先检查其是否存在,然后再运行可执行文件。

    OIDC (AD FS)

    创建凭据配置文件,让库从临时文件中读取 AD FS 访问令牌:

    gcloud iam workload-identity-pools create-cred-config \
        projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID \
        --service-account=SERVICE_ACCOUNT_EMAIL \
        --service-account-token-lifetime-seconds=SERVICE_ACCOUNT_TOKEN_LIFETIME \
        --output-file=FILEPATH.json \
        --credential-source-file=TOKEN_FILEPATH \
        --credential-source-type=text
    

    替换以下值:

    • PROJECT_NUMBER:包含工作负载身份池的项目的编号
    • POOL_ID:工作负载身份池的 ID
    • PROVIDER_ID:工作负载身份池提供方的 ID
    • SERVICE_ACCOUNT_EMAIL:服务帐号的电子邮件地址
    • SERVICE_ACCOUNT_TOKEN_LIFETIME:服务帐号访问令牌的有效时长(以秒为单位);如果未提供,则默认为 1 小时。如果需要超过一小时的有效时长,则必须在强制执行 constraints/iam.allowServiceAccountCredentialLifetimeExtension 限制条件的组织政策中将该服务帐号添加为允许值。
    • FILEPATH:用于保存配置的文件
    • TOKEN_FILEPATH:包含 AD FS 令牌的临时文件的路径

    SAML

    如需使用文件溯源凭据,请使用 --credential-source-file 标志:

    gcloud iam workload-identity-pools create-cred-config \
        projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID \
        --service-account=SERVICE_ACCOUNT_EMAIL \
        --service-account-token-lifetime-seconds=SERVICE_ACCOUNT_TOKEN_LIFETIME \
        --output-file=FILEPATH.json \
        --credential-source-file=TOKEN_FILEPATH \
        --credential-source-type=SOURCE_TYPE \
        --credential-source-field-name=FIELD_NAME \
        --subject-token-type=urn:ietf:params:oauth:token-type:saml2
    

    替换以下值:

    • PROJECT_NUMBER:包含工作负载身份池的项目的编号
    • POOL_ID:工作负载身份池的 ID
    • PROVIDER_ID:工作负载身份池提供方的 ID
    • SERVICE_ACCOUNT_EMAIL:服务帐号的电子邮件地址
    • SERVICE_ACCOUNT_TOKEN_LIFETIME:服务帐号访问令牌的有效时长(以秒为单位);如果未提供,则默认为 1 小时。如果需要超过一小时的有效时长,则必须在强制执行 constraints/iam.allowServiceAccountCredentialLifetimeExtension 限制条件的组织政策中将该服务帐号添加为允许值。
    • FILEPATH:用于保存配置的文件
    • TOKEN_FILEPATH:存储 SAML 断言的路径
    • SOURCE_TYPE:SAML 断言文件的格式,设置为 text(默认)或 json
    • FIELD_NAME:包含断言的文本文件中的字段(如果 SOURCE_TYPEjson

    如需使用网址来源的凭据,请使用 --credential-source-url 标志:

    gcloud iam workload-identity-pools create-cred-config \
        projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID \
        --service-account=SERVICE_ACCOUNT_EMAIL \
        --service-account-token-lifetime-seconds=SERVICE_ACCOUNT_TOKEN_LIFETIME \
        --output-file=FILEPATH.json \
        --credential-source-url="TOKEN_URL" \
        --credential-source-headers="KEY_1=VALUE_1,KEY_2=VALUE_2" \
        --credential-source-type=source_type \
        --credential-source-field-name=field_name
        --subject-token-type=urn:ietf:params:oauth:token-type:saml2
    

    替换以下值:

    • PROJECT_NUMBER:包含工作负载身份池的项目的编号
    • POOL_ID:工作负载身份池的 ID
    • PROVIDER_ID:工作负载身份池提供方的 ID
    • SERVICE_ACCOUNT_EMAIL:服务帐号的电子邮件地址
    • SERVICE_ACCOUNT_TOKEN_LIFETIME:服务帐号访问令牌的有效时长(以秒为单位);如果未提供,则默认为 1 小时。如果需要超过一小时的有效时长,则必须在强制执行 constraints/iam.allowServiceAccountCredentialLifetimeExtension 限制条件的组织政策中将该服务帐号添加为允许值。
    • FILEPATH:用于保存配置的文件
    • TOKEN_URL:要从中检索 SAML 断言的网址
    • KEY_nVALUE_n:要添加到对 TOKEN_URL 的 HTTP 请求中的自定义标头
    • SOURCE_TYPE:SAML 断言文件的格式,设置为 text(默认)或 json
    • FIELD_NAME:包含断言的文本文件中的字段(如果 SOURCE_TYPEjson

    如需使用可执行文件来源的凭据,请使用 --executable-command 标志:

    gcloud iam workload-identity-pools create-cred-config \
        projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID \
        --service-account=SERVICE_ACCOUNT_EMAIL \
        --service-account-token-lifetime-seconds=SERVICE_ACCOUNT_TOKEN_LIFETIME \
        --output-file=FILEPATH.json \
        --executable-command=EXECUTABLE_COMMAND \
        --executable-timeout-millis=EXECUTABLE_TIMEOUT \
        --executable-output-file=EXECUTABLE_OUTPUT_FILE
    

    替换以下值:

    • PROJECT_NUMBER:包含工作负载身份池的项目的编号
    • POOL_ID:工作负载身份池的 ID
    • PROVIDER_ID:工作负载身份池提供方的 ID
    • SERVICE_ACCOUNT_EMAIL:服务帐号的电子邮件地址
    • SERVICE_ACCOUNT_TOKEN_LIFETIME:服务帐号访问令牌的有效时长(以秒为单位);如果未提供,则默认为 1 小时。如果需要超过一小时的有效时长,则必须在强制执行 constraints/iam.allowServiceAccountCredentialLifetimeExtension 限制条件的组织政策中将该服务帐号添加为允许值。
    • FILEPATH:用于保存配置的文件
    • EXECUTABLE_COMMAND:要运行来检索 SAML 断言的完整命令
    • EXECUTABLE_TIMEOUT:等待可执行文件运行的可选时长(以毫秒为单位),默认为 30 秒
    • EXECUTABLE_OUTPUT_FILE:存储可执行响应的可选输出文件

    GitHub Actions

    修改 GitHub Actions YAML 文件并添加以下内容:

    • 通过添加以下配置,允许作业提取 GitHub ID 令牌:

      permissions:
        id-token: write
        contents: read
      
    • 添加步骤以创建凭据配置文件:

      - id: 'auth'
        name: 'Authenticate to Google Cloud'
        uses: 'google-github-actions/auth@v0.3.1'
        with:
          create_credentials_file: true
          workload_identity_provider: 'projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID'
          service_account: 'SERVICE_ACCOUNT_EMAIL'
      

    替换以下值:

    • PROJECT_NUMBER:包含工作负载身份池的项目的编号
    • POOL_ID:工作负载身份池的 ID
    • PROVIDER_ID:工作负载身份池提供方的 ID
    • SERVICE_ACCOUNT_EMAIL:服务帐号的电子邮件地址

    示例:

    jobs:
      build:
        # Allow the job to fetch a GitHub ID token
        permissions:
          id-token: write
          contents: read
    
        runs-on: ubuntu-latest
    
        steps:
          - uses: actions/checkout@v2
    
          - id: 'auth'
            name: 'Authenticate to Google Cloud'
            uses: 'google-github-actions/auth@v0.3.1'
            with:
              create_credentials_file: true
              workload_identity_provider: 'projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID'
              service_account: 'SERVICE_ACCOUNT_EMAIL'
    
  2. 初始化环境变量 GOOGLE_APPLICATION_CREDENTIALS 并将其指向凭据配置文件:

    Bash

      export GOOGLE_APPLICATION_CREDENTIALS=`pwd`/FILEPATH.json
      
    其中,FILEPATH 是凭据配置文件的相对文件路径。

    PowerShell

      $env:GOOGLE_APPLICATION_CREDENTIALS = Resolve-Path 'FILEPATH.json'
      
    其中,FILEPATH 是凭据配置文件的相对文件路径。

    GitHub Actions YAML

    google-github-actions/auth 操作会自动初始化 GOOGLE_APPLICATION_CREDENTIALS
  3. 使用支持工作负载身份联合并自动查找凭据的客户端库:

    C++

    大多数 C++ 版 Google Cloud 客户端库 通过使用 ChannelCredentials 对象支持身份联合,该对象是通过调用 grpc::GoogleDefaultCredentials() 创建的。如要初始化此凭据,必须使用 gRPC 的 1.36.0 版本或更高版本构建客户端库。

    C++ 版 Cloud Storage 客户端库使用的是 REST API,而不是 gRPC,因此不支持身份联合。

    Go

    如果 Go 客户端库使用 golang.org/x/oauth2 模块的 v0.0.0-20210218202405-ba52d332ba99 版本或更高版本,则客户端库支持身份联合。

    如要查看客户端库使用的模块版本,请运行以下命令:

    cd $GOPATH/src/cloud.google.com/go
    go list -m golang.org/x/oauth2
    

    Java

    如果 Java 客户端库使用 com.google.auth:google-auth-library-oauth2-http 工件的 0.24.0 版或更高版本,则客户端支持身份联合。

    如需查看该客户端库使用的工件版本,请在应用目录中运行以下 Maven 命令:

    mvn dependency:list -DincludeArtifactIds=google-auth-library-oauth2-http
    

    Node.js

    如果 Node.js 客户端库使用 google-auth-library 软件包的 7.0.2 版本或更高版本,则客户端支持身份联合。

    如要查看客户端库使用的软件包版本,请在应用目录中运行以下命令:

    npm list google-auth-library
    

    创建 GoogleAuth 对象时,您可以指定项目 ID,也可以允许 GoogleAuth 自动查找项目 ID。如要自动查找项目 ID,配置文件中的服务帐号必须具有项目的 Browser 角色 (roles/browser) 或具有同等权限的角色。如需了解详情,请参阅 google-auth-library 软件包的 README

    Python

    如果 Python 客户端库使用 google-auth 软件包的 1.27.0 版本或更高版本,则客户端支持身份联合。

    如要检查客户端库使用的软件包版本,请在已安装该软件包的环境中运行以下命令:

    pip show google-auth
    

    如要为身份验证客户端指定项目 ID,您可以设置 GOOGLE_CLOUD_PROJECT 环境变量,也可以允许客户端自动查找项目 ID。如要自动查找项目 ID,配置文件中的服务帐号必须具有项目的 Browser 角色 (roles/browser) 或具有同等权限的角色。如需了解详情,请参阅 google-auth 软件包用户指南

    gcloud

    如需使用工作负载身份联合进行身份验证,请使用 gcloud auth login 命令:

    gcloud auth login --cred-file=FILEPATH.json
    

    其中,FILEPATH 是凭据配置文件的文件路径。

    版本 363.0.0 及更高版本的 gcloud CLI 支持 gcloud CLI 中的工作负载身份联合。

    Terraform

    如果您使用 3.61.0 或更高版本,则 Google Cloud 提供商支持工作负载身份联合:

    terraform {
      required_providers {
        google = {
          source  = "hashicorp/google"
          version = "~> 3.61.0"
        }
      }
    }
    

    gsutil

    如需使用工作负载身份联合进行身份验证,请使用以下方法之一:

    将 gsutil 与 gcloud 搭配使用时,请照常登录:

    gcloud auth login --cred-file=FILEPATH.json
    

    将 gsutil 用作独立的命令行应用时,请修改 .boto 文件以包含以下部分:

    [Credentials]
    gs_external_account_file = FILEPATH
    

    在这两种情况下,FILEPATH 都是凭据配置文件的文件路径。

    379.0.0 版及更高版本的 gcloud CLI 支持 gsutil 中的工作负载身份联合。

    bq

    如需使用工作负载身份联合进行身份验证,请使用 gcloud auth login 命令:

    gcloud auth login --cred-file=FILEPATH.json
    

    其中,FILEPATH 是凭据配置文件的文件路径。

    390.0.0 版及更高版本的 gcloud CLI 支持 bq 中的工作负载身份联合。

使用 REST API 进行身份验证

如果您无法使用客户端库,则可以按照以下步骤让外部身份使用 REST API 获取短期访问令牌:

  1. 从外部身份提供商获取凭据:

    AWS

    创建一个 JSON 文档,其中包含您通常在向 AWS GetCallerIdentity() 端点发出的请求中包含的信息,包括有效的请求签名

    工作负载身份联合将此 JSON 文档称为 GetCallerIdentity 令牌。该令牌允许工作负载身份联合验证身份,而无需显示 AWS 私有访问密钥。

    GetCallerIdentity 令牌类似于以下内容:

    {
      "url": "https://sts.amazonaws.com?Action=GetCallerIdentity&Version=2011-06-15",
      "method": "POST",
      "headers": [
        {
          "key": "Authorization",
          "value" : "AWS4-HMAC-SHA256 Credential=AKIASOZTBDV4D7ABCDEDF/20200228/us-east-1/sts/aws4_request, SignedHeaders=host;x-amz-date,Signature=abcedefdfedfd"
        },
        {
          "key": "host",
          "value": "sts.amazonaws.com"
        },
        {
          "key": "x-amz-date",
          "value": "20200228T225005Z"
        },
        {
          "key": "x-goog-cloud-target-resource",
          "value": "//iam.googleapis.com/projects/12345678/locations/global/workloadIdentityPools/my-pool/providers/my-aws-provider"
        },
        {
          "key": "x-amz-security-token",
          "value": "GizFWJTqYX...xJ55YoJ8E9HNU="
        }
      ]
    }
    

    该令牌包含以下字段:

    • urlGetCallerIdentity() 的 AWS STS 端点的网址,附加一个标准 GetCallerIdentity() 请求正文作为查询参数。例如:https://sts.amazonaws.com?Action=GetCallerIdentity&Version=2011-06-15。区域端点也受支持。
    • method:HTTP 请求方法:POST
    • headers:HTTP 请求标头,其中必须包含以下内容:
      • Authorization:请求签名。
      • hosturl 字段的主机名,例如 sts.amazonaws.com
      • x-amz-date:您将发送请求的时间,格式为 ISO 8601 Basic 字符串。此值通常设置为当前时间,并可帮助防止重放攻击。
      • x-goog-cloud-target-resource:身份提供方的完整资源名称,不含 https: 前缀。例如:
        //iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID
        
      • x-amz-security-token:会话令牌。仅在使用临时安全凭据时才需要。

    以下示例会创建一个网址编码的 GetCallerIdentity 令牌。提取网址编码令牌以备后用。此外,它专门为您的参考创建了一个人类可读的令牌:

    import json
    import urllib
    
    import boto3
    from botocore.auth import SigV4Auth
    from botocore.awsrequest import AWSRequest
    
    def create_token_aws(project_number: str, pool_id: str, provider_id: str) -> None:
        # Prepare a GetCallerIdentity request.
        request = AWSRequest(
            method="POST",
            url="https://sts.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15",
            headers={
                "Host": "sts.amazonaws.com",
                "x-goog-cloud-target-resource": f"//iam.googleapis.com/projects/{project_number}/locations/global/workloadIdentityPools/{pool_id}/providers/{provider_id}"
            })
    
        # Set the session credentials and Sign the request.
        # get_credentials loads the required credentials as environment variables.
        # Refer:
        # https://boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html
        SigV4Auth(boto3.Session().get_credentials(), "sts", "us-east-1").add_auth(request)
    
        # Create token from signed request.
        token = {
            "url": request.url,
            "method": request.method,
            "headers": []
        }
        for key, value in request.headers.items():
            token["headers"].append({"key": key, "value": value})
    
        # The token lets workload identity federation verify the identity without revealing the AWS secret access key.
        print("Token:\n%s" % json.dumps(token, indent=2, sort_keys=True))
        print("URL encoded token:\n%s" % urllib.parse.quote(json.dumps(token)))
    
    def main():
        # TODO(Developer): Replace the below credentials.
        # project_number: Google Project number (not the project id)
        project_number = "my-project-number"
        pool_id = "my-pool-id"
        provider_id = "my-provider-id"
    
        create_token_aws(project_number, pool_id, provider_id)
    
    if __name__ == "__main__":
        main()

    初始化以下变量:

    Bash

    SUBJECT_TOKEN_TYPE="urn:ietf:params:aws:token-type:aws4_request"
    SUBJECT_TOKEN=TOKEN
    

    PowerShell

    $SubjectTokenType = "urn:ietf:params:aws:token-type:aws4_request"
    $SubjectToken = "TOKEN"
    

    其中 TOKEN 是由上述脚本生成的网址编码 GetCallerIdentity 令牌。

    Azure

    连接到具有已分配的代管式身份的 Azure 虚拟机,并从 Azure Instance Metadata Service (IMDS) 获取访问令牌

    Bash

    SUBJECT_TOKEN_TYPE="urn:ietf:params:oauth:token-type:jwt"
    SUBJECT_TOKEN=$(curl \
      "http://169.254.169.254/metadata/identity/oauth2/token?resource=APP_ID_URI&api-version=2018-02-01" \
      -H "Metadata: true" | jq -r .access_token)
    echo $SUBJECT_TOKEN
    

    此命令使用 jq 工具jq 默认在 Cloud Shell 中可用。

    PowerShell

    $SubjectTokenType = "urn:ietf:params:oauth:token-type:jwt"
    $SubjectToken = (Invoke-RestMethod `
      -Uri "http://169.254.169.254/metadata/identity/oauth2/token?resource=APP_ID_URI&api-version=2018-02-01" `
      -Headers @{Metadata="true"}).access_token
    Write-Host $SubjectToken
    

    其中,APP_ID_URI 是您已为工作负载身份联合配置的应用的应用 ID URI

    GitHub Actions

    使用 google-github-actions/auth 获取 GitHub ID 令牌并将其与短期有效的访问令牌交换:

    • 通过添加以下配置,允许作业提取 GitHub ID 令牌:

      permissions:
        id-token: write
        contents: read
      
    • 添加一个步骤以生成访问令牌,并使它在变量 ${{ steps.auth.outputs.access_token }} 中可用:

      - id: 'auth'
        name: 'Authenticate to Google Cloud'
        uses: 'google-github-actions/auth@v0.3.1'
        with:
          token_format: 'access_token'
          workload_identity_provider: 'projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID'
          service_account: 'SERVICE_ACCOUNT_EMAIL'
      

    替换以下值:

    • PROJECT_NUMBER:包含工作负载身份池的项目的编号
    • POOL_ID:工作负载身份池的 ID
    • PROVIDER_ID:工作负载身份池提供方的 ID
    • SERVICE_ACCOUNT_EMAIL:服务帐号的电子邮件地址

    示例:

    jobs:
      build:
        # Allow the job to fetch a GitHub ID token
        permissions:
          id-token: write
          contents: read
    
        runs-on: ubuntu-latest
    
        steps:
          - uses: actions/checkout@v2
    
          - id: 'auth'
            name: 'Authenticate to Google Cloud'
            uses: 'google-github-actions/auth@v0.3.1'
            with:
              token_format: 'access_token'
              workload_identity_provider: 'projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID'
              service_account: 'SERVICE_ACCOUNT_EMAIL'
    

    跳过以下步骤。

    OIDC

    从外部身份提供商获取令牌并初始化以下变量:

    Bash

    SUBJECT_TOKEN_TYPE="urn:ietf:params:oauth:token-type:jwt"
    SUBJECT_TOKEN=TOKEN
    

    PowerShell

    $SubjectTokenType = "urn:ietf:params:oauth:token-type:jwt"
    $SubjectToken = "TOKEN"
    

    其中,TOKEN 是您的外部身份提供商颁发的令牌。

    OIDC (AD FS)

    通过以下 PowerShell 命令,使用 IWA 向 AD FS 进行身份验证并获取访问令牌:

    $SubjectTokenType = "urn:ietf:params:oauth:token-type:jwt"
    $SubjectToken = (Invoke-RestMethod `
        -Uri "https://ADFS_DOMAIN/adfs/oauth2/token/" `
        -Method POST `
        -Body @{
            client_id = 'CLIENT_ID'
            grant_type = 'client_credentials'
            scope = 'openid'
            resource = 'RELYING_PARTY_ID'
            use_windows_client_authentication = 'true'
            } `
        -Credential USER).access_token
    

    替换以下值:

    • ADFS_DOMAIN:AD FS 服务器或服务器场的公共域名。
    • CLIENT_ID:AD FS 中应用注册的客户端 ID。
    • RELYING_PARTY_ID:在 AD FS 中为工作负载身份池创建 Web API 应用时使用的信赖方标识符。只有在使用自定义信赖方标识符时,才需要此参数。
    • USER:用于 IWA 的 Active Directory 用户。或者,将 -Credential 替换为 -UseDefaultCredentials 以使用当前凭据。

    SAML

    从外部身份提供商获取断言并初始化变量:

    Bash

    SUBJECT_TOKEN_TYPE="urn:ietf:params:oauth:token-type:saml2"
    SUBJECT_TOKEN=ASSERTION
    

    PowerShell

    $SubjectTokenType = "urn:ietf:params:oauth:token-type:saml2"
    $SubjectToken = "ASSERTION"
    

    其中,ASSERTION 是您的外部身份提供方颁发的 base64 编码的断言。

  2. 使用 Security Token Service API 将凭据交换为短期有效的访问令牌:

    Bash

    STS_TOKEN=$(curl -0 -X POST https://sts.googleapis.com/v1/token \
        -H 'Content-Type: text/json; charset=utf-8' \
        -d @- <<EOF | jq -r .access_token
        {
            "audience"           : "//iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID",
            "grantType"          : "urn:ietf:params:oauth:grant-type:token-exchange",
            "requestedTokenType" : "urn:ietf:params:oauth:token-type:access_token",
            "scope"              : "https://www.googleapis.com/auth/cloud-platform",
            "subjectTokenType"   : "$SUBJECT_TOKEN_TYPE",
            "subjectToken"       : "$SUBJECT_TOKEN"
        }
    EOF
    )
    echo $STS_TOKEN
    

    PowerShell

    [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
    $StsToken = (Invoke-RestMethod `
        -Method POST `
        -Uri "https://sts.googleapis.com/v1/token" `
        -ContentType "application/json" `
        -Body (@{
            "audience"           = "//iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID"
            "grantType"          = "urn:ietf:params:oauth:grant-type:token-exchange"
            "requestedTokenType" = "urn:ietf:params:oauth:token-type:access_token"
            "scope"              = "https://www.googleapis.com/auth/cloud-platform"
            "subjectTokenType"   = $SubjectTokenType
            "subjectToken"       = $SubjectToken
        } | ConvertTo-Json)).access_token
    Write-Host $StsToken
    

    替换以下值:

    • PROJECT_NUMBER:包含工作负载身份池的项目的编号
    • POOL_ID:工作负载身份池的 ID
    • PROVIDER_ID:工作负载身份池提供方的 ID
  3. 使用 Security Token Service 中的令牌调用 IAM Service Account Credentials APIgenerateAccessToken 方法来获取访问权限令牌:

    Bash

    ACCESS_TOKEN=$(curl -0 -X POST https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/SERVICE_ACCOUNT_EMAIL:generateAccessToken \
        -H "Content-Type: text/json; charset=utf-8" \
        -H "Authorization: Bearer $STS_TOKEN" \
        -d @- <<EOF | jq -r .accessToken
        {
            "scope": [ "https://www.googleapis.com/auth/cloud-platform" ]
        }
    EOF
    )
    echo $ACCESS_TOKEN
    

    PowerShell

    $AccessToken = (Invoke-RestMethod `
        -Method POST `
        -Uri "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/SERVICE_ACCOUNT_EMAIL:generateAccessToken" `
        -Headers @{ "Authorization" = "Bearer $StsToken" } `
        -ContentType "application/json" `
        -Body (@{
            "scope" = , "https://www.googleapis.com/auth/cloud-platform"
        } | ConvertTo-Json)).accessToken
    Write-Host $AccessToken
    

    SERVICE_ACCOUNT_EMAIL 替换为服务帐号的电子邮件地址。

外部凭据验证

Security Token Service API 使用以下步骤验证外部身份提供商颁发的凭据。

AWS

  • 验证 GetCallerIdentity 令牌中的以下字段:

    • url 应是一个 HTTPS URI,其主机名等于 sts.amazonaws.com(或区域子网域)且没有端口。恰好存在以下查询参数:
      • action = getcalleridentity
      • version(任意值)
    • methodPOST
    • 恰好存在以下 headersx-amz-dateauthorizationhostx-goog-cloud-target-resourcex-amz-security-token(可选)
      • x-goog-cloud-target-resource 的值是工作负载身份池提供方的资源名称。
      • x-amz-date 的值最多为 15 分钟,它是过去的时间而不是将来的时间。
  • sts.amazonaws.com 或相关区域子网域执行请求,并验证结果是否成功以及 AWS 帐号 ID 是否与为工作负载身份池提供方配置的帐号 ID 相匹配。

Azure

Azure 令牌是 OIDC 令牌,其验证方式与 OIDC 令牌相同。

GitHub Actions

GitHub 令牌是 OIDC 令牌,其验证方式与 OIDC 令牌相同。

OIDC

OIDC 令牌根据 OIDC 规范进行验证。具体而言,Security Token Service 执行以下步骤:

  • 发现文档和签名验证:

    • 通过将 /.well-known/openid-configuration 附加到在工作负载身份池提供方中配置的颁发者来构建发现端点 URI 并提取 OIDC 发现文档。
    • 验证发现文档中的 issuer 声明与工作负载身份池提供方中配置的颁发者相同。STS 为以下不符合 OIDC 规范的颁发者使用自定义验证逻辑:
      • Oracle Cloud (https://*.identity.oraclecloud.com)
      • Microsoft(https://login.microsoftonline.com/common/v2.0https://login.microsoftonline.com/consumers/v2.0https://login.microsoftonline.com/organizations/v2.0
    • 从发现文档中列出的 jwks_uri 中检索 JSON Web 密钥集 (JWKS)。
    • 如果 JWT 标头中存在 kid 声明,请使用来自 JWKS 的具有匹配密钥 ID 的密钥验证 JWT 签名,或者如果未找到匹配密钥则拒绝令牌。如果 JWT 标头中不存在 kid 声明,请尝试使用 JWKS 中列出的每个密钥验证 JWT 签名。如果任何密钥都可用于验证签名,则接受签名。
  • 标头验证:

    • alg 声明必须存在且等于 RS256ES256
  • 载荷验证:

    • iss 声明必须存在,且等于发现文档中的 issuer 声明。STS 为以下不符合 OIDC 规范的颁发者使用自定义验证逻辑:
      • Oracle Cloud (https://*.identity.oraclecloud.com)
      • Microsoft(https://login.microsoftonline.com/common/v2.0https://login.microsoftonline.com/consumers/v2.0https://login.microsoftonline.com/organizations/v2.0
    • aud 声明必须存在且等于 https://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID。如果配置了替代 allowed_audiences,则 aud 声明必须改为等于这些值之一。
    • exp 声明必须存在且是未来的时间
    • iat 声明必须存在且是过去的时间
    • exp 的值必须大于 iat 的值,最多相差 24 小时。

SAML

  • 对 SAML 凭据进行 Base64 解码并将其取消封送到 ResponseAssertion 对象。
  • 如果 SAML 凭据已取消封送到 Response 对象,请验证以下内容:

    • 响应 StatusCode 等于 urn:oasis:names:tc:SAML:2.0:status:Success
    • 只存在一个 Assertion
    • 至少有一个 ResponseAssertion 已签名。对于每项签名,请尝试使用工作负载身份池提供方中配置的每项 X.509 证书来验证签名。如果任何证书成功验证签名,则接受签名。
    • 如果 Response 已签名,则 ResponseIssuer 必须存在,且等于工作负载身份池提供方中配置的 SAML 身份提供方的实体 ID。另外,验证 Format 是否已被省略或等于 urn:oasis:names:tc:SAML:2.0:nameid-format:entity
  • 如果 SAML 凭据已取消封送到 Assertion 对象,请验证以下内容:

    • Assertion 已签名。对于每项签名,请尝试使用工作负载身份池提供方中配置的每项 X.509 证书来验证签名。如果任何证书成功验证签名,则接受签名。
  • 无论 SAML 凭据是取消封送到 Response 还是 Assertion 对象中,都请验证 Assertion 是否包含以下特性:

    • Issuer 必须存在,且等于工作负载身份池提供方中配置的 SAML 身份提供方的实体 ID。IssuerFormat 已被省略或其值等于 urn:oasis:names:tc:SAML:2.0:nameid-format:entity
    • IssueInstant 必须存在,并且在过去 1 小时内。
    • Subject 必须存在且包含以下特性:
      • NameID 必须存在。
      • 必须只有一个 SubjectConfirmation,其 Method 等于 urn:oasis:names:tc:SAML:2.0:cm:bearerNotOnOrAfter 必须存在于 SubjectConfirmationData 中,且它是在将来。
      • NotBefore 不存在。
    • Conditions 必须存在且包含以下特性:
      • 如果存在 NotBefore,则它必须是过去的时间。
      • 如果存在 NotOnOrAfter,则它必须是将来的时间。
      • 必须至少存在一个 AudienceRestriction。所有 AudienceRestriction 都必须包含一个等于工作负载身份池提供方的资源名称的 Audience
    • 必须至少存在一个 AuthnStatement
    • 如果存在任何 SessionNotOnOrAfter,则它们都必须是将来的时间。

除了上述特定于协议的验证步骤之外,Security Token Service API 还会验证是否满足特性条件

后续步骤