forked from Ivasoft/drone-docker
ssh agent support
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,3 +1,5 @@
|
|||||||
release
|
release
|
||||||
coverage.out
|
coverage.out
|
||||||
vendor
|
vendor
|
||||||
|
.vscode/
|
||||||
|
Dockerfile
|
||||||
|
|||||||
@@ -274,10 +274,10 @@ func main() {
|
|||||||
Usage: "platform value to pass to docker",
|
Usage: "platform value to pass to docker",
|
||||||
EnvVar: "PLUGIN_PLATFORM",
|
EnvVar: "PLUGIN_PLATFORM",
|
||||||
},
|
},
|
||||||
cli.StringSliceFlag{
|
cli.StringFlag{
|
||||||
Name: "ssh-agent",
|
Name: "ssh-agent-key",
|
||||||
Usage: "mount ssh agent",
|
Usage: "ssh agent key to use",
|
||||||
EnvVar: "PLUGIN_SSH_AGENT",
|
EnvVar: "PLUGIN_SSH_AGENT_KEY",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -323,7 +323,7 @@ func run(c *cli.Context) error {
|
|||||||
AddHost: c.StringSlice("add-host"),
|
AddHost: c.StringSlice("add-host"),
|
||||||
Quiet: c.Bool("quiet"),
|
Quiet: c.Bool("quiet"),
|
||||||
Platform: c.String("platform"),
|
Platform: c.String("platform"),
|
||||||
SSHAgent: c.StringSlice("ssh-agent"),
|
SSHAgentKey: c.String("ssh-agent-key"),
|
||||||
},
|
},
|
||||||
Daemon: docker.Daemon{
|
Daemon: docker.Daemon{
|
||||||
Registry: c.String("docker.registry"),
|
Registry: c.String("docker.registry"),
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
|
//go:build !windows
|
||||||
// +build !windows
|
// +build !windows
|
||||||
|
|
||||||
package docker
|
package docker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -17,8 +18,8 @@ func (p Plugin) startDaemon() {
|
|||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
} else {
|
} else {
|
||||||
cmd.Stdout = ioutil.Discard
|
cmd.Stdout = io.Discard
|
||||||
cmd.Stderr = ioutil.Discard
|
cmd.Stderr = io.Discard
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
trace(cmd)
|
trace(cmd)
|
||||||
|
|||||||
64
docker.go
64
docker.go
@@ -1,10 +1,7 @@
|
|||||||
package docker
|
package docker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/base64"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -13,11 +10,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
SSHAgentSockPath = "/tmp/drone-ssh-agent-sock"
|
|
||||||
SSHPrivateKeyFromEnv = "SSH_KEY"
|
|
||||||
)
|
|
||||||
|
|
||||||
type (
|
type (
|
||||||
// Daemon defines Docker daemon parameters.
|
// Daemon defines Docker daemon parameters.
|
||||||
Daemon struct {
|
Daemon struct {
|
||||||
@@ -71,7 +63,8 @@ type (
|
|||||||
AddHost []string // Docker build add-host
|
AddHost []string // Docker build add-host
|
||||||
Quiet bool // Docker build quiet
|
Quiet bool // Docker build quiet
|
||||||
Platform string // Docker build platform
|
Platform string // Docker build platform
|
||||||
SSHAgent []string // Docker build ssh
|
SSHAgentKey string // Docker build ssh agent key
|
||||||
|
SSHKeyPath string // Docker build ssh key path
|
||||||
}
|
}
|
||||||
|
|
||||||
// Plugin defines the Docker plugin parameters.
|
// Plugin defines the Docker plugin parameters.
|
||||||
@@ -153,7 +146,7 @@ func (p Plugin) Exec() error {
|
|||||||
os.MkdirAll(dockerHome, 0600)
|
os.MkdirAll(dockerHome, 0600)
|
||||||
|
|
||||||
path := filepath.Join(dockerHome, "config.json")
|
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 {
|
if err != nil {
|
||||||
return fmt.Errorf("Error writing config.json: %s", err)
|
return fmt.Errorf("Error writing config.json: %s", err)
|
||||||
}
|
}
|
||||||
@@ -189,10 +182,12 @@ 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)
|
// 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 != "" {
|
||||||
if len(p.Build.SSHAgent) > 0 {
|
var sshErr error
|
||||||
fmt.Printf("ssh agent set to \"%s\"\n", p.Build.SSHAgent)
|
p.Build.SSHKeyPath, sshErr = writeSSHPrivateKey(p.Build.SSHAgentKey)
|
||||||
cmds = append(cmds, commandSSHAgentForwardingSetup(p.Build)...)
|
if sshErr != nil {
|
||||||
|
return sshErr
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cmds = append(cmds, commandBuild(p.Build)) // docker build
|
cmds = append(cmds, commandBuild(p.Build)) // docker build
|
||||||
@@ -344,8 +339,8 @@ func commandBuild(build Build) *exec.Cmd {
|
|||||||
if build.Platform != "" {
|
if build.Platform != "" {
|
||||||
args = append(args, "--platform", build.Platform)
|
args = append(args, "--platform", build.Platform)
|
||||||
}
|
}
|
||||||
for _, sshagent := range build.SSHAgent {
|
if build.SSHKeyPath != "" {
|
||||||
args = append(args, "--ssh", sshagent)
|
args = append(args, "--ssh", build.SSHKeyPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
if build.AutoLabel {
|
if build.AutoLabel {
|
||||||
@@ -373,7 +368,7 @@ func commandBuild(build Build) *exec.Cmd {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// we need to enable buildkit, for secret support and ssh agent support
|
// we need to enable buildkit, for secret support and ssh agent support
|
||||||
if build.Secret != "" || len(build.SecretEnvs) > 0 || len(build.SecretFiles) > 0 || len(build.SSHAgent) > 0 {
|
if build.Secret != "" || len(build.SecretEnvs) > 0 || len(build.SecretFiles) > 0 || build.SSHAgentKey != "" {
|
||||||
os.Setenv("DOCKER_BUILDKIT", "1")
|
os.Setenv("DOCKER_BUILDKIT", "1")
|
||||||
}
|
}
|
||||||
return exec.Command(dockerExe, args...)
|
return exec.Command(dockerExe, args...)
|
||||||
@@ -526,38 +521,21 @@ func commandRmi(tag string) *exec.Cmd {
|
|||||||
return exec.Command(dockerExe, "rmi", tag)
|
return exec.Command(dockerExe, "rmi", tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
func commandSSHAgentForwardingSetup(build Build) []*exec.Cmd {
|
func writeSSHPrivateKey(key string) (path string, err error) {
|
||||||
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", "-a", SSHAgentSockPath))
|
|
||||||
cmds = append(cmds, exec.Command("ssh-add"))
|
|
||||||
return cmds
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeSSHPrivateKey() error {
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
var err error
|
|
||||||
privateKey, err := base64.StdEncoding.DecodeString(privateKeyBase64)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("unable to base64 decode private key")
|
|
||||||
}
|
|
||||||
home, err := os.UserHomeDir()
|
home, err := os.UserHomeDir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to determine home directory: %s", err)
|
return "", fmt.Errorf("unable to determine home directory: %s", err)
|
||||||
}
|
}
|
||||||
if err := os.MkdirAll(filepath.Join(home, ".ssh"), 0700); err != nil {
|
if err := os.MkdirAll(filepath.Join(home, ".ssh"), 0700); err != nil {
|
||||||
return fmt.Errorf("unable to create .ssh directory: %s", err)
|
return "", fmt.Errorf("unable to create .ssh directory: %s", err)
|
||||||
}
|
}
|
||||||
if err := os.WriteFile(filepath.Join(home, ".ssh", "id_rsa"), privateKey, 0400); err != nil {
|
pathToKey := filepath.Join(home, ".ssh", "id_rsa")
|
||||||
return fmt.Errorf("unable to write ssh key: %s", err)
|
if err := os.WriteFile(pathToKey, []byte(key), 0400); err != nil {
|
||||||
|
return "", fmt.Errorf("unable to write ssh key %s: %s", pathToKey, err)
|
||||||
}
|
}
|
||||||
return nil
|
path = fmt.Sprintf("default=%s", pathToKey)
|
||||||
|
|
||||||
|
return path, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// trace writes each command to stdout with the command wrapped in an xml
|
// trace writes each command to stdout with the command wrapped in an xml
|
||||||
|
|||||||
@@ -135,6 +135,26 @@ func TestCommandBuild(t *testing.T) {
|
|||||||
"test/platform",
|
"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 {
|
for _, tc := range tcs {
|
||||||
|
|||||||
Reference in New Issue
Block a user