@@ -10,9 +10,11 @@ package main
1010import (
1111 "archive/tar"
1212 "bufio"
13+ "bytes"
1314 "compress/gzip"
1415 "context"
1516 "embed"
17+ "encoding/base64"
1618 "encoding/json"
1719 "fmt"
1820 "io"
@@ -58,6 +60,7 @@ var aptUpdated = false
5860const (
5961 dockerSocketFN = "/var/run/docker.sock"
6062 gitpodUserId = 33333
63+ gitpodGroupId = 33333
6164 containerIf = "eth0"
6265)
6366
@@ -185,13 +188,88 @@ func runWithinNetns() (err error) {
185188 }()
186189 }
187190
191+ if imageAuth , _ := os .LookupEnv ("GITPOD_IMAGE_AUTH" ); strings .TrimSpace (imageAuth ) != "" {
192+ if err := waitUntilSocketPresent (dockerSocketFN ); err == nil {
193+ tryAuthenticateForAllHosts (imageAuth )
194+ }
195+ }
196+
188197 err = cmd .Wait ()
189198 if err != nil {
190199 return err
191200 }
192201 return nil
193202}
194203
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+
195273type ConvertUserArg func (arg , value string ) ([]string , error )
196274
197275var allowedDockerArgs = map [string ]ConvertUserArg {
0 commit comments