Add custom docker registry authentication (#665)

* Add custom docker registry authentication

Uses DOCKER_USERNAME and DOCKER_PASSWORD as secrets provided into
the act cli.

Closes #527

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

* Add test to check if pull authentication is filled in

* Update debug message to be more descriptive

Co-authored-by: Ryan (hackercat) <me@hackerc.at>

Co-authored-by: Björn Brauer <zaubernerd@zaubernerd.de>
Co-authored-by: Ryan (hackercat) <me@hackerc.at>
This commit is contained in:
Markus Wolf 2021-05-05 18:37:17 +02:00 committed by GitHub
parent 616d7fcaeb
commit 710a3ac94c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 61 additions and 4 deletions

View File

@ -2,6 +2,8 @@ package container
import (
"context"
"encoding/base64"
"encoding/json"
"fmt"
"strings"
@ -17,6 +19,8 @@ type NewDockerPullExecutorInput struct {
Image string
ForcePull bool
Platform string
Username string
Password string
}
// NewDockerPullExecutor function to create a run executor for the container
@ -54,9 +58,13 @@ func NewDockerPullExecutor(input NewDockerPullExecutorInput) common.Executor {
return err
}
reader, err := cli.ImagePull(ctx, imageRef, types.ImagePullOptions{
Platform: input.Platform,
})
imagePullOptions, err := getImagePullOptions(ctx, input)
if err != nil {
return err
}
reader, err := cli.ImagePull(ctx, imageRef, imagePullOptions)
_ = logDockerResponse(logger, reader, err != nil)
if err != nil {
return err
@ -65,6 +73,30 @@ func NewDockerPullExecutor(input NewDockerPullExecutorInput) common.Executor {
}
}
func getImagePullOptions(ctx context.Context, input NewDockerPullExecutorInput) (types.ImagePullOptions, error) {
imagePullOptions := types.ImagePullOptions{
Platform: input.Platform,
}
if input.Username != "" && input.Password != "" {
logger := common.Logger(ctx)
logger.Debugf("using authentication for docker pull")
authConfig := types.AuthConfig{
Username: input.Username,
Password: input.Password,
}
encodedJSON, err := json.Marshal(authConfig)
if err != nil {
return imagePullOptions, err
}
imagePullOptions.RegistryAuth = base64.URLEncoding.EncodeToString(encodedJSON)
}
return imagePullOptions, nil
}
func cleanImage(image string) string {
imageParts := len(strings.Split(image, "/"))
if imageParts == 1 {

View File

@ -1,10 +1,11 @@
package container
import (
"context"
"testing"
log "github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
"gotest.tools/v3/assert"
)
func init() {
@ -27,3 +28,19 @@ func TestCleanImage(t *testing.T) {
assert.Equal(t, table.imageOut, imageOut)
}
}
func TestGetImagePullOptions(t *testing.T) {
ctx := context.Background()
options, err := getImagePullOptions(ctx, NewDockerPullExecutorInput{})
assert.NilError(t, err, "Failed to create ImagePullOptions")
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.NilError(t, err, "Failed to create ImagePullOptions")
assert.Equal(t, options.RegistryAuth, "eyJ1c2VybmFtZSI6InVzZXJuYW1lIiwicGFzc3dvcmQiOiJwYXNzd29yZCJ9", "Username and Password should be provided")
}

View File

@ -37,6 +37,8 @@ import (
// NewContainerInput the input for the New function
type NewContainerInput struct {
Image string
Username string
Password string
Entrypoint []string
Cmd []string
WorkingDir string
@ -126,6 +128,8 @@ func (cr *containerReference) Pull(forcePull bool) common.Executor {
Image: cr.input.Image,
ForcePull: forcePull,
Platform: cr.input.Platform,
Username: cr.input.Username,
Password: cr.input.Password,
})
}
func (cr *containerReference) Copy(destPath string, files ...*FileEntry) common.Executor {

View File

@ -118,6 +118,8 @@ func (rc *RunContext) startJobContainer() common.Executor {
Entrypoint: []string{"/usr/bin/tail", "-f", "/dev/null"},
WorkingDir: rc.Config.ContainerWorkdir(),
Image: image,
Username: rc.Config.Secrets["DOCKER_USERNAME"],
Password: rc.Config.Secrets["DOCKER_PASSWORD"],
Name: name,
Env: envList,
Mounts: mounts,

View File

@ -247,6 +247,8 @@ func (sc *StepContext) newStepContainer(ctx context.Context, image string, cmd [
Entrypoint: entrypoint,
WorkingDir: rc.Config.ContainerWorkdir(),
Image: image,
Username: rc.Config.Secrets["DOCKER_USERNAME"],
Password: rc.Config.Secrets["DOCKER_PASSWORD"],
Name: createContainerName(rc.jobContainerName(), step.ID),
Env: envList,
Mounts: mounts,