Skip to content

Commit e532eea

Browse files
committed
login: use normalized hostname when storing
Normalization/converting the registry address to just a hostname happens inside of `command.GetDefaultAuthConfig`. Use this value for the rest of the login flow/storage. Signed-off-by: Laura Brehm <laurabrehm@hey.com>
1 parent 6273e65 commit e532eea

File tree

2 files changed

+191
-67
lines changed

2 files changed

+191
-67
lines changed

cli/command/registry/login.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ func runLogin(ctx context.Context, dockerCli command.Cli, opts loginOptions) err
106106
// if we failed to authenticate with stored credentials (or didn't have stored credentials),
107107
// prompt the user for new credentials
108108
if err != nil || authConfig.Username == "" || authConfig.Password == "" {
109-
response, err = loginUser(ctx, dockerCli, opts, authConfig.Username, serverAddress)
109+
response, err = loginUser(ctx, dockerCli, opts, authConfig.Username, authConfig.ServerAddress)
110110
if err != nil {
111111
return err
112112
}

cli/command/registry/login_test.go

Lines changed: 190 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
registrytypes "github.com/docker/docker/api/types/registry"
1717
"github.com/docker/docker/api/types/system"
1818
"github.com/docker/docker/client"
19+
"github.com/docker/docker/registry"
1920
"gotest.tools/v3/assert"
2021
is "gotest.tools/v3/assert/cmp"
2122
"gotest.tools/v3/fs"
@@ -83,108 +84,231 @@ func TestLoginWithCredStoreCreds(t *testing.T) {
8384
}
8485

8586
func TestRunLogin(t *testing.T) {
86-
const (
87-
storedServerAddress = "reg1"
88-
validUsername = "u1"
89-
validPassword = "p1"
90-
validPassword2 = "p2"
91-
)
92-
93-
validAuthConfig := configtypes.AuthConfig{
94-
ServerAddress: storedServerAddress,
95-
Username: validUsername,
96-
Password: validPassword,
97-
}
98-
expiredAuthConfig := configtypes.AuthConfig{
99-
ServerAddress: storedServerAddress,
100-
Username: validUsername,
101-
Password: expiredPassword,
102-
}
103-
validIdentityToken := configtypes.AuthConfig{
104-
ServerAddress: storedServerAddress,
105-
Username: validUsername,
106-
IdentityToken: useToken,
107-
}
10887
testCases := []struct {
109-
doc string
110-
inputLoginOption loginOptions
111-
inputStoredCred *configtypes.AuthConfig
112-
expectedErr string
113-
expectedSavedCred configtypes.AuthConfig
88+
doc string
89+
priorCredentials map[string]configtypes.AuthConfig
90+
input loginOptions
91+
expectedCredentials map[string]configtypes.AuthConfig
92+
expectedErr string
11493
}{
11594
{
11695
doc: "valid auth from store",
117-
inputLoginOption: loginOptions{
118-
serverAddress: storedServerAddress,
96+
priorCredentials: map[string]configtypes.AuthConfig{
97+
"reg1": {
98+
Username: "my-username",
99+
Password: "a-password",
100+
ServerAddress: "reg1",
101+
},
102+
},
103+
input: loginOptions{
104+
serverAddress: "reg1",
105+
},
106+
expectedCredentials: map[string]configtypes.AuthConfig{
107+
"reg1": {
108+
Username: "my-username",
109+
Password: "a-password",
110+
ServerAddress: "reg1",
111+
},
112+
},
113+
},
114+
{
115+
doc: "expired auth from store",
116+
priorCredentials: map[string]configtypes.AuthConfig{
117+
"reg1": {
118+
Username: "my-username",
119+
Password: expiredPassword,
120+
ServerAddress: "reg1",
121+
},
122+
},
123+
input: loginOptions{
124+
serverAddress: "reg1",
119125
},
120-
inputStoredCred: &validAuthConfig,
121-
expectedSavedCred: validAuthConfig,
126+
expectedErr: "Error: Cannot perform an interactive login from a non TTY device",
122127
},
123128
{
124-
doc: "expired auth",
125-
inputLoginOption: loginOptions{
126-
serverAddress: storedServerAddress,
129+
doc: "store valid username and password",
130+
priorCredentials: map[string]configtypes.AuthConfig{},
131+
input: loginOptions{
132+
serverAddress: "reg1",
133+
user: "my-username",
134+
password: "p2",
135+
},
136+
expectedCredentials: map[string]configtypes.AuthConfig{
137+
"reg1": {
138+
Username: "my-username",
139+
Password: "p2",
140+
ServerAddress: "reg1",
141+
},
127142
},
128-
inputStoredCred: &expiredAuthConfig,
129-
expectedErr: "Error: Cannot perform an interactive login from a non TTY device",
130143
},
131144
{
132-
doc: "valid username and password",
133-
inputLoginOption: loginOptions{
134-
serverAddress: storedServerAddress,
135-
user: validUsername,
136-
password: validPassword2,
145+
doc: "unknown user w/ prior credentials",
146+
priorCredentials: map[string]configtypes.AuthConfig{
147+
"reg1": {
148+
Username: "my-username",
149+
Password: "a-password",
150+
ServerAddress: "reg1",
151+
},
152+
},
153+
input: loginOptions{
154+
serverAddress: "reg1",
155+
user: unknownUser,
156+
password: "a-password",
137157
},
138-
inputStoredCred: &validAuthConfig,
139-
expectedSavedCred: configtypes.AuthConfig{
140-
ServerAddress: storedServerAddress,
141-
Username: validUsername,
142-
Password: validPassword2,
158+
expectedErr: errUnknownUser,
159+
expectedCredentials: map[string]configtypes.AuthConfig{
160+
"reg1": {
161+
Username: "a-password",
162+
Password: "a-password",
163+
ServerAddress: "reg1",
164+
},
143165
},
144166
},
145167
{
146-
doc: "unknown user",
147-
inputLoginOption: loginOptions{
148-
serverAddress: storedServerAddress,
168+
doc: "unknown user w/o prior credentials",
169+
priorCredentials: map[string]configtypes.AuthConfig{},
170+
input: loginOptions{
171+
serverAddress: "reg1",
149172
user: unknownUser,
150-
password: validPassword,
173+
password: "a-password",
151174
},
152-
inputStoredCred: &validAuthConfig,
153-
expectedErr: errUnknownUser,
175+
expectedErr: errUnknownUser,
176+
expectedCredentials: map[string]configtypes.AuthConfig{},
154177
},
155178
{
156-
doc: "valid token",
157-
inputLoginOption: loginOptions{
158-
serverAddress: storedServerAddress,
159-
user: validUsername,
179+
doc: "store valid token",
180+
priorCredentials: map[string]configtypes.AuthConfig{},
181+
input: loginOptions{
182+
serverAddress: "reg1",
183+
user: "my-username",
160184
password: useToken,
161185
},
162-
inputStoredCred: &validIdentityToken,
163-
expectedSavedCred: validIdentityToken,
186+
expectedCredentials: map[string]configtypes.AuthConfig{
187+
"reg1": {
188+
Username: "my-username",
189+
IdentityToken: useToken,
190+
ServerAddress: "reg1",
191+
},
192+
},
193+
},
194+
{
195+
doc: "valid token from store",
196+
priorCredentials: map[string]configtypes.AuthConfig{
197+
"reg1": {
198+
Username: "my-username",
199+
Password: useToken,
200+
ServerAddress: "reg1",
201+
},
202+
},
203+
input: loginOptions{
204+
serverAddress: "reg1",
205+
},
206+
expectedCredentials: map[string]configtypes.AuthConfig{
207+
"reg1": {
208+
Username: "my-username",
209+
IdentityToken: useToken,
210+
ServerAddress: "reg1",
211+
},
212+
},
213+
},
214+
{
215+
doc: "no registry specified defaults to index server",
216+
priorCredentials: map[string]configtypes.AuthConfig{},
217+
input: loginOptions{
218+
user: "my-username",
219+
password: "my-password",
220+
},
221+
expectedCredentials: map[string]configtypes.AuthConfig{
222+
registry.IndexServer: {
223+
Username: "my-username",
224+
Password: "my-password",
225+
ServerAddress: registry.IndexServer,
226+
},
227+
},
228+
},
229+
{
230+
doc: "registry-1.docker.io",
231+
priorCredentials: map[string]configtypes.AuthConfig{},
232+
input: loginOptions{
233+
serverAddress: "registry-1.docker.io",
234+
user: "my-username",
235+
password: "my-password",
236+
},
237+
expectedCredentials: map[string]configtypes.AuthConfig{
238+
"registry-1.docker.io": {
239+
Username: "my-username",
240+
Password: "my-password",
241+
ServerAddress: "registry-1.docker.io",
242+
},
243+
},
244+
},
245+
// Regression test for https://github.com/docker/cli/issues/5382
246+
{
247+
doc: "sanitizes server address to remove repo",
248+
priorCredentials: map[string]configtypes.AuthConfig{},
249+
input: loginOptions{
250+
serverAddress: "registry-1.docker.io/bork/test",
251+
user: "my-username",
252+
password: "a-password",
253+
},
254+
expectedCredentials: map[string]configtypes.AuthConfig{
255+
"registry-1.docker.io": {
256+
Username: "my-username",
257+
Password: "a-password",
258+
ServerAddress: "registry-1.docker.io",
259+
},
260+
},
261+
},
262+
// Regression test for https://github.com/docker/cli/issues/5382
263+
{
264+
doc: "updates credential if server address includes repo",
265+
priorCredentials: map[string]configtypes.AuthConfig{
266+
"registry-1.docker.io": {
267+
Username: "my-username",
268+
Password: "a-password",
269+
ServerAddress: "registry-1.docker.io",
270+
},
271+
},
272+
input: loginOptions{
273+
serverAddress: "registry-1.docker.io/bork/test",
274+
user: "my-username",
275+
password: "new-password",
276+
},
277+
expectedCredentials: map[string]configtypes.AuthConfig{
278+
"registry-1.docker.io": {
279+
Username: "my-username",
280+
Password: "new-password",
281+
ServerAddress: "registry-1.docker.io",
282+
},
283+
},
164284
},
165285
}
286+
166287
for _, tc := range testCases {
167-
tc := tc
168288
t.Run(tc.doc, func(t *testing.T) {
169289
tmpFile := fs.NewFile(t, "test-run-login")
170290
defer tmpFile.Remove()
171291
cli := test.NewFakeCli(&fakeClient{})
172292
configfile := cli.ConfigFile()
173293
configfile.Filename = tmpFile.Path()
174294

175-
if tc.inputStoredCred != nil {
176-
cred := *tc.inputStoredCred
177-
assert.NilError(t, configfile.GetCredentialsStore(cred.ServerAddress).Store(cred))
295+
for _, priorCred := range tc.priorCredentials {
296+
assert.NilError(t, configfile.GetCredentialsStore(priorCred.ServerAddress).Store(priorCred))
178297
}
179-
loginErr := runLogin(context.Background(), cli, tc.inputLoginOption)
298+
storedCreds, err := configfile.GetAllCredentials()
299+
assert.NilError(t, err)
300+
assert.DeepEqual(t, storedCreds, tc.priorCredentials)
301+
302+
loginErr := runLogin(context.Background(), cli, tc.input)
180303
if tc.expectedErr != "" {
181304
assert.Error(t, loginErr, tc.expectedErr)
182305
return
183306
}
184307
assert.NilError(t, loginErr)
185-
savedCred, credStoreErr := configfile.GetCredentialsStore(tc.inputStoredCred.ServerAddress).Get(tc.inputStoredCred.ServerAddress)
186-
assert.Check(t, credStoreErr)
187-
assert.DeepEqual(t, tc.expectedSavedCred, savedCred)
308+
309+
outputCreds, err := configfile.GetAllCredentials()
310+
assert.Check(t, err)
311+
assert.DeepEqual(t, outputCreds, tc.expectedCredentials)
188312
})
189313
}
190314
}

0 commit comments

Comments
 (0)