-
Notifications
You must be signed in to change notification settings - Fork 4.7k
/
cfg.go
154 lines (139 loc) · 5.26 KB
/
cfg.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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
package dockercfg
import (
"encoding/base64"
"encoding/json"
"io/ioutil"
"os"
"os/user"
"path/filepath"
"strings"
docker "github.com/fsouza/go-dockerclient"
"github.com/golang/glog"
"github.com/spf13/pflag"
kapi "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/credentialprovider"
)
//TODO: Remove this code once the methods in Kubernetes kubelet/dockertools/config.go are public
const (
PushAuthType = "PUSH_DOCKERCFG_PATH"
PullAuthType = "PULL_DOCKERCFG_PATH"
PullSourceAuthType = "PULL_SOURCE_DOCKERCFG_PATH_"
)
// Helper contains all the valid config options for reading the local dockercfg file
type Helper struct {
}
// NewHelper creates a Flags object with the default values set.
func NewHelper() *Helper {
return &Helper{}
}
// InstallFlags installs the Docker flag helper into a FlagSet with the default
// options and default values from the Helper object.
func (h *Helper) InstallFlags(flags *pflag.FlagSet) {
}
// GetDockerAuth returns a valid Docker AuthConfiguration entry, and whether it was read
// from the local dockercfg file
func (h *Helper) GetDockerAuth(imageName, authType string) (docker.AuthConfiguration, bool) {
glog.V(3).Infof("Locating docker auth for image %s and type %s", imageName, authType)
var dockercfgPath string
if pathForAuthType := os.Getenv(authType); len(pathForAuthType) > 0 {
dockercfgPath = GetDockercfgFile(pathForAuthType)
} else {
dockercfgPath = GetDockercfgFile("")
}
if len(dockercfgPath) == 0 {
glog.V(3).Infof("Could not locate a docker config file")
return docker.AuthConfiguration{}, false
}
if _, err := os.Stat(dockercfgPath); err != nil {
glog.V(3).Infof("Problem accessing %s: %v", dockercfgPath, err)
return docker.AuthConfiguration{}, false
}
var cfg credentialprovider.DockerConfig
var err error
if strings.HasSuffix(dockercfgPath, kapi.DockerConfigJsonKey) || strings.HasSuffix(dockercfgPath, "config.json") {
cfg, err = readDockerConfigJson(dockercfgPath)
if err != nil {
glog.Errorf("Reading %s failed: %v", dockercfgPath, err)
return docker.AuthConfiguration{}, false
}
} else if strings.HasSuffix(dockercfgPath, kapi.DockerConfigKey) {
cfg, err = readDockercfg(dockercfgPath)
if err != nil {
glog.Errorf("Reading %s failed: %v", dockercfgPath, err)
return docker.AuthConfiguration{}, false
}
}
keyring := credentialprovider.BasicDockerKeyring{}
keyring.Add(cfg)
authConfs, found := keyring.Lookup(imageName)
if !found || len(authConfs) == 0 {
return docker.AuthConfiguration{}, false
}
glog.V(3).Infof("Using %s user for Docker authentication for image %s", authConfs[0].Username, imageName)
return authConfs[0], true
}
// GetDockercfgFile returns the path to the dockercfg file
func GetDockercfgFile(path string) string {
var cfgPath string
if path != "" {
cfgPath = path
// There are 3 valid ways to specify docker config in a secret.
// 1) with a .dockerconfigjson key pointing to a .docker/config.json file (the key used by k8s for
// dockerconfigjson type secrets and the new docker cfg format)
// 2) with a .dockercfg key+file (the key used by k8s for dockercfg type secrets and the old docker format)
// 3) with a config.json file because you created your secret using "oc secrets new mysecret .docker/config.json"
// so you automatically got a key named config.json containing the new docker cfg format content.
// we will check to see which one was provided in that priority order.
if _, err := os.Stat(filepath.Join(path, kapi.DockerConfigJsonKey)); err == nil {
cfgPath = filepath.Join(path, kapi.DockerConfigJsonKey)
} else if _, err := os.Stat(filepath.Join(path, kapi.DockerConfigKey)); err == nil {
cfgPath = filepath.Join(path, kapi.DockerConfigKey)
} else if _, err := os.Stat(filepath.Join(path, "config.json")); err == nil {
cfgPath = filepath.Join(path, "config.json")
}
} else if os.Getenv("DOCKERCFG_PATH") != "" {
cfgPath = os.Getenv("DOCKERCFG_PATH")
} else if currentUser, err := user.Current(); err == nil {
cfgPath = filepath.Join(currentUser.HomeDir, ".docker", "config.json")
}
glog.V(5).Infof("Using Docker authentication configuration in '%s'", cfgPath)
return cfgPath
}
// readDockercfg reads the contents of a .dockercfg file into a map
// with server name keys and AuthEntry values
func readDockercfg(filePath string) (cfg credentialprovider.DockerConfig, err error) {
content, err := ioutil.ReadFile(filePath)
if err != nil {
return
}
if err := json.Unmarshal(content, &cfg); err != nil {
return nil, err
}
return
}
// readDockerConfigJson reads the contents of a .docker/config.json file into a map
// with server name keys and AuthEntry values
func readDockerConfigJson(filePath string) (cfg credentialprovider.DockerConfig, err error) {
content, err := ioutil.ReadFile(filePath)
if err != nil {
return
}
var config credentialprovider.DockerConfigJson
if err = json.Unmarshal(content, &config); err != nil {
return
}
cfg = config.Auths
return
}
// getCredentials parses an auth string inside a dockercfg file into
// a username and password
func getCredentials(auth string) (username, password string, err error) {
creds, err := base64.StdEncoding.DecodeString(auth)
if err != nil {
return
}
unamepass := strings.Split(string(creds), ":")
username = unamepass[0]
password = unamepass[1]
return
}