Skip to content

How to access a Google Secret Manager secret using service account impersonation

This guide shows you how to access a Google Secret Manager secret from a CI job running on a GKE-hosted runner. It covers creating a service account and assigning the required IAM bindings using Terraform, as well as how to access the secret using service account impersonation from the CI job itself.

Prerequisites

  • This how-to assumes that you have already created a Google Secret Manager secret in the relevant Google Project that you wish to access. In this example the secret ID is referred to as <existing secret ID>.

Steps

  1. Create a dedicated Google IAM service account for this task. For example:

    resource "google_service_account" "secret_accessor" {
        account_id   = "secret_accessor"
        display_name = "Secret Accessor"
    }
    
  2. Grant the new Google IAM service account the ability to access the required Google Secret Manager secret by assigning it the secretmanager.secretAccessor role as follows.

    resource "google_secret_manager_secret_iam_member" "secret_accessor" {
      secret_id = "<existing secret ID>"
      role = "roles/secretmanager.secretAccessor"
      member = "serviceAccount:${resource.google_service_account.secret_accessor.email}"
    }
    
  3. Grant the gke-ci-run Kubernetes service account the ability to impersonate the new Google IAM service account using the Workload Identity namespace.

    resource "google_service_account_iam_member" "secret_accessor_impersonation" {
      service_account_id = google_service_account.secret_accessor.name
      role               = "roles/iam.serviceAccountTokenCreator"
      member             = "serviceAccount:gitlab-runner-prod-22257483.svc.id.goog[<product runner namespace>/gke-ci-run]"
    }
    
  4. Access the secret in a CI job using the following command in the script definition for the job.

```yaml
job1:
  image: registry.gitlab.developers.cam.ac.uk/uis/devops/infra/dockerimages/gcloud-docker:latest
  script: |
    my_secret=$(gcloud --impersonate-service-account=secret_accessor@<project id>.iam.gserviceaccount.com \
      --project <project id> secrets versions access latest --secret=<existing secret id>)
  tags:
    - $GKE_RUNNER_TAG
```

GitLab Project Factory Configuration

For gitlab-project-factory projects this is simplified greatly, the project factory provides a service account to access secrets, and a group level gitlab access token that will be stored in the secret manager.

These are then made available as pre-defined CI/CD variables, and can be accessed by jobs running GKE runners.

To access the general purpose gitlab access token:

```yaml
job1:
  image: registry.gitlab.developers.cam.ac.uk/uis/devops/infra/dockerimages/gcloud-docker:latest
  script: |
    my_secret=$(gcloud --impersonate-service-account=${GITLAB_TOKEN_ACCESSOR_SERVICE_ACCOUNT} \
      --project <project id> secrets versions access \
      ${GITLAB_ACCESS_TOKEN_SECRET_ID}/versions/latest)
  tags:
    - $GKE_RUNNER_TAG
```

Note that the GITLAB_ACCESS_TOKEN_SECRET_ID is the fully qualified resource id, so the version must be accessed using the full resource URI as described above.

Summary

In this guide you've learnt how to create a dedicated Google IAM service account with permission to access an existing secret. You've also learnt how to use Workload Identity to grant a product's gke-ci-run Kubernetes service account the ability to impersonate the new Google IAM service account to retrieve the secret value from a CI job script.

See also