Skip to content

Commit 202ea0e

Browse files
committed
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 <[email protected]>
1 parent efb24a5 commit 202ea0e

File tree

2 files changed

+47
-1
lines changed

2 files changed

+47
-1
lines changed

cli/command/image/trust.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ func getTrustedPullTargets(cli command.Cli, imgRefAndAuth trust.ImageRefAndAuth)
154154

155155
// imagePullPrivileged pulls the image and displays it to the output
156156
func imagePullPrivileged(ctx context.Context, cli command.Cli, imgRefAndAuth trust.ImageRefAndAuth, opts pullOptions) error {
157+
// 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)
157158
encodedAuth, err := authconfig.Encode(*imgRefAndAuth.AuthConfig())
158159
if err != nil {
159160
return err

cli/command/registry.go

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,44 @@ const (
3535
// [registry.IndexServer]: https://pkg.go.dev/github.com/docker/[email protected]+incompatible/registry#IndexServer
3636
const authConfigKey = "https://index.docker.io/v1/"
3737

38+
// NewAuthRequester returns a RequestPrivilegeFunc for the specified registry
39+
// and the given cmdName (used as informational message to the user).
40+
//
41+
// The returned function is a [registrytypes.RequestAuthConfig] to prompt the user
42+
// for credentials if needed. It is called as fallback if the credentials (if any)
43+
// used for the initial operation did not work.
44+
//
45+
// TODO(thaJeztah): cli Cli could be a Streams if it was not for cli.SetIn to be needed?
46+
// TODO(thaJeztah): ideally, this would accept reposName / imageRef as a regular string (we can parse it if needed!), or .. maybe generics and accept either?
47+
func NewAuthRequester(cli Cli, indexServer string, promptMsg string) registrytypes.RequestAuthConfig {
48+
configKey := getAuthConfigKey(indexServer)
49+
return newPrivilegeFunc(cli, configKey, promptMsg)
50+
}
51+
52+
func newPrivilegeFunc(cli Cli, indexServer string, promptMsg string) registrytypes.RequestAuthConfig {
53+
return func(ctx context.Context) (string, error) {
54+
// TODO(thaJeztah): can we make the prompt an argument? ("prompt func()" or "prompt func()?
55+
_, _ = fmt.Fprint(cli.Out(), "\n"+promptMsg+"\n")
56+
isDefaultRegistry := indexServer == authConfigKey
57+
authConfig, err := GetDefaultAuthConfig(cli.ConfigFile(), true, indexServer, isDefaultRegistry)
58+
if err != nil {
59+
_, _ = fmt.Fprintf(cli.Err(), "Unable to retrieve stored credentials for %s, error: %s.\n", indexServer, err)
60+
}
61+
62+
select {
63+
case <-ctx.Done():
64+
return "", ctx.Err()
65+
default:
66+
}
67+
68+
authConfig, err = PromptUserForCredentials(ctx, cli, "", "", authConfig.Username, indexServer)
69+
if err != nil {
70+
return "", err
71+
}
72+
return registrytypes.EncodeAuthConfig(authConfig)
73+
}
74+
}
75+
3876
// ResolveAuthConfig returns auth-config for the given registry from the
3977
// credential-store. It returns an empty AuthConfig if no credentials were
4078
// found.
@@ -44,7 +82,8 @@ const authConfigKey = "https://index.docker.io/v1/"
4482
//
4583
// [registry.ResolveAuthConfig]: https://pkg.go.dev/github.com/docker/[email protected]+incompatible/registry#ResolveAuthConfig
4684
func ResolveAuthConfig(cfg *configfile.ConfigFile, index *registrytypes.IndexInfo) registrytypes.AuthConfig {
47-
configKey := index.Name
85+
indexServer := index.Name
86+
configKey := getAuthConfigKey(indexServer)
4887
if index.Official {
4988
configKey = authConfigKey
5089
}
@@ -57,6 +96,7 @@ func ResolveAuthConfig(cfg *configfile.ConfigFile, index *registrytypes.IndexInf
5796
// If credentials for given serverAddress exists in the credential store, the configuration will be populated with values in it
5897
func GetDefaultAuthConfig(cfg *configfile.ConfigFile, checkCredStore bool, serverAddress string, isDefaultRegistry bool) (registrytypes.AuthConfig, error) {
5998
if !isDefaultRegistry {
99+
// FIXME(thaJeztah): should the same logic be used for getAuthConfigKey ?? Looks like we're normalizing things here, but not elsewhere? why?
60100
serverAddress = credentials.ConvertToHostname(serverAddress)
61101
}
62102
authCfg := configtypes.AuthConfig{}
@@ -83,6 +123,8 @@ func GetDefaultAuthConfig(cfg *configfile.ConfigFile, checkCredStore bool, serve
83123
// If defaultUsername is not empty, the username prompt includes that username
84124
// and the user can hit enter without inputting a username to use that default
85125
// username.
126+
//
127+
// TODO(thaJeztah): cli Cli could be a Streams if it was not for cli.SetIn to be needed?
86128
func PromptUserForCredentials(ctx context.Context, cli Cli, argUser, argPassword, defaultUsername, serverAddress string) (registrytypes.AuthConfig, error) {
87129
// On Windows, force the use of the regular OS stdin stream.
88130
//
@@ -174,6 +216,9 @@ func PromptUserForCredentials(ctx context.Context, cli Cli, argUser, argPassword
174216
// base64url encoded ([RFC 4648, Section 5]) JSON string for sending through
175217
// the "X-Registry-Auth" header.
176218
//
219+
// FIXME(thaJeztah): do we need a variant like this, but with "indexServer" (domainName) as input?
220+
// TODO(thaJeztah): should this accept an image ref-type, and use instead of ResolveAuthConfig
221+
//
177222
// [RFC 4648, Section 5]: https://tools.ietf.org/html/rfc4648#section-5
178223
func RetrieveAuthTokenFromImage(cfg *configfile.ConfigFile, image string) (string, error) {
179224
registryRef, err := reference.ParseNormalizedNamed(image)

0 commit comments

Comments
 (0)