Skip to content

Commit

Permalink
Merge pull request #382 from tphoney/enable-ssh-agent
Browse files Browse the repository at this point in the history
Add option to mount host ssh agent (--ssh)
  • Loading branch information
TP Honey authored Jan 26, 2023
2 parents 94c8139 + d704148 commit 2dcf4a5
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 7 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
release
coverage.out
vendor
.vscode/
Dockerfile
6 changes: 6 additions & 0 deletions cmd/drone-docker/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,11 @@ func main() {
Usage: "platform value to pass to docker",
EnvVar: "PLUGIN_PLATFORM",
},
cli.StringFlag{
Name: "ssh-agent-key",
Usage: "ssh agent key to use",
EnvVar: "PLUGIN_SSH_AGENT_KEY",
},
}

if err := app.Run(os.Args); err != nil {
Expand Down Expand Up @@ -318,6 +323,7 @@ func run(c *cli.Context) error {
AddHost: c.StringSlice("add-host"),
Quiet: c.Bool("quiet"),
Platform: c.String("platform"),
SSHAgentKey: c.String("ssh-agent-key"),
},
Daemon: docker.Daemon{
Registry: c.String("docker.registry"),
Expand Down
7 changes: 4 additions & 3 deletions daemon.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
//go:build !windows
// +build !windows

package docker

import (
"io/ioutil"
"io"
"os"
)

Expand All @@ -17,8 +18,8 @@ func (p Plugin) startDaemon() {
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
} else {
cmd.Stdout = ioutil.Discard
cmd.Stderr = ioutil.Discard
cmd.Stdout = io.Discard
cmd.Stderr = io.Discard
}
go func() {
trace(cmd)
Expand Down
39 changes: 35 additions & 4 deletions docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package docker

import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
Expand Down Expand Up @@ -64,6 +63,8 @@ type (
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
}

// Plugin defines the Docker plugin parameters.
Expand Down Expand Up @@ -106,6 +107,7 @@ type (

// Exec executes the plugin step
func (p Plugin) Exec() error {

// start the Docker daemon server
if !p.Daemon.Disabled {
p.startDaemon()
Expand Down Expand Up @@ -144,7 +146,7 @@ func (p Plugin) Exec() error {
os.MkdirAll(dockerHome, 0600)

path := filepath.Join(dockerHome, "config.json")
err := ioutil.WriteFile(path, []byte(p.Login.Config), 0600)
err := os.WriteFile(path, []byte(p.Login.Config), 0600)
if err != nil {
return fmt.Errorf("Error writing config.json: %s", err)
}
Expand Down Expand Up @@ -179,6 +181,15 @@ 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.SSHAgentKey != "" {
var sshErr error
p.Build.SSHKeyPath, sshErr = writeSSHPrivateKey(p.Build.SSHAgentKey)
if sshErr != nil {
return sshErr
}
}

cmds = append(cmds, commandBuild(p.Build)) // docker build

for _, tag := range p.Build.Tags {
Expand Down Expand Up @@ -328,6 +339,9 @@ func commandBuild(build Build) *exec.Cmd {
if build.Platform != "" {
args = append(args, "--platform", build.Platform)
}
if build.SSHKeyPath != "" {
args = append(args, "--ssh", build.SSHKeyPath)
}

if build.AutoLabel {
labelSchema := []string{
Expand All @@ -353,8 +367,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.SSHAgentKey != "" {
os.Setenv("DOCKER_BUILDKIT", "1")
}
return exec.Command(dockerExe, args...)
Expand Down Expand Up @@ -507,6 +521,23 @@ func commandRmi(tag string) *exec.Cmd {
return exec.Command(dockerExe, "rmi", tag)
}

func writeSSHPrivateKey(key string) (path string, err error) {
home, err := os.UserHomeDir()
if err != nil {
return "", fmt.Errorf("unable to determine home directory: %s", err)
}
if err := os.MkdirAll(filepath.Join(home, ".ssh"), 0700); err != nil {
return "", fmt.Errorf("unable to create .ssh directory: %s", err)
}
pathToKey := filepath.Join(home, ".ssh", "id_rsa")
if err := os.WriteFile(pathToKey, []byte(key), 0400); err != nil {
return "", fmt.Errorf("unable to write ssh key %s: %s", pathToKey, err)
}
path = fmt.Sprintf("default=%s", pathToKey)

return path, 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) {
Expand Down
20 changes: 20 additions & 0 deletions docker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,26 @@ func TestCommandBuild(t *testing.T) {
"test/platform",
),
},
{
name: "ssh agent",
build: Build{
Name: "plugins/drone-docker:latest",
Dockerfile: "Dockerfile",
Context: ".",
SSHKeyPath: "id_rsa=/root/.ssh/id_rsa",
},
want: exec.Command(
dockerExe,
"build",
"--rm=true",
"-f",
"Dockerfile",
"-t",
"plugins/drone-docker:latest",
".",
"--ssh id_rsa=/root/.ssh/id_rsa",
),
},
}

for _, tc := range tcs {
Expand Down

0 comments on commit 2dcf4a5

Please sign in to comment.