From e491078fc69ea21a5482193f2c93c6d660aa7467 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Mon, 29 Sep 2025 11:54:28 +0200 Subject: [PATCH] cli/command: explicitly map AuthConfig fields instead of a direct cast Commit [cli@27b2797] forked the AuthConfig type from the API, and changed existing code to do a direct cast / convert of the forked type to the API type. This can cause issues if the API types diverges, such as the removal of the Email field. This patch explicitly maps each field to the corresponding API type, but adds some TODOs, because various code-paths only included a subset of the fields, which may be intentional for fields that were meant to be handled on the daemon / registry-client only. We should evaluate these conversions to make sure these fields should be sent from the client or not (and possibly even removed from the API type). [cli@27b2797]: https://github.com/docker/cli/commit/27b2797f7deb3ca5b7f80371d825113deb1faca1 Signed-off-by: Sebastiaan van Stijn (cherry picked from commit 9f02d9643de89954f87bd99a978c7273c0a7c1ea) Signed-off-by: Sebastiaan van Stijn --- cli/command/image/build.go | 13 +++++++++-- cli/command/registry.go | 40 ++++++++++++++++++++++++++++------ cli/command/registry/login.go | 33 +++++++++++++++++++++++++--- cli/command/registry/search.go | 11 +++++++++- cli/command/registry_test.go | 13 +++++++++-- 5 files changed, 95 insertions(+), 15 deletions(-) diff --git a/cli/command/image/build.go b/cli/command/image/build.go index a8d2c4ae2e67..c0b002390cb7 100644 --- a/cli/command/image/build.go +++ b/cli/command/image/build.go @@ -340,8 +340,17 @@ func runBuild(ctx context.Context, dockerCli command.Cli, options buildOptions) configFile := dockerCli.ConfigFile() creds, _ := configFile.GetAllCredentials() authConfigs := make(map[string]registrytypes.AuthConfig, len(creds)) - for k, auth := range creds { - authConfigs[k] = registrytypes.AuthConfig(auth) + for k, authConfig := range creds { + authConfigs[k] = registrytypes.AuthConfig{ + Username: authConfig.Username, + Password: authConfig.Password, + ServerAddress: authConfig.ServerAddress, + + // TODO(thaJeztah): Are these expected to be included? + Auth: authConfig.Auth, + IdentityToken: authConfig.IdentityToken, + RegistryToken: authConfig.RegistryToken, + } } buildOpts := imageBuildOptions(dockerCli, options) buildOpts.Version = buildtypes.BuilderV1 diff --git a/cli/command/registry.go b/cli/command/registry.go index dd6e74d4d46f..0deb74cd9170 100644 --- a/cli/command/registry.go +++ b/cli/command/registry.go @@ -77,7 +77,16 @@ func ResolveAuthConfig(cfg *configfile.ConfigFile, index *registrytypes.IndexInf } a, _ := cfg.GetAuthConfig(configKey) - return registrytypes.AuthConfig(a) + return registrytypes.AuthConfig{ + Username: a.Username, + Password: a.Password, + ServerAddress: a.ServerAddress, + + // TODO(thaJeztah): Are these expected to be included? + Auth: a.Auth, + IdentityToken: a.IdentityToken, + RegistryToken: a.RegistryToken, + } } // GetDefaultAuthConfig gets the default auth config given a serverAddress @@ -86,19 +95,27 @@ func GetDefaultAuthConfig(cfg *configfile.ConfigFile, checkCredStore bool, serve if !isDefaultRegistry { serverAddress = credentials.ConvertToHostname(serverAddress) } - authconfig := configtypes.AuthConfig{} + authCfg := configtypes.AuthConfig{} var err error if checkCredStore { - authconfig, err = cfg.GetAuthConfig(serverAddress) + authCfg, err = cfg.GetAuthConfig(serverAddress) if err != nil { return registrytypes.AuthConfig{ ServerAddress: serverAddress, }, err } } - authconfig.ServerAddress = serverAddress - authconfig.IdentityToken = "" - return registrytypes.AuthConfig(authconfig), nil + + return registrytypes.AuthConfig{ + Username: authCfg.Username, + Password: authCfg.Password, + ServerAddress: serverAddress, + + // TODO(thaJeztah): Are these expected to be included? + Auth: authCfg.Auth, + IdentityToken: "", + RegistryToken: authCfg.RegistryToken, + }, nil } // PromptUserForCredentials handles the CLI prompt for the user to input @@ -213,7 +230,16 @@ func RetrieveAuthTokenFromImage(cfg *configfile.ConfigFile, image string) (strin return "", err } - encodedAuth, err := registrytypes.EncodeAuthConfig(registrytypes.AuthConfig(authConfig)) + encodedAuth, err := registrytypes.EncodeAuthConfig(registrytypes.AuthConfig{ + Username: authConfig.Username, + Password: authConfig.Password, + ServerAddress: authConfig.ServerAddress, + + // TODO(thaJeztah): Are these expected to be included? + Auth: authConfig.Auth, + IdentityToken: authConfig.IdentityToken, + RegistryToken: authConfig.RegistryToken, + }) if err != nil { return "", err } diff --git a/cli/command/registry/login.go b/cli/command/registry/login.go index 09e997c80090..d8b48210051a 100644 --- a/cli/command/registry/login.go +++ b/cli/command/registry/login.go @@ -259,12 +259,30 @@ func loginWithDeviceCodeFlow(ctx context.Context, dockerCLI command.Cli) (msg st return "", err } - response, err := loginWithRegistry(ctx, dockerCLI.Client(), registrytypes.AuthConfig(*authConfig)) + response, err := loginWithRegistry(ctx, dockerCLI.Client(), registrytypes.AuthConfig{ + Username: authConfig.Username, + Password: authConfig.Password, + ServerAddress: authConfig.ServerAddress, + + // TODO(thaJeztah): Are these expected to be included? + Auth: authConfig.Auth, + IdentityToken: authConfig.IdentityToken, + RegistryToken: authConfig.RegistryToken, + }) if err != nil { return "", err } - if err = storeCredentials(dockerCLI.ConfigFile(), registrytypes.AuthConfig(*authConfig)); err != nil { + if err = storeCredentials(dockerCLI.ConfigFile(), registrytypes.AuthConfig{ + Username: authConfig.Username, + Password: authConfig.Password, + ServerAddress: authConfig.ServerAddress, + + // TODO(thaJeztah): Are these expected to be included? + Auth: authConfig.Auth, + IdentityToken: authConfig.IdentityToken, + RegistryToken: authConfig.RegistryToken, + }); err != nil { return "", err } @@ -273,7 +291,16 @@ func loginWithDeviceCodeFlow(ctx context.Context, dockerCLI command.Cli) (msg st func storeCredentials(cfg *configfile.ConfigFile, authConfig registrytypes.AuthConfig) error { creds := cfg.GetCredentialsStore(authConfig.ServerAddress) - if err := creds.Store(configtypes.AuthConfig(authConfig)); err != nil { + if err := creds.Store(configtypes.AuthConfig{ + Username: authConfig.Username, + Password: authConfig.Password, + ServerAddress: authConfig.ServerAddress, + + // TODO(thaJeztah): Are these expected to be included? + Auth: authConfig.Auth, + IdentityToken: authConfig.IdentityToken, + RegistryToken: authConfig.RegistryToken, + }); err != nil { return errors.Errorf("Error saving credentials: %v", err) } diff --git a/cli/command/registry/search.go b/cli/command/registry/search.go index 654fe1440f04..f735cdaeedd1 100644 --- a/cli/command/registry/search.go +++ b/cli/command/registry/search.go @@ -102,7 +102,16 @@ func getAuth(dockerCLI command.Cli, reposName string) (encodedAuth string, err e // "no credentials found"). We'll get an error when search failed, // so fine to ignore in most situations. authConfig, _ := dockerCLI.ConfigFile().GetAuthConfig(authCfgKey) - return registrytypes.EncodeAuthConfig(registrytypes.AuthConfig(authConfig)) + return registrytypes.EncodeAuthConfig(registrytypes.AuthConfig{ + Username: authConfig.Username, + Password: authConfig.Password, + ServerAddress: authConfig.ServerAddress, + + // TODO(thaJeztah): Are these expected to be included? + Auth: authConfig.Auth, + IdentityToken: authConfig.IdentityToken, + RegistryToken: authConfig.RegistryToken, + }) } // splitReposSearchTerm breaks a search term into an index name and remote name diff --git a/cli/command/registry_test.go b/cli/command/registry_test.go index 353bfb2fd8fa..853dcc875eae 100644 --- a/cli/command/registry_test.go +++ b/cli/command/registry_test.go @@ -58,8 +58,17 @@ func TestGetDefaultAuthConfig(t *testing.T) { }, } cfg := configfile.New("filename") - for _, authconfig := range testAuthConfigs { - assert.Check(t, cfg.GetCredentialsStore(authconfig.ServerAddress).Store(configtypes.AuthConfig(authconfig))) + for _, authConfig := range testAuthConfigs { + assert.Check(t, cfg.GetCredentialsStore(authConfig.ServerAddress).Store(configtypes.AuthConfig{ + Username: authConfig.Username, + Password: authConfig.Password, + ServerAddress: authConfig.ServerAddress, + + // TODO(thaJeztah): Are these expected to be included? + Auth: authConfig.Auth, + IdentityToken: authConfig.IdentityToken, + RegistryToken: authConfig.RegistryToken, + })) } for _, tc := range testCases { serverAddress := tc.inputServerAddress