Skip to content

Commit b83bc67

Browse files
committed
config: print deprecation warning when falling back to ~/.dockercfg
Relates to the deprecation, added in 3c0a167 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 <[email protected]>
1 parent 70a0015 commit b83bc67

3 files changed

Lines changed: 57 additions & 3 deletions

File tree

cli/config/config.go

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ const (
2424
)
2525

2626
var (
27-
initConfigDir sync.Once
27+
initConfigDir = new(sync.Once)
2828
configDir string
2929
homeDir string
3030
)
3131

32-
// resetHomeDir is used in testing to resets the "homeDir" package variable to
32+
// resetHomeDir is used in testing to reset the "homeDir" package variable to
3333
// force re-lookup of the home directory between tests.
3434
func resetHomeDir() {
3535
homeDir = ""
@@ -42,6 +42,13 @@ func getHomeDir() string {
4242
return homeDir
4343
}
4444

45+
// resetConfigDir is used in testing to reset the "configDir" package variable
46+
// and its sync.Once to force re-lookup between tests.
47+
func resetConfigDir() {
48+
configDir = ""
49+
initConfigDir = new(sync.Once)
50+
}
51+
4552
func setConfigDir() {
4653
if configDir != "" {
4754
return
@@ -97,10 +104,20 @@ func LoadFromReader(configData io.Reader) (*configfile.ConfigFile, error) {
97104
return &configFile, err
98105
}
99106

107+
// TODO remove this temporary hack, which is used to warn about the deprecated ~/.dockercfg file
108+
var (
109+
mutex sync.RWMutex
110+
printLegacyFileWarning bool
111+
)
112+
100113
// Load reads the configuration files in the given directory, and sets up
101114
// the auth config information and returns values.
102115
// FIXME: use the internal golang config parser
103116
func Load(configDir string) (*configfile.ConfigFile, error) {
117+
mutex.Lock()
118+
printLegacyFileWarning = false
119+
mutex.Unlock()
120+
104121
if configDir == "" {
105122
configDir = Dir()
106123
}
@@ -125,6 +142,9 @@ func Load(configDir string) (*configfile.ConfigFile, error) {
125142
// Can't find latest config file so check for the old one
126143
filename = filepath.Join(getHomeDir(), oldConfigfile)
127144
if file, err := os.Open(filename); err == nil {
145+
mutex.Lock()
146+
printLegacyFileWarning = true
147+
mutex.Unlock()
128148
defer file.Close()
129149
if err := configFile.LegacyLoadFromReader(file); err != nil {
130150
return configFile, errors.Wrap(err, filename)
@@ -140,6 +160,11 @@ func LoadDefaultConfigFile(stderr io.Writer) *configfile.ConfigFile {
140160
if err != nil {
141161
fmt.Fprintf(stderr, "WARNING: Error loading config file: %v\n", err)
142162
}
163+
mutex.RLock()
164+
defer mutex.RUnlock()
165+
if printLegacyFileWarning {
166+
_, _ = fmt.Fprintln(stderr, "WARNING: Support for the legacy ~/.dockercfg configuration file and file-format is deprecated and will be removed in an upcoming release")
167+
}
143168
if !configFile.ContainsAuth() {
144169
configFile.CredentialsStore = credentials.DetectDefaultStore(configFile.CredentialsStore)
145170
}

cli/config/config_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ import (
1212

1313
"github.com/docker/cli/cli/config/configfile"
1414
"github.com/docker/cli/cli/config/credentials"
15+
"github.com/docker/cli/cli/config/types"
1516
"gotest.tools/v3/assert"
1617
is "gotest.tools/v3/assert/cmp"
1718
"gotest.tools/v3/env"
19+
"gotest.tools/v3/fs"
1820
)
1921

2022
var homeKey = "HOME"
@@ -223,6 +225,31 @@ func TestOldJSON(t *testing.T) {
223225
}
224226
}
225227

228+
func TestOldJSONFallbackDeprecationWarning(t *testing.T) {
229+
js := `{"https://index.docker.io/v1/":{"auth":"am9lam9lOmhlbGxv","email":"[email protected]"}}`
230+
tmpHome := fs.NewDir(t, t.Name(), fs.WithFile(oldConfigfile, js))
231+
defer tmpHome.Remove()
232+
defer env.PatchAll(t, map[string]string{homeKey: tmpHome.Path(), "DOCKER_CONFIG": ""})()
233+
234+
// reset the homeDir, configDir, and its sync.Once, to force them being resolved again
235+
resetHomeDir()
236+
resetConfigDir()
237+
238+
buffer := new(bytes.Buffer)
239+
configFile := LoadDefaultConfigFile(buffer)
240+
expected := configfile.New(tmpHome.Join(configFileDir, ConfigFileName))
241+
expected.AuthConfigs = map[string]types.AuthConfig{
242+
"https://index.docker.io/v1/": {
243+
Username: "joejoe",
244+
Password: "hello",
245+
246+
ServerAddress: "https://index.docker.io/v1/",
247+
},
248+
}
249+
assert.Assert(t, strings.Contains(buffer.String(), "WARNING: Support for the legacy ~/.dockercfg configuration file and file-format is deprecated and will be removed in an upcoming release"))
250+
assert.Check(t, is.DeepEqual(expected, configFile))
251+
}
252+
226253
func TestNewJSON(t *testing.T) {
227254
tmpHome, err := ioutil.TempDir("", "config-test")
228255
assert.NilError(t, err)

cmd/docker/docker_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ import (
1717
func TestClientDebugEnabled(t *testing.T) {
1818
defer debug.Disable()
1919

20-
tcmd := newDockerCommand(&command.DockerCli{})
20+
cli, err := command.NewDockerCli()
21+
assert.NilError(t, err)
22+
tcmd := newDockerCommand(cli)
2123
tcmd.SetFlag("debug", "true")
2224
cmd, _, err := tcmd.HandleGlobalFlags()
2325
assert.NilError(t, err)

0 commit comments

Comments
 (0)