Search code examples
authenticationgoogle-cloud-platformgitlabcicd

GitLab CI/CD fails to connect with GCP using Workload Identity Federation and ID Tokens


I am trying to run Terraform from GitLab CI/CD to deploy assets in GCP and would like to use Workload Identity Federations and ID Tokens (since CI_JOB_JWT_V2 is deprecated). My current GitLab CI/CD code is as follows:

 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

However, when running the pipeline, the last "Bucket List" command crashes with the following error:

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."}')

The .gcp_temp_cred.json looks like this:

{
  "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"
}

It seems there is an issue with the "audience" value for the ID Token configuration. Can anyone help me identify what's wrong with my configuration and how to resolve this issue?


Solution

  • First, make sure your ID token is set like this:

    id_tokens:
      GITLAB_TOKEN:
        aud: https://gitlab.domain.com #the same audience you've set in GCP
    

    Next make sure the GCP_WORKLOAD_IDENTITY_PROVIDER variable is set like this:

    projects/<project-number>/locations/global/workloadIdentityPools/<your-pool>/providers/<your-provider>
    

    Please note that you need to use the project number and NOT the project ID.

    Fully working code:

    image: google/cloud-sdk:slim
    id_tokens:
      GITLAB_TOKEN:
        aud: https://gitlab.mydomain.com
    variables:
      GCP_WORKLOAD_IDENTITY_PROVIDER: projects/897387698213/locations/global/workloadIdentityPools/gitlab-pool/providers/gitlab
      SERVICE_ACCOUNT_EMAIL: wif-gitlab@my-mega-project.iam.gserviceaccount.com
    before_script:
      - echo ${GITLAB_TOKEN} > ${CI_PROJECT_DIR}/.ci_job_jwt_file
      - gcloud iam workload-identity-pools create-cred-config ${GCP_WORKLOAD_IDENTITY_PROVIDER}
        --service-account="${SERVICE_ACCOUNT_EMAIL}"
        --output-file=${CI_PROJECT_DIR}/.gcp_temp_cred.json
        --credential-source-file=${CI_PROJECT_DIR}/.ci_job_jwt_file
      - gcloud auth login --cred-file=${CI_PROJECT_DIR}/.gcp_temp_cred.json
      - gcloud auth list
      - gcloud compute instances list --project=my-mega-project