diff --git a/cli/command/registry.go b/cli/command/registry.go index 75b979e18561..e39635283afa 100644 --- a/cli/command/registry.go +++ b/cli/command/registry.go @@ -194,8 +194,7 @@ func RetrieveAuthTokenFromImage(cfg *configfile.ConfigFile, image string) (strin if err != nil { return "", err } - configKey := getAuthConfigKey(reference.Domain(registryRef)) - authConfig, err := cfg.GetAuthConfig(configKey) + authConfig, err := cfg.GetAuthConfig(reference.Domain(registryRef)) if err != nil { return "", err } @@ -211,18 +210,3 @@ func RetrieveAuthTokenFromImage(cfg *configfile.ConfigFile, image string) (strin RegistryToken: authConfig.RegistryToken, }) } - -// getAuthConfigKey special-cases using the full index address of the official -// index as the AuthConfig key, and uses the (host)name[:port] for private indexes. -// -// It is similar to [registry.GetAuthConfigKey], but does not require on -// [registrytypes.IndexInfo] as intermediate. -// -// [registry.GetAuthConfigKey]: https://pkg.go.dev/github.com/docker/docker@v28.3.3+incompatible/registry#GetAuthConfigKey -// [registrytypes.IndexInfo]: https://pkg.go.dev/github.com/docker/docker@v28.3.3+incompatible/api/types/registry#IndexInfo -func getAuthConfigKey(domainName string) string { - if domainName == "docker.io" || domainName == "index.docker.io" { - return authConfigKey - } - return domainName -} diff --git a/cli/config/configfile/file.go b/cli/config/configfile/file.go index 246f23e983d8..f95cb3a5dc03 100644 --- a/cli/config/configfile/file.go +++ b/cli/config/configfile/file.go @@ -20,6 +20,34 @@ import ( "github.com/sirupsen/logrus" ) +// authConfigKey is the key used to store credentials for Docker Hub. It is +// a copy of [registry.IndexServer]. +// +// [registry.IndexServer]: https://pkg.go.dev/github.com/docker/docker@v28.5.1+incompatible/registry#IndexServer +const authConfigKey = "https://index.docker.io/v1/" + +// getAuthConfigKey returns the canonical key used to look up stored +// registry credentials for the given registry domain. +// +// For the official Docker Hub registry ("docker.io"), credentials are stored +// under the historical full index address ("https://index.docker.io/v1/"). +// +// For all other registries, the input is domainName to already be a normalized +// hostname (optionally including ":port") and is returned unchanged. +// +// This function performs key normalization only; it does not validate or parse +// the input. +// +// It is similar to [registry.GetAuthConfigKey] in the daemon. +// +// [registry.GetAuthConfigKey]: https://pkg.go.dev/github.com/docker/docker@v28.5.1+incompatible/registry#GetAuthConfigKey +func getAuthConfigKey(domainName string) string { + if domainName == "docker.io" || domainName == "index.docker.io" { + return authConfigKey + } + return domainName +} + // ConfigFile ~/.docker/config.json file info type ConfigFile struct { AuthConfigs map[string]types.AuthConfig `json:"auths"` @@ -293,7 +321,7 @@ func decodeAuth(authStr string) (string, string, error) { func (configFile *ConfigFile) GetCredentialsStore(registryHostname string) credentials.Store { store := credentials.NewFileStore(configFile) - if helper := getConfiguredCredentialStore(configFile, registryHostname); helper != "" { + if helper := getConfiguredCredentialStore(configFile, getAuthConfigKey(registryHostname)); helper != "" { store = newNativeStore(configFile, helper) } @@ -358,7 +386,8 @@ var newNativeStore = func(configFile *ConfigFile, helperSuffix string) credentia // GetAuthConfig for a repository from the credential store func (configFile *ConfigFile) GetAuthConfig(registryHostname string) (types.AuthConfig, error) { - return configFile.GetCredentialsStore(registryHostname).Get(registryHostname) + acKey := getAuthConfigKey(registryHostname) + return configFile.GetCredentialsStore(acKey).Get(acKey) } // getConfiguredCredentialStore returns the credential helper configured for the