Skip to content

Commit

Permalink
Docker auth (nektos#891)
Browse files Browse the repository at this point in the history
* feat: read docker credentials from local docker config

* fix: url.Parse requires protocol

Co-authored-by: Björn Brauer <zaubernerd@zaubernerd.de>

* fix: docker decides by the existence of . or : if...

... the image is in a custom registry or not.

Co-authored-by: Björn Brauer <zaubernerd@zaubernerd.de>

* fix: make docker hostname detection more robust

* test: mock docker config for getImagePullOptions test

By default github actions have a docker config set with a token to pull
images from docker hub.

Co-authored-by: Markus Wolf <markus.wolf@new-work.se>

Co-authored-by: Markus Wolf <markus.wolf@new-work.se>
  • Loading branch information
ZauberNerd and KnisterPeter authored Nov 27, 2021
1 parent 5bdb9ed commit b910a42
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 2 deletions.
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,7 @@ github.com/docker/docker v20.10.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05b
github.com/docker/docker v20.10.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v20.10.10+incompatible h1:GKkP0T7U4ks6X3lmmHKC2QDprnpRJor2Z5a8m62R9ZM=
github.com/docker/docker v20.10.10+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.6.3 h1:zI2p9+1NQYdnG6sMU26EX4aVGlqbInSQxQXLvzJ4RPQ=
github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
Expand Down
36 changes: 36 additions & 0 deletions pkg/container/docker_auth.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package container

import (
"strings"

"github.com/docker/cli/cli/config"
"github.com/docker/cli/cli/config/credentials"
"github.com/docker/docker/api/types"
log "github.com/sirupsen/logrus"
)

func LoadDockerAuthConfig(image string) (types.AuthConfig, error) {
config, err := config.Load(config.Dir())
if err != nil {
log.Warnf("Could not load docker config: %v", err)
return types.AuthConfig{}, err
}

if !config.ContainsAuth() {
config.CredentialsStore = credentials.DetectDefaultStore(config.CredentialsStore)
}

hostName := "index.docker.io"
index := strings.IndexRune(image, '/')
if index > -1 && (strings.ContainsAny(image[:index], ".:") || image[:index] == "localhost") {
hostName = image[:index]
}

authConfig, err := config.GetAuthConfig(hostName)
if err != nil {
log.Warnf("Could not get auth config from docker config: %v", err)
return types.AuthConfig{}, err
}

return types.AuthConfig(authConfig), nil
}
16 changes: 16 additions & 0 deletions pkg/container/docker_pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ func getImagePullOptions(ctx context.Context, input NewDockerPullExecutorInput)
imagePullOptions := types.ImagePullOptions{
Platform: input.Platform,
}

if input.Username != "" && input.Password != "" {
logger := common.Logger(ctx)
logger.Debugf("using authentication for docker pull")
Expand All @@ -91,6 +92,21 @@ func getImagePullOptions(ctx context.Context, input NewDockerPullExecutorInput)
return imagePullOptions, err
}

imagePullOptions.RegistryAuth = base64.URLEncoding.EncodeToString(encodedJSON)
} else {
authConfig, err := LoadDockerAuthConfig(input.Image)
if err != nil {
return imagePullOptions, err
}
if authConfig.Username == "" && authConfig.Password == "" {
return imagePullOptions, nil
}

encodedJSON, err := json.Marshal(authConfig)
if err != nil {
return imagePullOptions, err
}

imagePullOptions.RegistryAuth = base64.URLEncoding.EncodeToString(encodedJSON)
}

Expand Down
16 changes: 14 additions & 2 deletions pkg/container/docker_pull_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"context"
"testing"

"github.com/docker/cli/cli/config"

log "github.com/sirupsen/logrus"
assert "github.com/stretchr/testify/assert"
)
Expand Down Expand Up @@ -35,15 +37,25 @@ func TestCleanImage(t *testing.T) {
func TestGetImagePullOptions(t *testing.T) {
ctx := context.Background()

config.SetDir("/non-existent/docker")

options, err := getImagePullOptions(ctx, NewDockerPullExecutorInput{})
assert.Nil(t, err, "Failed to create ImagePullOptions")
assert.Equal(t, options.RegistryAuth, "", "RegistryAuth should be empty if no username or password is set")
assert.Equal(t, "", options.RegistryAuth, "RegistryAuth should be empty if no username or password is set")

options, err = getImagePullOptions(ctx, NewDockerPullExecutorInput{
Image: "",
Username: "username",
Password: "password",
})
assert.Nil(t, err, "Failed to create ImagePullOptions")
assert.Equal(t, options.RegistryAuth, "eyJ1c2VybmFtZSI6InVzZXJuYW1lIiwicGFzc3dvcmQiOiJwYXNzd29yZCJ9", "Username and Password should be provided")
assert.Equal(t, "eyJ1c2VybmFtZSI6InVzZXJuYW1lIiwicGFzc3dvcmQiOiJwYXNzd29yZCJ9", options.RegistryAuth, "Username and Password should be provided")

config.SetDir("testdata/docker-pull-options")

options, err = getImagePullOptions(ctx, NewDockerPullExecutorInput{
Image: "nektos/act",
})
assert.Nil(t, err, "Failed to create ImagePullOptions")
assert.Equal(t, "eyJ1c2VybmFtZSI6InVzZXJuYW1lIiwicGFzc3dvcmQiOiJwYXNzd29yZFxuIiwic2VydmVyYWRkcmVzcyI6Imh0dHBzOi8vaW5kZXguZG9ja2VyLmlvL3YxLyJ9", options.RegistryAuth, "RegistryAuth should be taken from local docker config")
}
7 changes: 7 additions & 0 deletions pkg/container/testdata/docker-pull-options/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"auths": {
"https://index.docker.io/v1/": {
"auth": "dXNlcm5hbWU6cGFzc3dvcmQK"
}
}
}

0 comments on commit b910a42

Please sign in to comment.