Merge pull request #20824 from runcom/fix-creds-store
cliconfig: credentials: support getting all auths
This commit is contained in:
commit
f4cb5f4a32
11 changed files with 161 additions and 7 deletions
|
@ -229,7 +229,7 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
|
|||
ShmSize: shmSize,
|
||||
Ulimits: flUlimits.GetList(),
|
||||
BuildArgs: runconfigopts.ConvertKVStringsToMap(flBuildArg.GetAll()),
|
||||
AuthConfigs: cli.configFile.AuthConfigs,
|
||||
AuthConfigs: cli.retrieveAuthConfigs(),
|
||||
}
|
||||
|
||||
response, err := cli.client.ImageBuild(context.Background(), options)
|
||||
|
|
|
@ -141,6 +141,11 @@ func getCredentials(c *cliconfig.ConfigFile, serverAddress string) (types.AuthCo
|
|||
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.
|
||||
// The store is determined by the config file settings.
|
||||
func storeCredentials(c *cliconfig.ConfigFile, auth types.AuthConfig) error {
|
||||
|
|
|
@ -193,3 +193,8 @@ func (cli *DockerCli) resolveAuthConfig(index *registrytypes.IndexInfo) types.Au
|
|||
a, _ := getCredentials(cli.configFile, configKey)
|
||||
return a
|
||||
}
|
||||
|
||||
func (cli *DockerCli) retrieveAuthConfigs() map[string]types.AuthConfig {
|
||||
acs, _ := getAllCredentials(cli.configFile)
|
||||
return acs
|
||||
}
|
||||
|
|
|
@ -10,6 +10,8 @@ type Store interface {
|
|||
Erase(serverAddress string) error
|
||||
// Get retrieves credentials from the store for a given server.
|
||||
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(authConfig types.AuthConfig) error
|
||||
}
|
||||
|
|
|
@ -43,6 +43,10 @@ func (c *fileStore) Get(serverAddress string) (types.AuthConfig, error) {
|
|||
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.
|
||||
func (c *fileStore) Store(authConfig types.AuthConfig) error {
|
||||
c.file.AuthConfigs[authConfig.ServerAddress] = authConfig
|
||||
|
|
|
@ -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) {
|
||||
f := newConfigFile(map[string]types.AuthConfig{
|
||||
"https://example.com": {
|
||||
|
|
|
@ -81,6 +81,20 @@ func (c *nativeStore) Get(serverAddress string) (types.AuthConfig, error) {
|
|||
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.
|
||||
func (c *nativeStore) Store(authConfig types.AuthConfig) error {
|
||||
if err := c.storeCredentialsInStore(authConfig); err != nil {
|
||||
|
@ -135,7 +149,7 @@ func (c *nativeStore) getCredentialsFromStore(serverAddress string) (types.AuthC
|
|||
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)
|
||||
}
|
||||
|
||||
|
@ -158,7 +172,7 @@ func (c *nativeStore) eraseCredentialsFromStore(serverURL string) error {
|
|||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
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)
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
|
||||
const (
|
||||
validServerAddress = "https://index.docker.io/v1"
|
||||
validServerAddress2 = "https://example.com:5002"
|
||||
invalidServerAddress = "https://foobar.example.com"
|
||||
missingCredsAddress = "https://missing.docker.io/v1"
|
||||
)
|
||||
|
@ -46,7 +47,7 @@ func (m *mockCommand) Output() ([]byte, error) {
|
|||
}
|
||||
case "get":
|
||||
switch inS {
|
||||
case validServerAddress:
|
||||
case validServerAddress, validServerAddress2:
|
||||
return []byte(`{"Username": "foo", "Password": "bar"}`), nil
|
||||
case missingCredsAddress:
|
||||
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.
|
||||
|
@ -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) {
|
||||
f := newConfigFile(map[string]types.AuthConfig{
|
||||
validServerAddress: {
|
||||
|
|
|
@ -6589,3 +6589,45 @@ func (s *DockerRegistryAuthSuite) TestBuildFromAuthenticatedRegistry(c *check.C)
|
|||
|
||||
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))
|
||||
}
|
||||
|
|
|
@ -385,7 +385,7 @@ func (s *DockerRegistryAuthSuite) TestPullWithExternalAuth(c *check.C) {
|
|||
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, "-e", s.reg.email, privateRegistryURL)
|
||||
dockerCmd(c, "--config", tmp, "login", "-u", s.reg.username, "-p", s.reg.password, privateRegistryURL)
|
||||
|
||||
b, err := ioutil.ReadFile(configPath)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
|
|
@ -38,7 +38,6 @@ import (
|
|||
func init() {
|
||||
cmd := exec.Command(dockerBinary, "images")
|
||||
cmd.Env = appendBaseEnv(true)
|
||||
fmt.Println("foobar", cmd.Env)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("err=%v\nout=%s\n", err, out))
|
||||
|
|
Loading…
Add table
Reference in a new issue