1
0
mirror of https://github.com/moby/moby.git synced 2025-08-01 05:47:11 +03:00

cliconfig: credentials: support getting all auths

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>
This commit is contained in:
Antonio Murdaca
2016-03-01 18:04:35 +01:00
parent 4eb7a4916f
commit 44152144ca
11 changed files with 161 additions and 7 deletions

View File

@ -229,7 +229,7 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
ShmSize: shmSize, ShmSize: shmSize,
Ulimits: flUlimits.GetList(), Ulimits: flUlimits.GetList(),
BuildArgs: runconfigopts.ConvertKVStringsToMap(flBuildArg.GetAll()), BuildArgs: runconfigopts.ConvertKVStringsToMap(flBuildArg.GetAll()),
AuthConfigs: cli.configFile.AuthConfigs, AuthConfigs: cli.retrieveAuthConfigs(),
} }
response, err := cli.client.ImageBuild(context.Background(), options) response, err := cli.client.ImageBuild(context.Background(), options)

View File

@ -147,6 +147,11 @@ func getCredentials(c *cliconfig.ConfigFile, serverAddress string) (types.AuthCo
return s.Get(serverAddress) return s.Get(serverAddress)
} }
func getAllCredentials(c *cliconfig.ConfigFile) (map[string]types.AuthConfig, error) {
s := loadCredentialsStore(c)
return s.GetAll()
}
// storeCredentials saves the user credentials in a credentials store. // storeCredentials saves the user credentials in a credentials store.
// The store is determined by the config file settings. // The store is determined by the config file settings.
func storeCredentials(c *cliconfig.ConfigFile, auth types.AuthConfig) error { func storeCredentials(c *cliconfig.ConfigFile, auth types.AuthConfig) error {

View File

@ -193,3 +193,8 @@ func (cli *DockerCli) resolveAuthConfig(index *registrytypes.IndexInfo) types.Au
a, _ := getCredentials(cli.configFile, configKey) a, _ := getCredentials(cli.configFile, configKey)
return a return a
} }
func (cli *DockerCli) retrieveAuthConfigs() map[string]types.AuthConfig {
acs, _ := getAllCredentials(cli.configFile)
return acs
}

View File

@ -10,6 +10,8 @@ type Store interface {
Erase(serverAddress string) error Erase(serverAddress string) error
// Get retrieves credentials from the store for a given server. // Get retrieves credentials from the store for a given server.
Get(serverAddress string) (types.AuthConfig, error) Get(serverAddress string) (types.AuthConfig, error)
// GetAll retrieves all the credentials from the store.
GetAll() (map[string]types.AuthConfig, error)
// Store saves credentials in the store. // Store saves credentials in the store.
Store(authConfig types.AuthConfig) error Store(authConfig types.AuthConfig) error
} }

View File

@ -43,6 +43,10 @@ func (c *fileStore) Get(serverAddress string) (types.AuthConfig, error) {
return authConfig, nil return authConfig, nil
} }
func (c *fileStore) GetAll() (map[string]types.AuthConfig, error) {
return c.file.AuthConfigs, nil
}
// Store saves the given credentials in the file store. // Store saves the given credentials in the file store.
func (c *fileStore) Store(authConfig types.AuthConfig) error { func (c *fileStore) Store(authConfig types.AuthConfig) error {
c.file.AuthConfigs[authConfig.ServerAddress] = authConfig c.file.AuthConfigs[authConfig.ServerAddress] = authConfig

View File

@ -70,6 +70,44 @@ func TestFileStoreGet(t *testing.T) {
} }
} }
func TestFileStoreGetAll(t *testing.T) {
s1 := "https://example.com"
s2 := "https://example2.com"
f := newConfigFile(map[string]types.AuthConfig{
s1: {
Auth: "super_secret_token",
Email: "foo@example.com",
ServerAddress: "https://example.com",
},
s2: {
Auth: "super_secret_token2",
Email: "foo@example2.com",
ServerAddress: "https://example2.com",
},
})
s := NewFileStore(f)
as, err := s.GetAll()
if err != nil {
t.Fatal(err)
}
if len(as) != 2 {
t.Fatalf("wanted 2, got %d", len(as))
}
if as[s1].Auth != "super_secret_token" {
t.Fatalf("expected auth `super_secret_token`, got %s", as[s1].Auth)
}
if as[s1].Email != "foo@example.com" {
t.Fatalf("expected email `foo@example.com`, got %s", as[s1].Email)
}
if as[s2].Auth != "super_secret_token2" {
t.Fatalf("expected auth `super_secret_token2`, got %s", as[s2].Auth)
}
if as[s2].Email != "foo@example2.com" {
t.Fatalf("expected email `foo@example2.com`, got %s", as[s2].Email)
}
}
func TestFileStoreErase(t *testing.T) { func TestFileStoreErase(t *testing.T) {
f := newConfigFile(map[string]types.AuthConfig{ f := newConfigFile(map[string]types.AuthConfig{
"https://example.com": { "https://example.com": {

View File

@ -81,6 +81,20 @@ func (c *nativeStore) Get(serverAddress string) (types.AuthConfig, error) {
return auth, nil return auth, nil
} }
// GetAll retrieves all the credentials from the native store.
func (c *nativeStore) GetAll() (map[string]types.AuthConfig, error) {
auths, _ := c.fileStore.GetAll()
for s, ac := range auths {
creds, _ := c.getCredentialsFromStore(s)
ac.Username = creds.Username
ac.Password = creds.Password
auths[s] = ac
}
return auths, nil
}
// Store saves the given credentials in the file store. // Store saves the given credentials in the file store.
func (c *nativeStore) Store(authConfig types.AuthConfig) error { func (c *nativeStore) Store(authConfig types.AuthConfig) error {
if err := c.storeCredentialsInStore(authConfig); err != nil { if err := c.storeCredentialsInStore(authConfig); err != nil {
@ -135,7 +149,7 @@ func (c *nativeStore) getCredentialsFromStore(serverAddress string) (types.AuthC
return ret, nil return ret, nil
} }
logrus.Debugf("error adding credentials - err: %v, out: `%s`", err, t) logrus.Debugf("error getting credentials - err: %v, out: `%s`", err, t)
return ret, fmt.Errorf(t) return ret, fmt.Errorf(t)
} }
@ -158,7 +172,7 @@ func (c *nativeStore) eraseCredentialsFromStore(serverURL string) error {
out, err := cmd.Output() out, err := cmd.Output()
if err != nil { if err != nil {
t := strings.TrimSpace(string(out)) t := strings.TrimSpace(string(out))
logrus.Debugf("error adding credentials - err: %v, out: `%s`", err, t) logrus.Debugf("error erasing credentials - err: %v, out: `%s`", err, t)
return fmt.Errorf(t) return fmt.Errorf(t)
} }

View File

@ -13,6 +13,7 @@ import (
const ( const (
validServerAddress = "https://index.docker.io/v1" validServerAddress = "https://index.docker.io/v1"
validServerAddress2 = "https://example.com:5002"
invalidServerAddress = "https://foobar.example.com" invalidServerAddress = "https://foobar.example.com"
missingCredsAddress = "https://missing.docker.io/v1" missingCredsAddress = "https://missing.docker.io/v1"
) )
@ -46,7 +47,7 @@ func (m *mockCommand) Output() ([]byte, error) {
} }
case "get": case "get":
switch inS { switch inS {
case validServerAddress: case validServerAddress, validServerAddress2:
return []byte(`{"Username": "foo", "Password": "bar"}`), nil return []byte(`{"Username": "foo", "Password": "bar"}`), nil
case missingCredsAddress: case missingCredsAddress:
return []byte(errCredentialsNotFound.Error()), errCommandExited return []byte(errCredentialsNotFound.Error()), errCommandExited
@ -67,7 +68,7 @@ func (m *mockCommand) Output() ([]byte, error) {
} }
} }
return []byte("unknown argument"), errCommandExited return []byte(fmt.Sprintf("unknown argument %q with %q", m.arg, inS)), errCommandExited
} }
// Input sets the input to send to a remote credentials helper. // Input sets the input to send to a remote credentials helper.
@ -178,6 +179,50 @@ func TestNativeStoreGet(t *testing.T) {
} }
} }
func TestNativeStoreGetAll(t *testing.T) {
f := newConfigFile(map[string]types.AuthConfig{
validServerAddress: {
Email: "foo@example.com",
},
validServerAddress2: {
Email: "foo@example2.com",
},
})
f.CredentialsStore = "mock"
s := &nativeStore{
commandFn: mockCommandFn,
fileStore: NewFileStore(f),
}
as, err := s.GetAll()
if err != nil {
t.Fatal(err)
}
if len(as) != 2 {
t.Fatalf("wanted 2, got %d", len(as))
}
if as[validServerAddress].Username != "foo" {
t.Fatalf("expected username `foo` for %s, got %s", validServerAddress, as[validServerAddress].Username)
}
if as[validServerAddress].Password != "bar" {
t.Fatalf("expected password `bar` for %s, got %s", validServerAddress, as[validServerAddress].Password)
}
if as[validServerAddress].Email != "foo@example.com" {
t.Fatalf("expected email `foo@example.com` for %s, got %s", validServerAddress, as[validServerAddress].Email)
}
if as[validServerAddress2].Username != "foo" {
t.Fatalf("expected username `foo` for %s, got %s", validServerAddress2, as[validServerAddress2].Username)
}
if as[validServerAddress2].Password != "bar" {
t.Fatalf("expected password `bar` for %s, got %s", validServerAddress2, as[validServerAddress2].Password)
}
if as[validServerAddress2].Email != "foo@example2.com" {
t.Fatalf("expected email `foo@example2.com` for %s, got %s", validServerAddress2, as[validServerAddress2].Email)
}
}
func TestNativeStoreGetMissingCredentials(t *testing.T) { func TestNativeStoreGetMissingCredentials(t *testing.T) {
f := newConfigFile(map[string]types.AuthConfig{ f := newConfigFile(map[string]types.AuthConfig{
validServerAddress: { validServerAddress: {

View File

@ -6589,3 +6589,45 @@ func (s *DockerRegistryAuthSuite) TestBuildFromAuthenticatedRegistry(c *check.C)
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
} }
func (s *DockerRegistryAuthSuite) TestBuildWithExternalAuth(c *check.C) {
osPath := os.Getenv("PATH")
defer os.Setenv("PATH", osPath)
workingDir, err := os.Getwd()
c.Assert(err, checker.IsNil)
absolute, err := filepath.Abs(filepath.Join(workingDir, "fixtures", "auth"))
c.Assert(err, checker.IsNil)
testPath := fmt.Sprintf("%s%c%s", osPath, filepath.ListSeparator, absolute)
os.Setenv("PATH", testPath)
repoName := fmt.Sprintf("%v/dockercli/busybox:authtest", privateRegistryURL)
tmp, err := ioutil.TempDir("", "integration-cli-")
c.Assert(err, checker.IsNil)
externalAuthConfig := `{ "credsStore": "shell-test" }`
configPath := filepath.Join(tmp, "config.json")
err = ioutil.WriteFile(configPath, []byte(externalAuthConfig), 0644)
c.Assert(err, checker.IsNil)
dockerCmd(c, "--config", tmp, "login", "-u", s.reg.username, "-p", s.reg.password, privateRegistryURL)
b, err := ioutil.ReadFile(configPath)
c.Assert(err, checker.IsNil)
c.Assert(string(b), checker.Not(checker.Contains), "\"auth\":")
dockerCmd(c, "--config", tmp, "tag", "busybox", repoName)
dockerCmd(c, "--config", tmp, "push", repoName)
// make sure the image is pulled when building
dockerCmd(c, "rmi", repoName)
buildCmd := exec.Command(dockerBinary, "--config", tmp, "build", "-")
buildCmd.Stdin = strings.NewReader(fmt.Sprintf("FROM %s", repoName))
out, _, err := runCommandWithOutput(buildCmd)
c.Assert(err, check.IsNil, check.Commentf(out))
}

View File

@ -385,7 +385,7 @@ func (s *DockerRegistryAuthSuite) TestPullWithExternalAuth(c *check.C) {
err = ioutil.WriteFile(configPath, []byte(externalAuthConfig), 0644) err = ioutil.WriteFile(configPath, []byte(externalAuthConfig), 0644)
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
dockerCmd(c, "--config", tmp, "login", "-u", s.reg.username, "-p", s.reg.password, "-e", s.reg.email, privateRegistryURL) dockerCmd(c, "--config", tmp, "login", "-u", s.reg.username, "-p", s.reg.password, privateRegistryURL)
b, err := ioutil.ReadFile(configPath) b, err := ioutil.ReadFile(configPath)
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)

View File

@ -38,7 +38,6 @@ import (
func init() { func init() {
cmd := exec.Command(dockerBinary, "images") cmd := exec.Command(dockerBinary, "images")
cmd.Env = appendBaseEnv(true) cmd.Env = appendBaseEnv(true)
fmt.Println("foobar", cmd.Env)
out, err := cmd.CombinedOutput() out, err := cmd.CombinedOutput()
if err != nil { if err != nil {
panic(fmt.Errorf("err=%v\nout=%s\n", err, out)) panic(fmt.Errorf("err=%v\nout=%s\n", err, out))