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:[CI-14277]:add support for base64 encoded env secret docker secre… #39

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions app.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,16 @@ func Run() {
Usage: "secret key value pair eg id=MYSECRET",
EnvVar: "PLUGIN_SECRET",
},
cli.BoolFlag{
Name: "encoded-secrets-from-env",
Usage: "base64 encoded values",
EnvVar: "PLUGIN_ENCODED_ENV_SECRET",
},
cli.BoolFlag{
Name: "decode-env-secret",
Usage: "decode env values default-false",
EnvVar: "PLUGIN_DECODE_ENV_SECRET",
},
cli.StringSliceFlag{
Name: "secrets-from-env",
Usage: "secret key value pair eg secret_name=secret",
Expand Down Expand Up @@ -403,6 +413,8 @@ func run(c *cli.Context) error {
Platform: c.String("platform"),
SSHAgentKey: c.String("ssh-agent-key"),
BuildxLoad: c.Bool("buildx-load"),
DecodeEnvSecret: c.Bool("decode-env-secret"),
EncodedSecretEnvs: c.StringSlice("encoded-secrets-from-env"),
},
Daemon: Daemon{
Registry: c.String("docker.registry"),
Expand Down
93 changes: 59 additions & 34 deletions docker.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package docker

import (
"encoding/base64"
"encoding/json"
"fmt"
//"log"
"os"
"os/exec"
"path/filepath"
Expand Down Expand Up @@ -52,34 +54,36 @@ type (

// Build defines Docker build parameters.
Build struct {
Remote string // Git remote URL
Name string // Docker build using default named tag
Dockerfile string // Docker build Dockerfile
Context string // Docker build context
Tags []string // Docker build tags
Args []string // Docker build args
ArgsEnv []string // Docker build args from env
Target string // Docker build target
Squash bool // Docker build squash
Pull bool // Docker build pull
CacheFrom []string // Docker buildx cache-from
CacheTo []string // Docker buildx cache-to
Compress bool // Docker build compress
Repo string // Docker build repository
LabelSchema []string // label-schema Label map
AutoLabel bool // auto-label bool
Labels []string // Label map
Link string // Git repo link
NoCache bool // Docker build no-cache
Secret string // secret keypair
SecretEnvs []string // Docker build secrets with env var as source
SecretFiles []string // Docker build secrets with file as source
AddHost []string // Docker build add-host
Quiet bool // Docker build quiet
Platform string // Docker build platform
SSHAgentKey string // Docker build ssh agent key
SSHKeyPath string // Docker build ssh key path
BuildxLoad bool // Docker buildx --load
Remote string // Git remote URL
Name string // Docker build using default named tag
Dockerfile string // Docker build Dockerfile
Context string // Docker build context
Tags []string // Docker build tags
Args []string // Docker build args
ArgsEnv []string // Docker build args from env
Target string // Docker build target
Squash bool // Docker build squash
Pull bool // Docker build pull
CacheFrom []string // Docker buildx cache-from
CacheTo []string // Docker buildx cache-to
Compress bool // Docker build compress
Repo string // Docker build repository
LabelSchema []string // label-schema Label map
AutoLabel bool // auto-label bool
Labels []string // Label map
Link string // Git repo link
NoCache bool // Docker build no-cache
Secret string // secret keypair
SecretEnvs []string // Docker build secrets with env var as source
SecretFiles []string // Docker build secrets with file as source
AddHost []string // Docker build add-host
Quiet bool // Docker build quiet
Platform string // Docker build platform
SSHAgentKey string // Docker build ssh agent key
SSHKeyPath string // Docker build ssh key path
BuildxLoad bool // Docker buildx --load
DecodeEnvSecret bool // Decode the secret value in env
EncodedSecretEnvs []string // Docker build secrets that are encoded using base64
}

// Plugin defines the Docker plugin parameters.
Expand Down Expand Up @@ -164,7 +168,6 @@ func (p Plugin) Exec() error {
default:
fmt.Println("Registry credentials or Docker config not provided. Guest mode enabled.")
}

// create Auth Config File
if p.Login.Config != "" {
os.MkdirAll(dockerHome, 0600)
Expand Down Expand Up @@ -507,10 +510,18 @@ func commandBuildx(build Build, builder Builder, dryrun bool, metadataFile strin
args = append(args, "--secret", build.Secret)
}
for _, secret := range build.SecretEnvs {
if arg, err := getSecretStringCmdArg(secret); err == nil {
if arg, err := getSecretStringCmdArg(secret, build.DecodeEnvSecret); err == nil {
args = append(args, "--secret", arg)
}
}
// Handle base64 encoded secrets
if build.DecodeEnvSecret {
for _, encodedSecret := range build.EncodedSecretEnvs {
if arg, err := getSecretStringCmdArg(encodedSecret, build.DecodeEnvSecret); err == nil {
args = append(args, "--secret", arg)
}
}
}
for _, secret := range build.SecretFiles {
if arg, err := getSecretFileCmdArg(secret); err == nil {
args = append(args, "--secret", arg)
Expand Down Expand Up @@ -555,19 +566,25 @@ func commandBuildx(build Build, builder Builder, dryrun bool, metadataFile strin
return exec.Command(dockerExe, args...)
}

func getSecretStringCmdArg(kvp string) (string, error) {
return getSecretCmdArg(kvp, false)
func getSecretStringCmdArg(kvp string, decode bool) (string, error) {
if decode {
// Handle base64 encoded secrets
return getSecretCmdArg(kvp, false, true)
}
// Original behavior
return getSecretCmdArg(kvp, false, false)
}

func getSecretFileCmdArg(kvp string) (string, error) {
return getSecretCmdArg(kvp, true)
return getSecretCmdArg(kvp, true, false)
}

func getSecretCmdArg(kvp string, file bool) (string, error) {
func getSecretCmdArg(kvp string, file bool, decode bool) (string, error) {
delimIndex := strings.IndexByte(kvp, '=')
if delimIndex == -1 {
return "", fmt.Errorf("%s is not a valid secret", kvp)
}
//log.Printf("kvp string : ", kvp)

key := kvp[:delimIndex]
value := kvp[delimIndex+1:]
Expand All @@ -579,6 +596,14 @@ func getSecretCmdArg(kvp string, file bool) (string, error) {
if file {
return fmt.Sprintf("id=%s,src=%s", key, value), nil
}
if decode {
decodedValue, err := base64.StdEncoding.DecodeString(value)
//log.Printf("decoded value of secret : ", decodedValue)
if err != nil {
return "", fmt.Errorf("failed to decode base64 value: %v", err)
}
value = string(decodedValue)
}

return fmt.Sprintf("id=%s,env=%s", key, value), nil
}
Expand Down
32 changes: 32 additions & 0 deletions docker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,38 @@ func TestCommandBuildx(t *testing.T) {
"--metadata-file /tmp/metadata.json",
),
},
// Add this new test case
{
name: "decoded secret from env var",
build: Build{
Name: "plugins/drone-docker:latest",
Dockerfile: "Dockerfile",
Context: ".",
SecretEnvs: []string{
"foo_secret=FOO_SECRET_ENV_VAR",
},
EncodedSecretEnvs: []string{
"encoded_secret=RU5DT0RFRF9TRUNSRVRfRU5WX1ZBUg==", // Base64 for "ENCODED_SECRET_ENV_VAR"
},
DecodeEnvSecret: true,
Repo: "plugins/drone-docker",
Tags: []string{"latest"},
},
want: exec.Command(
dockerExe,
"buildx",
"build",
"--rm=true",
"-f",
"Dockerfile",
"-t",
"plugins/drone-docker:latest",
"--push",
".",
"--secret", "id=foo_secret,env=FOO_SECRET_ENV_VAR",
"--secret", "id=encoded_secret,env=ENCODED_SECRET_ENV_VAR",
),
},
}

for _, tc := range tcs {
Expand Down