forked from openshift/origin
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcredentials.go
88 lines (72 loc) · 3.12 KB
/
credentials.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
package dockercredentials
import (
"net/url"
"strings"
"github.com/golang/glog"
"github.com/docker/distribution/registry/client/auth"
"k8s.io/kubernetes/pkg/credentialprovider"
"github.com/openshift/origin/pkg/image/registryclient"
)
var (
emptyKeyring = &credentialprovider.BasicDockerKeyring{}
)
func NewLocal() auth.CredentialStore {
return &keyringCredentialStore{
DockerKeyring: credentialprovider.NewDockerKeyring(),
RefreshTokenStore: registryclient.NewRefreshTokenStore(),
}
}
type keyringCredentialStore struct {
credentialprovider.DockerKeyring
registryclient.RefreshTokenStore
}
func (s *keyringCredentialStore) Basic(url *url.URL) (string, string) {
return BasicFromKeyring(s.DockerKeyring, url)
}
// BasicFromKeyring finds Basic authorization credentials from a Docker keyring for the given URL as username and
// password. It returns empty strings if no such URL matches.
func BasicFromKeyring(keyring credentialprovider.DockerKeyring, target *url.URL) (string, string) {
// TODO: compare this logic to Docker authConfig in v2 configuration
var value string
if len(target.Scheme) == 0 || target.Scheme == "https" {
value = target.Host + target.Path
} else {
// always require an explicit port to look up HTTP credentials
if !strings.Contains(target.Host, ":") {
value = target.Host + ":80" + target.Path
} else {
value = target.Host + target.Path
}
}
// Lookup(...) expects an image (not a URL path).
// The keyring strips /v1/ and /v2/ version prefixes,
// so we should also when selecting a valid auth for a URL.
pathWithSlash := target.Path + "/"
if strings.HasPrefix(pathWithSlash, "/v1/") || strings.HasPrefix(pathWithSlash, "/v2/") {
value = target.Host + target.Path[3:]
}
configs, found := keyring.Lookup(value)
if !found || len(configs) == 0 {
// do a special case check for docker.io to match historical lookups when we respond to a challenge
if value == "auth.docker.io/token" {
glog.V(5).Infof("Being asked for %s (%s), trying %s for legacy behavior", target, value, "index.docker.io/v1")
return BasicFromKeyring(keyring, &url.URL{Host: "index.docker.io", Path: "/v1"})
}
// docker 1.9 saves 'docker.io' in config in f23, see https://bugzilla.redhat.com/show_bug.cgi?id=1309739
if value == "index.docker.io" {
glog.V(5).Infof("Being asked for %s (%s), trying %s for legacy behavior", target, value, "docker.io")
return BasicFromKeyring(keyring, &url.URL{Host: "docker.io"})
}
// try removing the canonical ports for the given requests
if (strings.HasSuffix(target.Host, ":443") && target.Scheme == "https") ||
(strings.HasSuffix(target.Host, ":80") && target.Scheme == "http") {
host := strings.SplitN(target.Host, ":", 2)[0]
glog.V(5).Infof("Being asked for %s (%s), trying %s without port", target, value, host)
return BasicFromKeyring(keyring, &url.URL{Scheme: target.Scheme, Host: host, Path: target.Path})
}
glog.V(5).Infof("Unable to find a secret to match %s (%s)", target, value)
return "", ""
}
glog.V(5).Infof("Found secret to match %s (%s): %s", target, value, configs[0].ServerAddress)
return configs[0].Username, configs[0].Password
}