Skip to content

Commit 416acc6

Browse files
authoredOct 29, 2024··
feat(envbuilder.go): add support for build secrets (#391)
1 parent 561cc53 commit 416acc6

File tree

8 files changed

+311
-47
lines changed

8 files changed

+311
-47
lines changed
 

Diff for: ‎devcontainer/devcontainer.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -400,11 +400,11 @@ func ImageFromDockerfile(dockerfileContent string) (name.Reference, error) {
400400
arg = strings.TrimSpace(arg)
401401
if strings.Contains(arg, "=") {
402402
parts := strings.SplitN(arg, "=", 2)
403-
key, err := lexer.ProcessWord(parts[0], args)
403+
key, _, err := lexer.ProcessWord(parts[0], shell.EnvsFromSlice(args))
404404
if err != nil {
405405
return nil, fmt.Errorf("processing %q: %w", line, err)
406406
}
407-
val, err := lexer.ProcessWord(parts[1], args)
407+
val, _, err := lexer.ProcessWord(parts[1], shell.EnvsFromSlice(args))
408408
if err != nil {
409409
return nil, fmt.Errorf("processing %q: %w", line, err)
410410
}
@@ -421,7 +421,7 @@ func ImageFromDockerfile(dockerfileContent string) (name.Reference, error) {
421421
if imageRef == "" {
422422
return nil, fmt.Errorf("no FROM directive found")
423423
}
424-
imageRef, err := lexer.ProcessWord(imageRef, args)
424+
imageRef, _, err := lexer.ProcessWord(imageRef, shell.EnvsFromSlice(args))
425425
if err != nil {
426426
return nil, fmt.Errorf("processing %q: %w", imageRef, err)
427427
}

Diff for: ‎envbuilder.go

+6
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,11 @@ func run(ctx context.Context, opts options.Options, execArgs *execArgsInfo) erro
529529
if opts.CacheRepo != "" {
530530
destinations = append(destinations, opts.CacheRepo)
531531
}
532+
533+
buildSecrets := options.GetBuildSecrets(os.Environ())
534+
// Ensure that build secrets do not make it into the runtime environment or the setup script:
535+
options.ClearBuildSecretsFromProcessEnvironment()
536+
532537
kOpts := &config.KanikoOptions{
533538
// Boilerplate!
534539
CustomPlatform: platforms.Format(platforms.Normalize(platforms.DefaultSpec())),
@@ -553,6 +558,7 @@ func run(ctx context.Context, opts options.Options, execArgs *execArgsInfo) erro
553558
},
554559
ForceUnpack: true,
555560
BuildArgs: buildParams.BuildArgs,
561+
BuildSecrets: buildSecrets,
556562
CacheRepo: opts.CacheRepo,
557563
Cache: opts.CacheRepo != "" || opts.BaseImageCacheDir != "",
558564
DockerfilePath: buildParams.DockerfilePath,

Diff for: ‎go.mod

+13-14
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ go 1.22.4
44

55
// There are a few options we need added to Kaniko!
66
// See: https://github.com/GoogleContainerTools/kaniko/compare/main...coder:kaniko:main
7-
replace github.com/GoogleContainerTools/kaniko => github.com/coder/kaniko v0.0.0-20240925122543-caa18967f374
7+
replace github.com/GoogleContainerTools/kaniko => github.com/coder/kaniko v0.0.0-20241028054616-350cbb820e05
88

99
// Required to import codersdk due to gvisor dependency.
1010
replace tailscale.com => github.com/coder/tailscale v1.1.1-0.20240702054557-aa558fbe5374
@@ -19,8 +19,8 @@ require (
1919
github.com/coder/serpent v0.7.0
2020
github.com/containerd/platforms v0.2.1
2121
github.com/distribution/distribution/v3 v3.0.0-alpha.1
22-
github.com/docker/cli v27.2.0+incompatible
23-
github.com/docker/docker v26.1.5+incompatible
22+
github.com/docker/cli v27.2.1+incompatible
23+
github.com/docker/docker v27.3.1+incompatible
2424
github.com/fatih/color v1.17.0
2525
github.com/gliderlabs/ssh v0.3.7
2626
github.com/go-git/go-billy/v5 v5.5.0
@@ -31,7 +31,7 @@ require (
3131
github.com/hashicorp/go-multierror v1.1.1
3232
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
3333
github.com/mattn/go-isatty v0.0.20
34-
github.com/moby/buildkit v0.13.1
34+
github.com/moby/buildkit v0.16.0
3535
github.com/otiai10/copy v1.14.0
3636
github.com/prometheus/procfs v0.15.1
3737
github.com/sirupsen/logrus v1.9.3
@@ -100,25 +100,22 @@ require (
100100
github.com/cespare/xxhash/v2 v2.2.0 // indirect
101101
github.com/charmbracelet/lipgloss v0.8.0 // indirect
102102
github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589 // indirect
103-
github.com/cilium/ebpf v0.12.3 // indirect
104103
github.com/cloudflare/circl v1.3.7 // indirect
105104
github.com/coder/pretty v0.0.0-20230908205945-e89ba86370e0 // indirect
106105
github.com/coder/quartz v0.1.0 // indirect
107106
github.com/coder/terraform-provider-coder v0.23.0 // indirect
108107
github.com/containerd/cgroups v1.1.0 // indirect
109-
github.com/containerd/cgroups/v3 v3.0.2 // indirect
110-
github.com/containerd/containerd v1.7.19 // indirect
108+
github.com/containerd/containerd v1.7.21 // indirect
111109
github.com/containerd/containerd/api v1.7.19 // indirect
112110
github.com/containerd/continuity v0.4.3 // indirect
113111
github.com/containerd/errdefs v0.1.0 // indirect
114112
github.com/containerd/fifo v1.1.0 // indirect
115113
github.com/containerd/log v0.1.0 // indirect
116114
github.com/containerd/stargz-snapshotter/estargz v0.15.1 // indirect
117115
github.com/containerd/ttrpc v1.2.5 // indirect
118-
github.com/containerd/typeurl/v2 v2.1.1 // indirect
116+
github.com/containerd/typeurl/v2 v2.2.0 // indirect
119117
github.com/coreos/go-iptables v0.6.0 // indirect
120118
github.com/coreos/go-oidc/v3 v3.10.0 // indirect
121-
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
122119
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
123120
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
124121
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect
@@ -151,7 +148,7 @@ require (
151148
github.com/golang/protobuf v1.5.4 // indirect
152149
github.com/google/btree v1.1.2 // indirect
153150
github.com/google/nftables v0.2.0 // indirect
154-
github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b // indirect
151+
github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 // indirect
155152
github.com/gorilla/handlers v1.5.1 // indirect
156153
github.com/gorilla/mux v1.8.1 // indirect
157154
github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 // indirect
@@ -164,7 +161,7 @@ require (
164161
github.com/hashicorp/go-version v1.7.0 // indirect
165162
github.com/hashicorp/golang-lru v1.0.2 // indirect
166163
github.com/hashicorp/golang-lru/arc/v2 v2.0.5 // indirect
167-
github.com/hashicorp/golang-lru/v2 v2.0.5 // indirect
164+
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
168165
github.com/hashicorp/hcl/v2 v2.21.0 // indirect
169166
github.com/hashicorp/logutils v1.0.0 // indirect
170167
github.com/hashicorp/terraform-plugin-go v0.12.0 // indirect
@@ -202,11 +199,12 @@ require (
202199
github.com/moby/patternmatcher v0.6.0 // indirect
203200
github.com/moby/swarmkit/v2 v2.0.0-20230315203717-e28e8ba9bc83 // indirect
204201
github.com/moby/sys/mount v0.3.3 // indirect
205-
github.com/moby/sys/mountinfo v0.7.1 // indirect
202+
github.com/moby/sys/mountinfo v0.7.2 // indirect
206203
github.com/moby/sys/sequential v0.5.0 // indirect
207-
github.com/moby/sys/signal v0.7.0 // indirect
204+
github.com/moby/sys/signal v0.7.1 // indirect
208205
github.com/moby/sys/symlink v0.2.0 // indirect
209-
github.com/moby/sys/user v0.1.0 // indirect
206+
github.com/moby/sys/user v0.3.0 // indirect
207+
github.com/moby/sys/userns v0.1.0 // indirect
210208
github.com/moby/term v0.5.0 // indirect
211209
github.com/morikuni/aec v1.0.0 // indirect
212210
github.com/muesli/reflow v0.3.0 // indirect
@@ -245,6 +243,7 @@ require (
245243
github.com/tailscale/wireguard-go v0.0.0-20231121184858-cc193a0b3272 // indirect
246244
github.com/tcnksm/go-httpstat v0.2.0 // indirect
247245
github.com/tinylib/msgp v1.1.8 // indirect
246+
github.com/tonistiigi/go-csvvalue v0.0.0-20240710180619-ddb21b71c0b4 // indirect
248247
github.com/twpayne/go-vfs/v5 v5.0.4 // indirect
249248
github.com/u-root/uio v0.0.0-20240209044354-b3d14b93376a // indirect
250249
github.com/valyala/fasthttp v1.55.0 // indirect

Diff for: ‎go.sum

+26-26
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,8 @@ github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoC
171171
github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI=
172172
github.com/coder/coder/v2 v2.10.1-0.20240704130443-c2d44d16a352 h1:L/EjCuZxs5tOcqqCaASj/nu65TRYEFcTt8qRQfHZXX0=
173173
github.com/coder/coder/v2 v2.10.1-0.20240704130443-c2d44d16a352/go.mod h1:P1KoQSgnKEAG6Mnd3YlGzAophty+yKA9VV48LpfNRvo=
174-
github.com/coder/kaniko v0.0.0-20240925122543-caa18967f374 h1:/cyXf0vTSwFh7evQqeWHXXl14aRfC4CsNIYxOenJytQ=
175-
github.com/coder/kaniko v0.0.0-20240925122543-caa18967f374/go.mod h1:XoTDIhNF0Ll4tLmRYdOn31udU9w5zFrY2PME/crSRCA=
174+
github.com/coder/kaniko v0.0.0-20241028054616-350cbb820e05 h1:KZc6vG/WnSWG8RtUevGrCdZbF7XJaaZ32ocig6sZLQk=
175+
github.com/coder/kaniko v0.0.0-20241028054616-350cbb820e05/go.mod h1:3rM/KOQ4LgF8mE+O1P6pLDa/E57mzxIxNdUOMKi1qpg=
176176
github.com/coder/pretty v0.0.0-20230908205945-e89ba86370e0 h1:3A0ES21Ke+FxEM8CXx9n47SZOKOpgSE1bbJzlE4qPVs=
177177
github.com/coder/pretty v0.0.0-20230908205945-e89ba86370e0/go.mod h1:5UuS2Ts+nTToAMeOjNlnHFkPahrtDkmpydBen/3wgZc=
178178
github.com/coder/quartz v0.1.0 h1:cLL+0g5l7xTf6ordRnUMMiZtRE8Sq5LxpghS63vEXrQ=
@@ -187,10 +187,8 @@ github.com/coder/terraform-provider-coder v0.23.0 h1:DuNLWxhnGlXyG0g+OCAZRI6xd8+
187187
github.com/coder/terraform-provider-coder v0.23.0/go.mod h1:wMun9UZ9HT2CzF6qPPBup1odzBpVUc0/xSFoXgdI3tk=
188188
github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=
189189
github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw=
190-
github.com/containerd/cgroups/v3 v3.0.2 h1:f5WFqIVSgo5IZmtTT3qVBo6TzI1ON6sycSBKkymb9L0=
191-
github.com/containerd/cgroups/v3 v3.0.2/go.mod h1:JUgITrzdFqp42uI2ryGA+ge0ap/nxzYgkGmIcetmErE=
192-
github.com/containerd/containerd v1.7.19 h1:/xQ4XRJ0tamDkdzrrBAUy/LE5nCcxFKdBm4EcPrSMEE=
193-
github.com/containerd/containerd v1.7.19/go.mod h1:h4FtNYUUMB4Phr6v+xG89RYKj9XccvbNSCKjdufCrkc=
190+
github.com/containerd/containerd v1.7.21 h1:USGXRK1eOC/SX0L195YgxTHb0a00anxajOzgfN0qrCA=
191+
github.com/containerd/containerd v1.7.21/go.mod h1:e3Jz1rYRUZ2Lt51YrH9Rz0zPyJBOlSvB3ghr2jbVD8g=
194192
github.com/containerd/containerd/api v1.7.19 h1:VWbJL+8Ap4Ju2mx9c9qS1uFSB1OVYr5JJrW2yT5vFoA=
195193
github.com/containerd/containerd/api v1.7.19/go.mod h1:fwGavl3LNwAV5ilJ0sbrABL44AQxmNjDRcwheXDb6Ig=
196194
github.com/containerd/continuity v0.4.3 h1:6HVkalIp+2u1ZLH1J/pYX2oBVXlJZvh1X1A7bEZ9Su8=
@@ -207,15 +205,13 @@ github.com/containerd/stargz-snapshotter/estargz v0.15.1 h1:eXJjw9RbkLFgioVaTG+G
207205
github.com/containerd/stargz-snapshotter/estargz v0.15.1/go.mod h1:gr2RNwukQ/S9Nv33Lt6UC7xEx58C+LHRdoqbEKjz1Kk=
208206
github.com/containerd/ttrpc v1.2.5 h1:IFckT1EFQoFBMG4c3sMdT8EP3/aKfumK1msY+Ze4oLU=
209207
github.com/containerd/ttrpc v1.2.5/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o=
210-
github.com/containerd/typeurl/v2 v2.1.1 h1:3Q4Pt7i8nYwy2KmQWIw2+1hTvwTE/6w9FqcttATPO/4=
211-
github.com/containerd/typeurl/v2 v2.1.1/go.mod h1:IDp2JFvbwZ31H8dQbEIY7sDl2L3o3HZj1hsSQlywkQ0=
208+
github.com/containerd/typeurl/v2 v2.2.0 h1:6NBDbQzr7I5LHgp34xAXYF5DOTQDn05X58lsPEmzLso=
209+
github.com/containerd/typeurl/v2 v2.2.0/go.mod h1:8XOOxnyatxSWuG8OfsZXVnAF4iZfedjS/8UHSPJnX4g=
212210
github.com/coreos/go-iptables v0.6.0 h1:is9qnZMPYjLd8LYqmm/qlE+wwEgJIkTYdhV3rfZo4jk=
213211
github.com/coreos/go-iptables v0.6.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q=
214212
github.com/coreos/go-oidc/v3 v3.10.0 h1:tDnXHnLyiTVyT/2zLDGj09pFPkhND8Gl8lnTRhoEaJU=
215213
github.com/coreos/go-oidc/v3 v3.10.0/go.mod h1:5j11xcw0D3+SGxn6Z/WFADsgcWVMyNAlSQupk0KK3ac=
216214
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
217-
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
218-
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
219215
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
220216
github.com/creack/pty v1.1.21 h1:1/QdRyBaHHJP61QkWMXlOIBfsgdDeeKfK8SYVUWJKf0=
221217
github.com/creack/pty v1.1.21/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
@@ -236,12 +232,12 @@ github.com/distribution/distribution/v3 v3.0.0-alpha.1 h1:jn7I1gvjOvmLztH1+1cLiU
236232
github.com/distribution/distribution/v3 v3.0.0-alpha.1/go.mod h1:LCp4JZp1ZalYg0W/TN05jarCQu+h4w7xc7ZfQF4Y/cY=
237233
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
238234
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
239-
github.com/docker/cli v27.2.0+incompatible h1:yHD1QEB1/0vr5eBNpu8tncu8gWxg8EydFPOSKHzXSMM=
240-
github.com/docker/cli v27.2.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
235+
github.com/docker/cli v27.2.1+incompatible h1:U5BPtiD0viUzjGAjV1p0MGB8eVA3L3cbIrnyWmSJI70=
236+
github.com/docker/cli v27.2.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
241237
github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
242238
github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
243-
github.com/docker/docker v26.1.5+incompatible h1:NEAxTwEjxV6VbBMBoGG3zPqbiJosIApZjxlbrG9q3/g=
244-
github.com/docker/docker v26.1.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
239+
github.com/docker/docker v27.3.1+incompatible h1:KttF0XoteNTicmUtBO0L2tP+J7FGRFTjaEF4k6WdhfI=
240+
github.com/docker/docker v27.3.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
245241
github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo=
246242
github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M=
247243
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
@@ -394,8 +390,8 @@ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
394390
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
395391
github.com/google/nftables v0.2.0 h1:PbJwaBmbVLzpeldoeUKGkE2RjstrjPKMl6oLrfEJ6/8=
396392
github.com/google/nftables v0.2.0/go.mod h1:Beg6V6zZ3oEn0JuiUQ4wqwuyqqzasOltcoXPtgLbFp4=
397-
github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b h1:h9U78+dx9a4BKdQkBBos92HalKpaGKHrp+3Uo6yTodo=
398-
github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
393+
github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 h1:k7nVchz72niMH6YLQNvHSdIE7iqsQxK1P41mySCvssg=
394+
github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw=
399395
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
400396
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
401397
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@@ -439,8 +435,8 @@ github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iP
439435
github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
440436
github.com/hashicorp/golang-lru/arc/v2 v2.0.5 h1:l2zaLDubNhW4XO3LnliVj0GXO3+/CGNJAg1dcN2Fpfw=
441437
github.com/hashicorp/golang-lru/arc/v2 v2.0.5/go.mod h1:ny6zBSQZi2JxIeYcv7kt2sH2PXJtirBN7RDhRpxPkxU=
442-
github.com/hashicorp/golang-lru/v2 v2.0.5 h1:wW7h1TG88eUIJ2i69gaE3uNVtEPIagzhGvHgwfx2Vm4=
443-
github.com/hashicorp/golang-lru/v2 v2.0.5/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
438+
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
439+
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
444440
github.com/hashicorp/hc-install v0.7.0 h1:Uu9edVqjKQxxuD28mR5TikkKDd/p55S8vzPC1659aBk=
445441
github.com/hashicorp/hc-install v0.7.0/go.mod h1:ELmmzZlGnEcqoUMKUuykHaPCIR1sYLYX+KSggWSKZuA=
446442
github.com/hashicorp/hcl/v2 v2.21.0 h1:lve4q/o/2rqwYOgUg3y3V2YPyD1/zkCLGjIV74Jit14=
@@ -556,8 +552,8 @@ github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c h1:cqn374
556552
github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
557553
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
558554
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
559-
github.com/moby/buildkit v0.13.1 h1:L8afOFhPq2RPJJSr/VyzbufwID7jquZVB7oFHbPRcPE=
560-
github.com/moby/buildkit v0.13.1/go.mod h1:aNmNQKLBFYAOFuzQjR3VA27/FijlvtBD1pjNwTSN37k=
555+
github.com/moby/buildkit v0.16.0 h1:wOVBj1o5YNVad/txPQNXUXdelm7Hs/i0PUFjzbK0VKE=
556+
github.com/moby/buildkit v0.16.0/go.mod h1:Xqx/5GlrqE1yIRORk0NSCVDFpQAU1WjlT6KHYZdisIQ=
561557
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
562558
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
563559
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
@@ -569,16 +565,18 @@ github.com/moby/swarmkit/v2 v2.0.0-20230315203717-e28e8ba9bc83/go.mod h1:GvjR7mC
569565
github.com/moby/sys/mount v0.3.3 h1:fX1SVkXFJ47XWDoeFW4Sq7PdQJnV2QIDZAqjNqgEjUs=
570566
github.com/moby/sys/mount v0.3.3/go.mod h1:PBaEorSNTLG5t/+4EgukEQVlAvVEc6ZjTySwKdqp5K0=
571567
github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
572-
github.com/moby/sys/mountinfo v0.7.1 h1:/tTvQaSJRr2FshkhXiIpux6fQ2Zvc4j7tAhMTStAG2g=
573-
github.com/moby/sys/mountinfo v0.7.1/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
568+
github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg=
569+
github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4=
574570
github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=
575571
github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo=
576-
github.com/moby/sys/signal v0.7.0 h1:25RW3d5TnQEoKvRbEKUGay6DCQ46IxAVTT9CUMgmsSI=
577-
github.com/moby/sys/signal v0.7.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg=
572+
github.com/moby/sys/signal v0.7.1 h1:PrQxdvxcGijdo6UXXo/lU/TvHUWyPhj7UOpSo8tuvk0=
573+
github.com/moby/sys/signal v0.7.1/go.mod h1:Se1VGehYokAkrSQwL4tDzHvETwUZlnY7S5XtQ50mQp8=
578574
github.com/moby/sys/symlink v0.2.0 h1:tk1rOM+Ljp0nFmfOIBtlV3rTDlWOwFRhjEeAhZB0nZc=
579575
github.com/moby/sys/symlink v0.2.0/go.mod h1:7uZVF2dqJjG/NsClqul95CqKOBRQyYSNnJ6BMgR/gFs=
580-
github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg=
581-
github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU=
576+
github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo=
577+
github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=
578+
github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g=
579+
github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=
582580
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
583581
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
584582
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -729,6 +727,8 @@ github.com/tcnksm/go-httpstat v0.2.0 h1:rP7T5e5U2HfmOBmZzGgGZjBQ5/GluWUylujl0tJ0
729727
github.com/tcnksm/go-httpstat v0.2.0/go.mod h1:s3JVJFtQxtBEBC9dwcdTTXS9xFnM3SXAZwPG41aurT8=
730728
github.com/tinylib/msgp v1.1.8 h1:FCXC1xanKO4I8plpHGH2P7koL/RzZs12l/+r7vakfm0=
731729
github.com/tinylib/msgp v1.1.8/go.mod h1:qkpG+2ldGg4xRFmx+jfTvZPxfGFhi64BcnL9vkCm/Tw=
730+
github.com/tonistiigi/go-csvvalue v0.0.0-20240710180619-ddb21b71c0b4 h1:7I5c2Ig/5FgqkYOh/N87NzoyI9U15qUPXhDD8uCupv8=
731+
github.com/tonistiigi/go-csvvalue v0.0.0-20240710180619-ddb21b71c0b4/go.mod h1:278M4p8WsNh3n4a1eqiFcV2FGk7wE5fwUpUom9mK9lE=
732732
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
733733
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
734734
github.com/twpayne/go-vfs/v5 v5.0.4 h1:/ne3h+rW7f5YOyOFguz+3ztfUwzOLR0Vts3y0mMAitg=

Diff for: ‎integration/integration_test.go

+78-3
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ import (
3737
gossh "golang.org/x/crypto/ssh"
3838

3939
clitypes "github.com/docker/cli/cli/config/types"
40-
"github.com/docker/docker/api/types"
4140
"github.com/docker/docker/api/types/container"
4241
"github.com/docker/docker/api/types/filters"
4342
"github.com/docker/docker/api/types/image"
@@ -981,6 +980,82 @@ func TestUnsetOptionsEnv(t *testing.T) {
981980
}
982981
}
983982

983+
func TestUnsetSecretEnvs(t *testing.T) {
984+
t.Parallel()
985+
986+
// Ensures that a Git repository with a devcontainer.json is cloned and built.
987+
srv := gittest.CreateGitServer(t, gittest.Options{
988+
Files: map[string]string{
989+
".devcontainer/devcontainer.json": `{
990+
"name": "Test",
991+
"build": {
992+
"dockerfile": "Dockerfile"
993+
},
994+
}`,
995+
".devcontainer/Dockerfile": "FROM " + testImageAlpine + "\nENV FROM_DOCKERFILE=foo",
996+
},
997+
})
998+
ctr, err := runEnvbuilder(t, runOpts{env: []string{
999+
envbuilderEnv("GIT_URL", srv.URL),
1000+
envbuilderEnv("GIT_PASSWORD", "supersecret"),
1001+
options.EnvWithBuildSecretPrefix("FOO", "foo"),
1002+
envbuilderEnv("INIT_SCRIPT", "env > /root/env.txt && sleep infinity"),
1003+
}})
1004+
require.NoError(t, err)
1005+
1006+
output := execContainer(t, ctr, "cat /root/env.txt")
1007+
envsAvailableToInitScript := strings.Split(strings.TrimSpace(output), "\n")
1008+
1009+
leftoverBuildSecrets := options.GetBuildSecrets(envsAvailableToInitScript)
1010+
require.Empty(t, leftoverBuildSecrets, "build secrets should not be available to init script")
1011+
}
1012+
1013+
func TestBuildSecrets(t *testing.T) {
1014+
t.Parallel()
1015+
1016+
buildSecretVal := "foo"
1017+
1018+
srv := gittest.CreateGitServer(t, gittest.Options{
1019+
Files: map[string]string{
1020+
".devcontainer/devcontainer.json": `{
1021+
"name": "Test",
1022+
"build": {
1023+
"dockerfile": "Dockerfile"
1024+
},
1025+
}`,
1026+
".devcontainer/Dockerfile": "FROM " + testImageAlpine +
1027+
// Test whether build secrets are written to the default location
1028+
"\nRUN --mount=type=secret,id=FOO cat /run/secrets/FOO > /foo_from_file" +
1029+
// Test whether:
1030+
// * build secrets are written to env
1031+
// * build secrets are written to a custom target
1032+
// * build secrets are both written to env and target if both are specified
1033+
"\nRUN --mount=type=secret,id=FOO,env=FOO,target=/etc/foo echo $FOO > /foo_from_env && cat /etc/foo > /foo_from_custom_target" +
1034+
// Test what happens when you specify the same secret twice
1035+
"\nRUN --mount=type=secret,id=FOO,target=/etc/duplicate_foo --mount=type=secret,id=FOO,target=/etc/duplicate_foo cat /etc/duplicate_foo > /duplicate_foo_from_custom_target",
1036+
},
1037+
})
1038+
1039+
ctr, err := runEnvbuilder(t, runOpts{env: []string{
1040+
envbuilderEnv("GIT_URL", srv.URL),
1041+
envbuilderEnv("GIT_PASSWORD", "supersecret"),
1042+
options.EnvWithBuildSecretPrefix("FOO", buildSecretVal),
1043+
}})
1044+
require.NoError(t, err)
1045+
1046+
output := execContainer(t, ctr, "cat /foo_from_file")
1047+
assert.Equal(t, buildSecretVal, strings.TrimSpace(output))
1048+
1049+
output = execContainer(t, ctr, "cat /foo_from_env")
1050+
assert.Equal(t, buildSecretVal, strings.TrimSpace(output))
1051+
1052+
output = execContainer(t, ctr, "cat /foo_from_custom_target")
1053+
assert.Equal(t, buildSecretVal, strings.TrimSpace(output))
1054+
1055+
output = execContainer(t, ctr, "cat /duplicate_foo_from_custom_target")
1056+
assert.Equal(t, buildSecretVal, strings.TrimSpace(output))
1057+
}
1058+
9841059
func TestLifecycleScripts(t *testing.T) {
9851060
t.Parallel()
9861061

@@ -2397,14 +2472,14 @@ func execContainer(t *testing.T, containerID, command string) string {
23972472
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
23982473
require.NoError(t, err)
23992474
defer cli.Close()
2400-
execConfig := types.ExecConfig{
2475+
execConfig := container.ExecOptions{
24012476
AttachStdout: true,
24022477
AttachStderr: true,
24032478
Cmd: []string{"/bin/sh", "-c", command},
24042479
}
24052480
execID, err := cli.ContainerExecCreate(ctx, containerID, execConfig)
24062481
require.NoError(t, err)
2407-
resp, err := cli.ContainerExecAttach(ctx, execID.ID, types.ExecStartCheck{})
2482+
resp, err := cli.ContainerExecAttach(ctx, execID.ID, container.ExecAttachOptions{})
24082483
require.NoError(t, err)
24092484
defer resp.Close()
24102485
var buf bytes.Buffer

Diff for: ‎options/secrets.go

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package options
2+
3+
import (
4+
"fmt"
5+
"os"
6+
7+
"github.com/coder/serpent"
8+
)
9+
10+
var buildSecretPrefix = fmt.Sprintf("%sBUILD_SECRET_", envPrefix)
11+
12+
// EnvWithBuildSecretPrefix returns a string in the format of a build secret environment variable.
13+
func EnvWithBuildSecretPrefix(secretName, secretValue string) string {
14+
return fmt.Sprintf("%s%s=%s", buildSecretPrefix, secretName, secretValue)
15+
}
16+
17+
// GetBuildSecrets sources build secrets from the given environment.
18+
//
19+
// In a normal docker build, build secrets would be passed in via the
20+
// `docker build --secret` flag. envbuilder is more analogous to a
21+
// `docker run` that just happens to build its own container. It doesn't have
22+
// access to the `--secret` flag. As an alternative, we source these from the
23+
// envbuilder process environment.
24+
func GetBuildSecrets(environ []string) []string {
25+
buildSecrets := serpent.ParseEnviron(environ, buildSecretPrefix).ToOS()
26+
return buildSecrets
27+
}
28+
29+
// ClearBuildSecretsFromProcessEnvironment unsets all build secrets from the process environment.
30+
// NOTE: This does not remove them from /proc/self/environ. They are still visible
31+
// there unless execve(2) is called.
32+
//
33+
// Unlike runtime secrets in the devcontainer spec or orchestration systems like
34+
// Kubernetes, build secrets should not be available at run time. envbuilder blurs
35+
// the line between build time and run time by transitioning from one to the other
36+
// within the same process in the same container.
37+
//
38+
// These build secrets should not make it into the runtime environment of the runtime
39+
// container init process. It is therefore useful to unset build secret environment
40+
// variables to ensure they aren't accidentally passed into the exec call.
41+
func ClearBuildSecretsFromProcessEnvironment() {
42+
buildSecrets := serpent.ParseEnviron(os.Environ(), buildSecretPrefix)
43+
for _, secret := range buildSecrets {
44+
os.Unsetenv(buildSecretPrefix + secret.Name)
45+
}
46+
}

Diff for: ‎options/secrets_test.go

+138
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
package options_test
2+
3+
import (
4+
"os"
5+
"strings"
6+
"testing"
7+
8+
"github.com/coder/envbuilder/options"
9+
"github.com/stretchr/testify/assert"
10+
"github.com/stretchr/testify/require"
11+
)
12+
13+
func TestGetBuildSecrets(t *testing.T) {
14+
// This test cannot be run in parallel, because it needs to modify the OS environment
15+
tests := []struct {
16+
name string
17+
envVars map[string]string
18+
expectedSecrets []string
19+
}{
20+
{
21+
name: "no secrets set",
22+
envVars: map[string]string{},
23+
expectedSecrets: []string{},
24+
},
25+
{
26+
name: "single secret",
27+
envVars: map[string]string{
28+
"ENVBUILDER_BUILD_SECRET_FOO": "bar",
29+
},
30+
expectedSecrets: []string{"FOO=bar"},
31+
},
32+
{
33+
name: "multiple secrets",
34+
envVars: map[string]string{
35+
"ENVBUILDER_BUILD_SECRET_FOO": "bar",
36+
"NOT_A_SECRET": "baz",
37+
"ENVBUILDER_BUILD_SECRET_BAZ": "qux",
38+
},
39+
expectedSecrets: []string{"FOO=bar", "BAZ=qux"},
40+
},
41+
}
42+
43+
for _, tt := range tests {
44+
t.Run(tt.name, func(t *testing.T) {
45+
preserveEnv(t)
46+
os.Clearenv()
47+
48+
options.ClearBuildSecretsFromProcessEnvironment()
49+
require.Empty(t, options.GetBuildSecrets(os.Environ()))
50+
51+
// Set environment variables for the test case
52+
for key, value := range tt.envVars {
53+
t.Setenv(key, value)
54+
}
55+
56+
// when
57+
secrets := options.GetBuildSecrets(os.Environ())
58+
59+
// then
60+
assert.ElementsMatch(t, tt.expectedSecrets, secrets)
61+
})
62+
}
63+
}
64+
65+
func TestClearBuildSecrets(t *testing.T) {
66+
// This test cannot be run in parallel, because it needs to modify the OS environment
67+
tests := []struct {
68+
name string
69+
initialEnvVars map[string]string
70+
expectedSecretsBeforeClear []string
71+
expectedEnvironAfterClear []string
72+
}{
73+
{
74+
name: "single secret",
75+
initialEnvVars: map[string]string{
76+
"ENVBUILDER_BUILD_SECRET_FOO": "bar",
77+
},
78+
expectedSecretsBeforeClear: []string{"FOO=bar"},
79+
},
80+
{
81+
name: "multiple secrets",
82+
initialEnvVars: map[string]string{
83+
"ENVBUILDER_BUILD_SECRET_FOO": "bar",
84+
"ENVBUILDER_BUILD_SECRET_BAZ": "qux",
85+
},
86+
expectedSecretsBeforeClear: []string{"FOO=bar", "BAZ=qux"},
87+
},
88+
{
89+
name: "only build secrets are cleared",
90+
initialEnvVars: map[string]string{
91+
"ENVBUILDER_BUILD_SECRET_FOO": "foo",
92+
"BAR": "bar",
93+
},
94+
expectedSecretsBeforeClear: []string{"FOO=foo"},
95+
expectedEnvironAfterClear: []string{"BAR=bar"},
96+
},
97+
}
98+
99+
for _, tt := range tests {
100+
t.Run(tt.name, func(t *testing.T) {
101+
preserveEnv(t)
102+
os.Clearenv()
103+
104+
// Set environment variables for the test case
105+
for key, value := range tt.initialEnvVars {
106+
t.Setenv(key, value)
107+
}
108+
109+
// Verify secrets before clearing
110+
secrets := options.GetBuildSecrets(os.Environ())
111+
assert.ElementsMatch(t, tt.expectedSecretsBeforeClear, secrets)
112+
113+
// Clear the secrets
114+
options.ClearBuildSecretsFromProcessEnvironment()
115+
116+
// Verify secrets after clearing
117+
environ := os.Environ()
118+
secrets = options.GetBuildSecrets(environ)
119+
assert.Empty(t, secrets)
120+
})
121+
}
122+
}
123+
124+
// preserveEnv takes a snapshot of the current process environment and restores it after the current
125+
// test to ensure that we don't cause flakes by modifying the environment for other tests.
126+
func preserveEnv(t *testing.T) {
127+
envSnapshot := make(map[string]string)
128+
for _, envVar := range os.Environ() {
129+
parts := strings.SplitN(envVar, "=", 2)
130+
envSnapshot[parts[0]] = parts[1]
131+
}
132+
t.Cleanup(func() {
133+
os.Clearenv()
134+
for key, value := range envSnapshot {
135+
os.Setenv(key, value)
136+
}
137+
})
138+
}

Diff for: ‎scripts/Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@ ARG TARGETARCH
33

44
COPY envbuilder-${TARGETARCH} /.envbuilder/bin/envbuilder
55

6-
ENV KANIKO_DIR /.envbuilder
6+
ENV KANIKO_DIR=/.envbuilder
77

88
ENTRYPOINT ["/.envbuilder/bin/envbuilder"]

0 commit comments

Comments
 (0)
Please sign in to comment.