A Buildkite plugin to assume a Google Cloud service account using workload identity federation.
The plugin requests an OIDC token from Buildkite and uses it to a populate Google Cloud credentials file assuming you have followed the corresponding setup on Google cloud.
The path to the file is populated in GOOGLE_APPLICATION_CREDENTIALS
for SDKs that use Application Default Credentials, and in CLOUDSDK_AUTH_CREDENTIAL_FILE_OVERRIDE
for the gcloud
CLI.
- The default audience as shown on the Workload Identity Federation Provider page, without the
https:
prefix, or a custom audience that you configure.
- The service account for which you want to acquire an access token.
- The time (in seconds) the OIDC token will be valid for before expiry. Must be a non-negative integer. If the flag is omitted or set to 0, the API will choose a default finite lifetime. (default: 0)
- An installed binary that when specified, will run twice to process the values of
audience
andservice-account
via stdin. This is intended to be used to render environment variables with an application such asenvsubst
. (default: '')
- A list of claims to add to the requested buildkite oidc token. The agent currently supports requesting claims for
organization_id
andpipeline_id
. If requested, these will include the respective buildkite organization and/or pipeline UUID claims in the token. (default: [])
Add the following to your pipeline.yml
:
steps:
- command: |
echo "Credentials are located at \$GOOGLE_APPLICATION_CREDENTIALS"
plugins:
- gcp-workload-identity-federation#v1.4.0:
audience: "//iam.googleapis.com/projects/123456789/locations/global/workloadIdentityPools/buildkite-example-pipeline/providers/buildkite"
service-account: "buildkite-example-pipeline@oidc-project.iam.gserviceaccount.com"
For the token to be available in the container(s) run by docker when using those plugins in the same step as this one, you will need to make sure to share the following with the containers:
- the volume
$BUILDKITE_OIDC_TMPDIR
- the following environment variables:
BUILDKITE_OIDC_TMPDIR
CLOUDSDK_AUTH_CREDENTIAL_FILE_OVERRIDE
(if usinggcloud
)GOOGLE_APPLICATION_CREDENTIALS
(if using any other gcp lib)
For example:
steps:
- command: |
echo "Credentials are located at \$GOOGLE_APPLICATION_CREDENTIALS or \$CLOUDSDK_AUTH_CREDENTIAL_FILE_OVERRIDE"
plugins:
- gcp-workload-identity-federation#v1.4.0:
audience: "//iam.googleapis.com/projects/123456789/locations/global/workloadIdentityPools/buildkite-example-pipeline/providers/buildkite"
service-account: "buildkite-example-pipeline@oidc-project.iam.gserviceaccount.com"
- docker#v5.9.0:
image: <IMAGE>
expand-volume-vars: true
volumes:
- \$BUILDKITE_OIDC_TMPDIR:/\$BUILDKITE_OIDC_TMPDIR
environment:
- BUILDKITE_OIDC_TMPDIR
- CLOUDSDK_AUTH_CREDENTIAL_FILE_OVERRIDE # if using 'gcloud'
- GOOGLE_APPLICATION_CREDENTIALS # if using literally any other gcp lib
You should already have a Google Cloud project and a Service Account to assume. See Google's documentation for more detailed instructions for these steps.
-
Create a Workload Identity Pool.
We recommend creating a different pool for each security boundary.
In this example we're using
buildkite-example-pipeline
. -
Add a provider to the pool.
Use OpenID Connect, and give it a name like
buildkite
.Use
https://agent.buildkite.com
as the Issuer.Copy the value of the default audience or provide your own.
-
Configure provider attributes.
Because Google limits the length of attributes to 127 characters, we suggest the following mapping:
Google OIDC google.subject
"organization:" + assertion.sub.split(":")[1] + ":pipeline:" + assertion.sub.split(":")[3]
attribute.pipeline_slug
assertion.pipeline_slug
attribute.build_branch
assertion.build_branch
With this mapping you can use a CEL expression to restrict which pipelines can assume the service account:
google.subject == "organization:acme:pipeline:buildkite-example-pipeline"
-
Grant access to the service account.
-
Configure this plugin using the workload provider audience without the leading
https:
, and the service account email address.
Add the following to your pipeline.yml
:
steps:
- command: |
echo "Credentials are located at \$GOOGLE_APPLICATION_CREDENTIALS"
plugins:
- gcp-workload-identity-federation#v1.4.0:
audience: "//iam.googleapis.com/projects/123456789/locations/global/workloadIdentityPools/buildkite-example-pipeline/providers/buildkite"
service-account: "buildkite-example-pipeline@oidc-project.iam.gserviceaccount.com"
To run testing, shellchecks and plugin linting use use bk run
with the Buildkite CLI.
bk run
Or if you want to run just the tests, you can use the docker Plugin Tester:
docker run --rm -ti -v "${PWD}":/plugin buildkite/plugin-tester:latest
- Fork the repo
- Make the changes
- Run the tests
- Commit and push your changes
- Send a pull request