-
Notifications
You must be signed in to change notification settings - Fork 197
/
config.go
131 lines (109 loc) · 2.96 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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package docker
import (
"encoding/base64"
"encoding/json"
"fmt"
"net/url"
"strings"
"github.com/google/go-containerregistry/pkg/name"
)
type BasicAuth string
func NewBasicAuth(username, password string) BasicAuth {
var v = new(BasicAuth)
v.Encode(username, password)
return *v
}
func (v *BasicAuth) Encode(username, password string) {
*v = BasicAuth(base64.StdEncoding.EncodeToString(
[]byte(fmt.Sprintf("%s:%s", username, password))))
}
func (v *BasicAuth) Decode() (string, string, error) {
bytes, err := base64.StdEncoding.DecodeString(string(*v))
if err != nil {
return "", "", err
}
split := strings.SplitN(string(bytes), ":", 2)
if len(split) != 2 {
return "", "", fmt.Errorf("expected username and password concatenated with a colon (:)")
}
return split[0], split[1], nil
}
func (v BasicAuth) String() string {
return "[REDACTED]"
}
// Auth represent credentials used to login to a Docker registry.
type Auth struct {
Auth BasicAuth `json:"auth,omitempty"`
Username string `json:"username,omitempty"`
Password string `json:"password,omitempty"`
}
func (v Auth) String() string {
return "[REDACTED]"
}
// Config represents Docker configuration which is typically saved as `~/.docker/config.json`.
type Config struct {
Auths map[string]Auth `json:"auths"`
}
func (c *Config) Read(contents []byte) error {
if err := json.Unmarshal(contents, c); err != nil {
return err
}
var err error
c.Auths, err = decodeAuths(c.Auths)
return err
}
func decodeAuths(auths map[string]Auth) (map[string]Auth, error) {
decodedAuths := make(map[string]Auth)
for server, entry := range auths {
if entry == (Auth{}) {
continue
}
if strings.TrimSpace(string(entry.Auth)) == "" {
decodedAuths[server] = Auth{
Username: entry.Username,
Password: entry.Password,
}
continue
}
username, password, err := entry.Auth.Decode()
if err != nil {
return nil, err
}
decodedAuths[server] = Auth{
Auth: entry.Auth,
Username: username,
Password: password,
}
}
return decodedAuths, nil
}
func (c Config) Write() ([]byte, error) {
bytes, err := json.Marshal(&c)
if err != nil {
return nil, err
}
return bytes, nil
}
// GetServerFromImageRef returns registry server from the specified imageRef.
func GetServerFromImageRef(imageRef string) (string, error) {
ref, err := name.ParseReference(imageRef)
if err != nil {
return "", err
}
return ref.Context().RegistryStr(), nil
}
// GetServerFromDockerAuthKey returns the registry server for the specified Docker auth key.
//
// In ~/.docker/config.json auth keys can be specified as URLs or host names.
// For the sake of comparison we need to normalize the registry identifier.
func GetServerFromDockerAuthKey(key string) (string, error) {
absoluteURL := key
if !(strings.HasPrefix(key, "http://") || strings.HasPrefix(key, "https://")) {
absoluteURL = "https://" + absoluteURL
}
parsed, err := url.Parse(absoluteURL)
if err != nil {
return "", err
}
return parsed.Host, nil
}