gitlab.com/jfprevost/gitlab-runner-notlscheck@v11.11.4+incompatible/helpers/docker/auth_config.go (about) 1 package docker_helpers 2 3 import ( 4 "bytes" 5 "encoding/base64" 6 "encoding/json" 7 "fmt" 8 "io" 9 "os" 10 "os/user" 11 "path" 12 "strings" 13 14 "github.com/docker/cli/cli/config/configfile" 15 "github.com/docker/cli/cli/config/credentials" 16 "github.com/docker/docker/api/types" 17 "github.com/docker/docker/pkg/homedir" 18 ) 19 20 // DefaultDockerRegistry is the name of the index 21 const DefaultDockerRegistry = "docker.io" 22 23 // EncodeAuthConfig constructs a token from an AuthConfig, suitable for 24 // authorizing against the Docker API with. 25 func EncodeAuthConfig(authConfig *types.AuthConfig) (string, error) { 26 var buf bytes.Buffer 27 if err := json.NewEncoder(&buf).Encode(authConfig); err != nil { 28 return "", err 29 } 30 31 return base64.URLEncoding.EncodeToString(buf.Bytes()), nil 32 } 33 34 // SplitDockerImageName breaks a reposName into an index name and remote name 35 func SplitDockerImageName(reposName string) (string, string) { 36 nameParts := strings.SplitN(reposName, "/", 2) 37 var indexName, remoteName string 38 if len(nameParts) == 1 || (!strings.Contains(nameParts[0], ".") && 39 !strings.Contains(nameParts[0], ":") && nameParts[0] != "localhost") { 40 // This is a Docker Index repos (ex: samalba/hipache or ubuntu) 41 // 'docker.io' 42 indexName = DefaultDockerRegistry 43 remoteName = reposName 44 } else { 45 indexName = nameParts[0] 46 remoteName = nameParts[1] 47 } 48 49 if indexName == "index."+DefaultDockerRegistry { 50 indexName = DefaultDockerRegistry 51 } 52 return indexName, remoteName 53 } 54 55 var HomeDirectory = homedir.Get() 56 57 func ReadDockerAuthConfigsFromHomeDir(userName string) (map[string]types.AuthConfig, error) { 58 homeDir := HomeDirectory 59 60 if userName != "" { 61 u, err := user.Lookup(userName) 62 if err != nil { 63 return nil, err 64 } 65 homeDir = u.HomeDir 66 } 67 68 if homeDir == "" { 69 return nil, fmt.Errorf("Failed to get home directory") 70 } 71 72 p := path.Join(homeDir, ".docker", "config.json") 73 74 r, err := os.Open(p) 75 defer r.Close() 76 77 if err != nil { 78 p := path.Join(homeDir, ".dockercfg") 79 r, err = os.Open(p) 80 if err != nil && !os.IsNotExist(err) { 81 return nil, err 82 } 83 } 84 85 if r == nil { 86 return make(map[string]types.AuthConfig), nil 87 } 88 89 return ReadAuthConfigsFromReader(r) 90 } 91 92 func ReadAuthConfigsFromReader(r io.Reader) (map[string]types.AuthConfig, error) { 93 config := &configfile.ConfigFile{} 94 95 if err := config.LoadFromReader(r); err != nil { 96 return nil, err 97 } 98 99 auths := make(map[string]types.AuthConfig) 100 addAll(auths, config.AuthConfigs) 101 102 if config.CredentialsStore != "" { 103 authsFromCredentialsStore, err := readAuthConfigsFromCredentialsStore(config) 104 if err != nil { 105 return nil, err 106 } 107 addAll(auths, authsFromCredentialsStore) 108 } 109 110 return auths, nil 111 } 112 113 func readAuthConfigsFromCredentialsStore(config *configfile.ConfigFile) (map[string]types.AuthConfig, error) { 114 store := credentials.NewNativeStore(config, config.CredentialsStore) 115 116 newAuths, err := store.GetAll() 117 118 if err != nil { 119 return nil, err 120 } 121 122 return newAuths, nil 123 } 124 125 func addAll(to, from map[string]types.AuthConfig) { 126 for reg, ac := range from { 127 to[reg] = ac 128 } 129 } 130 131 // ResolveDockerAuthConfig taken from: https://github.com/docker/docker/blob/master/registry/auth.go 132 func ResolveDockerAuthConfig(indexName string, configs map[string]types.AuthConfig) *types.AuthConfig { 133 if configs == nil { 134 return nil 135 } 136 137 convertToHostname := func(url string) string { 138 stripped := url 139 if strings.HasPrefix(url, "http://") { 140 stripped = strings.Replace(url, "http://", "", 1) 141 } else if strings.HasPrefix(url, "https://") { 142 stripped = strings.Replace(url, "https://", "", 1) 143 } 144 145 nameParts := strings.SplitN(stripped, "/", 2) 146 if nameParts[0] == "index."+DefaultDockerRegistry { 147 return DefaultDockerRegistry 148 } 149 return nameParts[0] 150 } 151 152 // Maybe they have a legacy config file, we will iterate the keys converting 153 // them to the new format and testing 154 for registry, authConfig := range configs { 155 if indexName == convertToHostname(registry) { 156 return &authConfig 157 } 158 } 159 160 // When all else fails, return an empty auth config 161 return nil 162 }