From 65be72ab99e8966b082483abf1f05294846d0519 Mon Sep 17 00:00:00 2001 From: Alex Martani Date: Thu, 11 May 2023 11:55:16 -0700 Subject: [PATCH 1/2] Add `expand-image-vars` option to allow image names to contain environment variables --- README.md | 8 ++++++++ hooks/command | 14 ++++++++++---- plugin.yml | 2 ++ tests/command.bats | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 53 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index af90a95..d80fdcf 100644 --- a/README.md +++ b/README.md @@ -129,6 +129,14 @@ Example: `node:7` ### Optional +### `expand-image-vars` (optional, boolean, unsafe) + +When set to true, it will activate interpolation of variables in the elements of the `image` configuration variable. When turned off (the default), attempting to use variables will fail as the literal `$VARIABLE_NAME` string will be passed as the image name. + +Environment variable interporation rules apply here. `$VARIABLE_NAME` is resolved at pipeline upload time, whereas `$$VARIABLE_NAME` is at run time. All things being equal, you likely want `$$VARIABLE_NAME`. + +:warning: **Important:** this is considered an unsafe option as the most compatible way to achieve this is to run the strings through `eval` which could lead to arbitrary code execution or information leaking if you don't have complete control of the pipeline + ### `add-host` (optional, array) Additional lines can be added to `/etc/hosts` in the container, in an array of mappings. See https://docs.docker.com/engine/reference/run/#managing-etchosts for more details. diff --git a/hooks/command b/hooks/command index 7211bf4..31b45e2 100755 --- a/hooks/command +++ b/hooks/command @@ -365,10 +365,16 @@ if [[ "${BUILDKITE_PLUGIN_DOCKER_PROPAGATE_AWS_AUTH_TOKENS:-false}" =~ ^(true|on fi fi +if [[ "${BUILDKITE_PLUGIN_DOCKER_EXPAND_IMAGE_VARS:-false}" =~ ^(true|on|1)$ ]] ; then + image=$(eval echo "${BUILDKITE_PLUGIN_DOCKER_IMAGE}") +else + image="${BUILDKITE_PLUGIN_DOCKER_IMAGE}" +fi + if [[ "${BUILDKITE_PLUGIN_DOCKER_ALWAYS_PULL:-false}" =~ ^(true|on|1)$ ]] ; then - echo "--- :docker: Pulling ${BUILDKITE_PLUGIN_DOCKER_IMAGE}" + echo "--- :docker: Pulling ${image}" if ! retry "${BUILDKITE_PLUGIN_DOCKER_PULL_RETRIES:-3}" \ - docker pull "${BUILDKITE_PLUGIN_DOCKER_IMAGE}" ; then + docker pull "${image}" ; then echo "!!! :docker: Pull failed." exit "$retry_exit_status" fi @@ -487,7 +493,7 @@ fi args+=("--label" "com.buildkite.job-id=${BUILDKITE_JOB_ID}") # Add the image in before the shell and command -args+=("${BUILDKITE_PLUGIN_DOCKER_IMAGE}") +args+=("${image}") # Set a default shell if one is needed if [[ -z $shell_disabled ]] && [[ ${#shell[@]} -eq 0 ]] ; then @@ -534,7 +540,7 @@ elif [[ ${#command[@]} -gt 0 ]] ; then done fi -echo "--- :docker: Running command in ${BUILDKITE_PLUGIN_DOCKER_IMAGE}" +echo "--- :docker: Running command in ${image}" echo -ne '\033[90m$\033[0m docker run ' >&2 # Print all the arguments, with a space after, properly shell quoted diff --git a/plugin.yml b/plugin.yml index 4571b0d..2ff6eaa 100644 --- a/plugin.yml +++ b/plugin.yml @@ -27,6 +27,8 @@ configuration: type: string image: type: string + expand-image-vars: + type: boolean ipc: type: string leave-container: diff --git a/tests/command.bats b/tests/command.bats index 49ef7d2..ae1c79e 100644 --- a/tests/command.bats +++ b/tests/command.bats @@ -1242,3 +1242,36 @@ EOF unstub docker } + +@test "Do not expand image vars by default" { + export BUILDKITE_PLUGIN_DOCKER_IMAGE='123456789012.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com/image:tag' + export AWS_DEFAULT_REGION="us-east-1" + export BUILDKITE_COMMAND="pwd" + + stub docker \ + "run -t -i --rm --init --volume $PWD:/workdir --workdir /workdir --label com.buildkite.job-id=1-2-3-4 123456789012.dkr.ecr.\$\{AWS_DEFAULT_REGION\}.amazonaws.com/image:tag /bin/sh -e -c 'pwd' : echo ran command in docker" + + run "$PWD"/hooks/command + + assert_success + assert_output --partial "ran command in docker" + + unstub docker +} + +@test "Expand image vars" { + export BUILDKITE_PLUGIN_DOCKER_EXPAND_IMAGE_VARS=true + export BUILDKITE_PLUGIN_DOCKER_IMAGE='123456789012.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com/image:tag' + export AWS_DEFAULT_REGION="us-east-1" + export BUILDKITE_COMMAND="pwd" + + stub docker \ + "run -t -i --rm --init --volume $PWD:/workdir --workdir /workdir --label com.buildkite.job-id=1-2-3-4 123456789012.dkr.ecr.us-east-1.amazonaws.com/image:tag /bin/sh -e -c 'pwd' : echo ran command in docker" + + run "$PWD"/hooks/command + + assert_success + assert_output --partial "ran command in docker" + + unstub docker +} From cbbc4f3dff7c7ce39dafb661ae1d444891eda419 Mon Sep 17 00:00:00 2001 From: Alex Martani Date: Sun, 28 May 2023 11:31:42 -0700 Subject: [PATCH 2/2] Move added documentation to alphabetical ordering --- README.md | 16 ++++++++-------- plugin.yml | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index d80fdcf..9a6d8a2 100644 --- a/README.md +++ b/README.md @@ -129,14 +129,6 @@ Example: `node:7` ### Optional -### `expand-image-vars` (optional, boolean, unsafe) - -When set to true, it will activate interpolation of variables in the elements of the `image` configuration variable. When turned off (the default), attempting to use variables will fail as the literal `$VARIABLE_NAME` string will be passed as the image name. - -Environment variable interporation rules apply here. `$VARIABLE_NAME` is resolved at pipeline upload time, whereas `$$VARIABLE_NAME` is at run time. All things being equal, you likely want `$$VARIABLE_NAME`. - -:warning: **Important:** this is considered an unsafe option as the most compatible way to achieve this is to run the strings through `eval` which could lead to arbitrary code execution or information leaking if you don't have complete control of the pipeline - ### `add-host` (optional, array) Additional lines can be added to `/etc/hosts` in the container, in an array of mappings. See https://docs.docker.com/engine/reference/run/#managing-etchosts for more details. @@ -189,6 +181,14 @@ An array of additional files to pass into to the docker container as environment If you set this to `VALUE`, and `VALUE` is an environment variable containing a space-separated list of environment variables such as `A B C D`, then A, B, C, and D will all be propagated to the container. This is helpful when you've set up an `environment` hook to export secrets as environment variables, and you'd also like to programmatically ensure that secrets get propagated to containers, instead of listing them all out. +### `expand-image-vars` (optional, boolean, unsafe) + +When set to true, it will activate interpolation of variables in the elements of the `image` configuration variable. When turned off (the default), attempting to use variables will fail as the literal `$VARIABLE_NAME` string will be passed as the image name. + +Environment variable interporation rules apply here. `$VARIABLE_NAME` is resolved at pipeline upload time, whereas `$$VARIABLE_NAME` is at run time. All things being equal, you likely want `$$VARIABLE_NAME`. + +:warning: **Important:** this is considered an unsafe option as the most compatible way to achieve this is to run the strings through `eval` which could lead to arbitrary code execution or information leaking if you don't have complete control of the pipeline + ### `propagate-environment` (optional, boolean) Whether or not to automatically propagate all* pipeline environment variables into the docker container. Avoiding the need to be specified with `environment`. diff --git a/plugin.yml b/plugin.yml index 2ff6eaa..2e14f93 100644 --- a/plugin.yml +++ b/plugin.yml @@ -25,10 +25,10 @@ configuration: type: array env-propagation-list: type: string - image: - type: string expand-image-vars: type: boolean + image: + type: string ipc: type: string leave-container: