@@ -10,9 +10,11 @@ package main
10
10
import (
11
11
"archive/tar"
12
12
"bufio"
13
+ "bytes"
13
14
"compress/gzip"
14
15
"context"
15
16
"embed"
17
+ "encoding/base64"
16
18
"encoding/json"
17
19
"fmt"
18
20
"io"
@@ -58,6 +60,7 @@ var aptUpdated = false
58
60
const (
59
61
dockerSocketFN = "/var/run/docker.sock"
60
62
gitpodUserId = 33333
63
+ gitpodGroupId = 33333
61
64
containerIf = "eth0"
62
65
)
63
66
@@ -185,13 +188,88 @@ func runWithinNetns() (err error) {
185
188
}()
186
189
}
187
190
191
+ if imageAuth , _ := os .LookupEnv ("GITPOD_IMAGE_AUTH" ); strings .TrimSpace (imageAuth ) != "" {
192
+ if err := waitUntilSocketPresent (dockerSocketFN ); err == nil {
193
+ tryAuthenticateForAllHosts (imageAuth )
194
+ }
195
+ }
196
+
188
197
err = cmd .Wait ()
189
198
if err != nil {
190
199
return err
191
200
}
192
201
return nil
193
202
}
194
203
204
+ func waitUntilSocketPresent (dockerSocketFN string ) error {
205
+ socketTimeout := 30 * time .Second
206
+ socketCtx , cancel := context .WithTimeout (context .Background (), socketTimeout )
207
+ defer cancel ()
208
+
209
+ ticker := time .NewTicker (100 * time .Millisecond )
210
+ defer ticker .Stop ()
211
+
212
+ for {
213
+ select {
214
+ case <- socketCtx .Done ():
215
+ log .WithError (socketCtx .Err ()).Warn ("timeout waiting for docker socket" )
216
+ return socketCtx .Err ()
217
+ case <- ticker .C :
218
+ if _ , err := os .Stat (dockerSocketFN ); err == nil {
219
+ // Socket file exists
220
+ return nil
221
+ }
222
+ }
223
+ }
224
+ }
225
+
226
+ func tryAuthenticateForAllHosts (imageAuth string ) {
227
+ splitHostAndCredentials := func (s string ) (string , string ) {
228
+ parts := strings .SplitN (s , ":" , 2 )
229
+ if len (parts ) < 2 {
230
+ return "" , ""
231
+ }
232
+ return parts [0 ], parts [1 ]
233
+ }
234
+ splitCredentials := func (host , s string ) (string , string , error ) {
235
+ credentials , err := base64 .StdEncoding .DecodeString (s )
236
+ if err != nil {
237
+ return "" , "" , fmt .Errorf ("Cannot decode docker credentials for host %s: %w" , host , err )
238
+ }
239
+ parts := strings .SplitN (string (credentials ), ":" , 2 )
240
+ if len (parts ) < 2 {
241
+ return "" , "" , fmt .Errorf ("Credentials in wrong format" )
242
+ }
243
+ return parts [0 ], parts [1 ], nil
244
+ }
245
+
246
+ authenticationPerHost := strings .Split (imageAuth , "," )
247
+ for _ , hostCredentials := range authenticationPerHost {
248
+ host , credentials := splitHostAndCredentials (hostCredentials )
249
+ if host == "" || credentials == "" {
250
+ log .Warnf ("Unable to authenticate with host %s, skipping." , host )
251
+ continue
252
+ }
253
+ username , password , decodeErr := splitCredentials (host , credentials )
254
+ if decodeErr != nil || username == "" || password == "" {
255
+ log .WithError (decodeErr ).Warnf ("Unable to authenticate with host %s, skipping." , host )
256
+ continue
257
+ }
258
+
259
+ loginCmd := exec .Command ("docker" , "login" , "--username" , username , "--password-stdin" , host )
260
+ loginCmd .SysProcAttr = & syscall.SysProcAttr {}
261
+ loginCmd .Env = append (loginCmd .Env , "USER=gitpod" )
262
+ loginCmd .SysProcAttr .Credential = & syscall.Credential {Uid : gitpodUserId , Gid : gitpodGroupId }
263
+ loginCmd .Stdin = bytes .NewBufferString (password )
264
+ loginErr := loginCmd .Run ()
265
+ if loginErr != nil {
266
+ log .WithError (loginErr ).Warnf ("Unable to authenticate with host %s, skipping.%s" , host )
267
+ continue
268
+ }
269
+ log .Infof ("Authenticated with host %s" , host )
270
+ }
271
+ }
272
+
195
273
type ConvertUserArg func (arg , value string ) ([]string , error )
196
274
197
275
var allowedDockerArgs = map [string ]ConvertUserArg {
0 commit comments