Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: fallback matching of registry authentication config #1927

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
23 changes: 22 additions & 1 deletion docker_auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"encoding/base64"
"encoding/json"
"net/url"
"os"

"github.com/cpuguy83/dockercfg"
Expand All @@ -24,13 +25,33 @@ func DockerImageAuth(ctx context.Context, image string) (string, registry.AuthCo
return reg, registry.AuthConfig{}, err
}

if cfg, ok := cfgs[reg]; ok {
if cfg, ok := getRegistryAuth(reg, cfgs); ok {
return reg, cfg, nil
}

return reg, registry.AuthConfig{}, dockercfg.ErrCredentialsNotFound
}

func getRegistryAuth(reg string, cfgs map[string]registry.AuthConfig) (registry.AuthConfig, bool) {
if cfg, ok := cfgs[reg]; ok {
return cfg, true
}

// fallback match using authentication key host
for k, cfg := range cfgs {
keyURL, err := url.Parse(k)
if err != nil {
continue
}

if keyURL.Host == reg {
return cfg, true
}
}

return registry.AuthConfig{}, false
}

// defaultRegistry returns the default registry to use when pulling images
// It will use the docker daemon to get the default registry, returning "https://index.docker.io/v1/" if
// it fails to get the information from the daemon
Expand Down
52 changes: 47 additions & 5 deletions docker_auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@ func TestGetDockerConfig(t *testing.T) {
// Then, we can safely run the tests that rely on it.
defaultCfg, err := dockercfg.LoadDefaultConfig()
require.Nil(t, err)
require.NotNil(t, defaultCfg)
require.NotEmpty(t, defaultCfg)
sermio-te marked this conversation as resolved.
Show resolved Hide resolved

t.Run("without DOCKER_CONFIG env var retrieves default", func(t *testing.T) {
t.Setenv("DOCKER_CONFIG", "")

cfg, err := getDockerConfig()
require.Nil(t, err)
require.NotNil(t, cfg)
require.NotEmpty(t, cfg)

assert.Equal(t, defaultCfg, cfg)
})
Expand All @@ -55,7 +55,7 @@ func TestGetDockerConfig(t *testing.T) {

cfg, err := getDockerConfig()
require.Nil(t, err)
require.NotNil(t, cfg)
require.NotEmpty(t, cfg)

assert.Equal(t, 3, len(cfg.AuthConfigs))

Expand Down Expand Up @@ -83,7 +83,7 @@ func TestGetDockerConfig(t *testing.T) {

cfg, err := getDockerConfig()
require.Nil(t, err)
require.NotNil(t, cfg)
require.NotEmpty(t, cfg)

assert.Equal(t, 1, len(cfg.AuthConfigs))

Expand All @@ -109,13 +109,55 @@ func TestGetDockerConfig(t *testing.T) {

registry, cfg, err := DockerImageAuth(context.Background(), exampleAuth+"/my/image:latest")
require.Nil(t, err)
require.NotNil(t, cfg)
require.NotEmpty(t, cfg)

assert.Equal(t, exampleAuth, registry)
assert.Equal(t, "gopher", cfg.Username)
assert.Equal(t, "secret", cfg.Password)
assert.Equal(t, base64, cfg.Auth)
})

t.Run("match registry authentication by host", func(t *testing.T) {
base64 := "Z29waGVyOnNlY3JldA==" // gopher:secret
imageReg := "example-auth.com"
imagePath := "/my/image:latest"

t.Setenv("DOCKER_AUTH_CONFIG", `{
"auths": {
"`+exampleAuth+`": { "username": "gopher", "password": "secret", "auth": "`+base64+`" }
},
"credsStore": "desktop"
}`)

registry, cfg, err := DockerImageAuth(context.Background(), imageReg+imagePath)
require.Nil(t, err)
require.NotEmpty(t, cfg)

assert.Equal(t, imageReg, registry)
assert.Equal(t, "gopher", cfg.Username)
assert.Equal(t, "secret", cfg.Password)
assert.Equal(t, base64, cfg.Auth)
})

t.Run("fail to match registry authentication due to invalid host", func(t *testing.T) {
base64 := "Z29waGVyOnNlY3JldA==" // gopher:secret
imageReg := "example-auth.com"
imagePath := "/my/image:latest"
invalidRegistryURL := "://invalid-host"

t.Setenv("DOCKER_AUTH_CONFIG", `{
"auths": {
"`+invalidRegistryURL+`": { "username": "gopher", "password": "secret", "auth": "`+base64+`" }
},
"credsStore": "desktop"
}`)

registry, cfg, err := DockerImageAuth(context.Background(), imageReg+imagePath)
require.Equal(t, err, dockercfg.ErrCredentialsNotFound)
require.Empty(t, cfg)

assert.Equal(t, imageReg, registry)
})
}

func TestBuildContainerFromDockerfile(t *testing.T) {
Expand Down