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

Dataproc集群curl内嵌gcloud auth print-access-token报403权限错误

问题根因

这个问题本质是不同运行上下文下gcloud CLI返回的访问令牌所属身份不一致:
Dataproc集群节点基于GCE实例运行,预装的gcloud CLI在非交互子shell(也就是你写在curl参数里的$()命令替换环境)中执行时,会优先走GCE元数据服务器获取节点默认绑定的计算服务账号令牌,跳过你在交互式shell中配置的服务账号模拟、个人账号登录等用户级凭证配置;而你手动单独执行gcloud auth print-access-token时,处于交互式shell环境,gcloud会正常加载用户目录下的凭证配置,返回你预期的、拥有Secret Manager访问权限的账号令牌。
你看到的403错误,就是因为内嵌执行拿到的是节点默认计算服务账号的令牌,这个账号默认没有被授予目标密钥的secretmanager.versions.access权限。
你描述的其他现象也完全符合这个逻辑:

  • 本地生成的curl(带本地有权限的token)复制到集群执行能成功,因为token本身是对的
  • 集群内嵌生成的curl(带节点默认SA的无权限token)拿到本地执行会失败,因为token对应的账号没权限
  • 手动单独拿token再粘贴到curl里在两边都能成,因为手动获取时走的是交互式凭证加载逻辑,拿到的是有权限的正确token
    另外还有个小概率触发点:非交互模式下gcloud会把部分版本更新提示、配置警告从stderr改到stdout输出,导致Bearer后面拼接的令牌夹杂无效字符,也会触发鉴权失败。
验证方法

在集群节点上执行以下两组命令,对比两个令牌对应的账号邮箱就能直接确认:

# 1. 模拟你手动单独拿token的场景
TOKEN_INTERACTIVE=$(gcloud auth print-access-token)
curl "https://www.googleapis.com/oauth2/v3/tokeninfo?access_token=$TOKEN_INTERACTIVE"
# 2. 模拟curl内嵌命令替换拿token的场景
curl -s -o /dev/null -w "%{authorization}" -H "Authorization: Bearer $(gcloud auth print-access-token | tee /tmp/sub_token.txt)" https://example.com
curl "https://www.googleapis.com/oauth2/v3/tokeninfo?access_token=$(cat /tmp/sub_token.txt)"

正常你会看到第二个命令返回的邮箱是节点默认计算服务账号,格式一般是<项目编号>-compute@developer.gserviceaccount.com,和第一个命令返回的目标服务账号不一致。如果没装jq工具,直接在返回结果里找email字段即可。

修复方案

选任意一种即可,优先推荐第一种:

  • 拆分令牌获取逻辑,显式指定使用账号
    不要直接在curl参数里内嵌命令替换拿token,先单独获取令牌存为变量,同时显式指定要使用的服务账号,避免不同环境下的配置漂移:
    # 脚本开头加这行,让管道命令的错误能被正常捕获
    set -eo pipefail
    
    GetAuthJson() {
      # 显式指定目标服务账号,丢弃gcloud的警告类输出
      local ACCESS_TOKEN
      ACCESS_TOKEN=$(gcloud auth print-access-token \
        --impersonate-service-account=<你的目标服务账号邮箱> 2>/dev/null)
      if [ -z "$ACCESS_TOKEN" ]; then
        Error "Failed to get valid GCP access token"
      fi
    
      authjson=$(curl -fsS "https://secretmanager.googleapis.com/v1/projects/$PROJECT_ID/secrets/$AUTH_JSON/versions/1:access" \
        --request "GET" \
        --header "authorization: Bearer ${ACCESS_TOKEN}" \
        --header "content-type: application/json")
      if [ $? -ne 0 ]; then
        Error "Unable to extract the $PIPENAME Auth json details from GCP Secret Manager"
      fi
    
      echo "$authjson" | grep -o '"data": "[^"]*' | grep -o '[^"]*$' >"$BASE_DIR/encodedauth.json"
      if [ $? -ne 0 ]; then
        Error "Unable to save the $PIPENAME auth.json server secret to auth.json"
      fi
    
      base64 -d "$BASE_DIR/encodedauth.json" >/etc/secrets/auth.json
      if [ $? -ne 0 ]; then
        Error "Unable to decode the $PIPENAME auth.json server secret"
      fi
      Log "auth.json secret extraction done"
    }
    
  • 给节点默认服务账号授权
    如果你的脚本逻辑确实需要使用节点默认身份,直接给节点绑定的计算服务账号授予目标Secret的Secret Manager Secret Accessor角色即可,缺点是权限配置和节点绑定,迁移灵活性差。
  • 禁止gcloud自动使用元数据凭证
    在脚本开头添加环境变量,强制gcloud无论是否在交互环境都加载用户配置的凭证,不自动fallback到GCE元数据身份:
    export CLOUDSDK_AUTH_DISABLE_GCE_METADATA=1
    

内容的提问来源于stack exchange,提问作者amarnath harish

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 19:18:46