Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 22 additions & 7 deletions internal/ocidocker/dockerhub.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,24 @@
package ocidocker

var DockerHubHosts = map[string]struct{}{
"": {},
"docker.io": {},
"index.docker.io": {},
"registry-1.docker.io": {},
"registry.hub.docker.com": {},
}
import (
"sync"
)

var (
// DockerHubHosts is a map of hostnames associated with Docker Hub's registry. The number is a priority ranking
// used to determine the order we will search for auth credentials
DockerHubHosts = map[string]byte{
"docker.io": 0,
"index.docker.io": 1,
"registry-1.docker.io": 2,
"registry.hub.docker.com": 3,
}
// DockerHubHostsSorted is a slice of hostnames associated with Docker Hub's registry, sorted by their ranking
DockerHubHostsSorted = sync.OnceValue(func() []string {
sorted := make([]string, len(DockerHubHosts))
for host, rank := range DockerHubHosts {
sorted[rank] = host
}
return sorted
})
)
12 changes: 12 additions & 0 deletions internal/ocidocker/dockerhub_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package ocidocker

import "testing"

func TestHostsSorted(t *testing.T) {
sorted := DockerHubHostsSorted()
for i, host := range sorted {
if i != int(DockerHubHosts[host]) {
t.Errorf("host %s not sorted", host)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice - I was worried this might not catch certain edge cases, but it sure does: https://go.dev/play/p/VcLZWcOKSUg

the error message sucks, but makes it really obvious you need to go back and look at the list of exactly 5 items and figure out which one is screwed up 😂 ❤️

}
}
}
2 changes: 1 addition & 1 deletion ociauth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ func (r *registry) setAuthorizationFromChallenge(ctx context.Context, req *http.
// the outer context is cancelled, but we'll ignore that. We probably shouldn't.
func (r *registry) init() error {
inner := func() error {
info, err := r.config.EntryForRegistry(r.host)
info, err := dockerWrapper{r.config}.EntryForRegistry(r.host)
if err != nil {
return fmt.Errorf("cannot acquire auth info for registry %q: %v", r.host, err)
}
Expand Down
31 changes: 31 additions & 0 deletions ociauth/docker.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package ociauth

import (
"github.com/docker/oci/internal/ocidocker"
)

// DockerWrapper is an ociauth.Config implementation that wraps an underlying ociauth.Config in order to check
// credentials for every Docker Hub domain when credentials for any Hub domain are requested.
type dockerWrapper struct {
Config
}

// EntryForRegistry returns credentials for a given host.
func (w dockerWrapper) EntryForRegistry(host string) (ConfigEntry, error) {
var zero ConfigEntry // "EntryForRegistry" doesn't return an error on a miss - it just returns an empty object (so we create this to have something to trivially compare against for our fallback)
if entry, err := w.Config.EntryForRegistry(host); err == nil && entry != zero {
return entry, err
} else if _, ok := ocidocker.DockerHubHosts[host]; ok {
for _, dockerHubHost := range ocidocker.DockerHubHostsSorted() {
if dockerHubHost == "" {
continue
}
if entry, err = w.Config.EntryForRegistry(dockerHubHost); err == nil && entry != zero {
return entry, err
}
}
return entry, err
} else {
return entry, err
}
}
3 changes: 2 additions & 1 deletion ociref/reference.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,8 @@ func ParseRelative(refStr string) (Reference, error) {
return Reference{}, fmt.Errorf("invalid digest %q: %v", ref.Digest, err)
}
}
if _, ok := ocidocker.DockerHubHosts[ref.Host]; ok {
// Normalize Docker Hub registry hosts, also default to Docker if none is provided
if _, ok := ocidocker.DockerHubHosts[ref.Host]; ok || ref.Host == "" {
ref.Host = "docker.io"
}
if ref.Host == "docker.io" && !strings.Contains(ref.Repository, "/") {
Expand Down
Loading