mirror of https://github.com/docker/cli.git
WIP: don't require IndexInfo
Lots to do here; too many wrappers everywhere, which may become easier when content trust is removed (which adds another level of abstraction) Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
parent
ba21666654
commit
274b2dcba7
|
|
@ -18,7 +18,6 @@ import (
|
|||
"github.com/docker/cli/internal/jsonstream"
|
||||
"github.com/docker/cli/internal/registry"
|
||||
"github.com/docker/cli/internal/tui"
|
||||
"github.com/moby/moby/api/pkg/authconfig"
|
||||
"github.com/moby/moby/api/types/auxprogress"
|
||||
"github.com/moby/moby/client"
|
||||
"github.com/morikuni/aec"
|
||||
|
|
@ -106,12 +105,8 @@ To push the complete multi-platform image, remove the --platform flag.
|
|||
}
|
||||
}
|
||||
|
||||
// Resolve the Repository name from fqn to RepositoryInfo
|
||||
indexInfo := registry.NewIndexInfo(ref)
|
||||
|
||||
// Resolve the Auth config relevant for this server
|
||||
authConfig := command.ResolveAuthConfig(dockerCli.ConfigFile(), indexInfo)
|
||||
encodedAuth, err := authconfig.Encode(authConfig)
|
||||
encodedAuth, err := command.RetrieveAuthTokenFromImage(dockerCli.ConfigFile(), ref.String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -134,6 +129,9 @@ To push the complete multi-platform image, remove the --platform flag.
|
|||
}()
|
||||
|
||||
if !opts.untrusted {
|
||||
// Resolve the Repository name from fqn to RepositoryInfo
|
||||
indexInfo := registry.NewIndexInfo(ref)
|
||||
authConfig := command.ResolveAuthConfig(dockerCli.ConfigFile(), indexInfo)
|
||||
return pushTrustedReference(ctx, dockerCli, indexInfo, ref, authConfig, responseBody)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -150,6 +150,7 @@ func getTrustedPullTargets(cli command.Cli, imgRefAndAuth trust.ImageRefAndAuth)
|
|||
|
||||
// imagePullPrivileged pulls the image and displays it to the output
|
||||
func imagePullPrivileged(ctx context.Context, cli command.Cli, imgRefAndAuth trust.ImageRefAndAuth, opts pullOptions) error {
|
||||
// TODO(thaJeztah): get rid of this trust.ImageRefAndAuth monstrosity; we're wrapping wrappers around wrappers; all we need here is the image ref (or even less: the registry name)
|
||||
encodedAuth, err := authconfig.Encode(*imgRefAndAuth.AuthConfig())
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -35,6 +35,44 @@ const (
|
|||
// [registry.IndexServer]: https://pkg.go.dev/github.com/docker/docker@v28.3.3+incompatible/registry#IndexServer
|
||||
const authConfigKey = "https://index.docker.io/v1/"
|
||||
|
||||
// NewAuthRequester returns a RequestPrivilegeFunc for the specified registry
|
||||
// and the given cmdName (used as informational message to the user).
|
||||
//
|
||||
// The returned function is a [registrytypes.RequestAuthConfig] to prompt the user
|
||||
// for credentials if needed. It is called as fallback if the credentials (if any)
|
||||
// used for the initial operation did not work.
|
||||
//
|
||||
// TODO(thaJeztah): cli Cli could be a Streams if it was not for cli.SetIn to be needed?
|
||||
// TODO(thaJeztah): ideally, this would accept reposName / imageRef as a regular string (we can parse it if needed!), or .. maybe generics and accept either?
|
||||
func NewAuthRequester(cli Cli, indexServer string, promptMsg string) registrytypes.RequestAuthConfig {
|
||||
configKey := getAuthConfigKey(indexServer)
|
||||
return newPrivilegeFunc(cli, configKey, promptMsg)
|
||||
}
|
||||
|
||||
func newPrivilegeFunc(cli Cli, indexServer string, promptMsg string) registrytypes.RequestAuthConfig {
|
||||
return func(ctx context.Context) (string, error) {
|
||||
// TODO(thaJeztah): can we make the prompt an argument? ("prompt func()" or "prompt func()?
|
||||
_, _ = fmt.Fprint(cli.Out(), "\n"+promptMsg+"\n")
|
||||
isDefaultRegistry := indexServer == authConfigKey
|
||||
authConfig, err := GetDefaultAuthConfig(cli.ConfigFile(), true, indexServer, isDefaultRegistry)
|
||||
if err != nil {
|
||||
_, _ = fmt.Fprintf(cli.Err(), "Unable to retrieve stored credentials for %s, error: %s.\n", indexServer, err)
|
||||
}
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return "", ctx.Err()
|
||||
default:
|
||||
}
|
||||
|
||||
authConfig, err = PromptUserForCredentials(ctx, cli, "", "", authConfig.Username, indexServer)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return registrytypes.EncodeAuthConfig(authConfig)
|
||||
}
|
||||
}
|
||||
|
||||
// ResolveAuthConfig returns auth-config for the given registry from the
|
||||
// credential-store. It returns an empty AuthConfig if no credentials were
|
||||
// found.
|
||||
|
|
@ -44,7 +82,8 @@ const authConfigKey = "https://index.docker.io/v1/"
|
|||
//
|
||||
// [registry.ResolveAuthConfig]: https://pkg.go.dev/github.com/docker/docker@v28.3.3+incompatible/registry#ResolveAuthConfig
|
||||
func ResolveAuthConfig(cfg *configfile.ConfigFile, index *registrytypes.IndexInfo) registrytypes.AuthConfig {
|
||||
configKey := index.Name
|
||||
indexServer := index.Name
|
||||
configKey := getAuthConfigKey(indexServer)
|
||||
if index.Official {
|
||||
configKey = authConfigKey
|
||||
}
|
||||
|
|
@ -57,6 +96,7 @@ func ResolveAuthConfig(cfg *configfile.ConfigFile, index *registrytypes.IndexInf
|
|||
// 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) {
|
||||
if !isDefaultRegistry {
|
||||
// FIXME(thaJeztah): should the same logic be used for getAuthConfigKey ?? Looks like we're normalizing things here, but not elsewhere? why?
|
||||
serverAddress = credentials.ConvertToHostname(serverAddress)
|
||||
}
|
||||
authCfg := configtypes.AuthConfig{}
|
||||
|
|
@ -83,6 +123,8 @@ 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.
|
||||
//
|
||||
// TODO(thaJeztah): cli Cli could be a Streams if it was not for cli.SetIn to be needed?
|
||||
func PromptUserForCredentials(ctx context.Context, cli Cli, argUser, argPassword, defaultUsername, serverAddress string) (registrytypes.AuthConfig, error) {
|
||||
// On Windows, force the use of the regular OS stdin stream.
|
||||
//
|
||||
|
|
@ -174,6 +216,9 @@ func PromptUserForCredentials(ctx context.Context, cli Cli, argUser, argPassword
|
|||
// base64url encoded ([RFC 4648, Section 5]) JSON string for sending through
|
||||
// the "X-Registry-Auth" header.
|
||||
//
|
||||
// FIXME(thaJeztah): do we need a variant like this, but with "indexServer" (domainName) as input?
|
||||
// TODO(thaJeztah): should this accept an image ref-type, and use instead of ResolveAuthConfig
|
||||
//
|
||||
// [RFC 4648, Section 5]: https://tools.ietf.org/html/rfc4648#section-5
|
||||
func RetrieveAuthTokenFromImage(cfg *configfile.ConfigFile, image string) (string, error) {
|
||||
registryRef, err := reference.ParseNormalizedNamed(image)
|
||||
|
|
|
|||
Loading…
Reference in New Issue