/
config.go
117 lines (94 loc) · 2.63 KB
/
config.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package config
import (
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"os"
"strings"
)
// DefaultDockerJSON is the defalt path for Docker JSON config file
var DefaultDockerJSON = "~/.docker/config.json"
// Config encapsulates configuration loaded from Docker 'config.json' file
type Config struct {
Auths map[string]Auth `json:"auths"`
usernames map[string]string
passwords map[string]string
}
// Auth contains Docker registry username and password in base64-encoded form
type Auth struct {
B64Auth string `json:"auth"`
}
// IsEmpty return true if structure has no relevant data inside
func (c *Config) IsEmpty() bool {
return len(c.Auths) == 0
}
// GetCredentials gets per-registry credentials from loaded Docker config
func (c *Config) GetCredentials(registry string) (string, string, bool) {
if _, defined := c.usernames[registry]; !defined {
return "", "", false
}
return c.usernames[registry], c.passwords[registry], true
}
// GetRegistryAuth gets per-registry base64 authentication string
func (c *Config) GetRegistryAuth(registry string) string {
username, password, defined := c.GetCredentials(registry)
if !defined {
return ""
}
jsonString := fmt.Sprintf(`{ "username": "%s", "password": "%s" }`, username, password)
return base64.StdEncoding.EncodeToString([]byte(jsonString))
}
// Load loads a Config object from Docker JSON configuration file specified
func Load(fileName string) (*Config, error) {
f, err := os.Open(fixPath(fileName))
defer f.Close()
if err != nil {
if fileName == DefaultDockerJSON {
return &Config{}, nil
}
return nil, err
}
c, err := parseConfig(f)
if err != nil {
return nil, err
}
c.usernames = make(map[string]string)
c.passwords = make(map[string]string)
for registry, a := range c.Auths {
b, err := base64.StdEncoding.DecodeString(a.B64Auth)
if err != nil {
return nil, err
}
authenticationToken := string(b)
usernameAndPassword := strings.Split(authenticationToken, ":")
if len(usernameAndPassword) != 2 {
if fileName != DefaultDockerJSON {
errStr := "Invalid auth for Docker registry: %s\nBase64-encoded string is wrong: %s (%s)\n"
return nil, errors.New(
fmt.Sprint(
errStr,
registry,
a.B64Auth,
authenticationToken,
),
)
}
continue
}
c.usernames[registry] = usernameAndPassword[0]
c.passwords[registry] = usernameAndPassword[1]
}
return c, nil
}
func parseConfig(f *os.File) (*Config, error) {
c := &Config{}
err := json.NewDecoder(f).Decode(c)
if err != nil {
return nil, err
}
return c, nil
}
func fixPath(path string) string {
return strings.Replace(path, "~", os.Getenv("HOME"), 1)
}