【问题标题】:How can I retrieve an id_token to access a Google Cloud Function?如何检索 id_token 以访问 Google Cloud 函数?
【发布时间】:2021-04-15 18:09:36
【问题描述】:

我正在尝试生成一个 id_token 以使用我从here 获得的以下代码对 Google Cloud Functions 进行经过身份验证的调用:

# IAP audience is the ClientID of IAP-App-Engine-app in 
# the API->credentials page
# Cloud Function and Cloud Run need the base URL of the service
audience = 'my_cloud_function_url'
# #1 Get the default credential to generate the access token
credentials, project_id = google.auth.default()

# #2 To use the current service account email
service_account_email = credentials.service_account_email

# Don't work with user account, so define manually the email
# service_account_email = 'MY SERVICE ACCOUNT EMAIL'
# #3 prepare the call the the service account credentials API
sa_credentials_url =  f'https://iamcredentials.googleapis.com/' \
                      f'v1/projects/-/serviceAccounts/'  \
                      f'{service_account_email}:generateIdToken'
headers = {'Content-Type': 'application/json'}
# Create an AuthorizedSession that includes 
# automatically the access_token based on your credentials
authed_session = AuthorizedSession(credentials)
# Define the audience in the request body
# add the parameter "'includeEmail':true" for IAP access
body = json.dumps({'audience': audience})
# Make the call 
token_response = authed_session.request('POST',sa_credentials_url,
                                        data=body, headers=headers)

jwt = token_response.json()
id_token = jwt['token']

我没有在 Google Cloud 环境中运行它,因此我将我的 GOOGLE_APPLICATION_CREDENTIALS 设置为来自我在控制台中生成的服务帐户的 json 文件。我要求我的网络管理员在 ['https://www.googleapis.com/auth/cloud-platform'] 范围内授权服务帐户。

当我运行脚本时,我收到以下错误:

{'error': {'code': 403, 'message': 'The caller does not have permission', 'status': 'PERMISSION_DENIED'}}

我认为此错误与此服务帐户没有某些实习生访问权限有关,但我不确定,有人可以帮我解决这个问题吗?

编辑:

正如@guillaume blaquiere 在 cmets 上所说,您可以在不调用服务帐户凭据 API 的情况下获取 id_token,我可以获得 id_token,但无法使用该 id_token 调用我的服务帐户

import google.oauth2.id_token
import google.auth.transport.requests

request = google.auth.transport.requests.Request()
audience = 'my_cloud_function_url'

id_token = google.oauth2.id_token.fetch_id_token(request, audience)
headers = {'Authorization': f'bearer {id_token}'}
service_response = requests.get(audience, headers=headers)

有谁知道为什么 id_token 无效?

【问题讨论】:

    标签: python google-cloud-functions google-authentication service-accounts


    【解决方案1】:

    403 错误The caller does not have permission 表示您的云函数的运行服务帐户没有调用该函数所需的角色。您能否前往 IAM 并检查您的服务帐户是否具有 Cloud Functions Invoker 角色?如果服务帐号没有权限,请按照以下步骤操作:

    1. IAM 中检查您的服务帐户的角色,查找角色 列并验证它是否没有上述角色。
    2. 要添加权限,请将鼠标悬停在您的服务帐户上,然后在名为Inheritance 的右侧列中单击编辑
    3. 从选择角色下拉菜单中选择角色Cloud Functions > Cloud Functions Invoker
    4. 点击保存

    【讨论】:

    • 您能否说明我必须向哪个服务帐户申请授权?我没有使用我的 gcp 项目的标准服务帐户,我要求经理创建另一个,这就是我用来尝试获取 id_token 的一个。
    • @Hugo-Cruz,请您的经理为您提供一个具有 Cloud Function Invoker 角色的服务帐户。
    【解决方案2】:

    您不需要调用 Service Account Credential API,您可以使用 fetch_id_token 方法(但您必须知道它存在哪个!它不是很知名和记录!)

    import google.oauth2.id_token
    import google.auth.transport.requests
    
    request = google.auth.transport.requests.Request()
    audience = 'my_cloud_function_url'
    
    id_token = google.oauth2.id_token.fetch_id_token(request, audience)
    

    库使用您在 GOOGLE_APPLICATION_CREDENTIALS 环境变量中设置的默认凭据。所以,用这个 python lib 获取 ID 令牌很方便!

    【讨论】:

    • 我尝试了这个并获得了一个 id_token(与我从控制台上的 gcloud auth print-identity-token 命令获得的相同),但无法使用此令牌访问我的云功能,你知道为什么吗?
    • 你放的观众是什么?你能分享吗(隐藏你的projectID)?生成令牌后如何执行对 Cloud Function 的调用?
    • 我正在使用云函数的触发器:region-name-project-id.cloudfunctions.net/cf-name 用于调用我正在使用的 cf:headers = {'Authorization': f'bearer {id_token}'} service_response = requests.get( cf_trigger_url, headers=headers)
    • 你得到的是 403 还是 401?
    • 我得到了 403
    猜你喜欢
    • 2016-03-08
    • 2017-09-13
    • 2020-07-07
    • 1970-01-01
    • 2018-03-29
    • 2021-12-18
    • 1970-01-01
    • 2023-03-27
    • 2017-08-19
    相关资源
    最近更新 更多