Fix for issue 3797.

Docker's logic for resolving credentials from .dockercfg accepts two kinds of matches:
1. an exact match between the dockercfg entry and the image prefix
2. a hostname match between the dockercfg entry and the image prefix

This change implements the latter, which permits the docker client to take .dockercfg entries of the form:
   https://quay.io/v1/
and use them for images of the form:
   quay.io/foo/bar
even though they are not a prefix-match.
pull/6/head
Matt Moore 2015-01-26 14:06:12 -08:00
parent 4c2d554c73
commit 2d396797a9
2 changed files with 58 additions and 3 deletions

View File

@ -66,9 +66,20 @@ func (dk *BasicDockerKeyring) Add(cfg DockerConfig) {
continue continue
} }
registry := parsed.Host + parsed.Path // The docker client allows exact matches:
dk.creds[registry] = creds // foo.bar.com/namespace
dk.index = append(dk.index, registry) // Or hostname matches:
// foo.bar.com
// See ResolveAuthConfig in docker/registry/auth.go.
if parsed.Host != "" {
// NOTE: foo.bar.com comes through as Path.
dk.creds[parsed.Host] = creds
dk.index = append(dk.index, parsed.Host)
}
if parsed.Path != "/" {
dk.creds[parsed.Host+parsed.Path] = creds
dk.index = append(dk.index, parsed.Host+parsed.Path)
}
} }
// Update the index used to identify which credentials to use for a given // Update the index used to identify which credentials to use for a given

View File

@ -262,6 +262,50 @@ func TestDockerKeyringLookup(t *testing.T) {
} }
} }
// This validates that dockercfg entries with a scheme and url path are properly matched
// by images that only match the hostname.
// NOTE: the above covers the case of a more specific match trumping just hostname.
func TestIssue3797(t *testing.T) {
rex := docker.AuthConfiguration{
Username: "rex",
Password: "tiny arms",
Email: "rex@example.com",
}
dk := &credentialprovider.BasicDockerKeyring{}
dk.Add(credentialprovider.DockerConfig{
"https://quay.io/v1/": credentialprovider.DockerConfigEntry{
Username: rex.Username,
Password: rex.Password,
Email: rex.Email,
},
})
tests := []struct {
image string
match docker.AuthConfiguration
ok bool
}{
// direct match
{"quay.io", rex, true},
// partial matches
{"quay.io/foo", rex, true},
{"quay.io/foo/bar", rex, true},
}
for i, tt := range tests {
match, ok := dk.Lookup(tt.image)
if tt.ok != ok {
t.Errorf("case %d: expected ok=%t, got %t", i, tt.ok, ok)
}
if !reflect.DeepEqual(tt.match, match) {
t.Errorf("case %d: expected match=%#v, got %#v", i, tt.match, match)
}
}
}
type imageTrackingDockerClient struct { type imageTrackingDockerClient struct {
*FakeDockerClient *FakeDockerClient
imageName string imageName string