Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

saving configuration file is not forward-compatible #5559

Open
thaJeztah opened this issue Oct 20, 2024 · 0 comments
Open

saving configuration file is not forward-compatible #5559

thaJeztah opened this issue Oct 20, 2024 · 0 comments

Comments

@thaJeztah
Copy link
Member

thaJeztah commented Oct 20, 2024

Description

The config/configfile package always uses the current schema of the config-file to save the file to disk. This can be problematic, as there's many code-bases that use this code to authenticate (and store credentials), and those code-bases may be using an older version of the code. For example, go-containerregistry up until recently (previous patch release) used v24.0 as dependency;
https://github.com/google/go-containerregistry/blob/v0.20.1/go.mod#L7

Those libraries will continue to work, because they're only using the "auths" field from the configuration file, but if someone would log in using those tools they may be discarding configuration options from the config-file. As an example, c5016c6 (#4376) introduced a new "features" field in the CLI configuration file. That change is part of Docker v26.1 and up, but older versions are not aware of it.

Reproducer

I'm running this inside a container, which doesn't have a credentials-helper configured. The container has an older version of the Docker CLI (v25.0);

$ docker run -it --rm -v /var/run/docker.sock:/var/run/docker.sock docker:25.0-cli sh

$ docker --version
Docker version 25.0.5, build 5dc9bcc

Inside the container, I create a config-file in a temporary directory that contains experimental and features fields;

$ mkdir temp-config
$ echo '{"experimental":"enabled", "features":{"hooks": "true", "something-else": "false"}}' > temp-config/config.json

When running docker login or docker logout, the config is overwritten with only fields known by that version of the code;

$ cat ./temp-config/config.json
{"experimental":"enabled", "features":{"hooks": "true", "something-else": "false"}}

$ docker --config=./temp-config/ logout
Removing login credentials for https://index.docker.io/v1/

$ cat temp-config/config.json
{
	"auths": {},
	"experimental": "enabled"
}

Some other actions, such as switching the context will result in the same;

# reset the config-file
$ echo '{"experimental":"enabled", "features":{"hooks": "true", "something-else": "false"}}' > temp-config/config.json

$ docker --config=./temp-config/ context create somecontext
somecontext
Successfully created context "somecontext"

$ cat ./temp-config/config.json
{"experimental":"enabled", "features":{"hooks": "true", "something-else": "false"}}

$ docker --config=./temp-config/ context use somecontext
somecontext
Current context is now "somecontext"

$ cat ./temp-config/config.json
{
	"auths": {},
	"experimental": "enabled",
	"currentContext": "somecontext"
}

Solutions

The overall design of configuration file(s) as used by the CLI and plugins needs some re-thinking. This problem is partially because we have a poor separation of "config" and "state"; storing authentication in the config-file itself was never a great choice (and amplifies this issue), and ideally, the CLI would not mutate settings created by the user (or at least limited to actual config changes, not "state").

For actions mentioned (login, logout, switching default context), we only modify a single field in the config-file any other changes present in the config file don't have to be "understood" by the code, and we could change the code to "patch" the config-file.

i.e., when updating the config-file;

  1. read the config into a generic map[string]any
  2. patch the field to update (auths or currentContext)
  3. marshal the map[string]any to JSON and write it to the file.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant