From ec8eac685fd95cac6989674aba325abfffdd442b Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Thu, 4 Dec 2025 00:12:09 +0100 Subject: [PATCH] cli/config/types: make AuthConfig an alias for registry.AuthConfig The AuthConfig type was forked from the docker/docker API types in commit 27b2797f7deb3ca5b7f80371d825113deb1faca1 to reduce the dependency on the docker API types in BuildKit and Buildx (see [buildkit#800]). Now that the API is a separate module with minimal dependencies, this should no longer be a big concern, so this patch un-forks the type. [buildkit#800]: https://github.com/moby/buildkit/pull/800 Signed-off-by: Sebastiaan van Stijn --- cli/command/container/auth_config_utils.go | 4 +- cli/command/container/create.go | 4 +- cli/command/registry.go | 31 ++++---- cli/command/registry/login.go | 3 +- cli/command/registry/login_test.go | 49 ++++++------ cli/command/registry_test.go | 3 +- cli/config/config.go | 4 +- cli/config/configfile/file.go | 76 +++++++++---------- cli/config/configfile/file_test.go | 82 ++++++++++----------- cli/config/credentials/credentials.go | 8 +- cli/config/credentials/file_store.go | 12 +-- cli/config/credentials/file_store_test.go | 28 +++---- cli/config/credentials/native_store.go | 24 +++--- cli/config/credentials/native_store_test.go | 32 ++++---- cli/config/memorystore/store.go | 18 ++--- cli/config/memorystore/store_test.go | 16 ++-- cli/config/types/authconfig.go | 17 +---- internal/oauth/manager/manager.go | 10 +-- internal/oauth/manager/manager_test.go | 22 +++--- 19 files changed, 214 insertions(+), 229 deletions(-) diff --git a/cli/command/container/auth_config_utils.go b/cli/command/container/auth_config_utils.go index f908bd84982f..efae3be4b419 100644 --- a/cli/command/container/auth_config_utils.go +++ b/cli/command/container/auth_config_utils.go @@ -7,7 +7,7 @@ import ( "github.com/docker/cli/cli/config" "github.com/docker/cli/cli/config/configfile" - "github.com/docker/cli/cli/config/types" + "github.com/moby/moby/api/types/registry" ) // readCredentials resolves auth-config from the current environment to be @@ -22,7 +22,7 @@ import ( // formatted, or when failing to read from the credentials store. // // A nil value is returned if neither option contained any credentials. -func readCredentials(dockerCLI config.Provider) (creds map[string]types.AuthConfig, _ error) { +func readCredentials(dockerCLI config.Provider) (creds map[string]registry.AuthConfig, _ error) { if v, ok := os.LookupEnv("DOCKER_AUTH_CONFIG"); ok && v != "" { // The results are expected to have been unmarshaled the same as // when reading from a config-file, which includes decoding the diff --git a/cli/command/container/create.go b/cli/command/container/create.go index a58eeaa16d2e..410f1da5ea34 100644 --- a/cli/command/container/create.go +++ b/cli/command/container/create.go @@ -18,11 +18,11 @@ import ( "github.com/docker/cli/cli/command" "github.com/docker/cli/cli/command/completion" "github.com/docker/cli/cli/config/configfile" - "github.com/docker/cli/cli/config/types" "github.com/docker/cli/cli/streams" "github.com/docker/cli/internal/jsonstream" "github.com/docker/cli/opts" "github.com/moby/moby/api/types/mount" + "github.com/moby/moby/api/types/registry" "github.com/moby/moby/client" ocispec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/spf13/cobra" @@ -239,7 +239,7 @@ func createContainer(ctx context.Context, dockerCli command.Cli, containerCfg *c } const dockerConfigPathInContainer = "/run/secrets/docker/config.json" - var apiSocketCreds map[string]types.AuthConfig + var apiSocketCreds map[string]registry.AuthConfig if options.useAPISocket { // We'll create two new mounts to handle this flag: diff --git a/cli/command/registry.go b/cli/command/registry.go index 87c81c6da5da..a17c6bf5d3e6 100644 --- a/cli/command/registry.go +++ b/cli/command/registry.go @@ -11,13 +11,12 @@ import ( "github.com/distribution/reference" "github.com/docker/cli/cli/config/configfile" "github.com/docker/cli/cli/config/credentials" - configtypes "github.com/docker/cli/cli/config/types" "github.com/docker/cli/cli/hints" "github.com/docker/cli/cli/streams" "github.com/docker/cli/internal/prompt" "github.com/docker/cli/internal/tui" "github.com/moby/moby/api/pkg/authconfig" - registrytypes "github.com/moby/moby/api/types/registry" + "github.com/moby/moby/api/types/registry" "github.com/morikuni/aec" ) @@ -40,14 +39,14 @@ const authConfigKey = "https://index.docker.io/v1/" // found. // // Deprecated: this function is no longer used, and will be removed in the next release. -func ResolveAuthConfig(cfg *configfile.ConfigFile, index *registrytypes.IndexInfo) registrytypes.AuthConfig { +func ResolveAuthConfig(cfg *configfile.ConfigFile, index *registry.IndexInfo) registry.AuthConfig { configKey := index.Name if index.Official { configKey = authConfigKey } a, _ := cfg.GetAuthConfig(configKey) - return registrytypes.AuthConfig{ + return registry.AuthConfig{ Username: a.Username, Password: a.Password, ServerAddress: a.ServerAddress, @@ -61,22 +60,22 @@ func ResolveAuthConfig(cfg *configfile.ConfigFile, index *registrytypes.IndexInf // GetDefaultAuthConfig gets the default auth config given a serverAddress // If credentials for given serverAddress exists in the credential store, the configuration will be populated with values in it -func GetDefaultAuthConfig(cfg *configfile.ConfigFile, checkCredStore bool, serverAddress string, isDefaultRegistry bool) (registrytypes.AuthConfig, error) { +func GetDefaultAuthConfig(cfg *configfile.ConfigFile, checkCredStore bool, serverAddress string, isDefaultRegistry bool) (registry.AuthConfig, error) { if !isDefaultRegistry { serverAddress = credentials.ConvertToHostname(serverAddress) } - authCfg := configtypes.AuthConfig{} + authCfg := registry.AuthConfig{} var err error if checkCredStore { authCfg, err = cfg.GetAuthConfig(serverAddress) if err != nil { - return registrytypes.AuthConfig{ + return registry.AuthConfig{ ServerAddress: serverAddress, }, err } } - return registrytypes.AuthConfig{ + return registry.AuthConfig{ Username: authCfg.Username, Password: authCfg.Password, ServerAddress: serverAddress, @@ -97,7 +96,7 @@ func GetDefaultAuthConfig(cfg *configfile.ConfigFile, checkCredStore bool, serve // If defaultUsername is not empty, the username prompt includes that username // and the user can hit enter without inputting a username to use that default // username. -func PromptUserForCredentials(ctx context.Context, cli Cli, argUser, argPassword, defaultUsername, serverAddress string) (registrytypes.AuthConfig, error) { +func PromptUserForCredentials(ctx context.Context, cli Cli, argUser, argPassword, defaultUsername, serverAddress string) (registry.AuthConfig, error) { // On Windows, force the use of the regular OS stdin stream. // // See: @@ -134,13 +133,13 @@ func PromptUserForCredentials(ctx context.Context, cli Cli, argUser, argPassword var err error argUser, err = prompt.ReadInput(ctx, cli.In(), cli.Out(), msg) if err != nil { - return registrytypes.AuthConfig{}, err + return registry.AuthConfig{}, err } if argUser == "" { argUser = defaultUsername } if argUser == "" { - return registrytypes.AuthConfig{}, errors.New("error: username is required") + return registry.AuthConfig{}, errors.New("error: username is required") } } @@ -148,7 +147,7 @@ func PromptUserForCredentials(ctx context.Context, cli Cli, argUser, argPassword if argPassword == "" { restoreInput, err := prompt.DisableInputEcho(cli.In()) if err != nil { - return registrytypes.AuthConfig{}, err + return registry.AuthConfig{}, err } defer func() { if err := restoreInput(); err != nil { @@ -168,15 +167,15 @@ func PromptUserForCredentials(ctx context.Context, cli Cli, argUser, argPassword argPassword, err = prompt.ReadInput(ctx, cli.In(), cli.Out(), "Password: ") if err != nil { - return registrytypes.AuthConfig{}, err + return registry.AuthConfig{}, err } _, _ = fmt.Fprintln(cli.Out()) if argPassword == "" { - return registrytypes.AuthConfig{}, errors.New("error: password is required") + return registry.AuthConfig{}, errors.New("error: password is required") } } - return registrytypes.AuthConfig{ + return registry.AuthConfig{ Username: argUser, Password: argPassword, ServerAddress: serverAddress, @@ -200,7 +199,7 @@ func RetrieveAuthTokenFromImage(cfg *configfile.ConfigFile, image string) (strin return "", err } - encodedAuth, err := authconfig.Encode(registrytypes.AuthConfig{ + encodedAuth, err := authconfig.Encode(registry.AuthConfig{ Username: authConfig.Username, Password: authConfig.Password, ServerAddress: authConfig.ServerAddress, diff --git a/cli/command/registry/login.go b/cli/command/registry/login.go index 17d0d883ba1d..a292e1fd0a59 100644 --- a/cli/command/registry/login.go +++ b/cli/command/registry/login.go @@ -11,7 +11,6 @@ import ( "github.com/docker/cli/cli" "github.com/docker/cli/cli/command" "github.com/docker/cli/cli/config/configfile" - configtypes "github.com/docker/cli/cli/config/types" "github.com/docker/cli/internal/commands" "github.com/docker/cli/internal/oauth/manager" "github.com/docker/cli/internal/registry" @@ -283,7 +282,7 @@ 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{ + if err := creds.Store(registrytypes.AuthConfig{ Username: authConfig.Username, Password: authConfig.Password, ServerAddress: authConfig.ServerAddress, diff --git a/cli/command/registry/login_test.go b/cli/command/registry/login_test.go index 41f833483503..fc477be32054 100644 --- a/cli/command/registry/login_test.go +++ b/cli/command/registry/login_test.go @@ -10,7 +10,6 @@ import ( "time" "github.com/creack/pty" - configtypes "github.com/docker/cli/cli/config/types" "github.com/docker/cli/cli/streams" "github.com/docker/cli/internal/prompt" "github.com/docker/cli/internal/registry" @@ -90,14 +89,14 @@ func TestLoginWithCredStoreCreds(t *testing.T) { func TestRunLogin(t *testing.T) { testCases := []struct { doc string - priorCredentials map[string]configtypes.AuthConfig + priorCredentials map[string]registrytypes.AuthConfig input loginOptions - expectedCredentials map[string]configtypes.AuthConfig + expectedCredentials map[string]registrytypes.AuthConfig expectedErr string }{ { doc: "valid auth from store", - priorCredentials: map[string]configtypes.AuthConfig{ + priorCredentials: map[string]registrytypes.AuthConfig{ "reg1": { Username: "my-username", Password: "a-password", @@ -107,7 +106,7 @@ func TestRunLogin(t *testing.T) { input: loginOptions{ serverAddress: "reg1", }, - expectedCredentials: map[string]configtypes.AuthConfig{ + expectedCredentials: map[string]registrytypes.AuthConfig{ "reg1": { Username: "my-username", Password: "a-password", @@ -117,7 +116,7 @@ func TestRunLogin(t *testing.T) { }, { doc: "expired auth from store", - priorCredentials: map[string]configtypes.AuthConfig{ + priorCredentials: map[string]registrytypes.AuthConfig{ "reg1": { Username: "my-username", Password: expiredPassword, @@ -131,13 +130,13 @@ func TestRunLogin(t *testing.T) { }, { doc: "store valid username and password", - priorCredentials: map[string]configtypes.AuthConfig{}, + priorCredentials: map[string]registrytypes.AuthConfig{}, input: loginOptions{ serverAddress: "reg1", user: "my-username", password: "p2", }, - expectedCredentials: map[string]configtypes.AuthConfig{ + expectedCredentials: map[string]registrytypes.AuthConfig{ "reg1": { Username: "my-username", Password: "p2", @@ -147,7 +146,7 @@ func TestRunLogin(t *testing.T) { }, { doc: "unknown user w/ prior credentials", - priorCredentials: map[string]configtypes.AuthConfig{ + priorCredentials: map[string]registrytypes.AuthConfig{ "reg1": { Username: "my-username", Password: "a-password", @@ -160,7 +159,7 @@ func TestRunLogin(t *testing.T) { password: "a-password", }, expectedErr: errUnknownUser, - expectedCredentials: map[string]configtypes.AuthConfig{ + expectedCredentials: map[string]registrytypes.AuthConfig{ "reg1": { Username: "a-password", Password: "a-password", @@ -170,24 +169,24 @@ func TestRunLogin(t *testing.T) { }, { doc: "unknown user w/o prior credentials", - priorCredentials: map[string]configtypes.AuthConfig{}, + priorCredentials: map[string]registrytypes.AuthConfig{}, input: loginOptions{ serverAddress: "reg1", user: unknownUser, password: "a-password", }, expectedErr: errUnknownUser, - expectedCredentials: map[string]configtypes.AuthConfig{}, + expectedCredentials: map[string]registrytypes.AuthConfig{}, }, { doc: "store valid token", - priorCredentials: map[string]configtypes.AuthConfig{}, + priorCredentials: map[string]registrytypes.AuthConfig{}, input: loginOptions{ serverAddress: "reg1", user: "my-username", password: useToken, }, - expectedCredentials: map[string]configtypes.AuthConfig{ + expectedCredentials: map[string]registrytypes.AuthConfig{ "reg1": { Username: "my-username", IdentityToken: useToken, @@ -197,7 +196,7 @@ func TestRunLogin(t *testing.T) { }, { doc: "valid token from store", - priorCredentials: map[string]configtypes.AuthConfig{ + priorCredentials: map[string]registrytypes.AuthConfig{ "reg1": { Username: "my-username", Password: useToken, @@ -207,7 +206,7 @@ func TestRunLogin(t *testing.T) { input: loginOptions{ serverAddress: "reg1", }, - expectedCredentials: map[string]configtypes.AuthConfig{ + expectedCredentials: map[string]registrytypes.AuthConfig{ "reg1": { Username: "my-username", IdentityToken: useToken, @@ -217,12 +216,12 @@ func TestRunLogin(t *testing.T) { }, { doc: "no registry specified defaults to index server", - priorCredentials: map[string]configtypes.AuthConfig{}, + priorCredentials: map[string]registrytypes.AuthConfig{}, input: loginOptions{ user: "my-username", password: "my-password", }, - expectedCredentials: map[string]configtypes.AuthConfig{ + expectedCredentials: map[string]registrytypes.AuthConfig{ registry.IndexServer: { Username: "my-username", Password: "my-password", @@ -232,13 +231,13 @@ func TestRunLogin(t *testing.T) { }, { doc: "registry-1.docker.io", - priorCredentials: map[string]configtypes.AuthConfig{}, + priorCredentials: map[string]registrytypes.AuthConfig{}, input: loginOptions{ serverAddress: "registry-1.docker.io", user: "my-username", password: "my-password", }, - expectedCredentials: map[string]configtypes.AuthConfig{ + expectedCredentials: map[string]registrytypes.AuthConfig{ "registry-1.docker.io": { Username: "my-username", Password: "my-password", @@ -249,13 +248,13 @@ func TestRunLogin(t *testing.T) { // Regression test for https://github.com/docker/cli/issues/5382 { doc: "sanitizes server address to remove repo", - priorCredentials: map[string]configtypes.AuthConfig{}, + priorCredentials: map[string]registrytypes.AuthConfig{}, input: loginOptions{ serverAddress: "registry-1.docker.io/bork/test", user: "my-username", password: "a-password", }, - expectedCredentials: map[string]configtypes.AuthConfig{ + expectedCredentials: map[string]registrytypes.AuthConfig{ "registry-1.docker.io": { Username: "my-username", Password: "a-password", @@ -266,7 +265,7 @@ func TestRunLogin(t *testing.T) { // Regression test for https://github.com/docker/cli/issues/5382 { doc: "updates credential if server address includes repo", - priorCredentials: map[string]configtypes.AuthConfig{ + priorCredentials: map[string]registrytypes.AuthConfig{ "registry-1.docker.io": { Username: "my-username", Password: "a-password", @@ -278,7 +277,7 @@ func TestRunLogin(t *testing.T) { user: "my-username", password: "new-password", }, - expectedCredentials: map[string]configtypes.AuthConfig{ + expectedCredentials: map[string]registrytypes.AuthConfig{ "registry-1.docker.io": { Username: "my-username", Password: "new-password", @@ -428,7 +427,7 @@ func TestLoginNonInteractive(t *testing.T) { if serverAddress == "" { serverAddress = "https://index.docker.io/v1/" } - assert.NilError(t, cfg.GetCredentialsStore(serverAddress).Store(configtypes.AuthConfig{ + assert.NilError(t, cfg.GetCredentialsStore(serverAddress).Store(registrytypes.AuthConfig{ Username: "my-username", Password: "my-password", ServerAddress: serverAddress, diff --git a/cli/command/registry_test.go b/cli/command/registry_test.go index 91372ad56eb1..a5a5dd0f72a4 100644 --- a/cli/command/registry_test.go +++ b/cli/command/registry_test.go @@ -7,7 +7,6 @@ import ( "github.com/docker/cli/cli/command" "github.com/docker/cli/cli/config/configfile" - configtypes "github.com/docker/cli/cli/config/types" "github.com/moby/moby/api/pkg/authconfig" "github.com/moby/moby/api/types/registry" "gotest.tools/v3/assert" @@ -60,7 +59,7 @@ func TestGetDefaultAuthConfig(t *testing.T) { } cfg := configfile.New("filename") for _, authConfig := range testAuthConfigs { - assert.Check(t, cfg.GetCredentialsStore(authConfig.ServerAddress).Store(configtypes.AuthConfig{ + assert.Check(t, cfg.GetCredentialsStore(authConfig.ServerAddress).Store(registry.AuthConfig{ Username: authConfig.Username, Password: authConfig.Password, ServerAddress: authConfig.ServerAddress, diff --git a/cli/config/config.go b/cli/config/config.go index 5a637805091c..65307ff929f7 100644 --- a/cli/config/config.go +++ b/cli/config/config.go @@ -12,7 +12,7 @@ import ( "github.com/docker/cli/cli/config/configfile" "github.com/docker/cli/cli/config/credentials" - "github.com/docker/cli/cli/config/types" + "github.com/moby/moby/api/types/registry" ) const ( @@ -109,7 +109,7 @@ func Path(p ...string) (string, error) { // a reader. It returns an error if configData is malformed. func LoadFromReader(configData io.Reader) (*configfile.ConfigFile, error) { configFile := configfile.ConfigFile{ - AuthConfigs: make(map[string]types.AuthConfig), + AuthConfigs: make(map[string]registry.AuthConfig), } err := configFile.LoadFromReader(configData) return &configFile, err diff --git a/cli/config/configfile/file.go b/cli/config/configfile/file.go index fab3ed4cba13..bb4ec4112fa2 100644 --- a/cli/config/configfile/file.go +++ b/cli/config/configfile/file.go @@ -12,37 +12,37 @@ import ( "github.com/docker/cli/cli/config/credentials" "github.com/docker/cli/cli/config/memorystore" - "github.com/docker/cli/cli/config/types" + "github.com/moby/moby/api/types/registry" "github.com/sirupsen/logrus" ) // ConfigFile ~/.docker/config.json file info type ConfigFile struct { - AuthConfigs map[string]types.AuthConfig `json:"auths"` - HTTPHeaders map[string]string `json:"HttpHeaders,omitempty"` - PsFormat string `json:"psFormat,omitempty"` - ImagesFormat string `json:"imagesFormat,omitempty"` - NetworksFormat string `json:"networksFormat,omitempty"` - PluginsFormat string `json:"pluginsFormat,omitempty"` - VolumesFormat string `json:"volumesFormat,omitempty"` - StatsFormat string `json:"statsFormat,omitempty"` - DetachKeys string `json:"detachKeys,omitempty"` - CredentialsStore string `json:"credsStore,omitempty"` - CredentialHelpers map[string]string `json:"credHelpers,omitempty"` - Filename string `json:"-"` // Note: for internal use only - ServiceInspectFormat string `json:"serviceInspectFormat,omitempty"` - ServicesFormat string `json:"servicesFormat,omitempty"` - TasksFormat string `json:"tasksFormat,omitempty"` - SecretFormat string `json:"secretFormat,omitempty"` - ConfigFormat string `json:"configFormat,omitempty"` - NodesFormat string `json:"nodesFormat,omitempty"` - PruneFilters []string `json:"pruneFilters,omitempty"` - Proxies map[string]ProxyConfig `json:"proxies,omitempty"` - CurrentContext string `json:"currentContext,omitempty"` - CLIPluginsExtraDirs []string `json:"cliPluginsExtraDirs,omitempty"` - Plugins map[string]map[string]string `json:"plugins,omitempty"` - Aliases map[string]string `json:"aliases,omitempty"` - Features map[string]string `json:"features,omitempty"` + AuthConfigs map[string]registry.AuthConfig `json:"auths"` + HTTPHeaders map[string]string `json:"HttpHeaders,omitempty"` + PsFormat string `json:"psFormat,omitempty"` + ImagesFormat string `json:"imagesFormat,omitempty"` + NetworksFormat string `json:"networksFormat,omitempty"` + PluginsFormat string `json:"pluginsFormat,omitempty"` + VolumesFormat string `json:"volumesFormat,omitempty"` + StatsFormat string `json:"statsFormat,omitempty"` + DetachKeys string `json:"detachKeys,omitempty"` + CredentialsStore string `json:"credsStore,omitempty"` + CredentialHelpers map[string]string `json:"credHelpers,omitempty"` + Filename string `json:"-"` // Note: for internal use only + ServiceInspectFormat string `json:"serviceInspectFormat,omitempty"` + ServicesFormat string `json:"servicesFormat,omitempty"` + TasksFormat string `json:"tasksFormat,omitempty"` + SecretFormat string `json:"secretFormat,omitempty"` + ConfigFormat string `json:"configFormat,omitempty"` + NodesFormat string `json:"nodesFormat,omitempty"` + PruneFilters []string `json:"pruneFilters,omitempty"` + Proxies map[string]ProxyConfig `json:"proxies,omitempty"` + CurrentContext string `json:"currentContext,omitempty"` + CLIPluginsExtraDirs []string `json:"cliPluginsExtraDirs,omitempty"` + Plugins map[string]map[string]string `json:"plugins,omitempty"` + Aliases map[string]string `json:"aliases,omitempty"` + Features map[string]string `json:"features,omitempty"` } type configEnvAuth struct { @@ -82,7 +82,7 @@ type ProxyConfig struct { // New initializes an empty configuration file for the given filename 'fn' func New(fn string) *ConfigFile { return &ConfigFile{ - AuthConfigs: make(map[string]types.AuthConfig), + AuthConfigs: make(map[string]registry.AuthConfig), HTTPHeaders: make(map[string]string), Filename: fn, Plugins: make(map[string]map[string]string), @@ -120,9 +120,9 @@ func (configFile *ConfigFile) ContainsAuth() bool { } // GetAuthConfigs returns the mapping of repo to auth configuration -func (configFile *ConfigFile) GetAuthConfigs() map[string]types.AuthConfig { +func (configFile *ConfigFile) GetAuthConfigs() map[string]registry.AuthConfig { if configFile.AuthConfigs == nil { - configFile.AuthConfigs = make(map[string]types.AuthConfig) + configFile.AuthConfigs = make(map[string]registry.AuthConfig) } return configFile.AuthConfigs } @@ -131,7 +131,7 @@ func (configFile *ConfigFile) GetAuthConfigs() map[string]types.AuthConfig { // the given writer func (configFile *ConfigFile) SaveToWriter(writer io.Writer) error { // Encode sensitive data into a new/temp struct - tmpAuthConfigs := make(map[string]types.AuthConfig, len(configFile.AuthConfigs)) + tmpAuthConfigs := make(map[string]registry.AuthConfig, len(configFile.AuthConfigs)) for k, authConfig := range configFile.AuthConfigs { authCopy := authConfig // encode and save the authstring, while blanking out the original fields @@ -249,7 +249,7 @@ func (configFile *ConfigFile) ParseProxyConfig(host string, runOpts map[string]* } // encodeAuth creates a base64 encoded string to containing authorization information -func encodeAuth(authConfig *types.AuthConfig) string { +func encodeAuth(authConfig *registry.AuthConfig) string { if authConfig.Username == "" && authConfig.Password == "" { return "" } @@ -318,7 +318,7 @@ func (configFile *ConfigFile) GetCredentialsStore(registryHostname string) crede return envStore } -func parseEnvConfig(v string) (map[string]types.AuthConfig, error) { +func parseEnvConfig(v string) (map[string]registry.AuthConfig, error) { envConfig := &configEnv{} decoder := json.NewDecoder(strings.NewReader(v)) decoder.DisallowUnknownFields() @@ -329,7 +329,7 @@ func parseEnvConfig(v string) (map[string]types.AuthConfig, error) { return nil, errors.New("DOCKER_AUTH_CONFIG does not support more than one JSON object") } - authConfigs := make(map[string]types.AuthConfig) + authConfigs := make(map[string]registry.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) @@ -338,7 +338,7 @@ func parseEnvConfig(v string) (map[string]types.AuthConfig, error) { if err != nil { return nil, err } - authConfigs[addr] = types.AuthConfig{ + authConfigs[addr] = registry.AuthConfig{ Username: username, Password: password, ServerAddress: addr, @@ -353,7 +353,7 @@ 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) { +func (configFile *ConfigFile) GetAuthConfig(registryHostname string) (registry.AuthConfig, error) { return configFile.GetCredentialsStore(registryHostname).Get(registryHostname) } @@ -371,9 +371,9 @@ func getConfiguredCredentialStore(c *ConfigFile, registryHostname string) string // GetAllCredentials returns all of the credentials stored in all of the // configured credential stores. -func (configFile *ConfigFile) GetAllCredentials() (map[string]types.AuthConfig, error) { - auths := make(map[string]types.AuthConfig) - addAll := func(from map[string]types.AuthConfig) { +func (configFile *ConfigFile) GetAllCredentials() (map[string]registry.AuthConfig, error) { + auths := make(map[string]registry.AuthConfig) + addAll := func(from map[string]registry.AuthConfig) { for reg, ac := range from { auths[reg] = ac } diff --git a/cli/config/configfile/file_test.go b/cli/config/configfile/file_test.go index 92df02c74352..91a4688b1ac8 100644 --- a/cli/config/configfile/file_test.go +++ b/cli/config/configfile/file_test.go @@ -8,7 +8,7 @@ import ( "testing" "github.com/docker/cli/cli/config/credentials" - "github.com/docker/cli/cli/config/types" + "github.com/moby/moby/api/types/registry" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" "gotest.tools/v3/fs" @@ -16,10 +16,10 @@ import ( ) func TestEncodeAuth(t *testing.T) { - newAuthConfig := &types.AuthConfig{Username: "ken", Password: "test"} + newAuthConfig := ®istry.AuthConfig{Username: "ken", Password: "test"} authStr := encodeAuth(newAuthConfig) - expected := &types.AuthConfig{} + expected := ®istry.AuthConfig{} var err error expected.Username, expected.Password, err = decodeAuth(authStr) assert.NilError(t, err) @@ -168,7 +168,7 @@ func TestConfigFile(t *testing.T) { type mockNativeStore struct { GetAllCallCount int - authConfigs map[string]types.AuthConfig + authConfigs map[string]registry.AuthConfig authConfigErrors map[string]error } @@ -177,29 +177,29 @@ func (c *mockNativeStore) Erase(registryHostname string) error { return nil } -func (c *mockNativeStore) Get(registryHostname string) (types.AuthConfig, error) { +func (c *mockNativeStore) Get(registryHostname string) (registry.AuthConfig, error) { return c.authConfigs[registryHostname], c.authConfigErrors[registryHostname] } -func (c *mockNativeStore) GetAll() (map[string]types.AuthConfig, error) { +func (c *mockNativeStore) GetAll() (map[string]registry.AuthConfig, error) { c.GetAllCallCount++ return c.authConfigs, nil } -func (*mockNativeStore) Store(_ types.AuthConfig) error { +func (*mockNativeStore) Store(_ registry.AuthConfig) error { return nil } // make sure it satisfies the interface var _ credentials.Store = (*mockNativeStore)(nil) -func NewMockNativeStore(authConfigs map[string]types.AuthConfig, authConfigErrors map[string]error) credentials.Store { +func NewMockNativeStore(authConfigs map[string]registry.AuthConfig, authConfigErrors map[string]error) credentials.Store { return &mockNativeStore{authConfigs: authConfigs, authConfigErrors: authConfigErrors} } func TestGetAllCredentialsFileStoreOnly(t *testing.T) { configFile := New("filename") - exampleAuth := types.AuthConfig{ + exampleAuth := registry.AuthConfig{ Username: "user", Password: "pass", } @@ -208,7 +208,7 @@ func TestGetAllCredentialsFileStoreOnly(t *testing.T) { authConfigs, err := configFile.GetAllCredentials() assert.NilError(t, err) - expected := make(map[string]types.AuthConfig) + expected := make(map[string]registry.AuthConfig) expected["example.com/foo"] = exampleAuth assert.Check(t, is.DeepEqual(expected, authConfigs)) } @@ -217,12 +217,12 @@ func TestGetAllCredentialsCredsStore(t *testing.T) { configFile := New("filename") configFile.CredentialsStore = "test_creds_store" testRegistryHostname := "example.com" - expectedAuth := types.AuthConfig{ + expectedAuth := registry.AuthConfig{ Username: "user", Password: "pass", } - testCredsStore := NewMockNativeStore(map[string]types.AuthConfig{testRegistryHostname: expectedAuth}, nil) + testCredsStore := NewMockNativeStore(map[string]registry.AuthConfig{testRegistryHostname: expectedAuth}, nil) tmpNewNativeStore := newNativeStore defer func() { newNativeStore = tmpNewNativeStore }() @@ -233,7 +233,7 @@ func TestGetAllCredentialsCredsStore(t *testing.T) { authConfigs, err := configFile.GetAllCredentials() assert.NilError(t, err) - expected := make(map[string]types.AuthConfig) + expected := make(map[string]registry.AuthConfig) expected[testRegistryHostname] = expectedAuth assert.Check(t, is.DeepEqual(expected, authConfigs)) assert.Check(t, is.Equal(1, testCredsStore.(*mockNativeStore).GetAllCallCount)) @@ -249,7 +249,7 @@ func TestGetAllCredentialsCredStoreErrorHandling(t *testing.T) { workingHelperRegistryHostname: "cred_helper", brokenHelperRegistryHostname: "broken_cred_helper", } - expectedAuth := types.AuthConfig{ + expectedAuth := registry.AuthConfig{ Username: "username", Password: "pass", } @@ -259,7 +259,7 @@ func TestGetAllCredentialsCredStoreErrorHandling(t *testing.T) { brokenHelperRegistryHostname: errors.New("an error"), } - testCredsStore := NewMockNativeStore(map[string]types.AuthConfig{ + testCredsStore := NewMockNativeStore(map[string]registry.AuthConfig{ workingHelperRegistryHostname: expectedAuth, // configure an auth entry for the "broken" credential // helper that will throw an error @@ -288,11 +288,11 @@ func TestGetAllCredentialsCredHelper(t *testing.T) { testExtraCredHelperRegistryHostname = "somethingweird.com" ) - unexpectedCredHelperAuth := types.AuthConfig{ + unexpectedCredHelperAuth := registry.AuthConfig{ Username: "file_store_user", Password: "file_store_pass", } - expectedCredHelperAuth := types.AuthConfig{ + expectedCredHelperAuth := registry.AuthConfig{ Username: "cred_helper_user", Password: "cred_helper_pass", } @@ -300,7 +300,7 @@ func TestGetAllCredentialsCredHelper(t *testing.T) { configFile := New("filename") configFile.CredentialHelpers = map[string]string{testCredHelperRegistryHostname: testCredHelperSuffix} - testCredHelper := NewMockNativeStore(map[string]types.AuthConfig{ + testCredHelper := NewMockNativeStore(map[string]registry.AuthConfig{ testCredHelperRegistryHostname: expectedCredHelperAuth, // Add in an extra auth entry which doesn't appear in CredentialHelpers section of the configFile. // This verifies that only explicitly configured registries are being requested from the cred helpers. @@ -316,7 +316,7 @@ func TestGetAllCredentialsCredHelper(t *testing.T) { authConfigs, err := configFile.GetAllCredentials() assert.NilError(t, err) - expected := make(map[string]types.AuthConfig) + expected := make(map[string]registry.AuthConfig) expected[testCredHelperRegistryHostname] = expectedCredHelperAuth assert.Check(t, is.DeepEqual(expected, authConfigs)) assert.Check(t, is.Equal(0, testCredHelper.(*mockNativeStore).GetAllCallCount)) @@ -329,11 +329,11 @@ func TestGetAllCredentialsFileStoreAndCredHelper(t *testing.T) { testCredHelperRegistryHostname = "credhelper.com" ) - expectedFileStoreAuth := types.AuthConfig{ + expectedFileStoreAuth := registry.AuthConfig{ Username: "file_store_user", Password: "file_store_pass", } - expectedCredHelperAuth := types.AuthConfig{ + expectedCredHelperAuth := registry.AuthConfig{ Username: "cred_helper_user", Password: "cred_helper_pass", } @@ -342,7 +342,7 @@ func TestGetAllCredentialsFileStoreAndCredHelper(t *testing.T) { configFile.CredentialHelpers = map[string]string{testCredHelperRegistryHostname: testCredHelperSuffix} configFile.AuthConfigs[testFileStoreRegistryHostname] = expectedFileStoreAuth - testCredHelper := NewMockNativeStore(map[string]types.AuthConfig{testCredHelperRegistryHostname: expectedCredHelperAuth}, nil) + testCredHelper := NewMockNativeStore(map[string]registry.AuthConfig{testCredHelperRegistryHostname: expectedCredHelperAuth}, nil) newNativeStore = func(configFile *ConfigFile, helperSuffix string) credentials.Store { return testCredHelper @@ -353,7 +353,7 @@ func TestGetAllCredentialsFileStoreAndCredHelper(t *testing.T) { authConfigs, err := configFile.GetAllCredentials() assert.NilError(t, err) - expected := make(map[string]types.AuthConfig) + expected := make(map[string]registry.AuthConfig) expected[testFileStoreRegistryHostname] = expectedFileStoreAuth expected[testCredHelperRegistryHostname] = expectedCredHelperAuth assert.Check(t, is.DeepEqual(expected, authConfigs)) @@ -372,17 +372,17 @@ func TestGetAllCredentialsCredStoreAndCredHelper(t *testing.T) { configFile.CredentialsStore = testCredStoreSuffix configFile.CredentialHelpers = map[string]string{testCredHelperRegistryHostname: testCredHelperSuffix} - expectedCredStoreAuth := types.AuthConfig{ + expectedCredStoreAuth := registry.AuthConfig{ Username: "cred_store_user", Password: "cred_store_pass", } - expectedCredHelperAuth := types.AuthConfig{ + expectedCredHelperAuth := registry.AuthConfig{ Username: "cred_helper_user", Password: "cred_helper_pass", } - testCredHelper := NewMockNativeStore(map[string]types.AuthConfig{testCredHelperRegistryHostname: expectedCredHelperAuth}, nil) - testCredsStore := NewMockNativeStore(map[string]types.AuthConfig{testCredStoreRegistryHostname: expectedCredStoreAuth}, nil) + testCredHelper := NewMockNativeStore(map[string]registry.AuthConfig{testCredHelperRegistryHostname: expectedCredHelperAuth}, nil) + testCredsStore := NewMockNativeStore(map[string]registry.AuthConfig{testCredStoreRegistryHostname: expectedCredStoreAuth}, nil) tmpNewNativeStore := newNativeStore defer func() { newNativeStore = tmpNewNativeStore }() @@ -396,7 +396,7 @@ func TestGetAllCredentialsCredStoreAndCredHelper(t *testing.T) { authConfigs, err := configFile.GetAllCredentials() assert.NilError(t, err) - expected := make(map[string]types.AuthConfig) + expected := make(map[string]registry.AuthConfig) expected[testCredStoreRegistryHostname] = expectedCredStoreAuth expected[testCredHelperRegistryHostname] = expectedCredHelperAuth assert.Check(t, is.DeepEqual(expected, authConfigs)) @@ -415,17 +415,17 @@ func TestGetAllCredentialsCredHelperOverridesDefaultStore(t *testing.T) { configFile.CredentialsStore = testCredStoreSuffix configFile.CredentialHelpers = map[string]string{testRegistryHostname: testCredHelperSuffix} - unexpectedCredStoreAuth := types.AuthConfig{ + unexpectedCredStoreAuth := registry.AuthConfig{ Username: "cred_store_user", Password: "cred_store_pass", } - expectedCredHelperAuth := types.AuthConfig{ + expectedCredHelperAuth := registry.AuthConfig{ Username: "cred_helper_user", Password: "cred_helper_pass", } - testCredHelper := NewMockNativeStore(map[string]types.AuthConfig{testRegistryHostname: expectedCredHelperAuth}, nil) - testCredsStore := NewMockNativeStore(map[string]types.AuthConfig{testRegistryHostname: unexpectedCredStoreAuth}, nil) + testCredHelper := NewMockNativeStore(map[string]registry.AuthConfig{testRegistryHostname: expectedCredHelperAuth}, nil) + testCredsStore := NewMockNativeStore(map[string]registry.AuthConfig{testRegistryHostname: unexpectedCredStoreAuth}, nil) tmpNewNativeStore := newNativeStore defer func() { newNativeStore = tmpNewNativeStore }() @@ -439,7 +439,7 @@ func TestGetAllCredentialsCredHelperOverridesDefaultStore(t *testing.T) { authConfigs, err := configFile.GetAllCredentials() assert.NilError(t, err) - expected := make(map[string]types.AuthConfig) + expected := make(map[string]registry.AuthConfig) expected[testRegistryHostname] = expectedCredHelperAuth assert.Check(t, is.DeepEqual(expected, authConfigs)) assert.Check(t, is.Equal(1, testCredsStore.(*mockNativeStore).GetAllCallCount)) @@ -450,19 +450,19 @@ func TestLoadFromReaderWithUsernamePassword(t *testing.T) { configFile := New("test-load") defer os.Remove("test-load") - want := types.AuthConfig{ + want := registry.AuthConfig{ Username: "user", Password: "pass", } - for _, tc := range []types.AuthConfig{ + for _, tc := range []registry.AuthConfig{ want, { Auth: encodeAuth(&want), }, } { cf := ConfigFile{ - AuthConfigs: map[string]types.AuthConfig{ + AuthConfigs: map[string]registry.AuthConfig{ "example.com/foo": tc, }, } @@ -508,7 +508,7 @@ func TestGetAllCredentialsFromEnvironment(t *testing.T) { authConfigs, err := config.GetAllCredentials() assert.NilError(t, err) - expected := map[string]types.AuthConfig{ + expected := map[string]registry.AuthConfig{ "env.example.test": { Username: "env_user", Password: "env_pass", @@ -519,7 +519,7 @@ func TestGetAllCredentialsFromEnvironment(t *testing.T) { }) t.Run("malformed DOCKER_AUTH_CONFIG should fallback to underlying store", func(t *testing.T) { - fallbackStore := map[string]types.AuthConfig{ + fallbackStore := map[string]registry.AuthConfig{ "fallback.example.test": { Username: "fallback_user", Password: "fallback_pass", @@ -541,7 +541,7 @@ func TestGetAllCredentialsFromEnvironment(t *testing.T) { t.Run("can fetch credentials from DOCKER_AUTH_CONFIG and underlying store", func(t *testing.T) { configFile := New("filename") - exampleAuth := types.AuthConfig{ + exampleAuth := registry.AuthConfig{ Username: "user", Password: "pass", } @@ -552,7 +552,7 @@ func TestGetAllCredentialsFromEnvironment(t *testing.T) { authConfigs, err := configFile.GetAllCredentials() assert.NilError(t, err) - expected := map[string]types.AuthConfig{ + expected := map[string]registry.AuthConfig{ "foo.example.test": exampleAuth, "env.example.test": { Username: "env_user", @@ -592,7 +592,7 @@ func TestParseEnvConfig(t *testing.T) { t.Run("should be able to load env credentials", func(t *testing.T) { got, err := parseEnvConfig(envTestAuthConfig) assert.NilError(t, err) - expected := map[string]types.AuthConfig{ + expected := map[string]registry.AuthConfig{ "env.example.test": { Username: "env_user", Password: "env_pass", diff --git a/cli/config/credentials/credentials.go b/cli/config/credentials/credentials.go index 28d58ec48d7d..63ca4cc4d01d 100644 --- a/cli/config/credentials/credentials.go +++ b/cli/config/credentials/credentials.go @@ -1,7 +1,7 @@ package credentials import ( - "github.com/docker/cli/cli/config/types" + "github.com/moby/moby/api/types/registry" ) // Store is the interface that any credentials store must implement. @@ -9,9 +9,9 @@ type Store interface { // Erase removes credentials from the store for a given server. Erase(serverAddress string) error // Get retrieves credentials from the store for a given server. - Get(serverAddress string) (types.AuthConfig, error) + Get(serverAddress string) (registry.AuthConfig, error) // GetAll retrieves all the credentials from the store. - GetAll() (map[string]types.AuthConfig, error) + GetAll() (map[string]registry.AuthConfig, error) // Store saves credentials in the store. - Store(authConfig types.AuthConfig) error + Store(authConfig registry.AuthConfig) error } diff --git a/cli/config/credentials/file_store.go b/cli/config/credentials/file_store.go index c69312b01490..1e87d848f174 100644 --- a/cli/config/credentials/file_store.go +++ b/cli/config/credentials/file_store.go @@ -8,12 +8,12 @@ import ( "strings" "sync/atomic" - "github.com/docker/cli/cli/config/types" + "github.com/moby/moby/api/types/registry" ) type store interface { Save() error - GetAuthConfigs() map[string]types.AuthConfig + GetAuthConfigs() map[string]registry.AuthConfig GetFilename() string } @@ -40,7 +40,7 @@ func (c *fileStore) Erase(serverAddress string) error { } // Get retrieves credentials for a specific server from the file store. -func (c *fileStore) Get(serverAddress string) (types.AuthConfig, error) { +func (c *fileStore) Get(serverAddress string) (registry.AuthConfig, error) { authConfig, ok := c.file.GetAuthConfigs()[serverAddress] if !ok { // Maybe they have a legacy config file, we will iterate the keys converting @@ -51,12 +51,12 @@ func (c *fileStore) Get(serverAddress string) (types.AuthConfig, error) { } } - authConfig = types.AuthConfig{} + authConfig = registry.AuthConfig{} } return authConfig, nil } -func (c *fileStore) GetAll() (map[string]types.AuthConfig, error) { +func (c *fileStore) GetAll() (map[string]registry.AuthConfig, error) { return c.file.GetAuthConfigs(), nil } @@ -77,7 +77,7 @@ var alreadyPrinted atomic.Bool // Store saves the given credentials in the file store. This function is // idempotent and does not update the file if credentials did not change. -func (c *fileStore) Store(authConfig types.AuthConfig) error { +func (c *fileStore) Store(authConfig registry.AuthConfig) error { authConfigs := c.file.GetAuthConfigs() if oldAuthConfig, ok := authConfigs[authConfig.ServerAddress]; ok && oldAuthConfig == authConfig { // Credentials didn't change, so skip updating the configuration file. diff --git a/cli/config/credentials/file_store_test.go b/cli/config/credentials/file_store_test.go index d4c8375ea25e..2a5161c370eb 100644 --- a/cli/config/credentials/file_store_test.go +++ b/cli/config/credentials/file_store_test.go @@ -3,13 +3,13 @@ package credentials import ( "testing" - "github.com/docker/cli/cli/config/types" + "github.com/moby/moby/api/types/registry" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" ) type fakeStore struct { - configs map[string]types.AuthConfig + configs map[string]registry.AuthConfig saveFn func(*fakeStore) error } @@ -22,7 +22,7 @@ func (f *fakeStore) Save() error { return nil } -func (f *fakeStore) GetAuthConfigs() map[string]types.AuthConfig { +func (f *fakeStore) GetAuthConfigs() map[string]registry.AuthConfig { return f.configs } @@ -36,18 +36,18 @@ func TestFileStoreIdempotent(t *testing.T) { var saveCount, expectedSaveCount int s := NewFileStore(&fakeStore{ - configs: map[string]types.AuthConfig{}, + configs: map[string]registry.AuthConfig{}, saveFn: func(*fakeStore) error { saveCount++ return nil }, }) - authOne := types.AuthConfig{ + authOne := registry.AuthConfig{ Username: "foo@example.com", Auth: "super_secret_token", ServerAddress: "https://example.com", } - authTwo := types.AuthConfig{ + authTwo := registry.AuthConfig{ Username: "bar@example.com", Auth: "also_super_secret_token", ServerAddress: "https://other.example.com", @@ -81,14 +81,14 @@ func TestFileStoreIdempotent(t *testing.T) { assert.NilError(t, s.Erase(authOne.ServerAddress)) retrievedAuth, err := s.Get(authOne.ServerAddress) assert.NilError(t, err) - assert.Check(t, is.Equal(retrievedAuth, types.AuthConfig{})) + assert.Check(t, is.Equal(retrievedAuth, registry.AuthConfig{})) assert.Check(t, is.Equal(saveCount, expectedSaveCount)) }) t.Run("erase non-existing credentials is a no-op", func(t *testing.T) { assert.NilError(t, s.Erase(authOne.ServerAddress)) retrievedAuth, err := s.Get(authOne.ServerAddress) assert.NilError(t, err) - assert.Check(t, is.Equal(retrievedAuth, types.AuthConfig{})) + assert.Check(t, is.Equal(retrievedAuth, registry.AuthConfig{})) assert.Check(t, is.Equal(saveCount, expectedSaveCount), "should not have saved if nothing changed") }) t.Run("erase other credentials", func(t *testing.T) { @@ -96,16 +96,16 @@ func TestFileStoreIdempotent(t *testing.T) { assert.NilError(t, s.Erase(authTwo.ServerAddress)) retrievedAuth, err := s.Get(authTwo.ServerAddress) assert.NilError(t, err) - assert.Check(t, is.Equal(retrievedAuth, types.AuthConfig{})) + assert.Check(t, is.Equal(retrievedAuth, registry.AuthConfig{})) assert.Check(t, is.Equal(saveCount, expectedSaveCount)) }) } func TestFileStoreAddCredentials(t *testing.T) { - f := &fakeStore{configs: map[string]types.AuthConfig{}} + f := &fakeStore{configs: map[string]registry.AuthConfig{}} s := NewFileStore(f) - auth := types.AuthConfig{ + auth := registry.AuthConfig{ Username: "foo@example.com", Auth: "super_secret_token", ServerAddress: "https://example.com", @@ -120,7 +120,7 @@ func TestFileStoreAddCredentials(t *testing.T) { } func TestFileStoreGet(t *testing.T) { - f := &fakeStore{configs: map[string]types.AuthConfig{ + f := &fakeStore{configs: map[string]registry.AuthConfig{ "https://example.com": { Username: "foo@example.com", Auth: "super_secret_token", @@ -144,7 +144,7 @@ func TestFileStoreGet(t *testing.T) { func TestFileStoreGetAll(t *testing.T) { s1 := "https://example.com" s2 := "https://example2.example.com" - f := &fakeStore{configs: map[string]types.AuthConfig{ + f := &fakeStore{configs: map[string]registry.AuthConfig{ s1: { Username: "foo@example.com", Auth: "super_secret_token", @@ -180,7 +180,7 @@ func TestFileStoreGetAll(t *testing.T) { } func TestFileStoreErase(t *testing.T) { - f := &fakeStore{configs: map[string]types.AuthConfig{ + f := &fakeStore{configs: map[string]registry.AuthConfig{ "https://example.com": { Username: "foo@example.com", Auth: "super_secret_token", diff --git a/cli/config/credentials/native_store.go b/cli/config/credentials/native_store.go index b9af145b9dcb..0e38d24d4d71 100644 --- a/cli/config/credentials/native_store.go +++ b/cli/config/credentials/native_store.go @@ -1,9 +1,9 @@ package credentials import ( - "github.com/docker/cli/cli/config/types" "github.com/docker/docker-credential-helpers/client" "github.com/docker/docker-credential-helpers/credentials" + "github.com/moby/moby/api/types/registry" ) const ( @@ -40,7 +40,7 @@ func (c *nativeStore) Erase(serverAddress string) error { } // Get retrieves credentials for a specific server from the native store. -func (c *nativeStore) Get(serverAddress string) (types.AuthConfig, error) { +func (c *nativeStore) Get(serverAddress string) (registry.AuthConfig, error) { // load user email if it exist or an empty auth config. auth, _ := c.fileStore.Get(serverAddress) @@ -57,7 +57,7 @@ func (c *nativeStore) Get(serverAddress string) (types.AuthConfig, error) { } // GetAll retrieves all the credentials from the native store. -func (c *nativeStore) GetAll() (map[string]types.AuthConfig, error) { +func (c *nativeStore) GetAll() (map[string]registry.AuthConfig, error) { auths, err := c.listCredentialsInStore() if err != nil { return nil, err @@ -67,27 +67,27 @@ func (c *nativeStore) GetAll() (map[string]types.AuthConfig, error) { // This call can be safely eliminated when emails are removed. fileConfigs, _ := c.fileStore.GetAll() - authConfigs := make(map[string]types.AuthConfig) - for registry := range auths { - creds, err := c.getCredentialsFromStore(registry) + authConfigs := make(map[string]registry.AuthConfig) + for registryHost := range auths { + creds, err := c.getCredentialsFromStore(registryHost) if err != nil { return nil, err } - ac := fileConfigs[registry] // might contain Email + ac := fileConfigs[registryHost] // might contain Email ac.Username = creds.Username ac.Password = creds.Password ac.IdentityToken = creds.IdentityToken if ac.ServerAddress == "" { ac.ServerAddress = creds.ServerAddress } - authConfigs[registry] = ac + authConfigs[registryHost] = ac } return authConfigs, nil } // Store saves the given credentials in the file store. -func (c *nativeStore) Store(authConfig types.AuthConfig) error { +func (c *nativeStore) Store(authConfig registry.AuthConfig) error { if err := c.storeCredentialsInStore(authConfig); err != nil { return err } @@ -100,7 +100,7 @@ func (c *nativeStore) Store(authConfig types.AuthConfig) error { } // storeCredentialsInStore executes the command to store the credentials in the native store. -func (c *nativeStore) storeCredentialsInStore(config types.AuthConfig) error { +func (c *nativeStore) storeCredentialsInStore(config registry.AuthConfig) error { creds := &credentials.Credentials{ ServerURL: config.ServerAddress, Username: config.Username, @@ -116,8 +116,8 @@ func (c *nativeStore) storeCredentialsInStore(config types.AuthConfig) error { } // getCredentialsFromStore executes the command to get the credentials from the native store. -func (c *nativeStore) getCredentialsFromStore(serverAddress string) (types.AuthConfig, error) { - var ret types.AuthConfig +func (c *nativeStore) getCredentialsFromStore(serverAddress string) (registry.AuthConfig, error) { + var ret registry.AuthConfig creds, err := client.Get(c.programFunc, serverAddress) if err != nil { diff --git a/cli/config/credentials/native_store_test.go b/cli/config/credentials/native_store_test.go index cb31071e602a..b10c9478333e 100644 --- a/cli/config/credentials/native_store_test.go +++ b/cli/config/credentials/native_store_test.go @@ -8,9 +8,9 @@ import ( "strings" "testing" - "github.com/docker/cli/cli/config/types" "github.com/docker/docker-credential-helpers/client" "github.com/docker/docker-credential-helpers/credentials" + "github.com/moby/moby/api/types/registry" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" ) @@ -91,12 +91,12 @@ func mockCommandFn(args ...string) client.Program { } func TestNativeStoreAddCredentials(t *testing.T) { - f := &fakeStore{configs: map[string]types.AuthConfig{}} + f := &fakeStore{configs: map[string]registry.AuthConfig{}} s := &nativeStore{ programFunc: mockCommandFn, fileStore: NewFileStore(f), } - auth := types.AuthConfig{ + auth := registry.AuthConfig{ Username: "foo", Password: "bar", ServerAddress: validServerAddress, @@ -107,19 +107,19 @@ func TestNativeStoreAddCredentials(t *testing.T) { actual, ok := f.GetAuthConfigs()[validServerAddress] assert.Check(t, ok) - expected := types.AuthConfig{ + expected := registry.AuthConfig{ ServerAddress: auth.ServerAddress, } assert.Check(t, is.DeepEqual(expected, actual)) } func TestNativeStoreAddInvalidCredentials(t *testing.T) { - f := &fakeStore{configs: map[string]types.AuthConfig{}} + f := &fakeStore{configs: map[string]registry.AuthConfig{}} s := &nativeStore{ programFunc: mockCommandFn, fileStore: NewFileStore(f), } - err := s.Store(types.AuthConfig{ + err := s.Store(registry.AuthConfig{ Username: "foo", Password: "bar", ServerAddress: invalidServerAddress, @@ -129,7 +129,7 @@ func TestNativeStoreAddInvalidCredentials(t *testing.T) { } func TestNativeStoreGet(t *testing.T) { - f := &fakeStore{configs: map[string]types.AuthConfig{ + f := &fakeStore{configs: map[string]registry.AuthConfig{ validServerAddress: { Username: "foo@example.com", }, @@ -141,7 +141,7 @@ func TestNativeStoreGet(t *testing.T) { actual, err := s.Get(validServerAddress) assert.NilError(t, err) - expected := types.AuthConfig{ + expected := registry.AuthConfig{ Username: "foo", Password: "bar", ServerAddress: validServerAddress, @@ -150,7 +150,7 @@ func TestNativeStoreGet(t *testing.T) { } func TestNativeStoreGetIdentityToken(t *testing.T) { - f := &fakeStore{configs: map[string]types.AuthConfig{ + f := &fakeStore{configs: map[string]registry.AuthConfig{ validServerAddress2: {}, }} @@ -161,7 +161,7 @@ func TestNativeStoreGetIdentityToken(t *testing.T) { actual, err := s.Get(validServerAddress2) assert.NilError(t, err) - expected := types.AuthConfig{ + expected := registry.AuthConfig{ IdentityToken: "abcd1234", ServerAddress: validServerAddress2, } @@ -169,7 +169,7 @@ func TestNativeStoreGetIdentityToken(t *testing.T) { } func TestNativeStoreGetAll(t *testing.T) { - f := &fakeStore{configs: map[string]types.AuthConfig{ + f := &fakeStore{configs: map[string]registry.AuthConfig{ validServerAddress: {}, }} @@ -180,7 +180,7 @@ func TestNativeStoreGetAll(t *testing.T) { as, err := s.GetAll() assert.NilError(t, err) assert.Check(t, is.Len(as, 2)) - expected := types.AuthConfig{ + expected := registry.AuthConfig{ Username: "foo", Password: "bar", ServerAddress: "https://index.docker.io/v1", @@ -192,7 +192,7 @@ func TestNativeStoreGetAll(t *testing.T) { } func TestNativeStoreGetMissingCredentials(t *testing.T) { - f := &fakeStore{configs: map[string]types.AuthConfig{ + f := &fakeStore{configs: map[string]registry.AuthConfig{ validServerAddress: {}, }} @@ -205,7 +205,7 @@ func TestNativeStoreGetMissingCredentials(t *testing.T) { } func TestNativeStoreGetInvalidAddress(t *testing.T) { - f := &fakeStore{configs: map[string]types.AuthConfig{ + f := &fakeStore{configs: map[string]registry.AuthConfig{ validServerAddress: {}, }} @@ -218,7 +218,7 @@ func TestNativeStoreGetInvalidAddress(t *testing.T) { } func TestNativeStoreErase(t *testing.T) { - f := &fakeStore{configs: map[string]types.AuthConfig{ + f := &fakeStore{configs: map[string]registry.AuthConfig{ validServerAddress: {}, }} @@ -232,7 +232,7 @@ func TestNativeStoreErase(t *testing.T) { } func TestNativeStoreEraseInvalidAddress(t *testing.T) { - f := &fakeStore{configs: map[string]types.AuthConfig{ + f := &fakeStore{configs: map[string]registry.AuthConfig{ validServerAddress: {}, }} diff --git a/cli/config/memorystore/store.go b/cli/config/memorystore/store.go index f8ec62b95a8e..38cbd5d56a1f 100644 --- a/cli/config/memorystore/store.go +++ b/cli/config/memorystore/store.go @@ -10,7 +10,7 @@ import ( "sync" "github.com/docker/cli/cli/config/credentials" - "github.com/docker/cli/cli/config/types" + "github.com/moby/moby/api/types/registry" ) // notFoundErr is the error returned when a plugin could not be found. @@ -26,7 +26,7 @@ var errValueNotFound notFoundErr = "value not found" type Config struct { lock sync.RWMutex - memoryCredentials map[string]types.AuthConfig + memoryCredentials map[string]registry.AuthConfig fallbackStore credentials.Store } @@ -45,7 +45,7 @@ func (e *Config) Erase(serverAddress string) error { return nil } -func (e *Config) Get(serverAddress string) (types.AuthConfig, error) { +func (e *Config) Get(serverAddress string) (registry.AuthConfig, error) { e.lock.RLock() defer e.lock.RUnlock() authConfig, ok := e.memoryCredentials[serverAddress] @@ -53,15 +53,15 @@ func (e *Config) Get(serverAddress string) (types.AuthConfig, error) { if e.fallbackStore != nil { return e.fallbackStore.Get(serverAddress) } - return types.AuthConfig{}, errValueNotFound + return registry.AuthConfig{}, errValueNotFound } return authConfig, nil } -func (e *Config) GetAll() (map[string]types.AuthConfig, error) { +func (e *Config) GetAll() (map[string]registry.AuthConfig, error) { e.lock.RLock() defer e.lock.RUnlock() - creds := make(map[string]types.AuthConfig) + creds := make(map[string]registry.AuthConfig) if e.fallbackStore != nil { fileCredentials, err := e.fallbackStore.GetAll() @@ -76,7 +76,7 @@ func (e *Config) GetAll() (map[string]types.AuthConfig, error) { return creds, nil } -func (e *Config) Store(authConfig types.AuthConfig) error { +func (e *Config) Store(authConfig registry.AuthConfig) error { e.lock.Lock() defer e.lock.Unlock() e.memoryCredentials[authConfig.ServerAddress] = authConfig @@ -108,7 +108,7 @@ func WithFallbackStore(store credentials.Store) Options { } // WithAuthConfig allows to set the initial credentials in the memory store. -func WithAuthConfig(config map[string]types.AuthConfig) Options { +func WithAuthConfig(config map[string]registry.AuthConfig) Options { return func(s *Config) error { s.memoryCredentials = config return nil @@ -120,7 +120,7 @@ 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), + memoryCredentials: make(map[string]registry.AuthConfig), } for _, opt := range opts { if err := opt(m); err != nil { diff --git a/cli/config/memorystore/store_test.go b/cli/config/memorystore/store_test.go index a92a170a3b6b..e0aba7992d5c 100644 --- a/cli/config/memorystore/store_test.go +++ b/cli/config/memorystore/store_test.go @@ -3,13 +3,13 @@ package memorystore import ( "testing" - "github.com/docker/cli/cli/config/types" + "github.com/moby/moby/api/types/registry" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" ) func TestMemoryStore(t *testing.T) { - config := map[string]types.AuthConfig{ + config := map[string]registry.AuthConfig{ "https://example.test": { Username: "something-something", ServerAddress: "https://example.test", @@ -17,7 +17,7 @@ func TestMemoryStore(t *testing.T) { }, } - fallbackConfig := map[string]types.AuthConfig{ + fallbackConfig := map[string]registry.AuthConfig{ "https://only-in-file.example.test": { Username: "something-something", ServerAddress: "https://only-in-file.example.test", @@ -44,7 +44,7 @@ func TestMemoryStore(t *testing.T) { }) t.Run("storing credentials in memory store should also be in defined fallback store", func(t *testing.T) { - err := memoryStore.Store(types.AuthConfig{ + err := memoryStore.Store(registry.AuthConfig{ Username: "not-in-store", ServerAddress: "https://not-in-store.example.test", Auth: "not-in-store_token", @@ -64,7 +64,7 @@ func TestMemoryStore(t *testing.T) { }) t.Run("delete credentials should remove credentials from memory store and fallback store", func(t *testing.T) { - err := memoryStore.Store(types.AuthConfig{ + err := memoryStore.Store(registry.AuthConfig{ Username: "a-new-credential", ServerAddress: "https://a-new-credential.example.test", Auth: "a-new-credential_token", @@ -80,7 +80,7 @@ func TestMemoryStore(t *testing.T) { } func TestMemoryStoreWithoutFallback(t *testing.T) { - config := map[string]types.AuthConfig{ + config := map[string]registry.AuthConfig{ "https://example.test": { Username: "something-something", ServerAddress: "https://example.test", @@ -103,7 +103,7 @@ func TestMemoryStoreWithoutFallback(t *testing.T) { }) t.Run("case store credentials", func(t *testing.T) { - err := memoryStore.Store(types.AuthConfig{ + err := memoryStore.Store(registry.AuthConfig{ Username: "not-in-store", ServerAddress: "https://not-in-store.example.test", Auth: "not-in-store_token", @@ -117,7 +117,7 @@ func TestMemoryStoreWithoutFallback(t *testing.T) { }) t.Run("delete credentials should remove credentials from memory store", func(t *testing.T) { - err := memoryStore.Store(types.AuthConfig{ + err := memoryStore.Store(registry.AuthConfig{ Username: "a-new-credential", ServerAddress: "https://a-new-credential.example.test", Auth: "a-new-credential_token", diff --git a/cli/config/types/authconfig.go b/cli/config/types/authconfig.go index 9fe90003b138..4b71f1c7c80f 100644 --- a/cli/config/types/authconfig.go +++ b/cli/config/types/authconfig.go @@ -1,17 +1,6 @@ package types -// AuthConfig contains authorization information for connecting to a Registry -type AuthConfig struct { - Username string `json:"username,omitempty"` - Password string `json:"password,omitempty"` - Auth string `json:"auth,omitempty"` - - ServerAddress string `json:"serveraddress,omitempty"` +import "github.com/moby/moby/api/types/registry" - // IdentityToken is used to authenticate the user and get - // an access token for the registry. - IdentityToken string `json:"identitytoken,omitempty"` - - // RegistryToken is a bearer token to be sent to a registry - RegistryToken string `json:"registrytoken,omitempty"` -} +// AuthConfig contains authorization information for connecting to a Registry +type AuthConfig = registry.AuthConfig diff --git a/internal/oauth/manager/manager.go b/internal/oauth/manager/manager.go index 96deb61b1325..f3763602fe94 100644 --- a/internal/oauth/manager/manager.go +++ b/internal/oauth/manager/manager.go @@ -10,12 +10,12 @@ import ( "strings" "github.com/docker/cli/cli/config/credentials" - "github.com/docker/cli/cli/config/types" "github.com/docker/cli/cli/streams" "github.com/docker/cli/internal/oauth" "github.com/docker/cli/internal/oauth/api" "github.com/docker/cli/internal/registry" "github.com/docker/cli/internal/tui" + registrytypes "github.com/moby/moby/api/types/registry" "github.com/morikuni/aec" "github.com/sirupsen/logrus" @@ -82,7 +82,7 @@ var ErrDeviceLoginStartFail = errors.New("failed to start device code flow login // tokens to create a Hub PAT which is returned to the caller. // The retrieved tokens are stored in the credentials store (under a separate // key), and the refresh token is concatenated with the client ID. -func (m *OAuthManager) LoginDevice(ctx context.Context, w io.Writer) (*types.AuthConfig, error) { +func (m *OAuthManager) LoginDevice(ctx context.Context, w io.Writer) (*registrytypes.AuthConfig, error) { state, err := m.api.GetDeviceCode(ctx, m.audience) if err != nil { logrus.Debugf("failed to start device code login: %v", err) @@ -149,7 +149,7 @@ func (m *OAuthManager) LoginDevice(ctx context.Context, w io.Writer) (*types.Aut return nil, err } - return &types.AuthConfig{ + return ®istrytypes.AuthConfig{ Username: claims.Domain.Username, Password: pat, ServerAddress: registry.IndexServer, @@ -193,12 +193,12 @@ const ( func (m *OAuthManager) storeTokensInStore(tokens api.TokenResponse, username string) error { return errors.Join( - m.store.Store(types.AuthConfig{ + m.store.Store(registrytypes.AuthConfig{ Username: username, Password: tokens.AccessToken, ServerAddress: accessTokenKey, }), - m.store.Store(types.AuthConfig{ + m.store.Store(registrytypes.AuthConfig{ Username: username, Password: tokens.RefreshToken + ".." + m.clientID, ServerAddress: refreshTokenKey, diff --git a/internal/oauth/manager/manager_test.go b/internal/oauth/manager/manager_test.go index 44a744999b8b..11d2e14b31c9 100644 --- a/internal/oauth/manager/manager_test.go +++ b/internal/oauth/manager/manager_test.go @@ -8,8 +8,8 @@ import ( "time" "github.com/docker/cli/cli/config/credentials" - "github.com/docker/cli/cli/config/types" "github.com/docker/cli/internal/oauth/api" + "github.com/moby/moby/api/types/registry" "gotest.tools/v3/assert" ) @@ -69,7 +69,7 @@ func TestLoginDevice(t *testing.T) { waitForDeviceToken: waitForDeviceToken, getAutoPAT: getAutoPat, } - store := newStore(map[string]types.AuthConfig{}) + store := newStore(map[string]registry.AuthConfig{}) manager := OAuthManager{ store: credentials.NewFileStore(store), audience: "https://hub.docker.com", @@ -84,7 +84,7 @@ func TestLoginDevice(t *testing.T) { assert.Equal(t, receivedAudience, "https://hub.docker.com") assert.Equal(t, receivedState, expectedState) - assert.DeepEqual(t, authConfig, &types.AuthConfig{ + assert.DeepEqual(t, authConfig, ®istry.AuthConfig{ Username: "bork!", Password: "a-pat", ServerAddress: "https://index.docker.io/v1/", @@ -114,7 +114,7 @@ func TestLoginDevice(t *testing.T) { waitForDeviceToken: waitForDeviceToken, getAutoPAT: getAutoPAT, } - store := newStore(map[string]types.AuthConfig{}) + store := newStore(map[string]registry.AuthConfig{}) manager := OAuthManager{ clientID: "client-id", store: credentials.NewFileStore(store), @@ -204,7 +204,7 @@ func TestLogout(t *testing.T) { return nil }, } - store := newStore(map[string]types.AuthConfig{ + store := newStore(map[string]registry.AuthConfig{ "https://index.docker.io/v1/access-token": { Password: validToken, }, @@ -230,7 +230,7 @@ func TestLogout(t *testing.T) { return errors.New("couldn't reach tenant") }, } - store := newStore(map[string]types.AuthConfig{ + store := newStore(map[string]registry.AuthConfig{ "https://index.docker.io/v1/access-token": { Password: validToken, }, @@ -257,7 +257,7 @@ func TestLogout(t *testing.T) { return nil }, } - store := newStore(map[string]types.AuthConfig{ + store := newStore(map[string]registry.AuthConfig{ "https://index.docker.io/v1/access-token": { Password: validToken, }, @@ -284,7 +284,7 @@ func TestLogout(t *testing.T) { return nil } a.revokeToken = revokeToken - store := newStore(map[string]types.AuthConfig{}) + store := newStore(map[string]registry.AuthConfig{}) manager := OAuthManager{ store: credentials.NewFileStore(store), api: a, @@ -343,14 +343,14 @@ func (t *testAPI) GetAutoPAT(_ context.Context, audience string, res api.TokenRe } type fakeStore struct { - configs map[string]types.AuthConfig + configs map[string]registry.AuthConfig } func (*fakeStore) Save() error { return nil } -func (f *fakeStore) GetAuthConfigs() map[string]types.AuthConfig { +func (f *fakeStore) GetAuthConfigs() map[string]registry.AuthConfig { return f.configs } @@ -358,6 +358,6 @@ func (*fakeStore) GetFilename() string { return "/tmp/docker-fakestore" } -func newStore(auths map[string]types.AuthConfig) *fakeStore { +func newStore(auths map[string]registry.AuthConfig) *fakeStore { return &fakeStore{configs: auths} }