首页 > 解决方案 > Google Cloud Build 获取身份令牌

问题描述

在我的场景中,我想在 Google Cloud Build 期间触发基于 HTTP 端点的 Google Cloud Function。HTTP 请求是使用带有 python:3.7-slim 容器的步骤完成的。

基于文档中的thisthis示例,我想使用以下代码:

REGION = 'us-central1'
PROJECT_ID = 'name-of-project'
RECEIVING_FUNCTION = 'my-cloud-function'

function_url = f'https://{REGION}-{PROJECT_ID}.cloudfunctions.net/{RECEIVING_FUNCTION}'

metadata_server_url = 'http://metadata/computeMetadata/v1/instance/service-accounts/default/identity?audience='
token_full_url = metadata_server_url + function_url
token_headers = {'Metadata-Flavor': 'Google'}

token_response = requests.get(token_full_url, headers=token_headers)
jwt = token_response.text
print(jwt)

r = requests.post(url=function_url, headers=function_headers, json=payload)

令人惊讶的是,代码失败是因为jwtNot Found(根据print声明)。我已经通过硬编码有效的身份令牌测试了代码和 IAM 设置,并且还在同一项目内的测试 VM 上测试了完全相同的获取机制。问题似乎是获取一些元数据在云构建中不起作用。

我错过了什么吗?感谢您的任何帮助!

标签: google-cloud-platformgoogle-cloud-functionsgoogle-cloud-build

解决方案


解决方案是使用新的 IAM api 在具有访问令牌的服务帐户上生成 ID_TOKEN,如果请求者(生成访问令牌的人)在服务帐户(或广泛使用该项目)。

第一个示例使用直接 API 调用

 - name: gcr.io/cloud-builders/gcloud
   entrypoint: "bash"
   args:
    - "-c"
    - |
        curl -X POST -H "content-type: application/json" \
        -H "Authorization: Bearer $(gcloud auth print-access-token)" \
        -d '{"audience": "YOUR AUDIENCE"}' \
         "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/YOUR SERVICE ACCOUNT:generateIdToken"
        # Use Cloud Build Service Account
        # service_account_email=$(gcloud config get-value account) 

这里是 Python 代码版本

- name: python:3.7
          entrypoint: "bash"
          args:
            - "-c"
            - |
                    pip3 install google-auth requests
                    python3 extract-token.py

extract-token.py包含以下代码

REGION = 'us-central1'
PROJECT_ID = 'name-of-project'
RECEIVING_FUNCTION = 'my-cloud-function'
function_url = f'https://{REGION}-{PROJECT_ID}.cloudfunctions.net/{RECEIVING_FUNCTION}'

import google.auth
credentials, project_id = google.auth.default(scopes='https://www.googleapis.com/auth/cloud-platform')

# To use the Cloud Build service account email
service_account_email = credentials.service_account_email
#service_account_email = "YOUR OWN SERVICE ACCOUNT"

metadata_server_url = f'https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/{service_account_email}:generateIdToken'
token_headers = {'content-type': 'application/json'}

from google.auth.transport.requests import AuthorizedSession
authed_session = AuthorizedSession(credentials)
import json
body = json.dumps({'audience': function_url})

token_response = authed_session.request('POST',metadata_server_url, data=body, headers=token_headers)
jwt = token_response.json()
print(jwt['token'])

如果您需要更多详细信息,请不要犹豫。

我想我会在 Medium 上写一篇关于这个的文章,如果你想要我的名字,请告诉我


推荐阅读