Skip to content

Commit

Permalink
Merge pull request #446 from Aishwarya-Lad/CI-11718-part2
Browse files Browse the repository at this point in the history
update docker config for base image
  • Loading branch information
jamie-harness authored Jun 28, 2024
2 parents 292ebe0 + 0a2f635 commit 6cade1e
Show file tree
Hide file tree
Showing 6 changed files with 223 additions and 8 deletions.
18 changes: 18 additions & 0 deletions cmd/drone-docker/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,21 @@ func main() {
Usage: "docker password",
EnvVar: "PLUGIN_PASSWORD,DOCKER_PASSWORD",
},
cli.StringFlag{
Name: "docker.baseimageusername",
Usage: "Docker username for base image registry",
EnvVar: "PLUGIN_DOCKER_USERNAME,PLUGIN_BASE_IMAGE_USERNAME,DOCKER_BASE_IMAGE_USERNAME",
},
cli.StringFlag{
Name: "docker.baseimagepassword",
Usage: "Docker password for base image registry",
EnvVar: "PLUGIN_DOCKER_PASSWORD,PLUGIN_BASE_IMAGE_PASSWORD,DOCKER_BASE_IMAGE_PASSWORD",
},
cli.StringFlag{
Name: "docker.baseimageregistry",
Usage: "Docker registry for base image registry",
EnvVar: "PLUGIN_DOCKER_REGISTRY,PLUGIN_BASE_IMAGE_REGISTRY,DOCKER_BASE_IMAGE_REGISTRY",
},
cli.StringFlag{
Name: "docker.email",
Usage: "docker email",
Expand Down Expand Up @@ -367,6 +382,9 @@ func run(c *cli.Context) error {
Experimental: c.Bool("daemon.experimental"),
RegistryType: registryType,
},
BaseImageRegistry: c.String("docker.baseimageregistry"),
BaseImageUsername: c.String("docker.baseimageusername"),
BaseImagePassword: c.String("docker.baseimagepassword"),
}

if c.Bool("tags.auto") {
Expand Down
74 changes: 66 additions & 8 deletions docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"strings"
"time"

"github.com/drone-plugins/drone-docker/internal/docker"
"github.com/drone-plugins/drone-plugin-lib/drone"
)

Expand Down Expand Up @@ -75,13 +76,16 @@ type (

// Plugin defines the Docker plugin parameters.
Plugin struct {
Login Login // Docker login configuration
Build Build // Docker build configuration
Daemon Daemon // Docker daemon configuration
Dryrun bool // Docker push is skipped
Cleanup bool // Docker purge is enabled
CardPath string // Card path to write file to
ArtifactFile string // Artifact path to write file to
Login Login // Docker login configuration
Build Build // Docker build configuration
Daemon Daemon // Docker daemon configuration
Dryrun bool // Docker push is skipped
Cleanup bool // Docker purge is enabled
CardPath string // Card path to write file to
ArtifactFile string // Artifact path to write file to
BaseImageRegistry string // Docker registry to pull base image
BaseImageUsername string // Docker registry username to pull base image
BaseImagePassword string // Docker registry password to pull base image
}

Card []struct {
Expand Down Expand Up @@ -154,7 +158,32 @@ func (p Plugin) Exec() error {
os.MkdirAll(dockerHome, 0600)

path := filepath.Join(dockerHome, "config.json")
err := os.WriteFile(path, []byte(p.Login.Config), 0600)
file, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
if err != nil {
return fmt.Errorf("Error writing config.json: %s", err)
}
err = os.WriteFile(path, []byte(p.Login.Config), 0600)
if err != nil {
return fmt.Errorf("Error writing config.json: %s", err)
}
file.Close()
}

// add base image docker credentials to the existing config file, else create new
if p.BaseImagePassword != "" {
json, err := setDockerAuth(p.Login.Username, p.Login.Password, p.Login.Registry,
p.BaseImageUsername, p.BaseImagePassword, p.BaseImageRegistry)
if err != nil {
return fmt.Errorf("Failed to set authentication in docker config %s", err)
}
os.MkdirAll(dockerHome, 0600)
path := filepath.Join(dockerHome, "config.json")
file, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
if err != nil {
return fmt.Errorf("Error opening config.json: %s", err)
}
defer file.Close()
_, err = file.Write(json)
if err != nil {
return fmt.Errorf("Error writing config.json: %s", err)
}
Expand Down Expand Up @@ -270,6 +299,35 @@ func (p Plugin) Exec() error {
return nil
}

// helper function to set the credentials
func setDockerAuth(username, password, registry, baseImageUsername,
baseImagePassword, baseImageRegistry string) ([]byte, error) {
var credentials []docker.RegistryCredentials
// add only docker registry to the config
dockerConfig := docker.NewConfig()
if password != "" {
pushToRegistryCreds := docker.RegistryCredentials{
Registry: registry,
Username: username,
Password: password,
}
// push registry auth
credentials = append(credentials, pushToRegistryCreds)
}

if baseImageRegistry != "" {
pullFromRegistryCreds := docker.RegistryCredentials{
Registry: baseImageRegistry,
Username: baseImageUsername,
Password: baseImagePassword,
}
// base image registry auth
credentials = append(credentials, pullFromRegistryCreds)
}
// Creates docker config for both the registries used for authentication
return dockerConfig.CreateDockerConfigJson(credentials)
}

// helper function to create the docker login command.
func commandLogin(login Login) *exec.Cmd {
if login.Email != "" {
Expand Down
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ require (
github.com/inhies/go-bytesize v0.0.0-20210819104631-275770b98743
github.com/joho/godotenv v1.3.0
github.com/sirupsen/logrus v1.9.0
github.com/stretchr/testify v1.8.1
github.com/urfave/cli v1.22.2
golang.org/x/oauth2 v0.13.0
)
Expand All @@ -17,13 +18,15 @@ require (
cloud.google.com/go/compute v1.23.1 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/s2a-go v0.1.7 // indirect
github.com/google/uuid v1.3.1 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.1 // indirect
github.com/googleapis/gax-go/v2 v2.12.0 // indirect
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
go.opencensus.io v0.24.0 // indirect
golang.org/x/crypto v0.14.0 // indirect
Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo=
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
Expand Down
71 changes: 71 additions & 0 deletions internal/docker/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package docker

import (
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"strings"
)

const (
v2HubRegistryURL string = "https://registry.hub.docker.com/v2/"
v1RegistryURL string = "https://index.docker.io/v1/" // Default registry
v2RegistryURL string = "https://index.docker.io/v2/" // v2 registry is not supported
)

type (
Auth struct {
Auth string `json:"auth"`
}

Config struct {
Auths map[string]Auth `json:"auths"`
CredHelpers map[string]string `json:"credHelpers,omitempty"`
}
)

type RegistryCredentials struct {
Registry string
Username string
Password string
}

func NewConfig() *Config {
return &Config{
Auths: make(map[string]Auth),
CredHelpers: make(map[string]string),
}
}

func (c *Config) SetAuth(registry, username, password string) {
authBytes := []byte(username + ":" + password)
encodedString := base64.StdEncoding.EncodeToString(authBytes)
c.Auths[registry] = Auth{Auth: encodedString}
}

func (c *Config) SetCredHelper(registry, helper string) {
c.CredHelpers[registry] = helper
}

func (c *Config) CreateDockerConfigJson(credentials []RegistryCredentials) ([]byte, error) {
for _, cred := range credentials {
if cred.Registry != "" && strings.Contains(cred.Registry, "docker") {

if cred.Username == "" {
return nil, fmt.Errorf("Username must be specified for registry: %s", cred.Registry)
}
if cred.Password == "" {
return nil, fmt.Errorf("Password must be specified for registry: %s", cred.Registry)
}
c.SetAuth(cred.Registry, cred.Username, cred.Password)
}
}

jsonBytes, err := json.Marshal(c)
if err != nil {
return nil, errors.New("failed to serialize docker config json")
}

return jsonBytes, nil
}
64 changes: 64 additions & 0 deletions internal/docker/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package docker

import (
"encoding/json"
"io/ioutil"
"os"
"path/filepath"
"testing"

"github.com/stretchr/testify/assert"
)

const (
RegistryV1 string = "https://index.docker.io/v1/"
RegistryV2 string = "https://index.docker.io/v2/"
RegistryECRPublic string = "public.ecr.aws"
)

func TestConfig(t *testing.T) {
c := NewConfig()
assert.NotNil(t, c.Auths)
assert.NotNil(t, c.CredHelpers)

c.SetAuth(RegistryV1, "test", "password")
expectedAuth := Auth{Auth: "dGVzdDpwYXNzd29yZA=="}
assert.Equal(t, expectedAuth, c.Auths[RegistryV1])

c.SetCredHelper(RegistryECRPublic, "ecr-login")
assert.Equal(t, "ecr-login", c.CredHelpers[RegistryECRPublic])

tempDir, err := ioutil.TempDir("", "docker-config-test")
assert.NoError(t, err)
defer os.RemoveAll(tempDir)

credentials := []RegistryCredentials{
{
Registry: "https://index.docker.io/v1/",
Username: "user1",
Password: "pass1",
},
{
Registry: "gcr.io",
Username: "user2",
Password: "pass2",
},
}

jsonBytes, err := c.CreateDockerConfigJson(credentials)
assert.NoError(t, err)

configPath := filepath.Join(tempDir, "config.json")
err = ioutil.WriteFile(configPath, jsonBytes, 0644)
assert.NoError(t, err)

data, err := ioutil.ReadFile(configPath)
assert.NoError(t, err)

var configFromFile Config
err = json.Unmarshal(data, &configFromFile)
assert.NoError(t, err)

assert.Equal(t, c.Auths, configFromFile.Auths)
assert.Equal(t, c.CredHelpers, configFromFile.CredHelpers)
}

0 comments on commit 6cade1e

Please sign in to comment.