Skip to content

Commit d6b861c

Browse files
committed
Add secrets support
Signed-off-by: Jason Dictos <jdictos@een.com>
1 parent c87d1c0 commit d6b861c

File tree

3 files changed

+75
-1
lines changed

3 files changed

+75
-1
lines changed

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,22 @@ version is the image's digest.
208208
{ "EMAIL": "me@yopmail.com", "HOW_MANY_THINGS": 1, "DO_THING": false }
209209
```
210210

211+
* `secrets`: *Optional.* A map of Docker build-time secrets. These will be
212+
available as mounted paths only during the docker build phase.
213+
214+
Secrets are not stored in any metadata or layers, so they are safe to use for
215+
access tokens and the like during the build.
216+
217+
Example:
218+
219+
```yaml
220+
secrets:
221+
secret1:
222+
env: BUILD_ID
223+
secret2:
224+
source: /a/secret/file.txt
225+
```
226+
211227
* `cache`: *Optional.* Default `false`. When the `build` parameter is set,
212228
first pull `image:tag` from the Docker registry (so as to use cached
213229
intermediate images when building). This will cause the resource to fail

assets/out

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ tag_prefix=$(jq -r '.params.tag_prefix // ""' < $payload)
7878
additional_tags=$(jq -r '.params.additional_tags // ""' < $payload)
7979
need_tag_as_latest=$(jq -r '.params.tag_as_latest // "false"' < $payload)
8080
build_args=$(jq -r '.params.build_args // {}' < $payload)
81+
secrets=$(jq -r '.params.secrets // {}' < $payload)
8182
build_args_file=$(jq -r '.params.build_args_file // ""' < $payload)
8283
labels=$(jq -r '.params.labels // {}' < $payload)
8384
labels_file=$(jq -r '.params.labels_file // ""' < $payload)
@@ -215,6 +216,32 @@ elif [ -n "$build" ]; then
215216
fi
216217
fi
217218

219+
expanded_secrets=()
220+
221+
secret_keys=($(echo "$secrets" | jq -r 'keys | join(" ")'))
222+
if [ "${#secret_keys[@]}" -gt 0 ]; then
223+
# Force buildkit on
224+
export DOCKER_BUILDKIT=1
225+
for key in "${secret_keys[@]}"; do
226+
value=$(echo "$secrets" | jq -r --arg "k" "$key" '.[$k]')
227+
for var in BUILD_ID BUILD_NAME BUILD_JOB_NAME BUILD_PIPELINE_NAME BUILD_TEAM_NAME ATC_EXTERNAL_URL; do
228+
value="${value//\$$var/${!var:-}}"
229+
value="${value//\$\{$var\}/${!var:-}}"
230+
done
231+
secret="id=${key}"
232+
sub=$(jq -r ".params.secrets.${key} // {}" < $payload)
233+
sub_keys=($(echo "$sub" | jq -r 'keys | join(" ")'))
234+
if [ "${#sub_keys[@]}" -gt 0 ]; then
235+
expanded_secrets+=("--secret")
236+
for key in "${sub_keys[@]}"; do
237+
value=$(echo "$sub" | jq -r --arg "k" "$key" '.[$k]')
238+
secret="${secret},${key}=${value}"
239+
done
240+
expanded_secrets+=("${secret}")
241+
fi
242+
done
243+
fi
244+
218245
expanded_labels=()
219246

220247
label_keys=($(echo "$labels" | jq -r 'keys | join(" ")'))
@@ -261,7 +288,7 @@ elif [ -n "$build" ]; then
261288
# NOTE: deactivate amazon-ecr-credential-helper so that builds go through with the DOCKER_BUILDKIT set
262289
cp ~/.docker/config.json ~/.docker/config.json.bak
263290
cat <<< "$(jq 'del(.credsStore)' ~/.docker/config.json)" > ~/.docker/config.json
264-
docker build -t "${repository}:${tag_name}" "${target[@]}" "${expanded_build_args[@]}" "${expanded_labels[@]}" "${ssh_args[@]}" -f "$dockerfile" $cache_from "$build"
291+
docker build -t "${repository}:${tag_name}" "${target[@]}" "${expanded_build_args[@]}" "${expanded_secrets[@]}" "${expanded_labels[@]}" "${ssh_args[@]}" -f "$dockerfile" $cache_from "$build"
265292
mv ~/.docker/config.json.bak ~/.docker/config.json # This restores the credsStore: ecr-login to config.json if needed
266293

267294
elif [ -n "$load_file" ]; then

tests/out_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,37 @@ var _ = Describe("Out", func() {
133133
})
134134
})
135135

136+
Context("when secrets are provided", func() {
137+
It("passes the arguments correctly to the docker daemon", func() {
138+
session := put(map[string]interface{}{
139+
"source": map[string]interface{}{
140+
"repository": "test",
141+
},
142+
"params": map[string]interface{}{
143+
"build": "/docker-image-resource/tests/fixtures/build",
144+
"secrets": map[string]interface{}{
145+
"secret1": map[string]interface{}{
146+
"env": "GITHUB_TOKEN",
147+
},
148+
"secret2": map[string]interface{}{
149+
"source": "/a/file/path.txt",
150+
},
151+
"secret3": map[string]interface{}{
152+
"source": "/a/file/path with a space in it.txt",
153+
},
154+
},
155+
},
156+
})
157+
158+
Expect(session.Err).To(gbytes.Say(dockerarg(`--secret`)))
159+
Expect(session.Err).To(gbytes.Say(dockerarg(`id=secret1,env=GITHUB_TOKEN`)))
160+
Expect(session.Err).To(gbytes.Say(dockerarg(`--secret`)))
161+
Expect(session.Err).To(gbytes.Say(dockerarg(`id=secret2,source=/a/file/path.txt`)))
162+
Expect(session.Err).To(gbytes.Say(dockerarg(`--secret`)))
163+
Expect(session.Err).To(gbytes.Say(dockerarg(`id=secret3,source=/a/file/path with a space in it.txt`)))
164+
})
165+
})
166+
136167
Context("when labels are provided", func() {
137168
It("passes the labels correctly to the docker daemon", func() {
138169
session := put(map[string]interface{}{

0 commit comments

Comments
 (0)