From 25a9ad6abdcda1867a9061ff6897740ebdc22bcb Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Wed, 25 Jun 2025 09:21:46 +0200 Subject: [PATCH] vendor: github.com/docker/cli v28.3.0 full diff: https://github.com/docker/cli/compare/v28.2.2...v28.3.0 Signed-off-by: Sebastiaan van Stijn --- go.mod | 2 +- go.sum | 4 +- .../docker/cli/cli/command/registry.go | 6 +- .../docker/cli/cli/config/configfile/file.go | 85 +++++++++++- .../cli/cli/config/memorystore/store.go | 126 ++++++++++++++++++ vendor/modules.txt | 3 +- 6 files changed, 217 insertions(+), 9 deletions(-) create mode 100644 vendor/github.com/docker/cli/cli/config/memorystore/store.go diff --git a/go.mod b/go.mod index 97af91a1..60090b90 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/creack/pty v1.1.24 github.com/davecgh/go-spew v1.1.1 github.com/distribution/reference v0.6.0 - github.com/docker/cli v28.2.2+incompatible + github.com/docker/cli v28.3.0+incompatible github.com/docker/cli-docs-tool v0.10.0 github.com/docker/docker v28.3.0+incompatible github.com/docker/go-units v0.5.0 diff --git a/go.sum b/go.sum index a109fc51..5d9e93ea 100644 --- a/go.sum +++ b/go.sum @@ -106,8 +106,8 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/cli v28.2.2+incompatible h1:qzx5BNUDFqlvyq4AHzdNB7gSyVTmU4cgsyN9SdInc1A= -github.com/docker/cli v28.2.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v28.3.0+incompatible h1:s+ttruVLhB5ayeuf2BciwDVxYdKi+RoUlxmwNHV3Vfo= +github.com/docker/cli v28.3.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/cli-docs-tool v0.10.0 h1:bOD6mKynPQgojQi3s2jgcUWGp/Ebqy1SeCr9VfKQLLU= github.com/docker/cli-docs-tool v0.10.0/go.mod h1:5EM5zPnT2E7yCLERZmrDA234Vwn09fzRHP4aX1qwp1U= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= diff --git a/vendor/github.com/docker/cli/cli/command/registry.go b/vendor/github.com/docker/cli/cli/command/registry.go index de8f3254..be49d85b 100644 --- a/vendor/github.com/docker/cli/cli/command/registry.go +++ b/vendor/github.com/docker/cli/cli/command/registry.go @@ -35,7 +35,7 @@ const ( const authConfigKey = "https://index.docker.io/v1/" // RegistryAuthenticationPrivilegedFunc returns a RequestPrivilegeFunc from the specified registry index info -// for the given command. +// for the given command to prompt the user for username and password. func RegistryAuthenticationPrivilegedFunc(cli Cli, index *registrytypes.IndexInfo, cmdName string) registrytypes.RequestAuthConfig { configKey := getAuthConfigKey(index.Name) isDefaultRegistry := configKey == authConfigKey || index.Official @@ -43,7 +43,7 @@ func RegistryAuthenticationPrivilegedFunc(cli Cli, index *registrytypes.IndexInf _, _ = fmt.Fprintf(cli.Out(), "\nLogin prior to %s:\n", cmdName) authConfig, err := GetDefaultAuthConfig(cli.ConfigFile(), true, configKey, isDefaultRegistry) if err != nil { - _, _ = fmt.Fprintf(cli.Err(), "Unable to retrieve stored credentials for %s, error: %s.\n", authConfigKey, err) + _, _ = fmt.Fprintf(cli.Err(), "Unable to retrieve stored credentials for %s, error: %s.\n", configKey, err) } select { @@ -52,7 +52,7 @@ func RegistryAuthenticationPrivilegedFunc(cli Cli, index *registrytypes.IndexInf default: } - authConfig, err = PromptUserForCredentials(ctx, cli, "", "", authConfig.Username, authConfigKey) + authConfig, err = PromptUserForCredentials(ctx, cli, "", "", authConfig.Username, configKey) if err != nil { return "", err } diff --git a/vendor/github.com/docker/cli/cli/config/configfile/file.go b/vendor/github.com/docker/cli/cli/config/configfile/file.go index 24969ef6..396f9003 100644 --- a/vendor/github.com/docker/cli/cli/config/configfile/file.go +++ b/vendor/github.com/docker/cli/cli/config/configfile/file.go @@ -3,12 +3,14 @@ package configfile import ( "encoding/base64" "encoding/json" + "fmt" "io" "os" "path/filepath" "strings" "github.com/docker/cli/cli/config/credentials" + "github.com/docker/cli/cli/config/memorystore" "github.com/docker/cli/cli/config/types" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -46,6 +48,31 @@ type ConfigFile struct { Experimental string `json:"experimental,omitempty"` } +type configEnvAuth struct { + Auth string `json:"auth"` +} + +type configEnv struct { + AuthConfigs map[string]configEnvAuth `json:"auths"` +} + +// dockerEnvConfig is an environment variable that contains a JSON encoded +// credential config. It only supports storing the credentials as a base64 +// encoded string in the format base64("username:pat"). +// +// Adding additional fields will produce a parsing error. +// +// Example: +// +// { +// "auths": { +// "example.test": { +// "auth": base64-encoded-username-pat +// } +// } +// } +const dockerEnvConfig = "DOCKER_AUTH_CONFIG" + // ProxyConfig contains proxy configuration settings type ProxyConfig struct { HTTPProxy string `json:"httpProxy,omitempty"` @@ -263,10 +290,64 @@ func decodeAuth(authStr string) (string, string, error) { // GetCredentialsStore returns a new credentials store from the settings in the // configuration file func (configFile *ConfigFile) GetCredentialsStore(registryHostname string) credentials.Store { + store := credentials.NewFileStore(configFile) + if helper := getConfiguredCredentialStore(configFile, registryHostname); helper != "" { - return newNativeStore(configFile, helper) + store = newNativeStore(configFile, helper) } - return credentials.NewFileStore(configFile) + + envConfig := os.Getenv(dockerEnvConfig) + if envConfig == "" { + return store + } + + authConfig, err := parseEnvConfig(envConfig) + if err != nil { + _, _ = fmt.Fprintln(os.Stderr, "Failed to create credential store from DOCKER_AUTH_CONFIG: ", err) + return store + } + + // use DOCKER_AUTH_CONFIG if set + // it uses the native or file store as a fallback to fetch and store credentials + envStore, err := memorystore.New( + memorystore.WithAuthConfig(authConfig), + memorystore.WithFallbackStore(store), + ) + if err != nil { + _, _ = fmt.Fprintln(os.Stderr, "Failed to create credential store from DOCKER_AUTH_CONFIG: ", err) + return store + } + + return envStore +} + +func parseEnvConfig(v string) (map[string]types.AuthConfig, error) { + envConfig := &configEnv{} + decoder := json.NewDecoder(strings.NewReader(v)) + decoder.DisallowUnknownFields() + if err := decoder.Decode(envConfig); err != nil && !errors.Is(err, io.EOF) { + return nil, err + } + if decoder.More() { + return nil, errors.New("DOCKER_AUTH_CONFIG does not support more than one JSON object") + } + + authConfigs := make(map[string]types.AuthConfig) + for addr, envAuth := range envConfig.AuthConfigs { + if envAuth.Auth == "" { + return nil, fmt.Errorf("DOCKER_AUTH_CONFIG environment variable is missing key `auth` for %s", addr) + } + username, password, err := decodeAuth(envAuth.Auth) + if err != nil { + return nil, err + } + authConfigs[addr] = types.AuthConfig{ + Username: username, + Password: password, + ServerAddress: addr, + } + } + return authConfigs, nil } // var for unit testing. diff --git a/vendor/github.com/docker/cli/cli/config/memorystore/store.go b/vendor/github.com/docker/cli/cli/config/memorystore/store.go new file mode 100644 index 00000000..19908346 --- /dev/null +++ b/vendor/github.com/docker/cli/cli/config/memorystore/store.go @@ -0,0 +1,126 @@ +//go:build go1.23 + +package memorystore + +import ( + "errors" + "fmt" + "maps" + "os" + "sync" + + "github.com/docker/cli/cli/config/credentials" + "github.com/docker/cli/cli/config/types" +) + +var errValueNotFound = errors.New("value not found") + +func IsErrValueNotFound(err error) bool { + return errors.Is(err, errValueNotFound) +} + +type Config struct { + lock sync.RWMutex + memoryCredentials map[string]types.AuthConfig + fallbackStore credentials.Store +} + +func (e *Config) Erase(serverAddress string) error { + e.lock.Lock() + defer e.lock.Unlock() + delete(e.memoryCredentials, serverAddress) + + if e.fallbackStore != nil { + err := e.fallbackStore.Erase(serverAddress) + if err != nil { + _, _ = fmt.Fprintln(os.Stderr, "memorystore: ", err) + } + } + + return nil +} + +func (e *Config) Get(serverAddress string) (types.AuthConfig, error) { + e.lock.RLock() + defer e.lock.RUnlock() + authConfig, ok := e.memoryCredentials[serverAddress] + if !ok { + if e.fallbackStore != nil { + return e.fallbackStore.Get(serverAddress) + } + return types.AuthConfig{}, errValueNotFound + } + return authConfig, nil +} + +func (e *Config) GetAll() (map[string]types.AuthConfig, error) { + e.lock.RLock() + defer e.lock.RUnlock() + creds := make(map[string]types.AuthConfig) + + if e.fallbackStore != nil { + fileCredentials, err := e.fallbackStore.GetAll() + if err != nil { + _, _ = fmt.Fprintln(os.Stderr, "memorystore: ", err) + } else { + creds = fileCredentials + } + } + + maps.Copy(creds, e.memoryCredentials) + return creds, nil +} + +func (e *Config) Store(authConfig types.AuthConfig) error { + e.lock.Lock() + defer e.lock.Unlock() + e.memoryCredentials[authConfig.ServerAddress] = authConfig + + if e.fallbackStore != nil { + return e.fallbackStore.Store(authConfig) + } + return nil +} + +// WithFallbackStore sets a fallback store. +// +// Write operations will be performed on both the memory store and the +// fallback store. +// +// Read operations will first check the memory store, and if the credential +// is not found, it will then check the fallback store. +// +// Retrieving all credentials will return from both the memory store and the +// fallback store, merging the results from both stores into a single map. +// +// Data stored in the memory store will take precedence over data in the +// fallback store. +func WithFallbackStore(store credentials.Store) Options { + return func(s *Config) error { + s.fallbackStore = store + return nil + } +} + +// WithAuthConfig allows to set the initial credentials in the memory store. +func WithAuthConfig(config map[string]types.AuthConfig) Options { + return func(s *Config) error { + s.memoryCredentials = config + return nil + } +} + +type Options func(*Config) error + +// New creates a new in memory credential store +func New(opts ...Options) (credentials.Store, error) { + m := &Config{ + memoryCredentials: make(map[string]types.AuthConfig), + } + for _, opt := range opts { + if err := opt(m); err != nil { + return nil, err + } + } + return m, nil +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 68d3b5bf..266e1156 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -218,7 +218,7 @@ github.com/davecgh/go-spew/spew # github.com/distribution/reference v0.6.0 ## explicit; go 1.20 github.com/distribution/reference -# github.com/docker/cli v28.2.2+incompatible +# github.com/docker/cli v28.3.0+incompatible ## explicit github.com/docker/cli/cli github.com/docker/cli/cli-plugins/metadata @@ -230,6 +230,7 @@ github.com/docker/cli/cli/command/formatter/tabwriter github.com/docker/cli/cli/config github.com/docker/cli/cli/config/configfile github.com/docker/cli/cli/config/credentials +github.com/docker/cli/cli/config/memorystore github.com/docker/cli/cli/config/types github.com/docker/cli/cli/connhelper github.com/docker/cli/cli/connhelper/commandconn