Skip to content

Commit 99946ad

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 01febbc commit 99946ad

File tree

1 file changed

+46
-1
lines changed

1 file changed

+46
-1
lines changed

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
}
@@ -66,6 +105,7 @@ func ResolveAuthConfig(cfg *configfile.ConfigFile, index *registrytypes.IndexInf
66105
// If credentials for given serverAddress exists in the credential store, the configuration will be populated with values in it
67106
func GetDefaultAuthConfig(cfg *configfile.ConfigFile, checkCredStore bool, serverAddress string, isDefaultRegistry bool) (registrytypes.AuthConfig, error) {
68107
if !isDefaultRegistry {
108+
// FIXME(thaJeztah): should the same logic be used for getAuthConfigKey ?? Looks like we're normalizing things here, but not elsewhere? why?
69109
serverAddress = credentials.ConvertToHostname(serverAddress)
70110
}
71111
authCfg := configtypes.AuthConfig{}
@@ -100,6 +140,8 @@ func GetDefaultAuthConfig(cfg *configfile.ConfigFile, checkCredStore bool, serve
100140
// If defaultUsername is not empty, the username prompt includes that username
101141
// and the user can hit enter without inputting a username to use that default
102142
// username.
143+
//
144+
// TODO(thaJeztah): cli Cli could be a Streams if it was not for cli.SetIn to be needed?
103145
func PromptUserForCredentials(ctx context.Context, cli Cli, argUser, argPassword, defaultUsername, serverAddress string) (registrytypes.AuthConfig, error) {
104146
// On Windows, force the use of the regular OS stdin stream.
105147
//
@@ -191,6 +233,9 @@ func PromptUserForCredentials(ctx context.Context, cli Cli, argUser, argPassword
191233
// base64url encoded ([RFC 4648, Section 5]) JSON string for sending through
192234
// the "X-Registry-Auth" header.
193235
//
236+
// FIXME(thaJeztah): do we need a variant like this, but with "indexServer" (domainName) as input?
237+
// TODO(thaJeztah): should this accept an image ref-type, and use instead of ResolveAuthConfig
238+
//
194239
// [RFC 4648, Section 5]: https://tools.ietf.org/html/rfc4648#section-5
195240
func RetrieveAuthTokenFromImage(cfg *configfile.ConfigFile, image string) (string, error) {
196241
registryRef, err := reference.ParseNormalizedNamed(image)

0 commit comments

Comments
 (0)