GitLab CI/CD通过工作负载身份联合连接GCP失败排查
我尝试通过GitLab CI/CD运行Terraform部署GCP资源,采用Workload Identity Federation和ID Tokens(CI_JOB_JWT_V2已弃用),当前GitLab CI/CD配置如下:
gcp-auth: stage: prepare image: google/cloud-sdk:slim id_tokens: GCP_TOKEN: aud: //iam.googleapis.com/projects/MyProjectID/locations/global/workloadIdentityPools/MyPoolID/providers/MyProvider script: - echo ${GCP_TOKEN} > .ci_job_jwt_file - gcloud iam workload-identity-pools create-cred-config "${GCP_WORKLOAD_IDENTITY_PROVIDER}" --service-account="${GCP_SERVICE_ACCOUNT}" --output-file=.gcp_temp_cred.json --credential-source-file=.ci_job_jwt_file - gcloud config set project ${GOOGLE_PROJECT} - gcloud auth login --cred-file=`pwd`/.gcp_temp_cred.json - gcloud storage buckets list
运行流水线时,gcloud storage buckets list命令报错:
ERROR: (gcloud.storage.buckets.list) There was a problem refreshing
your current auth tokens: ('Error code invalid_request: Invalid value
for "audience". This value should be the full resource name of the
Identity Provider. See
https://cloud.google.com/iam/docs/reference/sts/rest/v1/TopLevel/token
for the list of possible formats.',
'{"error":"invalid_request","error_description":"Invalid value for
"audience". This value should be the full resource name of the
Identity Provider. See
https://cloud.google.com/iam/docs/reference/sts/rest/v1/TopLevel/token
for the list of possible formats."}')
生成的.gcp_temp_cred.json内容如下:
{ "type": "external_account", "audience": "//iam.googleapis.com/gitlab-gitlab", "subject_token_type": "urn:ietf:params:oauth:token-type:jwt", "token_url": "https://sts.googleapis.com/v1/token", "credential_source": { "file": ".ci_job_jwt_file" }, "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/MyServiceAccountEmail:generateAccessToken" }
从错误信息和生成的配置文件来看,audience值存在明显问题,需要修正配置。
错误分析
- GitLab ID Token的aud参数未正确生效:生成的JWT中的audience被错误设置为
//iam.googleapis.com/gitlab-gitlab,而非指定的完整资源名称,说明id_tokens配置未正确传递aud值,或GCP_WORKLOAD_IDENTITY_PROVIDER变量取值错误。 - 手动写入JWT文件的冗余操作:将
GCP_TOKEN写入文件容易引入路径、权限问题,且gcloud命令支持直接读取环境变量中的Token,无需额外步骤。
解决步骤
1. 修正核心配置参数
- 确保
id_tokens中的aud值与GCP工作负载身份池提供者的完整资源名称完全一致,格式为://iam.googleapis.com/projects/[你的项目ID]/locations/global/workloadIdentityPools/[你的池ID]/providers/[你的提供者ID] - 检查
GCP_WORKLOAD_IDENTITY_PROVIDER变量取值,它应该是不带//iam.googleapis.com/前缀的资源名称,即:projects/[你的项目ID]/locations/global/workloadIdentityPools/[你的池ID]/providers/[你的提供者ID]
2. 简化认证流程(推荐)
使用--credential-source-env参数直接读取环境变量中的GCP_TOKEN,避免手动写入文件的操作,修正后的CI配置如下:
gcp-auth: stage: prepare image: google/cloud-sdk:slim id_tokens: GCP_TOKEN: aud: "//iam.googleapis.com/projects/MyProjectID/locations/global/workloadIdentityPools/MyPoolID/providers/MyProvider" script: # 直接从环境变量读取ID Token,无需写入文件 - gcloud iam workload-identity-pools create-cred-config "${GCP_WORKLOAD_IDENTITY_PROVIDER}" --service-account="${GCP_SERVICE_ACCOUNT}" --output-file=.gcp_temp_cred.json --credential-source-env="GCP_TOKEN" - gcloud config set project ${GOOGLE_PROJECT} - gcloud auth login --cred-file=.gcp_temp_cred.json - gcloud storage buckets list
3. 验证配置正确性
- 在GCP控制台的IAM -> 工作负载身份池页面,复制提供者的完整资源名称,确认与配置中的aud值一致。
- 检查GitLab CI变量
GCP_WORKLOAD_IDENTITY_PROVIDER、GCP_SERVICE_ACCOUNT、GOOGLE_PROJECT是否正确设置,且服务账户已绑定工作负载身份池的相关角色。
内容的提问来源于stack exchange,提问作者Jonas Laux

