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

GitHub Actions中使用gsutil报错:无法为已完成作业签发ID_TOKEN

问题描述

我配置了如下GitHub Actions工作流步骤:

jobs:
  build-and-test:
    runs-on: self-hosted
    permissions:
      contents: read
      id-token: write

    steps:
      - name: Check out
        uses: actions/checkout@v3
      - id: auth
        uses: "google-github-actions/auth@v1"
        with:
          workload_identity_provider: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER }}
          service_account: ${{ secrets.GCP_SERVICE_ACCOUNT }}
          token_format: "access_token"

这些步骤执行无报错,但后续执行以下步骤时失败:

- name: Download test data
        run: |
          mkdir -pv ${MY_VAR}
          gsutil -m rsync -r gs://some-bucket/some-folder ${MY_VAR}

报错信息如下:

google.auth.exceptions.RefreshError: (
  'Unable to retrieve Identity Pool subject token',
  '{
     "$id":"1",
     "innerException":null,
     "message":"Can\'t issue ID_TOKEN for job in \'Completed\' state.",
     "typeName":"GitHub.Actions.Runtime.WebApi.CannotGenerateIdTokenException, GitHub.Actions.Runtime.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=null",
     "typeKey":"CannotGenerateIdTokenException",
     "errorCode":0,
     "eventId":3000
   }'
)

我已确认secrets.GCP_WORKLOAD_IDENTITY_PROVIDER和secrets.GCP_SERVICE_ACCOUNT的值正确,查阅过官方排障文档,且手动使用相同服务账号执行gsutil命令可正常运行。

我的初步猜想:可能存在之前执行google-github-actions/auth时遗留的有效密钥,该密钥对应已完成的旧工作流运行导致失效。如何验证该猜想?为何auth步骤生成新密钥后,gsutil仍使用旧密钥?


解答

一、验证遗留密钥猜想的方法

  • 检查runner环境变量
    在Download test data步骤前新增输出环境变量的步骤,重点查看GCP认证相关变量:

    - name: Print GCP auth env vars
      run: |
        echo "GOOGLE_APPLICATION_CREDENTIALS: $GOOGLE_APPLICATION_CREDENTIALS"
        echo "GOOGLE_ACCESS_TOKEN: $GOOGLE_ACCESS_TOKEN"
        # 查看凭据文件内容(如果存在)
        if [ -f "$GOOGLE_APPLICATION_CREDENTIALS" ]; then cat "$GOOGLE_APPLICATION_CREDENTIALS"; fi
    

    如果输出的凭据文件内容包含旧工作流标识,或GOOGLE_ACCESS_TOKEN是之前运行生成的,即可证明存在遗留密钥。

  • 查看runner本地存储
    登录自托管runner所在机器,检查GCP默认凭据存储路径(通常为~/.config/gcloud/),查看credentials或application_default_credentials.json文件的修改时间和内容。若文件修改时间早于当前工作流启动时间,说明是遗留的旧密钥。

  • 隔离测试
    使用全新的自托管runner执行该工作流,若执行成功,说明原runner存在遗留认证数据;若仍失败,再排查其他问题。

二、gsutil使用旧密钥的原因

  • 自托管runner环境未自动重置
    GitHub Actions自托管runner不会在每次工作流结束后清理环境,之前运行时google-github-actions/auth生成的认证文件(如写入~/.config/gcloud/的文件)会被保留,gsutil默认优先读取本地存储的旧凭据。

  • 环境变量优先级问题
    若GOOGLE_APPLICATION_CREDENTIALS指向旧凭据文件且文件存在,gsutil会优先使用该文件中的凭据,而非当前工作流生成的新access token。此外,runner上已配置的gcloud默认账号也会覆盖临时认证。

  • token_format参数的影响
    你设置了token_format: "access_token",该参数仅生成临时access token注入环境变量,但不会覆盖本地已有的gcloud凭据文件。当旧凭据对应的工作流已完成,gsutil尝试刷新旧凭据时,就会触发无法生成ID_TOKEN的错误。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 05:25:14