11package docker
22
33import (
4+ "encoding/base64"
45 "fmt"
56 "io/ioutil"
7+ "log"
68 "os"
79 "os/exec"
810 "path/filepath"
@@ -11,6 +13,11 @@ import (
1113 "time"
1214)
1315
16+ const (
17+ SSHAgentSockPath = "/tmp/drone-ssh-agent-sock"
18+ SSHPrivateKeyFromEnv = "SSH_KEY"
19+ )
20+
1421type (
1522 // Daemon defines Docker daemon parameters.
1623 Daemon struct {
@@ -107,6 +114,7 @@ type (
107114
108115// Exec executes the plugin step
109116func (p Plugin ) Exec () error {
117+
110118 // start the Docker daemon server
111119 if ! p .Daemon .Disabled {
112120 p .startDaemon ()
@@ -180,6 +188,13 @@ func (p Plugin) Exec() error {
180188 cmds = append (cmds , commandPull (img ))
181189 }
182190
191+ // setup for using ssh agent (https://docs.docker.com/develop/develop-images/build_enhancements/#using-ssh-to-access-private-data-in-builds)
192+
193+ if len (p .Build .SSHAgent ) > 0 {
194+ fmt .Printf ("ssh agent set to \" %s\" \n " , p .Build .SSHAgent )
195+ cmds = append (cmds , commandSSHAgentForwardingSetup (p .Build )... )
196+ }
197+
183198 cmds = append (cmds , commandBuild (p .Build )) // docker build
184199
185200 for _ , tag := range p .Build .Tags {
@@ -329,8 +344,8 @@ func commandBuild(build Build) *exec.Cmd {
329344 if build .Platform != "" {
330345 args = append (args , "--platform" , build .Platform )
331346 }
332- if build . SSHAgent != "" {
333- args = append (args , "--ssh" , build . SSHAgent )
347+ for _ , sshagent := range build . SSHAgent {
348+ args = append (args , "--ssh" , sshagent )
334349 }
335350
336351 if build .AutoLabel {
@@ -357,8 +372,8 @@ func commandBuild(build Build) *exec.Cmd {
357372 }
358373 }
359374
360- // we need to enable buildkit, for secret support
361- if build .Secret != "" || len (build .SecretEnvs ) > 0 || len (build .SecretFiles ) > 0 {
375+ // we need to enable buildkit, for secret support and ssh agent support
376+ if build .Secret != "" || len (build .SecretEnvs ) > 0 || len (build .SecretFiles ) > 0 || len ( build . SSHAgent ) > 0 {
362377 os .Setenv ("DOCKER_BUILDKIT" , "1" )
363378 }
364379 return exec .Command (dockerExe , args ... )
@@ -511,6 +526,40 @@ func commandRmi(tag string) *exec.Cmd {
511526 return exec .Command (dockerExe , "rmi" , tag )
512527}
513528
529+ func commandSSHAgentForwardingSetup (build Build ) []* exec.Cmd {
530+ cmds := make ([]* exec.Cmd , 0 )
531+ if err := writeSSHPrivateKey (); err != nil {
532+ log .Fatalf ("unable to setup ssh agent forwarding: %s" , err )
533+ }
534+ os .Setenv ("SSH_AUTH_SOCK" , SSHAgentSockPath )
535+ cmds = append (cmds , exec .Command ("ssh-agent" , "-a" , SSHAgentSockPath ))
536+ cmds = append (cmds , exec .Command ("ssh-add" ))
537+ return cmds
538+ }
539+
540+ func writeSSHPrivateKey () error {
541+ privateKeyBase64 := os .Getenv (SSHPrivateKeyFromEnv )
542+ if privateKeyBase64 == "" {
543+ return fmt .Errorf ("%s must be defined and contain the base64 encoded private key to use for ssh agent forwarding" , SSHPrivateKeyFromEnv )
544+ }
545+ var err error
546+ privateKey , err := base64 .StdEncoding .DecodeString (privateKeyBase64 )
547+ if err != nil {
548+ return fmt .Errorf ("unable to base64 decode private key" )
549+ }
550+ home , err := os .UserHomeDir ()
551+ if err != nil {
552+ return fmt .Errorf ("unable to determine home directory: %s" , err )
553+ }
554+ if err := os .MkdirAll (filepath .Join (home , ".ssh" ), 0700 ); err != nil {
555+ return fmt .Errorf ("unable to create .ssh directory: %s" , err )
556+ }
557+ if err := os .WriteFile (filepath .Join (home , ".ssh" , "id_rsa" ), privateKey , 0400 ); err != nil {
558+ return fmt .Errorf ("unable to write ssh key: %s" , err )
559+ }
560+ return nil
561+ }
562+
514563// trace writes each command to stdout with the command wrapped in an xml
515564// tag so that it can be extracted and displayed in the logs.
516565func trace (cmd * exec.Cmd ) {
0 commit comments