From b85d92e5fab13e46d28ec7e4edd0636bd70e9d2e Mon Sep 17 00:00:00 2001 From: Ole Henning Date: Wed, 13 Oct 2021 13:54:11 +0200 Subject: [PATCH 01/15] Add option to mount host ssh agent (--ssh) --- cmd/drone-docker/main.go | 46 +++++++++++++++++++++++----------------- docker.go | 4 ++++ 2 files changed, 30 insertions(+), 20 deletions(-) diff --git a/cmd/drone-docker/main.go b/cmd/drone-docker/main.go index 3385bb80..4386d1d6 100644 --- a/cmd/drone-docker/main.go +++ b/cmd/drone-docker/main.go @@ -248,6 +248,11 @@ func main() { Usage: "additional host:IP mapping", EnvVar: "PLUGIN_ADD_HOST", }, + cli.StringSliceFlag{ + Name: "ssh-agent", + Usage: "mount ssh agent", + EnvVar: "PLUGIN_SSH_AGENT", + }, } if err := app.Run(os.Args); err != nil { @@ -267,26 +272,27 @@ func run(c *cli.Context) error { Config: c.String("docker.config"), }, Build: docker.Build{ - Remote: c.String("remote.url"), - Name: c.String("commit.sha"), - Dockerfile: c.String("dockerfile"), - Context: c.String("context"), - Tags: c.StringSlice("tags"), - Args: c.StringSlice("args"), - ArgsEnv: c.StringSlice("args-from-env"), - Target: c.String("target"), - Squash: c.Bool("squash"), - Pull: c.BoolT("pull-image"), - CacheFrom: c.StringSlice("cache-from"), - Compress: c.Bool("compress"), - Repo: c.String("repo"), - Labels: c.StringSlice("custom-labels"), - LabelSchema: c.StringSlice("label-schema"), - AutoLabel: c.BoolT("auto-label"), - Link: c.String("link"), - NoCache: c.Bool("no-cache"), - AddHost: c.StringSlice("add-host"), - Quiet: c.Bool("quiet"), + Remote: c.String("remote.url"), + Name: c.String("commit.sha"), + Dockerfile: c.String("dockerfile"), + Context: c.String("context"), + Tags: c.StringSlice("tags"), + Args: c.StringSlice("args"), + ArgsEnv: c.StringSlice("args-from-env"), + Target: c.String("target"), + Squash: c.Bool("squash"), + Pull: c.BoolT("pull-image"), + CacheFrom: c.StringSlice("cache-from"), + Compress: c.Bool("compress"), + Repo: c.String("repo"), + Labels: c.StringSlice("custom-labels"), + LabelSchema: c.StringSlice("label-schema"), + AutoLabel: c.BoolT("auto-label"), + Link: c.String("link"), + NoCache: c.Bool("no-cache"), + AddHost: c.StringSlice("add-host"), + Quiet: c.Bool("quiet"), + SSHAgent: c.String("ssh-agent"), }, Daemon: docker.Daemon{ Registry: c.String("docker.registry"), diff --git a/docker.go b/docker.go index 9effe4c5..4e2f2a6f 100644 --- a/docker.go +++ b/docker.go @@ -59,6 +59,7 @@ type ( NoCache bool // Docker build no-cache AddHost []string // Docker build add-host Quiet bool // Docker build quiet + SSHAgent string // Docker build ssh } // Plugin defines the Docker plugin parameters. @@ -264,6 +265,9 @@ func commandBuild(build Build) *exec.Cmd { if build.Quiet { args = append(args, "--quiet") } + if build.SSHAgent != "" { + args = append(args, "--ssh", build.SSHAgent) + } if build.AutoLabel { labelSchema := []string{ From 361e54c88be1a4a3d174232064dbb8e586d4113e Mon Sep 17 00:00:00 2001 From: Trent Albright Date: Fri, 1 Jul 2022 10:06:57 -0400 Subject: [PATCH 02/15] support agent forwarding --- docker.go | 43 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/docker.go b/docker.go index 4d357727..84ee4dd6 100644 --- a/docker.go +++ b/docker.go @@ -3,6 +3,7 @@ package docker import ( "fmt" "io/ioutil" + "log" "os" "os/exec" "path/filepath" @@ -11,6 +12,11 @@ import ( "time" ) +const ( + SSHAgentSockPath = "/tmp/drone-ssh-agent-sock" + SSHPrivateKeyFromEnv = "SSH_KEY" +) + type ( // Daemon defines Docker daemon parameters. Daemon struct { @@ -179,6 +185,11 @@ func (p Plugin) Exec() error { cmds = append(cmds, commandPull(img)) } + // setup for using ssh agent (https://docs.docker.com/develop/develop-images/build_enhancements/#using-ssh-to-access-private-data-in-builds) + if p.Build.SSHAgent != "" { + cmds = append(cmds, commandSSHAgentForwardingSetup(p.Build)...) + } + cmds = append(cmds, commandBuild(p.Build)) // docker build for _, tag := range p.Build.Tags { @@ -353,8 +364,8 @@ func commandBuild(build Build) *exec.Cmd { } } - // we need to enable buildkit, for secret support - if build.Secret != "" || len(build.SecretEnvs) > 0 || len(build.SecretFiles) > 0 { + // we need to enable buildkit, for secret support and ssh agent support + if build.Secret != "" || len(build.SecretEnvs) > 0 || len(build.SecretFiles) > 0 || build.SSHAgent != "" { os.Setenv("DOCKER_BUILDKIT", "1") } return exec.Command(dockerExe, args...) @@ -507,6 +518,34 @@ func commandRmi(tag string) *exec.Cmd { return exec.Command(dockerExe, "rmi", tag) } +func commandSSHAgentForwardingSetup(build Build) []*exec.Cmd { + cmds := make([]*exec.Cmd, 0) + if err := writeSSHPrivateKey(); err != nil { + log.Fatalf("unable to setup ssh agent forwarding: %s", err) + } + os.Setenv("SSH_AUTH_SOCK", SSHAgentSockPath) + cmds = append(cmds, exec.Command("ssh-agent", "-p", SSHAgentSockPath)) + cmds = append(cmds, exec.Command("ssh-add")) + return cmds +} + +func writeSSHPrivateKey() error { + privateKey := os.Getenv(SSHPrivateKeyFromEnv) + if privateKey == "" { + return fmt.Errorf("%s must be defined and contain the private key to use for ssh agent forwarding", SSHPrivateKeyFromEnv) + } + var err error + home, err := os.UserHomeDir() + if err != nil { + return fmt.Errorf("unable to determine home directory: %s", err) + } + os.MkdirAll(filepath.Join(home, ".ssh"), 0700) + if err := os.WriteFile(filepath.Join(home, ".ssh", "id_rsa"), []byte(privateKey), 0400); err != nil { + return fmt.Errorf("unable to write ssh key: %s", err) + } + return nil +} + // trace writes each command to stdout with the command wrapped in an xml // tag so that it can be extracted and displayed in the logs. func trace(cmd *exec.Cmd) { From 61ac47c34e624f09c29d7dfb1784d340315c7fd6 Mon Sep 17 00:00:00 2001 From: Trent Albright Date: Fri, 1 Jul 2022 12:14:35 -0400 Subject: [PATCH 03/15] missed error check --- docker.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docker.go b/docker.go index 84ee4dd6..54fa0652 100644 --- a/docker.go +++ b/docker.go @@ -539,7 +539,9 @@ func writeSSHPrivateKey() error { if err != nil { return fmt.Errorf("unable to determine home directory: %s", err) } - os.MkdirAll(filepath.Join(home, ".ssh"), 0700) + if err := os.MkdirAll(filepath.Join(home, ".ssh"), 0700); err != nil { + return fmt.Errorf("unable to create .ssh directory: %s", err) + } if err := os.WriteFile(filepath.Join(home, ".ssh", "id_rsa"), []byte(privateKey), 0400); err != nil { return fmt.Errorf("unable to write ssh key: %s", err) } From 9113df9b95f7dd157df45a94d0c367ea5a5f90a6 Mon Sep 17 00:00:00 2001 From: Trent Albright Date: Tue, 5 Jul 2022 07:47:56 -0400 Subject: [PATCH 04/15] add debugging --- docker.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docker.go b/docker.go index 54fa0652..c8b9c204 100644 --- a/docker.go +++ b/docker.go @@ -112,6 +112,10 @@ type ( // Exec executes the plugin step func (p Plugin) Exec() error { + + fmt.Printf("exec build: %#v", p.Build) + fmt.Printf("exec env: %#v", os.Environ()) + // start the Docker daemon server if !p.Daemon.Disabled { p.startDaemon() @@ -187,6 +191,7 @@ func (p Plugin) Exec() error { // setup for using ssh agent (https://docs.docker.com/develop/develop-images/build_enhancements/#using-ssh-to-access-private-data-in-builds) if p.Build.SSHAgent != "" { + fmt.Printf("ssh agent set to \"%s\"", p.Build.SSHAgent) cmds = append(cmds, commandSSHAgentForwardingSetup(p.Build)...) } From 170166841c57d27606c87b3cca02ba0d63a8c293 Mon Sep 17 00:00:00 2001 From: Trent Albright Date: Tue, 5 Jul 2022 08:43:38 -0400 Subject: [PATCH 05/15] fix empty val for SSHAgent --- docker.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/docker.go b/docker.go index c8b9c204..9582fca0 100644 --- a/docker.go +++ b/docker.go @@ -190,7 +190,7 @@ func (p Plugin) Exec() error { } // setup for using ssh agent (https://docs.docker.com/develop/develop-images/build_enhancements/#using-ssh-to-access-private-data-in-builds) - if p.Build.SSHAgent != "" { + if !sshAgentEmpty(p.Build.SSHAgent) { fmt.Printf("ssh agent set to \"%s\"", p.Build.SSHAgent) cmds = append(cmds, commandSSHAgentForwardingSetup(p.Build)...) } @@ -341,7 +341,7 @@ func commandBuild(build Build) *exec.Cmd { if build.Quiet { args = append(args, "--quiet") } - if build.SSHAgent != "" { + if !sshAgentEmpty(build.SSHAgent) { args = append(args, "--ssh", build.SSHAgent) } @@ -370,7 +370,7 @@ func commandBuild(build Build) *exec.Cmd { } // we need to enable buildkit, for secret support and ssh agent support - if build.Secret != "" || len(build.SecretEnvs) > 0 || len(build.SecretFiles) > 0 || build.SSHAgent != "" { + if build.Secret != "" || len(build.SecretEnvs) > 0 || len(build.SecretFiles) > 0 || !sshAgentEmpty(build.SSHAgent) { os.Setenv("DOCKER_BUILDKIT", "1") } return exec.Command(dockerExe, args...) @@ -566,3 +566,7 @@ func GetDroneDockerExecCmd() string { return "drone-docker" } + +func sshAgentEmpty(agent string) bool { + return agent == "" || agent == "[]" +} From 94f1820cdf7dc417828630ebf33c9576b1fd1bbf Mon Sep 17 00:00:00 2001 From: Trent Albright Date: Wed, 6 Jul 2022 07:17:33 -0400 Subject: [PATCH 06/15] fix flag type --- cmd/drone-docker/main.go | 2 +- docker.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/drone-docker/main.go b/cmd/drone-docker/main.go index 27ed97b2..dd2a6a56 100644 --- a/cmd/drone-docker/main.go +++ b/cmd/drone-docker/main.go @@ -264,7 +264,7 @@ func main() { Usage: "secret key value pairs eg secret_name=/path/to/secret", EnvVar: "PLUGIN_SECRETS_FROM_FILE", }, - cli.StringSliceFlag{ + cli.StringFlag{ Name: "ssh-agent", Usage: "mount ssh agent", EnvVar: "PLUGIN_SSH_AGENT", diff --git a/docker.go b/docker.go index 9582fca0..f41f8761 100644 --- a/docker.go +++ b/docker.go @@ -568,5 +568,5 @@ func GetDroneDockerExecCmd() string { } func sshAgentEmpty(agent string) bool { - return agent == "" || agent == "[]" + return agent == "" } From c4ff866362d6c7883920139bcb71132d863e22b5 Mon Sep 17 00:00:00 2001 From: Trent Albright Date: Wed, 6 Jul 2022 07:40:39 -0400 Subject: [PATCH 07/15] remove [] --- docker.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docker.go b/docker.go index f41f8761..d8cfe49a 100644 --- a/docker.go +++ b/docker.go @@ -191,6 +191,8 @@ func (p Plugin) Exec() error { // setup for using ssh agent (https://docs.docker.com/develop/develop-images/build_enhancements/#using-ssh-to-access-private-data-in-builds) if !sshAgentEmpty(p.Build.SSHAgent) { + p.Build.SSHAgent = strings.TrimSuffix(p.Build.SSHAgent, "]") + p.Build.SSHAgent = strings.TrimPrefix(p.Build.SSHAgent, "[") fmt.Printf("ssh agent set to \"%s\"", p.Build.SSHAgent) cmds = append(cmds, commandSSHAgentForwardingSetup(p.Build)...) } @@ -529,7 +531,7 @@ func commandSSHAgentForwardingSetup(build Build) []*exec.Cmd { log.Fatalf("unable to setup ssh agent forwarding: %s", err) } os.Setenv("SSH_AUTH_SOCK", SSHAgentSockPath) - cmds = append(cmds, exec.Command("ssh-agent", "-p", SSHAgentSockPath)) + cmds = append(cmds, exec.Command("ssh-agent", "-a", SSHAgentSockPath)) cmds = append(cmds, exec.Command("ssh-add")) return cmds } From e558dceebd49ce59012f5dbad097143d58f4aedc Mon Sep 17 00:00:00 2001 From: Trent Albright Date: Wed, 6 Jul 2022 07:59:56 -0400 Subject: [PATCH 08/15] debug --- docker.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docker.go b/docker.go index d8cfe49a..3b85629a 100644 --- a/docker.go +++ b/docker.go @@ -193,7 +193,7 @@ func (p Plugin) Exec() error { if !sshAgentEmpty(p.Build.SSHAgent) { p.Build.SSHAgent = strings.TrimSuffix(p.Build.SSHAgent, "]") p.Build.SSHAgent = strings.TrimPrefix(p.Build.SSHAgent, "[") - fmt.Printf("ssh agent set to \"%s\"", p.Build.SSHAgent) + fmt.Printf("ssh agent set to \"%s\"\n", p.Build.SSHAgent) cmds = append(cmds, commandSSHAgentForwardingSetup(p.Build)...) } @@ -532,6 +532,7 @@ func commandSSHAgentForwardingSetup(build Build) []*exec.Cmd { } os.Setenv("SSH_AUTH_SOCK", SSHAgentSockPath) cmds = append(cmds, exec.Command("ssh-agent", "-a", SSHAgentSockPath)) + cmds = append(cmds, exec.Command("cat", "/root/.ssh/id_rsa")) cmds = append(cmds, exec.Command("ssh-add")) return cmds } From e8fb61ecce5d4091ab70ae834b798f3c97d2fc66 Mon Sep 17 00:00:00 2001 From: Trent Albright Date: Wed, 6 Jul 2022 08:02:28 -0400 Subject: [PATCH 09/15] trigger From 4cd217c2cae954b44a7f22f2e3dd35842396c562 Mon Sep 17 00:00:00 2001 From: Trent Albright Date: Wed, 6 Jul 2022 08:23:39 -0400 Subject: [PATCH 10/15] base64 encode ssh key --- docker.go | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/docker.go b/docker.go index 3b85629a..92264029 100644 --- a/docker.go +++ b/docker.go @@ -1,6 +1,7 @@ package docker import ( + "encoding/base64" "fmt" "io/ioutil" "log" @@ -538,11 +539,16 @@ func commandSSHAgentForwardingSetup(build Build) []*exec.Cmd { } func writeSSHPrivateKey() error { - privateKey := os.Getenv(SSHPrivateKeyFromEnv) - if privateKey == "" { - return fmt.Errorf("%s must be defined and contain the private key to use for ssh agent forwarding", SSHPrivateKeyFromEnv) + privateKeyBase64 := os.Getenv(SSHPrivateKeyFromEnv) + if privateKeyBase64 == "" { + return fmt.Errorf("%s must be defined and contain the base64 encoded private key to use for ssh agent forwarding", SSHPrivateKeyFromEnv) } + privateKey := []byte{} var err error + _, err = base64.StdEncoding.Decode(privateKey, []byte(privateKeyBase64)) + if err != nil { + return fmt.Errorf("unable to base64 decode private key") + } home, err := os.UserHomeDir() if err != nil { return fmt.Errorf("unable to determine home directory: %s", err) @@ -550,7 +556,7 @@ func writeSSHPrivateKey() error { if err := os.MkdirAll(filepath.Join(home, ".ssh"), 0700); err != nil { return fmt.Errorf("unable to create .ssh directory: %s", err) } - if err := os.WriteFile(filepath.Join(home, ".ssh", "id_rsa"), []byte(privateKey), 0400); err != nil { + if err := os.WriteFile(filepath.Join(home, ".ssh", "id_rsa"), privateKey, 0400); err != nil { return fmt.Errorf("unable to write ssh key: %s", err) } return nil From 02498a2b8c7ccc6c0d6f21ed5d48f628c887f542 Mon Sep 17 00:00:00 2001 From: Trent Albright Date: Wed, 6 Jul 2022 08:41:02 -0400 Subject: [PATCH 11/15] fix --- docker.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docker.go b/docker.go index 92264029..3877e734 100644 --- a/docker.go +++ b/docker.go @@ -543,9 +543,8 @@ func writeSSHPrivateKey() error { if privateKeyBase64 == "" { return fmt.Errorf("%s must be defined and contain the base64 encoded private key to use for ssh agent forwarding", SSHPrivateKeyFromEnv) } - privateKey := []byte{} var err error - _, err = base64.StdEncoding.Decode(privateKey, []byte(privateKeyBase64)) + privateKey, err := base64.StdEncoding.DecodeString(privateKeyBase64) if err != nil { return fmt.Errorf("unable to base64 decode private key") } From 9c7c889618813d49b4e35672ad18a6212c70270d Mon Sep 17 00:00:00 2001 From: Trent Albright Date: Wed, 6 Jul 2022 09:56:27 -0400 Subject: [PATCH 12/15] remove debug output --- docker.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docker.go b/docker.go index 3877e734..84d86179 100644 --- a/docker.go +++ b/docker.go @@ -192,6 +192,8 @@ func (p Plugin) Exec() error { // setup for using ssh agent (https://docs.docker.com/develop/develop-images/build_enhancements/#using-ssh-to-access-private-data-in-builds) if !sshAgentEmpty(p.Build.SSHAgent) { + // TODO check in with one of the drone devs...this should not be necessary. I'm probably doing something + // wrong with the cli framework p.Build.SSHAgent = strings.TrimSuffix(p.Build.SSHAgent, "]") p.Build.SSHAgent = strings.TrimPrefix(p.Build.SSHAgent, "[") fmt.Printf("ssh agent set to \"%s\"\n", p.Build.SSHAgent) @@ -533,7 +535,6 @@ func commandSSHAgentForwardingSetup(build Build) []*exec.Cmd { } os.Setenv("SSH_AUTH_SOCK", SSHAgentSockPath) cmds = append(cmds, exec.Command("ssh-agent", "-a", SSHAgentSockPath)) - cmds = append(cmds, exec.Command("cat", "/root/.ssh/id_rsa")) cmds = append(cmds, exec.Command("ssh-add")) return cmds } From e650b4df72ec981ddeba0dbb3c62bb77b8a4d536 Mon Sep 17 00:00:00 2001 From: Trent Albright Date: Sat, 9 Jul 2022 14:59:33 -0400 Subject: [PATCH 13/15] code cleanup --- docker.go | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/docker.go b/docker.go index 84d86179..7aa2b64e 100644 --- a/docker.go +++ b/docker.go @@ -191,7 +191,7 @@ func (p Plugin) Exec() error { } // setup for using ssh agent (https://docs.docker.com/develop/develop-images/build_enhancements/#using-ssh-to-access-private-data-in-builds) - if !sshAgentEmpty(p.Build.SSHAgent) { + if p.Build.SSHAgent != "" { // TODO check in with one of the drone devs...this should not be necessary. I'm probably doing something // wrong with the cli framework p.Build.SSHAgent = strings.TrimSuffix(p.Build.SSHAgent, "]") @@ -346,7 +346,7 @@ func commandBuild(build Build) *exec.Cmd { if build.Quiet { args = append(args, "--quiet") } - if !sshAgentEmpty(build.SSHAgent) { + if build.SSHAgent != "" { args = append(args, "--ssh", build.SSHAgent) } @@ -375,7 +375,7 @@ func commandBuild(build Build) *exec.Cmd { } // we need to enable buildkit, for secret support and ssh agent support - if build.Secret != "" || len(build.SecretEnvs) > 0 || len(build.SecretFiles) > 0 || !sshAgentEmpty(build.SSHAgent) { + if build.Secret != "" || len(build.SecretEnvs) > 0 || len(build.SecretFiles) > 0 || build.SSHAgent != "" { os.Setenv("DOCKER_BUILDKIT", "1") } return exec.Command(dockerExe, args...) @@ -575,7 +575,3 @@ func GetDroneDockerExecCmd() string { return "drone-docker" } - -func sshAgentEmpty(agent string) bool { - return agent == "" -} From c0a07603d7e708d6bc69811ce9d855abc61a7ac2 Mon Sep 17 00:00:00 2001 From: Trent Albright Date: Sat, 9 Jul 2022 15:13:09 -0400 Subject: [PATCH 14/15] add test --- docker_test.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/docker_test.go b/docker_test.go index ea90181d..91cb4723 100644 --- a/docker_test.go +++ b/docker_test.go @@ -114,6 +114,26 @@ func TestCommandBuild(t *testing.T) { ".", ), }, + { + name: "ssh agent", + build: Build{ + Name: "plugins/drone-docker:latest", + Dockerfile: "Dockerfile", + Context: ".", + SSHAgent: "default", + }, + want: exec.Command( + dockerExe, + "build", + "--rm=true", + "-f", + "Dockerfile", + "-t", + "plugins/drone-docker:latest", + ".", + "--ssh default", + ), + }, } for _, tc := range tcs { From bf7dedcc46edb02061a83e94e877cb4834032089 Mon Sep 17 00:00:00 2001 From: BKK Date: Sat, 9 Jul 2022 21:02:26 -0400 Subject: [PATCH 15/15] Update docker.go --- docker.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/docker.go b/docker.go index 7aa2b64e..fd923e1f 100644 --- a/docker.go +++ b/docker.go @@ -114,9 +114,6 @@ type ( // Exec executes the plugin step func (p Plugin) Exec() error { - fmt.Printf("exec build: %#v", p.Build) - fmt.Printf("exec env: %#v", os.Environ()) - // start the Docker daemon server if !p.Daemon.Disabled { p.startDaemon()