RetrieveAuthTokenFromImage is exported and imported by other projects, so it keeps reading only the configuration file. The commands that pull and push call registryauth.EncodedAuth instead, which asks DOCKER_AUTH_CONFIG, then the Docker Desktop session, then the configuration file. This drops command.EncodedRegistryAuth from the public API.
Each DockerCli owns its Docker Desktop sessions through RegistryAuthProvider, created on first use, instead of package-level sessions shared by every caller. A command.Cli without RegistryAuthProvider uses only its configuration file. The fallback reads the current configuration file, since Initialize replaces it.
Remove the session fields and the constructors that only tests used, move the staging and dhi.io hostnames into internal/secretsengine, and use testing/synctest instead of a fake clock, so that the tests run in parallel. Only the DOCKER_AUTH_CONFIG test still sets the environment.
Signed-off-by: Alano Terblanche <18033717+Benehiko@users.noreply.github.com>
Provider, HubClient, and New were only used inside the package and by FakeCli. FakeCli now returns its configuration file as the auth provider, which is what the signed-out Docker Hub stub fell back to. NewDesktop returns an AuthProvider. Remove DockerCli.RegistryAuthProvider: EncodedRegistryAuth already falls back to RetrieveAuthTokenFromImage, which uses the Docker Desktop session, so the method only added to the public API.
Signed-off-by: Alano Terblanche <18033717+Benehiko@users.noreply.github.com>
Check that the Docker Desktop session is used for Docker Hub and dhi.io, that other registries use the configuration file, and that DOCKER_AUTH_CONFIG takes precedence over Docker Desktop. TestRetrieveAuthTokenFromImage disables the Docker Desktop lookup.
Signed-off-by: Alano Terblanche <18033717+Benehiko@users.noreply.github.com>
Tests that use FakeCli pull, push, and create containers through RetrieveAuthTokenFromImage. Disable the Docker Desktop lookup, so that they never reach the Docker Desktop of the machine they run on.
Signed-off-by: Alano Terblanche <18033717+Benehiko@users.noreply.github.com>
Run lookups against a fake secrets engine on a unix socket: signed in, signed out, no socket, a socket with nothing listening, and an engine that never answers. The benchmarks cover the same cases. BenchmarkExternalEngine runs against the engine at SECRETSENGINE_BENCH_SOCKET when it is set.
Signed-off-by: Alano Terblanche <18033717+Benehiko@users.noreply.github.com>
Cover which registries use the Docker Desktop session, keeping the production and staging sessions apart, caching the session until it expires, the retry interval after a failed lookup, and Disable.
Signed-off-by: Alano Terblanche <18033717+Benehiko@users.noreply.github.com>
When Docker Desktop is running and signed in, read the Docker Hub session from the Docker Desktop secrets engine, and send it as the registry credentials for Docker Hub (docker.io) and Docker Hardened Images (dhi.io) when pulling or pushing images through the daemon: docker pull, push, run, create, plugin install and push, service create and update, and stack deploy.
Credentials in DOCKER_AUTH_CONFIG take precedence for the registries they cover. Without a usable Docker Desktop session (no socket, nothing listening, signed out, or no answer within 5 seconds), the CLI uses its credential store, credential helpers, and configuration file as before. docker login and stored credentials are not changed.
Signed-off-by: Alano Terblanche <18033717+Benehiko@users.noreply.github.com>
Wrap errors in the OAuth manager instead of logging them, preserving
the underlying cause while allowing callers to detect startup failures.
Log failures at the fallback handler and scope the device-code login
result to its branch.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
- Remove extra newline before message
- Include the token in the URL (instead of requiring the user to manually
enter it on the website).
- Improve the "call to action"; ENTER can be used to automatically open
the browser (but the user can manually open it instead), and CTRL-C can
be used to cancel the login.
- Remove the "Waiting for authentication in the browser…" message, which
could be confusing if no browser was opened (yet), instead print a message
after successfully requesting the browser to be opened.
When running `docker login`;
docker login
i Info → Using web-based login. To sign in with credentials on the command line, use 'docker login -u <username>'
Your one-time device confirmation code is: NRJL-BLRL
Open this URL to authenticate: https://login.docker.com/activate?user_code=NRJL-BLRL
Press ENTER to open the URL in your browser, or Ctrl+C to cancel.
After pressing `ENTER`, it either prints the "success" message;
Press ENTER to open the URL in your browser, or Ctrl+C to cancel.
Opening browser…
or a failure when unable to launch a browser;
Press ENTER to open the URL in your browser, or Ctrl+C to cancel.
No browser found. Open the URL above manually to continue.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Before this patch, pressing `ENTER` to open the browser would silently
discard the error;
docker login
i Info → Using web-based login. To sign in with credentials on the command line, use 'docker login -u <username>'
Your one-time device confirmation code is: VGTB-VKBG
Press ENTER to open your browser or submit your device code here: https://login.docker.com/activate
Waiting for authentication in the browser…
With this patch, a failure is printed, so that the user can manually open
the URL (or cancel the login);
docker login
i Info → Using web-based login. To sign in with credentials on the command line, use 'docker login -u <username>'
Your one-time device confirmation code is: SZFX-BSGP
Press ENTER to open your browser or submit your device code here: https://login.docker.com/activate
Waiting for authentication in the browser…
No browser found. Open the URL above manually to continue.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Make the output less verbose, and combine the "web-based login" message
with the info message that's already printed.
Before this patch:
docker login
USING WEB-BASED LOGIN
i Info → To sign in with credentials on the command line, use 'docker login -u <username>'
Your one-time device confirmation code is: VVPV-NSSL
Press ENTER to open your browser or submit your device code here: https://login.docker.com/activate
Waiting for authentication in the browser…
With this patch:
docker login
i Info → Using web-based login. To sign in with credentials on the command line, use 'docker login -u <username>'
Your one-time device confirmation code is: QBBD-PQNS
Press ENTER to open your browser or submit your device code here: https://login.docker.com/activate
Waiting for authentication in the browser…
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Check the context after reading stdin to avoid launching the browser
if login was canceled while waiting for ENTER.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
translateV2AuthError only unwraps a url.Error from Do(); a 401
status never went through it. Use errhttp.ToNative so Auth()
treats that 401 as unauthorized and stops.
Signed-off-by: Dean Chen <862469039@qq.com>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Client-side login (daemon down) was wrapping a 401 as a plain error, so
Auth() moved on to the next endpoint. That can print Login Succeeded if
the HTTP fallback happens to answer 200.
Fixes#7237
Signed-off-by: Dean Chen <862469039@qq.com>
- drop support for go1.24
- update vendor.mod to go1.25.0
- update //go:build tags to go1.25
The golang.org/x/ dependencies now require go1.25 as a minimum,
so updating our build tags accordingly.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This package imports all "importable" packages, i.e., packages that:
- are not applications ("main")
- are not internal
- and that have non-test go-files
We do this to verify that our code can be consumed as a dependency
in "module mode". When using a dependency that does not have a go.mod
(i.e.; is not a "module"), go implicitly generates a go.mod. Lacking
information from the dependency itself, it assumes "go1.16" language
(see [DefaultGoModVersion]). Starting with Go1.21, go downgrades the
language version used for such dependencies, which means that any
language feature used that is not supported by go1.16 results in a
compile error;
# github.com/docker/cli/cli/context/store
/go/pkg/mod/github.com/docker/cli@v25.0.0-beta.2+incompatible/cli/context/store/storeconfig.go:6:24: predeclared any requires go1.18 or later (-lang was set to go1.16; check go.mod)
/go/pkg/mod/github.com/docker/cli@v25.0.0-beta.2+incompatible/cli/context/store/store.go:74:12: predeclared any requires go1.18 or later (-lang was set to go1.16; check go.mod)
These errors do NOT occur when using GOPATH mode, nor do they occur
when using "pseudo module mode" (the "-mod=mod -modfile=vendor.mod"
approach used in this repository).
As a workaround for this situation, we must include "//go:build" comments
in any file that uses newer go-language features (such as the "any" type
or the "min()", "max()" builtins).
From the go toolchain docs (https://go.dev/doc/toolchain):
> The go line for each module sets the language version the compiler enforces
> when compiling packages in that module. The language version can be changed
> on a per-file basis by using a build constraint.
>
> For example, a module containing code that uses the Go 1.21 language version
> should have a go.mod file with a go line such as go 1.21 or go 1.21.3.
> If a specific source file should be compiled only when using a newer Go
> toolchain, adding //go:build go1.22 to that source file both ensures that
> only Go 1.22 and newer toolchains will compile the file and also changes
> the language version in that file to Go 1.22.
This file is a generated module that imports all packages provided in
the repository, which replicates an external consumer using our code
as a dependency in go-module mode, and verifies all files in those
packages have the correct "//go:build <go language version>" set.
To test this package:
make shell
make -C ./internal/gocompat/
make: Entering directory '/go/src/github.com/docker/cli/internal/gocompat'
GO111MODULE=off go generate .
GO111MODULE=on go mod tidy
GO111MODULE=on go test -v
# github.com/docker/cli/templates
../../templates/templates.go:13:17: predeclared any requires go1.18 or later (-lang was set to go1.16; check go.mod)
# github.com/docker/cli/cli/compose/template
../../cli/compose/template/template.go:98:45: predeclared any requires go1.18 or later (-lang was set to go1.16; check go.mod)
../../cli/compose/template/template.go:105:27: predeclared any requires go1.18 or later (-lang was set to go1.16; check go.mod)
../../cli/compose/template/template.go:141:28: predeclared any requires go1.18 or later (-lang was set to go1.16; check go.mod)
# github.com/docker/cli/cli/compose/types
../../cli/compose/types/types.go:53:22: predeclared any requires go1.18 or later (-lang was set to go1.16; check go.mod)
../../cli/compose/types/types.go:86:34: predeclared any requires go1.18 or later (-lang was set to go1.16; check go.mod)
../../cli/compose/types/types.go:105:22: predeclared any requires go1.18 or later (-lang was set to go1.16; check go.mod)
../../cli/compose/types/types.go:137:34: predeclared any requires go1.18 or later (-lang was set to go1.16; check go.mod)
../../cli/compose/types/types.go:211:20: predeclared any requires go1.18 or later (-lang was set to go1.16; check go.mod)
../../cli/compose/types/types.go:343:35: predeclared any requires go1.18 or later (-lang was set to go1.16; check go.mod)
../../cli/compose/types/types.go:442:40: predeclared any requires go1.18 or later (-lang was set to go1.16; check go.mod)
../../cli/compose/types/types.go:469:24: predeclared any requires go1.18 or later (-lang was set to go1.16; check go.mod)
../../cli/compose/types/types.go:490:24: predeclared any requires go1.18 or later (-lang was set to go1.16; check go.mod)
../../cli/compose/types/types.go:587:28: predeclared any requires go1.18 or later (-lang was set to go1.16; check go.mod)
../../cli/compose/types/types.go:442:40: too many errors
# github.com/docker/cli/cli/context/store
../../cli/context/store/storeconfig.go:6:24: predeclared any requires go1.18 or later (-lang was set to go1.16; check go.mod)
../../cli/context/store/store.go:74:12: predeclared any requires go1.18 or later (-lang was set to go1.16; check go.mod)
../../cli/context/store/store.go:75:23: predeclared any requires go1.18 or later (-lang was set to go1.16; check go.mod)
../../cli/context/store/metadatastore.go:43:58: predeclared any requires go1.18 or later (-lang was set to go1.16; check go.mod)
../../cli/context/store/metadatastore.go:48:22: predeclared any requires go1.18 or later (-lang was set to go1.16; check go.mod)
../../cli/context/store/metadatastore.go:80:30: predeclared any requires go1.18 or later (-lang was set to go1.16; check go.mod)
# github.com/docker/cli/cli/command/idresolver
../../cli/command/idresolver/idresolver.go:6:2: "github.com/docker/docker/api/types" imported and not used
../../cli/command/idresolver/idresolver.go:7:2: "github.com/docker/docker/api/types/swarm" imported and not used
../../cli/command/idresolver/idresolver.go:9:2: "github.com/pkg/errors" imported and not used
../../cli/command/idresolver/idresolver.go:28:49: predeclared any requires go1.18 or later (-lang was set to go1.16; check go.mod)
../../cli/command/idresolver/idresolver.go:58:53: predeclared any requires go1.18 or later (-lang was set to go1.16; check go.mod)
# github.com/docker/cli/cli/compose/schema
../../cli/compose/schema/schema.go:20:46: predeclared any requires go1.18 or later (-lang was set to go1.16; check go.mod)
../../cli/compose/schema/schema.go:27:53: predeclared any requires go1.18 or later (-lang was set to go1.16; check go.mod)
../../cli/compose/schema/schema.go:45:32: predeclared any requires go1.18 or later (-lang was set to go1.16; check go.mod)
../../cli/compose/schema/schema.go:66:33: predeclared any requires go1.18 or later (-lang was set to go1.16; check go.mod)
FAIL gocompat [build failed]
make: *** [Makefile:3: verify] Error 1
make: Leaving directory '/go/src/github.com/docker/cli/internal/gocompat'
[DefaultGoModVersion]: https://github.com/golang/go/blob/58c28ba286dd0e98fe4cca80f5d64bbcb824a685/src/cmd/go/internal/gover/version.go#L15-L24
[2]: https://go.dev/doc/toolchain
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
- remove constructor
- fix mixed pointer/non-pointer receivers
- just embed the error we want to produce
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Create a copy of the registry package to use, so that code used only
for trust can be removed from the cli/internal package.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
move the `trust` subcommands to a plugin, so that the subcommands can
be installed separate from the `docker trust` integration in push/pull
(for situations where trust verification happens on the daemon side).
make binary
go build -o /usr/libexec/docker/cli-plugins/docker-trust ./cmd/docker-trust
docker info
Client:
Version: 28.2.0-dev
Context: default
Debug Mode: false
Plugins:
buildx: Docker Buildx (Docker Inc.)
Version: v0.24.0
Path: /usr/libexec/docker/cli-plugins/docker-buildx
trust: Manage trust on Docker images (Docker Inc.)
Version: unknown-version
Path: /usr/libexec/docker/cli-plugins/docker-trust
docker trust --help
Usage: docker trust [OPTIONS] COMMAND
Extended build capabilities with BuildKit
Options:
-D, --debug Enable debug logging
Management Commands:
key Manage keys for signing Docker images
signer Manage entities who can sign Docker images
Commands:
inspect Return low-level information about keys and signatures
revoke Remove trust for an image
sign Sign an image
Run 'docker trust COMMAND --help' for more information on a command.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Various dependencies, including "golang.org/x/.." started to update
the minimum required version,so we should follow suit for the next
release.
Note that the `//go:build` directives not necesserily have to be
updated, but it's good to keep them in sync until we have a go.mod
to control this.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Some tests had to be skipped as there's some issues to address, and
some of the result-types cannot be mocked / stubbed.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This interface is used in tests to provide a dummy notary client,
but none of the tests require any arguments, so let's remove them.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
The RegisterLegacy and Register functions register constructors for
commands, so we should expect them to be a fresh copy that is not
shared, which means that we can mutate the command in-place.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
The Register and RegisterLegacy functions are designed to be used
in package init() functions, which are guaranteed to be run
sequentially.
From the documentation (https://go.dev/ref/mem#init);
> Program initialization runs in a single goroutine, but that goroutine
> may create other goroutines, which run concurrently. If a package `p`
> imports package `q`, the completion of `q`'s `init` functions happens
> before the start of any of `p`'s.
>
> The completion of all `init` functions is synchronized before the
> start of the function `main.main`.
This patch removes the synchonisation as no concurrency should happen
if these functions are used as intended.
As the internal queue is not expected to be mutated after use, we also
don't have to return a copy.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
- Parse/format the repository name when constructing and store the
result.
- Remove the Name() accessor, as this type is only used internally,
and no longer had any special handling.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>