feat(registry): use the Docker Desktop Hub session for dhi.io

Docker Hardened Images on dhi.io authenticate with Docker Hub accounts (the registry advertises service=registry.docker.io), so resolve dhi.io credentials from the production Docker Hub session as well, with dhi.io as the server address. Other registries, including look-alikes of dhi.io, still use the Docker CLI credentials.

Signed-off-by: Alano Terblanche <[email protected]>
This commit is contained in:
Alano Terblanche
2026-10-07 14:24:28 +02:00
committed by Nicolas De loof
parent a9f71c935c
commit 81b6b59e79
3 changed files with 36 additions and 5 deletions
+8 -4
View File
@@ -103,6 +103,9 @@ type desktopAuthProvider struct {
func (p *desktopAuthProvider) GetAuthConfig(registryHostname string) (clitypes.AuthConfig, error) {
if session := p.sessionFor(registryHostname); session != nil {
if auth, ok := session.auth(); ok {
if registryHost(registryHostname) == DHIRegistryHost {
auth.ServerAddress = DHIRegistryHost
}
return auth, nil
}
}
@@ -111,18 +114,19 @@ func (p *desktopAuthProvider) GetAuthConfig(registryHostname string) (clitypes.A
func (p *desktopAuthProvider) sessionFor(registryHostname string) *desktopSession {
switch {
case GetAuthConfigKey(registryHostname) == IndexServer:
case GetAuthConfigKey(registryHostname) == IndexServer, registryHost(registryHostname) == DHIRegistryHost:
return p.hub
case isStagingRegistry(registryHostname):
case registryHost(registryHostname) == StagingRegistryHost:
return p.stagingHub
default:
return nil
}
}
func isStagingRegistry(registryHostname string) bool {
// registryHost strips the scheme and trailing slash from a registry address.
func registryHost(registryHostname string) string {
host := strings.TrimPrefix(strings.TrimPrefix(registryHostname, "https://"), "http://")
return strings.TrimSuffix(host, "/") == StagingRegistryHost
return strings.TrimSuffix(host, "/")
}
// desktopSession caches the Desktop session of one Docker Hub environment.
+26 -1
View File
@@ -194,8 +194,9 @@ func TestDesktopAuthProvider_DockerHubUsesDesktopSession(t *testing.T) {
func TestDesktopAuthProvider_OtherRegistriesUseFallback(t *testing.T) {
hosts := []string{
"ghcr.io", "localhost:5000", "registry.example.com",
// look-alikes of the staging registry
// look-alikes of the staging and DHI registries
StagingRegistryHost + ".example.com", "example.com/" + StagingRegistryHost,
DHIRegistryHost + ".example.com", "example.com/" + DHIRegistryHost, "registry." + DHIRegistryHost,
}
for _, host := range hosts {
t.Run(host, func(t *testing.T) {
@@ -212,6 +213,30 @@ func TestDesktopAuthProvider_OtherRegistriesUseFallback(t *testing.T) {
}
}
func TestDesktopAuthProvider_DHIUsesDockerHubSession(t *testing.T) {
for _, host := range []string{DHIRegistryHost, "https://" + DHIRegistryHost, "https://" + DHIRegistryHost + "/"} {
t.Run(host, func(t *testing.T) {
hub := &fakeHub{session: hubSession("hubuser", testNow.Add(time.Hour))}
p := newTestProvider(hub, nil)
p.signInToStaging()
want := desktopCredentials()
want.ServerAddress = DHIRegistryHost
got, err := p.GetAuthConfig(host)
assert.NilError(t, err)
assert.DeepEqual(t, got, want)
assert.Equal(t, len(p.fallback.hosts), 0)
assert.Equal(t, p.staging.sessionCalls.Load(), int32(0), "the staging session must not be read for DHI")
// DHI shares the cached Docker Hub session without changing it.
got, err = p.GetAuthConfig("docker.io")
assert.NilError(t, err)
assert.DeepEqual(t, got, desktopCredentials())
assert.Equal(t, hub.sessionCalls.Load(), int32(1))
})
}
}
func TestDesktopAuthProvider_StagingRegistryUsesStagingSession(t *testing.T) {
for _, host := range []string{StagingRegistryHost, StagingIndexServer, "https://" + StagingRegistryHost} {
t.Run(host, func(t *testing.T) {
+2
View File
@@ -43,6 +43,8 @@ const (
StagingRegistryHost = "registry-1-stage.docker.io"
// StagingIndexServer is the credentials key for StagingRegistryHost.
StagingIndexServer = "https://" + StagingRegistryHost + "/"
// DHIRegistryHost is the Docker Hardened Images registry.
DHIRegistryHost = "dhi.io"
)
// GetAuthConfigKey special-cases using the full index address of the official