The format had a stray colon and space included. While fixing that, also
updating the error message to clarify the error happened while parsing
the file (not so much "loading" it).
Before:
WARNING: Error loading config file: /root/.docker/config.json: : json: cannot unmarshal bool into Go struct field ConfigFile.features of type string
After:
WARNING: Error parsing config file (/root/.docker/config.json): json: cannot unmarshal bool into Go struct field ConfigFile.features of type string
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Before this change, the config-file was always updated, even if there
were no changes to save. This could cause issues when the config-file
already had credentials set and was read-only for the current user.
For example, on NixOS, this poses a problem because `config.json` is a
symlink to a write-protected file;
$ readlink ~/.docker/config.json
/home/username/.config/sops-nix/secrets/ghcr_auth
$ readlink -f ~/.docker/config.json
/run/user/1000/secrets.d/28/ghcr_auth
Which causes `docker login` to fail, even if no changes were to be made;
Error saving credentials: rename /home/derek/.docker/config.json2180380217 /home/username/.config/sops-nix/secrets/ghcr_auth: invalid cross-device link
This patch updates the code to only update the config file if changes
were detected. It there's nothing to save, it skips updating the file,
as well as skips printing the warning about credentials being stored
insecurely.
With this patch applied:
$ docker login -u yourname
Password:
WARNING! Your credentials are stored unencrypted in '/root/.docker/config.json'.
Configure a credential helper to remove this warning. See
https://docs.docker.com/go/credential-store/
Login Succeeded
$ docker login -u yourname
Password:
Login Succeeded
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
The fileStore itself is aware that it's insecure, so we can make it
responsible for printing the warning. It's not "perfect", as we use
`os.Stderr` unconditionally (not `dockerCli.Err()`), but probably won't
make a difference in _most_ cases.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This makes a quick pass through our tests;
Discard output/err
----------------------------------------------
Many tests were testing for error-conditions, but didn't discard output.
This produced a lot of noise when running the tests, and made it hard
to discover if there were actual failures, or if the output was expected.
For example:
=== RUN TestConfigCreateErrors
Error: "create" requires exactly 2 arguments.
See 'create --help'.
Usage: create [OPTIONS] CONFIG file|- [flags]
Create a config from a file or STDIN
Error: "create" requires exactly 2 arguments.
See 'create --help'.
Usage: create [OPTIONS] CONFIG file|- [flags]
Create a config from a file or STDIN
Error: error creating config
--- PASS: TestConfigCreateErrors (0.00s)
And after discarding output:
=== RUN TestConfigCreateErrors
--- PASS: TestConfigCreateErrors (0.00s)
Use sub-tests where possible
----------------------------------------------
Some tests were already set-up to use test-tables, and even had a usable
name (or in some cases "error" to check for). Change them to actual sub-
tests. Same test as above, but now with sub-tests and output discarded:
=== RUN TestConfigCreateErrors
=== RUN TestConfigCreateErrors/requires_exactly_2_arguments
=== RUN TestConfigCreateErrors/requires_exactly_2_arguments#01
=== RUN TestConfigCreateErrors/error_creating_config
--- PASS: TestConfigCreateErrors (0.00s)
--- PASS: TestConfigCreateErrors/requires_exactly_2_arguments (0.00s)
--- PASS: TestConfigCreateErrors/requires_exactly_2_arguments#01 (0.00s)
--- PASS: TestConfigCreateErrors/error_creating_config (0.00s)
PASS
It's not perfect in all cases (in the above, there's duplicate "expected"
errors, but Go conveniently adds "#01" for the duplicate). There's probably
also various tests I missed that could still use the same changes applied;
we can improve these in follow-ups.
Set cmd.Args to prevent test-failures
----------------------------------------------
When running tests from my IDE, it compiles the tests before running,
then executes the compiled binary to run the tests. Cobra doesn't like
that, because in that situation `os.Args` is taken as argument for the
command that's executed. The command that's tested now sees the test-
flags as arguments (`-test.v -test.run ..`), which causes various tests
to fail ("Command XYZ does not accept arguments").
# compile the tests:
go test -c -o foo.test
# execute the test:
./foo.test -test.v -test.run TestFoo
=== RUN TestFoo
Error: "foo" accepts no arguments.
The Cobra maintainers ran into the same situation, and for their own
use have added a special case to ignore `os.Args` in these cases;
https://github.com/spf13/cobra/blob/v1.8.1/command.go#L1078-L1083
args := c.args
// Workaround FAIL with "go test -v" or "cobra.test -test.v", see #155
if c.args == nil && filepath.Base(os.Args[0]) != "cobra.test" {
args = os.Args[1:]
}
Unfortunately, that exception is too specific (only checks for `cobra.test`),
so doesn't automatically fix the issue for other test-binaries. They did
provide a `cmd.SetArgs()` utility for this purpose
https://github.com/spf13/cobra/blob/v1.8.1/command.go#L276-L280
// SetArgs sets arguments for the command. It is set to os.Args[1:] by default, if desired, can be overridden
// particularly useful when testing.
func (c *Command) SetArgs(a []string) {
c.args = a
}
And the fix is to explicitly set the command's args to an empty slice to
prevent Cobra from falling back to using `os.Args[1:]` as arguments.
cmd := newSomeThingCommand()
cmd.SetArgs([]string{})
Some tests already take this issue into account, and I updated some tests
for this, but there's likely many other ones that can use the same treatment.
Perhaps the Cobra maintainers would accept a contribution to make their
condition less specific and to look for binaries ending with a `.test`
suffix (which is what compiled binaries usually are named as).
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
There's some consumers of the config package that don't need any of the
other parts of the code, but because of the pkg/homedir were now forced
to also depend on docker/docker.
This patch introduces a local copy of the function to prevent this.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Commit 27b2797f7d added a local implementation
of this function, so let's use the local variant to (slightly) reduce the
dependency on moby's registry package.
Also made some minor cleanups.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
When attempting to load a config-file that exists, but is not accessible for
the current user, we should not discard the error.
This patch makes sure that the error is returned by Load(), but does not yet
change LoadDefaultConfigFile, as this requires a change in signature.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This may need further discussion, but we currently handle dangling
symlinks gracefully, so let's add a test for this, and verify that
we don't replace symlinks with a file.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This will return the ServerAddress property when using the NativeStore.
This happens when you use docker credential helpers, not the credential
store.
The reason this fix is needed is because it needs to be propagated
properly down towards `moby/moby` project in the following logic:
```golang
func authorizationCredsFromAuthConfig(authConfig registrytypes.AuthConfig) docker.AuthorizerOpt {
cfgHost := registry.ConvertToHostname(authConfig.ServerAddress)
if cfgHost == "" || cfgHost == registry.IndexHostname {
cfgHost = registry.DefaultRegistryHost
}
return docker.WithAuthCreds(func(host string) (string, string, error) {
if cfgHost != host {
logrus.WithFields(logrus.Fields{
"host": host,
"cfgHost": cfgHost,
}).Warn("Host doesn't match")
return "", "", nil
}
if authConfig.IdentityToken != "" {
return "", authConfig.IdentityToken, nil
}
return authConfig.Username, authConfig.Password, nil
})
}
```
This logic resides in the following file :
`daemon/containerd/resolver.go` .
In the case when using the containerd storage feature when setting the
`cfgHost` variable from the `authConfig.ServerAddress` it will always be
empty. Since it will never be returned from the NativeStore currently.
Therefore Docker Hub images will work fine, but anything else will fail
since the `cfgHost` will always be the `registry.DefaultRegistryHost`.
Signed-off-by: Eric Bode <eric.bode@foundries.io>
Initialize AuthConfigs map if it's nil before returning it.
This fixes fileStore.Store nil dereference panic when adding a new key
to the map.
Signed-off-by: Danial Gharib <danial.mail.gh@gmail.com>
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
commit 8a30653ed5 introduced a sync.Once
to allow for the config-directory (and home-dir) to be looked up lazily
instead of in an `init()`.
However, the package-level `configDir` variable can be set through two
separate paths; implicitly (through `config.Dir()`), and explicitly,
through `config.SetDir()`. The existing code had no synchronisation for
this, which could lead to a potential race-condition (code requesting
`config.Dir()` and code setting a custom path through `config.SetDir()`).
This patch adds synchronisation by triggering the `sync.Once` as part of
`config.SetDir()` to prevent it being triggered later (overwriting the
value that was set). It also restores the `resetConfigDir()` utility that
was removed in 379122b033, to allow resetting
the `sync.Once` for this test.
In general, we should get rid of this package-level variable, and store
it as a config on the client (passing the option to locations where its
used instead).
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
the "golang.org/x/sys/execabs" package was introduced to address a security
issue on Windows, and changing the default behavior of os/exec was considered
a breaking change. go1.19 applied the behavior that was previously implemented
in the execabs package;
from the release notes: https://go.dev/doc/go1.19#os-exec-path
> Command and LookPath no longer allow results from a PATH search to be found
> relative to the current directory. This removes a common source of security
> problems but may also break existing programs that depend on using, say,
> exec.Command("prog") to run a binary named prog (or, on Windows, prog.exe)
> in the current directory. See the os/exec package documentation for information
> about how best to update such programs.
>
> On Windows, Command and LookPath now respect the NoDefaultCurrentDirectoryInExePath
> environment variable, making it possible to disable the default implicit search
> of “.” in PATH lookups on Windows systems.
With those changes, we no longer need to use the execabs package, and we can
switch back to os/exec.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
The `~/.dockercfg` file was replaced by `~/.docker/config.json` in 2015
(github.com/docker/docker/commit/18c9b6c6455f116ae59cde8544413b3d7d294a5e).
Commit b83bc67136 (v23.0.0, but backported to
v20.10) added a warning if no "current" config file was found but a legacy
file was, and if the CLI would fall back to using the deprecated file.
Commit ee218fa89e removed support for the
legacy file, but kept a warning in place if a legacy file was in place,
and now ignored.
This patch removes the warning as well, fully deprecating the legacy
`~/.dockercfg` file.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This FIXME was added in 2013 in c72ff318d3
and it's both unclear which "internal golang config parser" is referred to
here. Given that 10 Years have passed, this will unlikely happen, and doesn't
warrant a FIXME here.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
defaultCredentialsStore() on Linux does an exec.LookPath() for "pass", but
if a custom credential-store is passed to DetectDefaultStore, the result
of that won't be used.
This patch changes the logic to return early if a custom credential-store
is passed.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This field was deprecated in 6ea2767289, which
is part of docker 23.0, so users should have had a chance to migrate.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
cli/config/configfile/file_test.go:189:33: unused-parameter: parameter 'authConfig' seems to be unused, consider removing or renaming it as _ (revive)
func (c *mockNativeStore) Store(authConfig types.AuthConfig) error {
^
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Looks like the linter uses an explicit -lang, which (for go1.19)
results in some additional formatting for octal values.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Also removing redundant defer for env.PatchAll(), which is now automatically
handled in t.Cleanup()
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
The `~/.dockercfg` file was replaced by `~/.docker/config.json` in 2015
(github.com/docker/docker/commit/18c9b6c6455f116ae59cde8544413b3d7d294a5e),
but the CLI still falls back to checking if this file exists if no current
(`~/.docker/config.json`) file was found.
Given that no version of the CLI since Docker v1.7.0 has created this file,
and if such a file exists, it means someone hasn't re-authenticated for
5 years, it's probably safe to remove this fallback.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Locking was removed in https://github.com/docker/cli/pull/3025 which
allows for parallel calls to config.Load to modify global state.
The consequence in this case is innocuous, but it does trigger a
`DATA RACE` exception when tests run with `-race` option.
Signed-off-by: coryb <cbennett@netflix.com>
Support for ALL_PROXY as default build-arg was added recently in
buildkit and the classic builder.
This patch adds the `ALL_PROXY` environment variable to the list of
configurable proxy variables, and updates the documentation.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
- use var/const blocks when declaring a list of variables
- use const where possible
TestCheckKubernetesConfigurationRaiseAnErrorOnInvalidValue:
- use keys when assigning values
- make sure test is dereferenced in the loop
- use subtests
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Some tests were using domain names that were intended to be "fake", but are
actually registered domain names (such as mycorp.com).
Even though we were not actually making connections to these domains, it's
better to use domains that are designated for testing/examples in RFC2606:
https://tools.ietf.org/html/rfc2606
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Relates to the deprecation, added in 3c0a167ed5
The docker CLI up until v1.7.0 used the `~/.dockercfg` file to store credentials
after authenticating to a registry (`docker login`). Docker v1.7.0 replaced this
file with a new CLI configuration file, located in `~/.docker/config.json`. When
implementing the new configuration file, the old file (and file-format) was kept
as a fall-back, to assist existing users with migrating to the new file.
Given that the old file format encourages insecure storage of credentials
(credentials are stored unencrypted), and that no version of the CLI since
Docker v1.7.0 has created this file, the file is marked deprecated, and support
for this file will be removed in a future release.
This patch adds a deprecation warning, which is printed if the CLI falls back
to using the deprecated ~/.dockercfg file.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>