Skip to content

Commit 97942d0

Browse files
committed
prevent login prompt on registry operations with no TTY attached
When pulling or pushing images, the CLI could prompt for a password if the push/pull failed and the registry returned a 401 (Unauthorized) Ironically, this feature did not work when using Docker Hub (and possibly other registries using basic auth), due to some custom error handling added in [moby@19a93a6e3d42], which also discards the registry's status code, changing it to a 404; curl -v -XPOST --unix-socket /var/run/docker.sock 'http://localhost/v1.50/images/create?fromImage=docker.io%2Fexample%2Fprivate&tag=latest' ... < HTTP/1.1 404 Not Found < Content-Type: application/json ... {"message":"pull access denied for example/private, repository does not exist or may require 'docker login'"} And due to a bug, other registries (not using basic auth) returned a generic error, which resulted in a 500 Internal Server Error. That bug was fixed in docker 28.2, now returning the upstream status code and trigger an interactive prompt; docker pull icr.io/my-ns/my-image:latest Please login prior to pull: Username: This prompt would be triggered unconditionally, also if the CLI was run non-interactively and no TTY attached; docker pull icr.io/my-ns/my-image:latest < /dev/null Please login prior to pull: Username: With this PR, no prompt is shown ; # without STDIN attached docker pull icr.io/my-ns/my-image:latest < /dev/null Error response from daemon: error from registry: Authorization required. See https://cloud.ibm.com/docs/Registry?topic=Registry-troubleshoot-auth-req - Authorization required. See https://cloud.ibm.com/docs/Registry?topic=Registry-troubleshoot-auth-req For now, the prompt is still shown otherwise; docker pull icr.io/my-ns/my-image:latest Login prior to pull: Username: ^C [moby@19a93a6e3d42]: moby/moby@19a93a6 Signed-off-by: Sebastiaan van Stijn <[email protected]>
1 parent 747cb44 commit 97942d0

File tree

6 files changed

+23
-6
lines changed

6 files changed

+23
-6
lines changed

cli/command/image/push.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,10 @@ To push the complete multi-platform image, remove the --platform flag.
113113
if err != nil {
114114
return err
115115
}
116-
requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(dockerCli, repoInfo.Index, "push")
116+
var requestPrivilege registrytypes.RequestAuthConfig
117+
if dockerCli.In().IsTerminal() {
118+
requestPrivilege = command.RegistryAuthenticationPrivilegedFunc(dockerCli, repoInfo.Index, "push")
119+
}
117120
options := image.PushOptions{
118121
All: opts.all,
119122
RegistryAuth: encodedAuth,

cli/command/image/trust.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,10 @@ func imagePullPrivileged(ctx context.Context, cli command.Cli, imgRefAndAuth tru
149149
if err != nil {
150150
return err
151151
}
152-
requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(cli, imgRefAndAuth.RepoInfo().Index, "pull")
152+
var requestPrivilege registrytypes.RequestAuthConfig
153+
if cli.In().IsTerminal() {
154+
requestPrivilege = command.RegistryAuthenticationPrivilegedFunc(cli, imgRefAndAuth.RepoInfo().Index, "pull")
155+
}
153156
responseBody, err := cli.Client().ImagePull(ctx, reference.FamiliarString(imgRefAndAuth.Reference()), image.PullOptions{
154157
RegistryAuth: encodedAuth,
155158
PrivilegeFunc: requestPrivilege,

cli/command/plugin/install.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,13 +90,18 @@ func buildPullConfig(ctx context.Context, dockerCli command.Cli, opts pluginOpti
9090
return types.PluginInstallOptions{}, err
9191
}
9292

93+
var requestPrivilege registrytypes.RequestAuthConfig
94+
if dockerCli.In().IsTerminal() {
95+
requestPrivilege = command.RegistryAuthenticationPrivilegedFunc(dockerCli, repoInfo.Index, cmdName)
96+
}
97+
9398
options := types.PluginInstallOptions{
9499
RegistryAuth: encodedAuth,
95100
RemoteRef: remote,
96101
Disabled: opts.disable,
97102
AcceptAllPermissions: opts.grantPerms,
98103
AcceptPermissionsFunc: acceptPrivileges(dockerCli, opts.remote),
99-
PrivilegeFunc: command.RegistryAuthenticationPrivilegedFunc(dockerCli, repoInfo.Index, cmdName),
104+
PrivilegeFunc: requestPrivilege,
100105
Args: opts.args,
101106
}
102107
return options, nil

cli/command/registry.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ const (
3535
const authConfigKey = "https://index.docker.io/v1/"
3636

3737
// RegistryAuthenticationPrivilegedFunc returns a RequestPrivilegeFunc from the specified registry index info
38-
// for the given command.
38+
// for the given command to prompt the user for username and password.
3939
func RegistryAuthenticationPrivilegedFunc(cli Cli, index *registrytypes.IndexInfo, cmdName string) registrytypes.RequestAuthConfig {
4040
configKey := getAuthConfigKey(index.Name)
4141
isDefaultRegistry := configKey == authConfigKey || index.Official

cli/command/registry/search.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,10 @@ func runSearch(ctx context.Context, dockerCli command.Cli, options searchOptions
6363
return err
6464
}
6565

66-
requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(dockerCli, indexInfo, "search")
66+
var requestPrivilege registrytypes.RequestAuthConfig
67+
if dockerCli.In().IsTerminal() {
68+
requestPrivilege = command.RegistryAuthenticationPrivilegedFunc(dockerCli, indexInfo, "search")
69+
}
6770
results, err := dockerCli.Client().ImageSearch(ctx, options.term, registrytypes.SearchOptions{
6871
RegistryAuth: encodedAuth,
6972
PrivilegeFunc: requestPrivilege,

cli/command/trust/sign.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,10 @@ func runSignImage(ctx context.Context, dockerCLI command.Cli, options signOption
8282
return trust.NotaryError(imgRefAndAuth.RepoInfo().Name.Name(), err)
8383
}
8484
}
85-
requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(dockerCLI, imgRefAndAuth.RepoInfo().Index, "push")
85+
var requestPrivilege registrytypes.RequestAuthConfig
86+
if dockerCLI.In().IsTerminal() {
87+
requestPrivilege = command.RegistryAuthenticationPrivilegedFunc(dockerCLI, imgRefAndAuth.RepoInfo().Index, "push")
88+
}
8689
target, err := createTarget(notaryRepo, imgRefAndAuth.Tag())
8790
if err != nil || options.local {
8891
switch err := err.(type) {

0 commit comments

Comments
 (0)