docker build is broken because it sends to the daemon the full
cliconfig file which has only Email(s). This patch retrieves all auth
configs from the credentials store.
Signed-off-by: Antonio Murdaca <runcom@redhat.com>
| ... | ... |
@@ -229,7 +229,7 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
|
| 229 | 229 |
ShmSize: shmSize, |
| 230 | 230 |
Ulimits: flUlimits.GetList(), |
| 231 | 231 |
BuildArgs: runconfigopts.ConvertKVStringsToMap(flBuildArg.GetAll()), |
| 232 |
- AuthConfigs: cli.configFile.AuthConfigs, |
|
| 232 |
+ AuthConfigs: cli.retrieveAuthConfigs(), |
|
| 233 | 233 |
} |
| 234 | 234 |
|
| 235 | 235 |
response, err := cli.client.ImageBuild(context.Background(), options) |
| ... | ... |
@@ -147,6 +147,11 @@ func getCredentials(c *cliconfig.ConfigFile, serverAddress string) (types.AuthCo |
| 147 | 147 |
return s.Get(serverAddress) |
| 148 | 148 |
} |
| 149 | 149 |
|
| 150 |
+func getAllCredentials(c *cliconfig.ConfigFile) (map[string]types.AuthConfig, error) {
|
|
| 151 |
+ s := loadCredentialsStore(c) |
|
| 152 |
+ return s.GetAll() |
|
| 153 |
+} |
|
| 154 |
+ |
|
| 150 | 155 |
// storeCredentials saves the user credentials in a credentials store. |
| 151 | 156 |
// The store is determined by the config file settings. |
| 152 | 157 |
func storeCredentials(c *cliconfig.ConfigFile, auth types.AuthConfig) error {
|
| ... | ... |
@@ -193,3 +193,8 @@ func (cli *DockerCli) resolveAuthConfig(index *registrytypes.IndexInfo) types.Au |
| 193 | 193 |
a, _ := getCredentials(cli.configFile, configKey) |
| 194 | 194 |
return a |
| 195 | 195 |
} |
| 196 |
+ |
|
| 197 |
+func (cli *DockerCli) retrieveAuthConfigs() map[string]types.AuthConfig {
|
|
| 198 |
+ acs, _ := getAllCredentials(cli.configFile) |
|
| 199 |
+ return acs |
|
| 200 |
+} |
| ... | ... |
@@ -10,6 +10,8 @@ type Store interface {
|
| 10 | 10 |
Erase(serverAddress string) error |
| 11 | 11 |
// Get retrieves credentials from the store for a given server. |
| 12 | 12 |
Get(serverAddress string) (types.AuthConfig, error) |
| 13 |
+ // GetAll retrieves all the credentials from the store. |
|
| 14 |
+ GetAll() (map[string]types.AuthConfig, error) |
|
| 13 | 15 |
// Store saves credentials in the store. |
| 14 | 16 |
Store(authConfig types.AuthConfig) error |
| 15 | 17 |
} |
| ... | ... |
@@ -43,6 +43,10 @@ func (c *fileStore) Get(serverAddress string) (types.AuthConfig, error) {
|
| 43 | 43 |
return authConfig, nil |
| 44 | 44 |
} |
| 45 | 45 |
|
| 46 |
+func (c *fileStore) GetAll() (map[string]types.AuthConfig, error) {
|
|
| 47 |
+ return c.file.AuthConfigs, nil |
|
| 48 |
+} |
|
| 49 |
+ |
|
| 46 | 50 |
// Store saves the given credentials in the file store. |
| 47 | 51 |
func (c *fileStore) Store(authConfig types.AuthConfig) error {
|
| 48 | 52 |
c.file.AuthConfigs[authConfig.ServerAddress] = authConfig |
| ... | ... |
@@ -70,6 +70,44 @@ func TestFileStoreGet(t *testing.T) {
|
| 70 | 70 |
} |
| 71 | 71 |
} |
| 72 | 72 |
|
| 73 |
+func TestFileStoreGetAll(t *testing.T) {
|
|
| 74 |
+ s1 := "https://example.com" |
|
| 75 |
+ s2 := "https://example2.com" |
|
| 76 |
+ f := newConfigFile(map[string]types.AuthConfig{
|
|
| 77 |
+ s1: {
|
|
| 78 |
+ Auth: "super_secret_token", |
|
| 79 |
+ Email: "foo@example.com", |
|
| 80 |
+ ServerAddress: "https://example.com", |
|
| 81 |
+ }, |
|
| 82 |
+ s2: {
|
|
| 83 |
+ Auth: "super_secret_token2", |
|
| 84 |
+ Email: "foo@example2.com", |
|
| 85 |
+ ServerAddress: "https://example2.com", |
|
| 86 |
+ }, |
|
| 87 |
+ }) |
|
| 88 |
+ |
|
| 89 |
+ s := NewFileStore(f) |
|
| 90 |
+ as, err := s.GetAll() |
|
| 91 |
+ if err != nil {
|
|
| 92 |
+ t.Fatal(err) |
|
| 93 |
+ } |
|
| 94 |
+ if len(as) != 2 {
|
|
| 95 |
+ t.Fatalf("wanted 2, got %d", len(as))
|
|
| 96 |
+ } |
|
| 97 |
+ if as[s1].Auth != "super_secret_token" {
|
|
| 98 |
+ t.Fatalf("expected auth `super_secret_token`, got %s", as[s1].Auth)
|
|
| 99 |
+ } |
|
| 100 |
+ if as[s1].Email != "foo@example.com" {
|
|
| 101 |
+ t.Fatalf("expected email `foo@example.com`, got %s", as[s1].Email)
|
|
| 102 |
+ } |
|
| 103 |
+ if as[s2].Auth != "super_secret_token2" {
|
|
| 104 |
+ t.Fatalf("expected auth `super_secret_token2`, got %s", as[s2].Auth)
|
|
| 105 |
+ } |
|
| 106 |
+ if as[s2].Email != "foo@example2.com" {
|
|
| 107 |
+ t.Fatalf("expected email `foo@example2.com`, got %s", as[s2].Email)
|
|
| 108 |
+ } |
|
| 109 |
+} |
|
| 110 |
+ |
|
| 73 | 111 |
func TestFileStoreErase(t *testing.T) {
|
| 74 | 112 |
f := newConfigFile(map[string]types.AuthConfig{
|
| 75 | 113 |
"https://example.com": {
|
| ... | ... |
@@ -81,6 +81,20 @@ func (c *nativeStore) Get(serverAddress string) (types.AuthConfig, error) {
|
| 81 | 81 |
return auth, nil |
| 82 | 82 |
} |
| 83 | 83 |
|
| 84 |
+// GetAll retrieves all the credentials from the native store. |
|
| 85 |
+func (c *nativeStore) GetAll() (map[string]types.AuthConfig, error) {
|
|
| 86 |
+ auths, _ := c.fileStore.GetAll() |
|
| 87 |
+ |
|
| 88 |
+ for s, ac := range auths {
|
|
| 89 |
+ creds, _ := c.getCredentialsFromStore(s) |
|
| 90 |
+ ac.Username = creds.Username |
|
| 91 |
+ ac.Password = creds.Password |
|
| 92 |
+ auths[s] = ac |
|
| 93 |
+ } |
|
| 94 |
+ |
|
| 95 |
+ return auths, nil |
|
| 96 |
+} |
|
| 97 |
+ |
|
| 84 | 98 |
// Store saves the given credentials in the file store. |
| 85 | 99 |
func (c *nativeStore) Store(authConfig types.AuthConfig) error {
|
| 86 | 100 |
if err := c.storeCredentialsInStore(authConfig); err != nil {
|
| ... | ... |
@@ -135,7 +149,7 @@ func (c *nativeStore) getCredentialsFromStore(serverAddress string) (types.AuthC |
| 135 | 135 |
return ret, nil |
| 136 | 136 |
} |
| 137 | 137 |
|
| 138 |
- logrus.Debugf("error adding credentials - err: %v, out: `%s`", err, t)
|
|
| 138 |
+ logrus.Debugf("error getting credentials - err: %v, out: `%s`", err, t)
|
|
| 139 | 139 |
return ret, fmt.Errorf(t) |
| 140 | 140 |
} |
| 141 | 141 |
|
| ... | ... |
@@ -158,7 +172,7 @@ func (c *nativeStore) eraseCredentialsFromStore(serverURL string) error {
|
| 158 | 158 |
out, err := cmd.Output() |
| 159 | 159 |
if err != nil {
|
| 160 | 160 |
t := strings.TrimSpace(string(out)) |
| 161 |
- logrus.Debugf("error adding credentials - err: %v, out: `%s`", err, t)
|
|
| 161 |
+ logrus.Debugf("error erasing credentials - err: %v, out: `%s`", err, t)
|
|
| 162 | 162 |
return fmt.Errorf(t) |
| 163 | 163 |
} |
| 164 | 164 |
|
| ... | ... |
@@ -13,6 +13,7 @@ import ( |
| 13 | 13 |
|
| 14 | 14 |
const ( |
| 15 | 15 |
validServerAddress = "https://index.docker.io/v1" |
| 16 |
+ validServerAddress2 = "https://example.com:5002" |
|
| 16 | 17 |
invalidServerAddress = "https://foobar.example.com" |
| 17 | 18 |
missingCredsAddress = "https://missing.docker.io/v1" |
| 18 | 19 |
) |
| ... | ... |
@@ -46,7 +47,7 @@ func (m *mockCommand) Output() ([]byte, error) {
|
| 46 | 46 |
} |
| 47 | 47 |
case "get": |
| 48 | 48 |
switch inS {
|
| 49 |
- case validServerAddress: |
|
| 49 |
+ case validServerAddress, validServerAddress2: |
|
| 50 | 50 |
return []byte(`{"Username": "foo", "Password": "bar"}`), nil
|
| 51 | 51 |
case missingCredsAddress: |
| 52 | 52 |
return []byte(errCredentialsNotFound.Error()), errCommandExited |
| ... | ... |
@@ -67,7 +68,7 @@ func (m *mockCommand) Output() ([]byte, error) {
|
| 67 | 67 |
} |
| 68 | 68 |
} |
| 69 | 69 |
|
| 70 |
- return []byte("unknown argument"), errCommandExited
|
|
| 70 |
+ return []byte(fmt.Sprintf("unknown argument %q with %q", m.arg, inS)), errCommandExited
|
|
| 71 | 71 |
} |
| 72 | 72 |
|
| 73 | 73 |
// Input sets the input to send to a remote credentials helper. |
| ... | ... |
@@ -178,6 +179,50 @@ func TestNativeStoreGet(t *testing.T) {
|
| 178 | 178 |
} |
| 179 | 179 |
} |
| 180 | 180 |
|
| 181 |
+func TestNativeStoreGetAll(t *testing.T) {
|
|
| 182 |
+ f := newConfigFile(map[string]types.AuthConfig{
|
|
| 183 |
+ validServerAddress: {
|
|
| 184 |
+ Email: "foo@example.com", |
|
| 185 |
+ }, |
|
| 186 |
+ validServerAddress2: {
|
|
| 187 |
+ Email: "foo@example2.com", |
|
| 188 |
+ }, |
|
| 189 |
+ }) |
|
| 190 |
+ f.CredentialsStore = "mock" |
|
| 191 |
+ |
|
| 192 |
+ s := &nativeStore{
|
|
| 193 |
+ commandFn: mockCommandFn, |
|
| 194 |
+ fileStore: NewFileStore(f), |
|
| 195 |
+ } |
|
| 196 |
+ as, err := s.GetAll() |
|
| 197 |
+ if err != nil {
|
|
| 198 |
+ t.Fatal(err) |
|
| 199 |
+ } |
|
| 200 |
+ |
|
| 201 |
+ if len(as) != 2 {
|
|
| 202 |
+ t.Fatalf("wanted 2, got %d", len(as))
|
|
| 203 |
+ } |
|
| 204 |
+ |
|
| 205 |
+ if as[validServerAddress].Username != "foo" {
|
|
| 206 |
+ t.Fatalf("expected username `foo` for %s, got %s", validServerAddress, as[validServerAddress].Username)
|
|
| 207 |
+ } |
|
| 208 |
+ if as[validServerAddress].Password != "bar" {
|
|
| 209 |
+ t.Fatalf("expected password `bar` for %s, got %s", validServerAddress, as[validServerAddress].Password)
|
|
| 210 |
+ } |
|
| 211 |
+ if as[validServerAddress].Email != "foo@example.com" {
|
|
| 212 |
+ t.Fatalf("expected email `foo@example.com` for %s, got %s", validServerAddress, as[validServerAddress].Email)
|
|
| 213 |
+ } |
|
| 214 |
+ if as[validServerAddress2].Username != "foo" {
|
|
| 215 |
+ t.Fatalf("expected username `foo` for %s, got %s", validServerAddress2, as[validServerAddress2].Username)
|
|
| 216 |
+ } |
|
| 217 |
+ if as[validServerAddress2].Password != "bar" {
|
|
| 218 |
+ t.Fatalf("expected password `bar` for %s, got %s", validServerAddress2, as[validServerAddress2].Password)
|
|
| 219 |
+ } |
|
| 220 |
+ if as[validServerAddress2].Email != "foo@example2.com" {
|
|
| 221 |
+ t.Fatalf("expected email `foo@example2.com` for %s, got %s", validServerAddress2, as[validServerAddress2].Email)
|
|
| 222 |
+ } |
|
| 223 |
+} |
|
| 224 |
+ |
|
| 181 | 225 |
func TestNativeStoreGetMissingCredentials(t *testing.T) {
|
| 182 | 226 |
f := newConfigFile(map[string]types.AuthConfig{
|
| 183 | 227 |
validServerAddress: {
|
| ... | ... |
@@ -6589,3 +6589,45 @@ func (s *DockerRegistryAuthSuite) TestBuildFromAuthenticatedRegistry(c *check.C) |
| 6589 | 6589 |
|
| 6590 | 6590 |
c.Assert(err, checker.IsNil) |
| 6591 | 6591 |
} |
| 6592 |
+ |
|
| 6593 |
+func (s *DockerRegistryAuthSuite) TestBuildWithExternalAuth(c *check.C) {
|
|
| 6594 |
+ osPath := os.Getenv("PATH")
|
|
| 6595 |
+ defer os.Setenv("PATH", osPath)
|
|
| 6596 |
+ |
|
| 6597 |
+ workingDir, err := os.Getwd() |
|
| 6598 |
+ c.Assert(err, checker.IsNil) |
|
| 6599 |
+ absolute, err := filepath.Abs(filepath.Join(workingDir, "fixtures", "auth")) |
|
| 6600 |
+ c.Assert(err, checker.IsNil) |
|
| 6601 |
+ testPath := fmt.Sprintf("%s%c%s", osPath, filepath.ListSeparator, absolute)
|
|
| 6602 |
+ |
|
| 6603 |
+ os.Setenv("PATH", testPath)
|
|
| 6604 |
+ |
|
| 6605 |
+ repoName := fmt.Sprintf("%v/dockercli/busybox:authtest", privateRegistryURL)
|
|
| 6606 |
+ |
|
| 6607 |
+ tmp, err := ioutil.TempDir("", "integration-cli-")
|
|
| 6608 |
+ c.Assert(err, checker.IsNil) |
|
| 6609 |
+ |
|
| 6610 |
+ externalAuthConfig := `{ "credsStore": "shell-test" }`
|
|
| 6611 |
+ |
|
| 6612 |
+ configPath := filepath.Join(tmp, "config.json") |
|
| 6613 |
+ err = ioutil.WriteFile(configPath, []byte(externalAuthConfig), 0644) |
|
| 6614 |
+ c.Assert(err, checker.IsNil) |
|
| 6615 |
+ |
|
| 6616 |
+ dockerCmd(c, "--config", tmp, "login", "-u", s.reg.username, "-p", s.reg.password, privateRegistryURL) |
|
| 6617 |
+ |
|
| 6618 |
+ b, err := ioutil.ReadFile(configPath) |
|
| 6619 |
+ c.Assert(err, checker.IsNil) |
|
| 6620 |
+ c.Assert(string(b), checker.Not(checker.Contains), "\"auth\":") |
|
| 6621 |
+ |
|
| 6622 |
+ dockerCmd(c, "--config", tmp, "tag", "busybox", repoName) |
|
| 6623 |
+ dockerCmd(c, "--config", tmp, "push", repoName) |
|
| 6624 |
+ |
|
| 6625 |
+ // make sure the image is pulled when building |
|
| 6626 |
+ dockerCmd(c, "rmi", repoName) |
|
| 6627 |
+ |
|
| 6628 |
+ buildCmd := exec.Command(dockerBinary, "--config", tmp, "build", "-") |
|
| 6629 |
+ buildCmd.Stdin = strings.NewReader(fmt.Sprintf("FROM %s", repoName))
|
|
| 6630 |
+ |
|
| 6631 |
+ out, _, err := runCommandWithOutput(buildCmd) |
|
| 6632 |
+ c.Assert(err, check.IsNil, check.Commentf(out)) |
|
| 6633 |
+} |
| ... | ... |
@@ -385,7 +385,7 @@ func (s *DockerRegistryAuthSuite) TestPullWithExternalAuth(c *check.C) {
|
| 385 | 385 |
err = ioutil.WriteFile(configPath, []byte(externalAuthConfig), 0644) |
| 386 | 386 |
c.Assert(err, checker.IsNil) |
| 387 | 387 |
|
| 388 |
- dockerCmd(c, "--config", tmp, "login", "-u", s.reg.username, "-p", s.reg.password, "-e", s.reg.email, privateRegistryURL) |
|
| 388 |
+ dockerCmd(c, "--config", tmp, "login", "-u", s.reg.username, "-p", s.reg.password, privateRegistryURL) |
|
| 389 | 389 |
|
| 390 | 390 |
b, err := ioutil.ReadFile(configPath) |
| 391 | 391 |
c.Assert(err, checker.IsNil) |