@@ -35,6 +35,44 @@ const (
3535// [registry.IndexServer]: https://pkg.go.dev/github.com/docker/[email protected] +incompatible/registry#IndexServer 3636const 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 4684func 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
67106func 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?
103145func 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
195240func RetrieveAuthTokenFromImage (cfg * configfile.ConfigFile , image string ) (string , error ) {
196241 registryRef , err := reference .ParseNormalizedNamed (image )
0 commit comments