From 86f1a0a8a0838470d2ec16744d0ba965e94818ed Mon Sep 17 00:00:00 2001 From: Rudi Floren Date: Tue, 28 Jan 2025 19:02:30 +0100 Subject: [PATCH 1/7] feat: add support for GCP token propagation --- README.md | 6 ++++++ commands/run.sh | 17 +++++++++++++++++ plugin.yml | 2 ++ tests/run.bats | 26 ++++++++++++++++++++++++++ 4 files changed, 51 insertions(+) diff --git a/README.md b/README.md index 6e54b2a2..a06b6494 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,12 @@ Will propagate `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_SESSION_TOKEN` When the `AWS_WEB_IDENTITY_TOKEN_FILE` is specified, it will also mount it automatically for you and make it usable within the container. +#### `propagate-gcp-auth-tokens` (run only, boolean) + +Whether or not to automatically propagate gcp auth credentials into the docker container. Avoiding the need to be specified with `environment`. This is useful if you are using a workload identity federation to impersonate a service account and you want to pass it to the docker container. This is compatible with the `gcp-workload-identity-federation` plugin. + +Will propagate `GOOGLE_APPLICATION_CREDENTIALS`, `CLOUDSDK_AUTH_CREDENTIAL_FILE_OVERRIDE` and `BUILDKITE_OIDC_TMPDIR` and also mount the dir specified by `BUILDKITE_OIDC_TMPDIR` into the container. + #### `command` (run only, array) Sets the command for the Docker image, and defaults the `shell` option to `false`. Useful if the Docker image has an entrypoint, or doesn't contain a shell. diff --git a/commands/run.sh b/commands/run.sh index b3de229b..3e58e756 100755 --- a/commands/run.sh +++ b/commands/run.sh @@ -164,6 +164,23 @@ if [[ "$(plugin_read_config PROPAGATE_AWS_AUTH_TOKENS "false")" =~ ^(true|on|1)$ fi fi +# Propagate gcp auth environment variables into the container e.g. from workload identity federation plugins +if [[ "$(plugin_read_config PROPAGATE_GCP_AUTH_TOKENS "false")" =~ ^(true|on|1)$ ]] ; then + if [[ -n "${GOOGLE_APPLICATION_CREDENTIALS:-}" ]] ; then + run_params+=( --env "GOOGLE_APPLICATION_CREDENTIALS" ) + fi + if [[ -n "${CLOUDSDK_AUTH_CREDENTIAL_FILE_OVERRIDE:-}" ]] ; then + run_params+=( --env "CLOUDSDK_AUTH_CREDENTIAL_FILE_OVERRIDE" ) + fi + if [[ -n "${BUILDKITE_OIDC_TMPDIR:-}" ]] ; then + run_params+=( --env "BUILDKITE_OIDC_TMPDIR" ) + # Add the OIDC temp dir as a volume + run_params+=( --volume "${BUILDKITE_OIDC_TMPDIR}:${BUILDKITE_OIDC_TMPDIR}" ) + fi +fi + + + # If requested, propagate a set of env vars as listed in a given env var to the # container. if [[ -n "$(plugin_read_config ENV_PROPAGATION_LIST)" ]]; then diff --git a/plugin.yml b/plugin.yml index a2e8dcf6..352fa078 100755 --- a/plugin.yml +++ b/plugin.yml @@ -115,6 +115,8 @@ configuration: progress: type: string enum: [ "auto", "tty", "plain", "json", "quiet" ] + propagate-gcp-auth-tokens: + type: boolean propagate-environment: type: boolean propagate-uid-gid: diff --git a/tests/run.bats b/tests/run.bats index 9453dec1..3e971a18 100644 --- a/tests/run.bats +++ b/tests/run.bats @@ -1340,3 +1340,29 @@ cmd3" unstub docker } + +@test "Run with propagate gcp auth tokens" { + export BUILDKITE_PLUGIN_DOCKER_COMPOSE_RUN=myservice + export BUILDKITE_PLUGIN_DOCKER_COMPOSE_CHECK_LINKED_CONTAINERS=false + export BUILDKITE_PLUGIN_DOCKER_COMPOSE_CLEANUP=false + export BUILDKITE_COMMAND="echo hello world" + export BUILDKITE_PLUGIN_DOCKER_COMPOSE_PROPAGATE_GCP_AUTH_TOKENS=true + + export BUILDKITE_OIDC_TMPDIR="/tmp/.tmp.Xdasd23" + export GOOGLE_APPLICATION_CREDENTIALS="${BUILDKITE_OIDC_TMPDIR}/credentials.json" + export CLOUDSDK_AUTH_CREDENTIAL_FILE_OVERRIDE="${GOOGLE_APPLICATION_CREDENTIALS}" + + stub docker \ + "compose -f docker-compose.yml -p buildkite1111 up -d --scale myservice=0 myservice : echo ran myservice dependencies" \ + "compose -f docker-compose.yml -p buildkite1111 run --name buildkite1111_myservice_build_1 --env GOOGLE_APPLICATION_CREDENTIALS --env CLOUDSDK_AUTH_CREDENTIAL_FILE_OVERRIDE --env BUILDKITE_OIDC_TMPDIR --volume \"/tmp/.tmp.Xdasd23:/tmp/.tmp.Xdasd23\" -T --rm myservice /bin/sh -e -c 'echo hello world' : echo ran myservice" + + stub buildkite-agent \ + "meta-data exists docker-compose-plugin-built-image-tag-myservice : exit 1" + + run "$PWD"/hooks/command + + assert_success + assert_output --partial "ran myservice" + unstub docker + unstub buildkite-agent +} From 64048c0e8293d993cf6a133424b2301a74b27197 Mon Sep 17 00:00:00 2001 From: Rudi Floren Date: Tue, 28 Jan 2025 19:02:55 +0100 Subject: [PATCH 2/7] fix: add missing propagate-gcp-auth-tokens entry to plugin.yml --- plugin.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugin.yml b/plugin.yml index 352fa078..c4c57703 100755 --- a/plugin.yml +++ b/plugin.yml @@ -115,6 +115,8 @@ configuration: progress: type: string enum: [ "auto", "tty", "plain", "json", "quiet" ] + propagate-aws-auth-tokens: + type: boolean propagate-gcp-auth-tokens: type: boolean propagate-environment: From f12a26272806433abce64ec3fdc770c39a38b27a Mon Sep 17 00:00:00 2001 From: Rudi Floren Date: Wed, 29 Jan 2025 14:05:40 +0100 Subject: [PATCH 3/7] chore: update plugin versions in examples --- docs/examples.md | 53 ++++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/docs/examples.md b/docs/examples.md index bf92218d..8a6a5151 100644 --- a/docs/examples.md +++ b/docs/examples.md @@ -10,7 +10,7 @@ The following pipeline will run `test.sh` inside a `app` service container using steps: - command: test.sh plugins: - - docker-compose#v5.5.0: + - docker-compose#v5.7.0: run: app ``` @@ -19,7 +19,7 @@ steps: ```yml steps: - plugins: - - docker-compose#v5.5.0: + - docker-compose#v5.7.0: run: app command: ["custom", "command", "values"] ``` @@ -30,7 +30,7 @@ The plugin will honor the value of the `COMPOSE_FILE` environment variable if on steps: - command: test.sh plugins: - - docker-compose#v5.5.0: + - docker-compose#v5.7.0: run: app config: docker-compose.tests.yml env: @@ -46,7 +46,7 @@ steps: - plugins: - docker-login#v2.0.1: username: xyz - - docker-compose#v5.5.0: + - docker-compose#v5.7.0: build: app push: app:index.docker.io/myorg/myrepo:tag - wait @@ -54,7 +54,7 @@ steps: plugins: - docker-login#v2.0.1: username: xyz - - docker-compose#v5.5.0: + - docker-compose#v5.7.0: run: app ``` @@ -71,7 +71,7 @@ steps: - command: generate-dist.sh artifact_paths: "dist/*" plugins: - - docker-compose#v5.5.0: + - docker-compose#v5.7.0: run: app volumes: - "./dist:/folder/dist" @@ -95,7 +95,7 @@ this plugin offers a `environment` block of its own: steps: - command: generate-dist.sh plugins: - - docker-compose#v5.5.0: + - docker-compose#v5.7.0: run: app env: - BUILDKITE_BUILD_NUMBER @@ -113,7 +113,7 @@ Alternatively, you can have the plugin add all environment variables defined for steps: - command: use-vars.sh plugins: - - docker-compose#v5.5.0: + - docker-compose#v5.7.0: run: app propagate-environment: true ``` @@ -129,7 +129,7 @@ steps: env: COMPOSE_PROFILES: "frontend,debug" plugins: - - docker-compose#v5.5.0: + - docker-compose#v5.7.0: run: app ``` @@ -138,6 +138,7 @@ It is important to understand that, as documented in the official documentation, ### Container Labels When running a command, the plugin will automatically add the following Docker labels to the container specified in the `run` option: + - `com.buildkite.pipeline_name=${BUILDKITE_PIPELINE_NAME}` - `com.buildkite.pipeline_slug=${BUILDKITE_PIPELINE_SLUG}` - `com.buildkite.build_number=${BUILDKITE_BUILD_NUMBER}` @@ -165,7 +166,7 @@ Alternatively, if you want to set build arguments when pre-building an image, th steps: - command: generate-dist.sh plugins: - - docker-compose#v5.5.0: + - docker-compose#v5.7.0: build: app args: - MY_CUSTOM_ARG=panda @@ -182,7 +183,7 @@ If you have multiple steps that use the same service/image (such as steps that r steps: - label: ":docker: Build" plugins: - - docker-compose#v5.5.0: + - docker-compose#v5.7.0: build: app push: app @@ -192,7 +193,7 @@ steps: command: test.sh parallelism: 25 plugins: - - docker-compose#v5.5.0: + - docker-compose#v5.7.0: run: app require-prebuild: true ``` @@ -211,7 +212,7 @@ steps: agents: queue: docker-builder plugins: - - docker-compose#v5.5.0: + - docker-compose#v5.7.0: build: - app - tests @@ -225,7 +226,7 @@ steps: command: test.sh parallelism: 25 plugins: - - docker-compose#v5.5.0: + - docker-compose#v5.7.0: run: tests ``` @@ -237,7 +238,7 @@ If you want to push your Docker images ready for deployment, you can use the `pu steps: - label: ":docker: Push" plugins: - - docker-compose#v5.5.0: + - docker-compose#v5.7.0: push: app ``` @@ -247,7 +248,7 @@ To push multiple images, you can use a list: steps: - label: ":docker: Push" plugins: - - docker-compose#v5.5.0: + - docker-compose#v5.7.0: push: - first-service - second-service @@ -259,7 +260,7 @@ If you want to push to a specific location (that's not defined as the `image` in steps: - label: ":docker: Push" plugins: - - docker-compose#v5.5.0: + - docker-compose#v5.7.0: push: - app:index.docker.io/myorg/myrepo/myapp - app:index.docker.io/myorg/myrepo/myapp:latest @@ -273,7 +274,7 @@ A newly spawned agent won't contain any of the docker caches for the first run w steps: - label: ":docker: Build an image" plugins: - - docker-compose#v5.5.0: + - docker-compose#v5.7.0: build: app push: app:index.docker.io/myorg/myrepo:my-branch cache-from: @@ -284,7 +285,7 @@ steps: - label: ":docker: Push to final repository" plugins: - - docker-compose#v5.5.0: + - docker-compose#v5.7.0: push: - app:myregistry:port/myrepo/myapp:latest ``` @@ -297,7 +298,7 @@ The values you add in the `cache-from` will be mapped to the corresponding servi steps: - label: ":docker: Build an image" plugins: - - docker-compose#v5.5.0: + - docker-compose#v5.7.0: build: app push: app:index.docker.io/myorg/myrepo:my-branch cache-from: @@ -308,7 +309,7 @@ steps: - label: ":docker: Push to final repository" plugins: - - docker-compose#v5.5.0: + - docker-compose#v5.7.0: push: - app:myregistry:port/myrepo/myapp:latest ``` @@ -325,7 +326,7 @@ The `docker` driver can handle most situations but for advance features with the steps: - label: ":docker: Build an image" plugins: - - docker-compose#v5.5.0: + - docker-compose#v5.7.0: build: app push: app:index.docker.io/myorg/myrepo:my-branch cache-from: @@ -347,7 +348,7 @@ By default, Builder Instances specified by `name` or that are created with `crea steps: - label: ":docker: Build an image" plugins: - - docker-compose#v5.5.0: + - docker-compose#v5.7.0: build: app push: app:index.docker.io/myorg/myrepo:my-branch cache-from: @@ -366,7 +367,7 @@ By default, Builder Instances specified by `name` or that are created with `crea steps: - label: ":docker: Build an image" plugins: - - docker-compose#v5.5.0: + - docker-compose#v5.7.0: build: app push: app:index.docker.io/myorg/myrepo:my-branch cache-from: @@ -392,7 +393,7 @@ A newly spawned agent won't contain any of the docker caches for the first run w steps: - label: ":docker: Build an image and push cache" plugins: - - docker-compose#v5.5.0: + - docker-compose#v5.7.0: build: app push: app:${DOCKER_REGISTRY}/${IMAGE_REPO}:cache cache-from: @@ -409,7 +410,7 @@ steps: - label: ":docker: Build an image using remote cache" plugins: - - docker-compose#v5.5.0: + - docker-compose#v5.7.0: build: app cache-from: - "app:type=registry,ref=${DOCKER_REGISTRY}/${IMAGE_REPO}:cache" From 0538e28c25f94c4f9379b1c63ac4186ba2958ad5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Jendrysik?= Date: Mon, 17 Mar 2025 16:56:00 +0100 Subject: [PATCH 4/7] =?UTF-8?q?Clarify=20upgrade=20path=20to=20v5=20?= =?UTF-8?q?=E2=80=94=20image-repository=20and=20image-name=20attrs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/upgrading-to-v5.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/upgrading-to-v5.md b/docs/upgrading-to-v5.md index 3857d17b..1da6c722 100644 --- a/docs/upgrading-to-v5.md +++ b/docs/upgrading-to-v5.md @@ -54,6 +54,17 @@ You need to: * delete these options * add a `push` or `run` on the very same step +Example change: +```diff +- - docker-compose#v4.16.0: ++ - docker-compose#v5.0.0: + build: base +- image-name: image-name-build_id +- image-repository: image-repo-host/builds + push: ++ - image-repo-host/builds:image-name-build_id +``` + ## `cli-version` If you were using this option to ensure that `docker compose` was used, you should be able to remove it safely. On the other hand, if your build environment only has the old v1 CLI interface (`docker-compose`), you will need to make some changes. From a2fbf6c6b0a8e2de0c9130681e28556ea2c39aea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Jendrysik?= Date: Wed, 19 Mar 2025 15:09:19 +0100 Subject: [PATCH 5/7] add note on expected format --- docs/upgrading-to-v5.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/upgrading-to-v5.md b/docs/upgrading-to-v5.md index 1da6c722..9b96ddcf 100644 --- a/docs/upgrading-to-v5.md +++ b/docs/upgrading-to-v5.md @@ -44,7 +44,7 @@ The plugin should print out the override file used in the step's logs for you to As per the documentation, the images you want to use as cache must have been built with the `BUILDKIT_INLINE_CACHE=1` build argument. Otherwise, the manifest used by docker to determine if the image contains layers that could be useful to pull will not be present and will not be used. -Note that docker silently ignores any `cache-from` configuration that is not valid or can not be used. +Note that docker silently ignores any `cache-from` configuration that is not valid or can not be used. ## `image-repository` and/or `image-name` @@ -53,6 +53,8 @@ These options were used to push images in `build` steps. You need to: * delete these options * add a `push` or `run` on the very same step +* combine them into a single entry in the format `repository:tag` + Example change: ```diff @@ -77,4 +79,4 @@ Alternatively, you can add the same variable definition to your pipeline as a gl ## `collapse-run-log-groups` -Just rename the option to `collapse-logs` \ No newline at end of file +Just rename the option to `collapse-logs` From dcc2720e465769877de7776213c6077559f203b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Jendrysik?= Date: Thu, 20 Mar 2025 12:10:36 +0100 Subject: [PATCH 6/7] doc: correct push format Fix example while upgrading to v5, following the expected format on `push`. --- docs/upgrading-to-v5.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/upgrading-to-v5.md b/docs/upgrading-to-v5.md index 9b96ddcf..e405bc4e 100644 --- a/docs/upgrading-to-v5.md +++ b/docs/upgrading-to-v5.md @@ -53,7 +53,7 @@ These options were used to push images in `build` steps. You need to: * delete these options * add a `push` or `run` on the very same step -* combine them into a single entry in the format `repository:tag` +* combine them into a single entry in the format `service:repository:tag` Example change: @@ -64,7 +64,7 @@ Example change: - image-name: image-name-build_id - image-repository: image-repo-host/builds push: -+ - image-repo-host/builds:image-name-build_id ++ - base:image-repo-host/builds:image-name-build_id ``` ## `cli-version` From 65cec7656063245264daafa4ebe4f386c25e9ed7 Mon Sep 17 00:00:00 2001 From: Jim Barber Date: Thu, 10 Apr 2025 16:54:53 +0800 Subject: [PATCH 7/7] Fix argument passing The builder.docker-opts and builder.platform arguments didn't work. The switch and its values were added to the builder_instance_args array as a single element, but the switch should be one element and its values the another. Otherwise it produces an invalid parameter when passed to the docker commands and errors are thrown. --- hooks/pre-command | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hooks/pre-command b/hooks/pre-command index c7b36905..9bd43ab7 100755 --- a/hooks/pre-command +++ b/hooks/pre-command @@ -41,12 +41,12 @@ if [[ "${builder_create}" == "true" ]]; then driver_opt="$(plugin_read_config BUILDER_DRIVER_OPT "")" if [[ -n "${driver_opt}" ]]; then - builder_instance_args+=("--driver-opt ${driver_opt}") + builder_instance_args+=("--driver-opt" "${driver_opt}") fi builder_platform="$(plugin_read_config BUILDER_PLATFORM "")" if [[ -n "${builder_platform}" ]]; then - builder_instance_args+=("--platform ${builder_platform}") + builder_instance_args+=("--platform" "${builder_platform}") fi remote_address="$(plugin_read_config BUILDER_REMOTE_ADDRESS "")"