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

GitHub Actions Docker环境下R的bigrquery无法通过WIF认证

问题:GitHub Actions中WIF认证下gcloud可正常工作但bigrquery无法识别凭证

问题背景

开发基于GitHub Actions的工作流,通过Workload Identity Federation(WIF)向Google Cloud认证。容器内的gcloud CLI命令可成功完成认证并执行BigQuery操作,但R的bigrquery包始终无法识别凭证,所有认证尝试均失败。

工作流相关代码片段

# Step 3: Authenticate to Google Cloud via Workload Identity Federation
- name: Authenticate to Google Cloud
  uses: google-github-actions/auth@v2.1.7
  id: auth
  with:
    workload_identity_provider: ${{ secrets.WIF_PROVIDER }}
    service_account: ${{ secrets.WIF_SERVICE_ACCOUNT }}
    token_format: "access_token"
    create_credentials_file: true

# Step 5: Docker login to Artifact Registry using the WIF token
- name: Docker login to Artifact Registry
  run: |
    echo ${{ steps.auth.outputs.access_token }} | docker login -u oauth2accesstoken --password-stdin https://${{ env.location }}-docker.pkg.dev

# Step 6: Pull the specified Docker image
- name: Pull Docker image
  run: docker pull ${{ env.location }}-docker.pkg.dev/${{ env.project }}/${{ env.repository }}/base-image:latest

- name: Debug for google auth in R
  run: |
    docker run --rm \
      -v ${{ steps.auth.outputs.credentials_file_path }}:/gcp/creds.json:ro \
      -e GOOGLE_APPLICATION_CREDENTIALS=/gcp/creds.json \
      -e SUPABASE_API_URL="${{ secrets.SUPABASE_API_URL }}" \
      -e SUPABASE_SERVICE_KEY="${{ secrets.SUPABASE_SERVICE_KEY }}" \
      -e GCP_PROJECT=${{ env.project}} \
      ${{ env.location }}-docker.pkg.dev/${{ env.project }}/${{ env.repository }}/base-image:latest \
      sh -c '
        gcloud auth login --cred-file=/gcp/creds.json
        gcloud config set project $GCP_PROJECT
        bq ls --project_id=$GCP_PROJECT --format=prettyjson # works fine

        # 以下R代码均认证失败
        # Rscript -e "library(bigrquery); bq_auth(use_oob = TRUE); print(bq_project_datasets($GCP_PROJECT))"
        # Rscript -e "library(bigrquery); bq_auth(path = \"/gcp/creds.json\"); print(bq_project_datasets($GCP_PROJECT))"
        # Rscript -e "library(bigrquery); library(gargle); gargle_token <- gargle::credentials_service_account(path = \"/gcp/creds.json\", scopes = \"https://www.googleapis.com/auth/cloud-platform\"); bq_auth(token = gargle_token); print(bq_project_datasets(${{ env.GCP_PROJECT }}))"
        # Rscript -e "library(bigrquery); library(gargle); gargle_token <- gargle::credentials_app_default(scopes = \"https://www.googleapis.com/auth/cloud-platform\"); bq_auth(token = gargle_token); print(bq_project_datasets(${{ env.GCP_PROJECT }}))"
        # Rscript -e "library(bigrquery); library(gargle); gargle_token <- gargle::credentials_external_account(path = Sys.getenv(\"GOOGLE_APPLICATION_CREDENTIALS\"), scopes = \"https://www.googleapis.com/auth/cloud-platform\"); bq_auth(token = gargle_token); print(bq_project_datasets(${{ env.GCP_PROJECT }}))"
      '

可正常运行的操作

  • WIF认证流程:GitHub Actions成功获取访问令牌并生成凭证JSON文件。
  • 容器内gcloud命令:
gcloud auth login --cred-file=/gcp/creds.json
gcloud config set project ${{ env.GCP_PROJECT }}
bq ls --project_id=${{ env.GCP_PROJECT }} --format=prettyjson 

以上命令均可正常执行,说明gcloud层面的认证完全正常。

无法运行的操作

所有尝试用bigrquery(及底层gargle包)认证的R代码均失败,尝试过的方式包括:

# 方式1
library(bigrquery)
bq_auth(use_oob = TRUE)

# 方式2
library(bigrquery)
bq_auth(use_oob = FALSE)

# 方式3
library(bigrquery)
bq_auth(path = "/gcp/creds.json")

# 方式4
library(bigrquery)
library(gargle)
gargle_token <- gargle::credentials_service_account(path = "/gcp/creds.json", 
    scopes = "https://www.googleapis.com/auth/cloud-platform")
bq_auth(token = gargle_token)

# 方式5
library(bigrquery)
library(gargle)
gargle_token <- gargle::credentials_external_account(path = Sys.getenv("GOOGLE_APPLICATION_CREDENTIALS"), 
    scopes = "https://www.googleapis.com/auth/cloud-platform")
bq_auth(token = gargle_token)

所有方式执行bq_project_datasets(${GCP_PROJECT})时均返回错误:

Error in `bq_auth()`:
! Can't get Google credentials.
ℹ Try calling `bq_auth()` directly with necessary specifics.

原因分析与解决方案

核心原因

WIF生成的是外部账户凭证(External Account Credentials),而非传统的服务账户密钥文件:

  • gcloud CLI针对WIF做了专门适配,能自动识别这种凭证格式;
  • 旧版gargle/bigrquery可能对外部账户凭证支持不足,且credentials_service_account仅适用于传统服务账户密钥,无法处理WIF凭证。

具体解决方案

1. 更新依赖包到最新版

确保bigrquery和gargle是最新版本,以支持WIF外部账户凭证:

install.packages(c("bigrquery", "gargle"))
# 若需要最新特性,可安装开发版
# remotes::install_github("r-lib/gargle")
# remotes::install_github("r-dbi/bigrquery")

2. 正确使用外部账户凭证认证

明确使用gargle::credentials_external_account加载WIF凭证,并指定BigQuery所需的权限范围:

Rscript -e 'library(bigrquery); library(gargle); 
# 加载WIF外部账户凭证
token <- gargle::credentials_external_account(
  path = Sys.getenv("GOOGLE_APPLICATION_CREDENTIALS"),
  scopes = "https://www.googleapis.com/auth/bigquery"
); 
bq_auth(token = token); 
print(bq_project_datasets(Sys.getenv("GCP_PROJECT")))'

3. 验证环境变量与文件权限

  • 确认GOOGLE_APPLICATION_CREDENTIALS和GCP_PROJECT环境变量在容器内已正确传递;
  • 挂载的凭证文件已设置为可读(:ro参数已正确添加)。

4. 开启调试模式定位问题

若仍失败,开启gargle的调试模式查看详细日志:

Rscript -e 'library(gargle); gargle::gargle_debug_on(); 
library(bigrquery); 
token <- gargle::credentials_external_account(
  path = Sys.getenv("GOOGLE_APPLICATION_CREDENTIALS"),
  scopes = "https://www.googleapis.com/auth/bigquery"
); 
bq_auth(token = token); 
print(bq_project_datasets(Sys.getenv("GCP_PROJECT")))'

5. 替代方案:复用gcloud的访问令牌

利用gcloud已认证的状态,提取访问令牌直接给bigrquery使用:
修改Docker的sh -c脚本:

sh -c '
  gcloud auth login --cred-file=/gcp/creds.json
  gcloud config set project $GCP_PROJECT
  bq ls --project_id=$GCP_PROJECT --format=prettyjson

  # 获取gcloud的访问令牌
  ACCESS_TOKEN=$(gcloud auth print-access-token)
  # 传递令牌给R并认证
  Rscript -e "library(bigrquery); 
  bq_auth(token = Sys.getenv(\"ACCESS_TOKEN\")); 
  print(bq_project_datasets(Sys.getenv(\"GCP_PROJECT\")))"
'

同时在docker run命令中添加环境变量传递:-e ACCESS_TOKEN=$ACCESS_TOKEN


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 21:07:33