diff --git a/pkg/credentialprovider/keyring.go b/pkg/credentialprovider/keyring.go index 518cacb4ae..6132c04bfa 100644 --- a/pkg/credentialprovider/keyring.go +++ b/pkg/credentialprovider/keyring.go @@ -66,9 +66,20 @@ func (dk *BasicDockerKeyring) Add(cfg DockerConfig) { continue } - registry := parsed.Host + parsed.Path - dk.creds[registry] = creds - dk.index = append(dk.index, registry) + // The docker client allows exact matches: + // foo.bar.com/namespace + // 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 diff --git a/pkg/kubelet/dockertools/docker_test.go b/pkg/kubelet/dockertools/docker_test.go index df1cf58c53..8609036ae1 100644 --- a/pkg/kubelet/dockertools/docker_test.go +++ b/pkg/kubelet/dockertools/docker_test.go @@ -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 { *FakeDockerClient imageName string