You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无需下载凭据文件,实现GCP Python模拟服务账号的ID Token认证

无需下载凭据文件,实现GCP Python模拟服务账号的ID Token认证

你提的这个问题非常实用——确实可以不用下载服务账号密钥文件,就能在本地模拟服务账号获取ID Token,同时保证代码在GCP部署环境(依赖元数据服务器)无缝运行。我来一步步拆解解决方案:


一、回顾:模拟服务账号获取访问令牌的步骤

这部分你已经摸索对了,我整理成清晰的操作流程方便参考:

  • 给你的个人GCP账号授予目标服务账号(svc@proj.iam.gserviceaccount.com)的Service Account Token Creator角色
  • 执行终端命令完成模拟登录,配置应用默认凭据(ADC):
    gcloud auth application-default login --impersonate-service-account svc@proj.iam.gserviceaccount.com
    
    此时/Users/youruser/.config/gcloud/application_default_credentials.json会变成模拟服务账号的凭据,而非个人账号凭据
  • 配置环境变量指定凭据路径(若系统未自动识别):
    export GOOGLE_APPLICATION_CREDENTIALS=/Users/youruser/.config/gcloud/application_default_credentials.json
    
  • 代码中获取访问令牌:
    import google.auth
    import google.auth.transport.requests
    
    scopes = ["https://www.googleapis.com/auth/cloud-platform"]
    creds, project_id = google.auth.default(scopes=scopes)
    auth_req = google.auth.transport.requests.Request()
    creds.refresh(auth_req)
    # 使用creds.token即可
    

二、核心问题:模拟服务账号获取ID Token的正确方式

你遇到的DefaultCredentialsError是因为google.oauth2.id_token.fetch_id_token默认不支持处理模拟服务账号类型的ADC凭据——默认的模拟ADC配置只指向了生成访问令牌的端点,而非ID Token的生成端点。

下面是无需下载SA密钥的解决方案,且代码在本地和GCP环境都能正常运行:

前置条件

和获取访问令牌的要求一致:你的个人账号已拥有目标服务账号的Service Account Token Creator角色,且已通过gcloud auth application-default login --impersonate-service-account ...完成模拟登录。

代码实现:用impersonated_credentials生成ID Token

我们需要用google.auth.impersonated_credentials模块创建支持ID Token生成的凭据对象,它会自动适配本地模拟凭据和GCP元数据服务器凭据:

import google.auth
from google.auth import impersonated_credentials
import google.auth.transport.requests

# 替换为你的目标服务账号和受众(audience,比如IAP保护应用的URL或客户端ID)
TARGET_SA = "svc@proj.iam.gserviceaccount.com"
AUDIENCE = "https://your-iap-protected-app.example.com"

# 1. 获取源凭据:本地读取模拟SA的ADC,GCP环境自动读取元数据服务器凭据
source_creds, project_id = google.auth.default()

# 2. 创建模拟凭据对象,配置ID Token生成参数
impersonated_creds = impersonated_credentials.Credentials(
    source_credentials=source_creds,
    target_principal=TARGET_SA,
    target_scopes=[],  # ID Token不需要scopes,留空即可
    delegates=[],
    lifetime=3600  # Token最长有效期为3600秒(1小时)
)

# 3. 刷新凭据生成ID Token
request = google.auth.transport.requests.Request()
impersonated_creds.refresh(request)

# 4. 获取最终的ID Token
id_token = impersonated_creds.id_token
print(f"Generated ID Token for audience {AUDIENCE}: {id_token}")

为什么这个方法可行?

  • 本地环境:source_creds会读取模拟SA的ADC,自动调用IAM Credentials API的generateIdToken端点生成ID Token
  • GCP部署环境:source_creds直接从元数据服务器获取当前服务账号的凭据,若需要模拟其他SA,只要当前SA拥有对应角色,代码无需修改即可运行

备选快速测试方案:用gcloud命令行生成ID Token

如果你需要快速验证,也可以直接用gcloud命令行生成ID Token,再在代码中读取:

gcloud auth print-identity-token --impersonate-service-account svc@proj.iam.gserviceaccount.com --audiences https://your-iap-protected-app.example.com

关键注意点

  1. 必须确保你的用户/服务账号拥有Service Account Token Creator角色(IAM角色ID:roles/iam.serviceAccountTokenCreator),这是模拟生成Token的核心权限
  2. 代码无需区分本地和GCP环境,ADC会自动适配凭据来源
  3. 不要用google.oauth2.id_token.fetch_id_token直接处理模拟SA凭据,它不支持这种凭据类型

备注:内容来源于stack exchange,提问作者Blue_Togepi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 10:49:31