Skip to content

Commit

Permalink
Revert "Revert "Check for Podman's auth.json in DefaultKeychain (goog…
Browse files Browse the repository at this point in the history
…le#1181)" (google#1184)"

This reverts commit bce5496.
  • Loading branch information
imjasonh committed Nov 17, 2021
1 parent bce5496 commit 4b4d9a9
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 26 deletions.
29 changes: 27 additions & 2 deletions pkg/authn/keychain.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ package authn

import (
"os"
"path/filepath"
"sync"

"github.com/docker/cli/cli/config"
"github.com/docker/cli/cli/config/configfile"
"github.com/docker/cli/cli/config/types"
"github.com/google/go-containerregistry/pkg/name"
)
Expand Down Expand Up @@ -62,8 +64,31 @@ const (
func (dk *defaultKeychain) Resolve(target Resource) (Authenticator, error) {
dk.mu.Lock()
defer dk.mu.Unlock()
cf, err := config.Load(os.Getenv("DOCKER_CONFIG"))
if err != nil {

// Podman users may have their container registry auth configured in a
// different location, that Docker packages aren't aware of.
// If the Docker config file isn't found, we'll fallback to look where
// Podman configures it, and parse that as a Docker auth config instead.
var cf *configfile.ConfigFile
var err error
if _, err := os.Stat(filepath.Join(os.Getenv("DOCKER_CONFIG"), "config.json")); err == nil {
cf, err = config.Load(os.Getenv("DOCKER_CONFIG"))
if err != nil {
return nil, err
}
} else if os.IsNotExist(err) {
f, err := os.Open(filepath.Join(os.Getenv("XDG_RUNTIME_DIR"), "containers/auth.json"))
if os.IsNotExist(err) {
return Anonymous, nil
} else if err != nil {
return nil, err
}
defer f.Close()
cf, err = config.LoadFromReader(f)
if err != nil {
return nil, err
}
} else {
return nil, err
}

Expand Down
120 changes: 96 additions & 24 deletions pkg/authn/keychain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,9 @@ func setupConfigDir(t *testing.T) string {
}
}

fresh = fresh + 1
p := fmt.Sprintf("%s/%d", tmpdir, fresh)
fresh++
p := filepath.Join(tmpdir, fmt.Sprintf("%d", fresh))
t.Logf("DOCKER_CONFIG=%s", p)
os.Setenv("DOCKER_CONFIG", p)
if err := os.Mkdir(p, 0777); err != nil {
t.Fatalf("mkdir %q: %v", p, err)
Expand Down Expand Up @@ -77,33 +78,102 @@ func TestNoConfig(t *testing.T) {
}
}

func TestPodmanConfig(t *testing.T) {
tmpdir := os.Getenv("TEST_TMPDIR")
if tmpdir == "" {
var err error
tmpdir, err = ioutil.TempDir("", "keychain_test")
if err != nil {
t.Fatalf("creating temp dir: %v", err)
}
}
fresh++
p := filepath.Join(tmpdir, fmt.Sprintf("%d", fresh))
os.Setenv("XDG_RUNTIME_DIR", p)
os.Unsetenv("DOCKER_CONFIG")
defer func() { os.Unsetenv("XDG_RUNTIME_DIR") }()
if err := os.MkdirAll(filepath.Join(p, "containers"), 0777); err != nil {
t.Fatalf("mkdir %q: %v", p, err)
}
cfg := filepath.Join(p, "containers/auth.json")
content := fmt.Sprintf(`{"auths": {"test.io": {"auth": %q}}}`, encode("foo", "bar"))
if err := ioutil.WriteFile(cfg, []byte(content), 0600); err != nil {
t.Fatalf("write %q: %v", cfg, err)
}

auth, err := DefaultKeychain.Resolve(testRegistry)
if err != nil {
t.Fatalf("Resolve() = %v", err)
}
got, err := auth.Authorization()
if err != nil {
t.Fatal(err)
}
want := &AuthConfig{
Username: "foo",
Password: "bar",
}
if !reflect.DeepEqual(got, want) {
t.Errorf("got %+v, want %+v", got, want)
}

// Now, configure DOCKER_CONFIG with a valid config file with different
// auth configured.
// This demonstrates that DOCKER_CONFIG is preferred if both are
// present.
content = fmt.Sprintf(`{"auths": {"test.io": {"auth": %q}}}`, encode("another-foo", "another-bar"))
cd := setupConfigFile(t, content)
defer os.RemoveAll(filepath.Dir(cd))

auth, err = DefaultKeychain.Resolve(testRegistry)
if err != nil {
t.Fatalf("Resolve() = %v", err)
}
got, err = auth.Authorization()
if err != nil {
t.Fatal(err)
}
want = &AuthConfig{
Username: "another-foo",
Password: "another-bar",
}
if !reflect.DeepEqual(got, want) {
t.Errorf("got %+v, want %+v", got, want)
}
}

func encode(user, pass string) string {
delimited := fmt.Sprintf("%s:%s", user, pass)
return base64.StdEncoding.EncodeToString([]byte(delimited))
}

func TestVariousPaths(t *testing.T) {
tests := []struct {
desc string
content string
wantErr bool
target name.Registry
cfg *AuthConfig
}{{
desc: "invalid config file",
target: testRegistry,
content: `}{`,
wantErr: true,
}, {
desc: "creds store does not exist",
target: testRegistry,
content: `{"credsStore":"#definitely-does-not-exist"}`,
wantErr: true,
}, {
desc: "valid config file",
target: testRegistry,
content: fmt.Sprintf(`{"auths": {"test.io": {"auth": %q}}}`, encode("foo", "bar")),
cfg: &AuthConfig{
Username: "foo",
Password: "bar",
},
}, {
desc: "valid config file; default registry",
target: defaultRegistry,
content: fmt.Sprintf(`{"auths": {"%s": {"auth": %q}}}`, DefaultAuthKey, encode("foo", "bar")),
cfg: &AuthConfig{
Expand All @@ -113,29 +183,31 @@ func TestVariousPaths(t *testing.T) {
}}

for _, test := range tests {
cd := setupConfigFile(t, test.content)
// For some reason, these tempdirs don't get cleaned up.
defer os.RemoveAll(filepath.Dir(cd))

auth, err := DefaultKeychain.Resolve(test.target)
if test.wantErr {
if err == nil {
t.Fatal("wanted err, got nil")
} else if err != nil {
// success
continue
t.Run(test.desc, func(t *testing.T) {
cd := setupConfigFile(t, test.content)
// For some reason, these tempdirs don't get cleaned up.
defer os.RemoveAll(filepath.Dir(cd))

auth, err := DefaultKeychain.Resolve(test.target)
if test.wantErr {
if err == nil {
t.Fatal("wanted err, got nil")
} else if err != nil {
// success
return
}
}
if err != nil {
t.Fatalf("wanted nil, got err: %v", err)
}
cfg, err := auth.Authorization()
if err != nil {
t.Fatal(err)
}
}
if err != nil {
t.Fatalf("wanted nil, got err: %v", err)
}
cfg, err := auth.Authorization()
if err != nil {
t.Fatal(err)
}

if !reflect.DeepEqual(cfg, test.cfg) {
t.Errorf("got %+v, want %+v", cfg, test.cfg)
}
if !reflect.DeepEqual(cfg, test.cfg) {
t.Errorf("got %+v, want %+v", cfg, test.cfg)
}
})
}
}

0 comments on commit 4b4d9a9

Please sign in to comment.