Skip to content
Permalink
Browse files

build: add SSH agent socket forwarder (`docker build --ssh $SSHMOUNTI…

…D=$SSH_AUTH_SOCK`)

Unlike `docker build --secret`, `docker build --ssh` allows the build container to
use SSH keys with passphrases.

  $ eval $(ssh-agent)
  $ ssh-add ~/.ssh/id_rsa
  (Input your passphrase here)
  $ docker build --ssh default=$SSH_AUTH_SOCK ...

This feature requires the daemon with `CapExecMountSSH` build capability (moby/moby#37973) .

Currently, the official Dockerfile frontend does not provide the syntax for using the SSH forwarder.

However, the experimental `RUN --mount=type=ssh` syntax can be enabled by using
the Dockerfile frontend image built with the `BUILDTAGS="dfrunmount dfssh"`, via the `# syntax =` "shebang".

The Dockerfile for the Dockerfile frontend is available at  github.com/moby/buildkit/frontend/dockerfile/cmd/dockerfile-frontend)
The pre-built image is also available as `tonistiigi/dockerfile:ssh20181002` .

An example Dockerfile with `RUN --mount=type=ssh`:

  # syntax = tonistiigi/dockerfile:ssh20181002
  FROM alpine
  RUN apk add --no-cache openssh-client
  RUN mkdir -p -m 0700 ~/.ssh && ssh-keyscan gitlab.com >> ~/.ssh/known_hosts
  RUN --mount=type=ssh ssh git@gitlab.com | tee /hello
  # "Welcome to GitLab, @GITLAB_USERNAME_ASSOCIATED_WITH_SSHKEY" should be printed here

More info available at moby/buildkit#608, moby/buildkit#655

Signed-off-by: Akihiro Suda <suda.akihiro@lab.ntt.co.jp>
  • Loading branch information...
AkihiroSuda committed Oct 5, 2018
1 parent 846c38c commit db7399a016bed833205a17129ed80fad4d15e48d
Showing with 18,002 additions and 0 deletions.
  1. +4 −0 cli/command/image/build.go
  2. +31 −0 cli/command/image/build_buildkit.go
  3. +1 −0 docs/reference/commandline/build.md
  4. +61 −0 vendor/github.com/moby/buildkit/session/sshforward/copy.go
  5. +3 −0 vendor/github.com/moby/buildkit/session/sshforward/generate.go
  6. +113 −0 vendor/github.com/moby/buildkit/session/sshforward/ssh.go
  7. +816 −0 vendor/github.com/moby/buildkit/session/sshforward/ssh.pb.go
  8. +22 −0 vendor/github.com/moby/buildkit/session/sshforward/ssh.proto
  9. +198 −0 vendor/github.com/moby/buildkit/session/sshforward/sshprovider/agentprovider.go
  10. +217 −0 vendor/golang.org/x/crypto/ed25519/ed25519.go
  11. +1,422 −0 vendor/golang.org/x/crypto/ed25519/internal/edwards25519/const.go
  12. +1,793 −0 vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go
  13. +264 −0 vendor/golang.org/x/crypto/internal/chacha20/chacha_generic.go
  14. +16 −0 vendor/golang.org/x/crypto/internal/chacha20/chacha_noasm.go
  15. +30 −0 vendor/golang.org/x/crypto/internal/chacha20/chacha_s390x.go
  16. +283 −0 vendor/golang.org/x/crypto/internal/chacha20/chacha_s390x.s
  17. +43 −0 vendor/golang.org/x/crypto/internal/chacha20/xor.go
  18. +32 −0 vendor/golang.org/x/crypto/internal/subtle/aliasing.go
  19. +35 −0 vendor/golang.org/x/crypto/internal/subtle/aliasing_appengine.go
  20. +33 −0 vendor/golang.org/x/crypto/poly1305/poly1305.go
  21. +22 −0 vendor/golang.org/x/crypto/poly1305/sum_amd64.go
  22. +125 −0 vendor/golang.org/x/crypto/poly1305/sum_amd64.s
  23. +22 −0 vendor/golang.org/x/crypto/poly1305/sum_arm.go
  24. +427 −0 vendor/golang.org/x/crypto/poly1305/sum_arm.s
  25. +14 −0 vendor/golang.org/x/crypto/poly1305/sum_noasm.go
  26. +139 −0 vendor/golang.org/x/crypto/poly1305/sum_ref.go
  27. +49 −0 vendor/golang.org/x/crypto/poly1305/sum_s390x.go
  28. +400 −0 vendor/golang.org/x/crypto/poly1305/sum_s390x.s
  29. +931 −0 vendor/golang.org/x/crypto/poly1305/sum_vmsl_s390x.s
  30. +683 −0 vendor/golang.org/x/crypto/ssh/agent/client.go
  31. +103 −0 vendor/golang.org/x/crypto/ssh/agent/forward.go
  32. +215 −0 vendor/golang.org/x/crypto/ssh/agent/keyring.go
  33. +523 −0 vendor/golang.org/x/crypto/ssh/agent/server.go
  34. +97 −0 vendor/golang.org/x/crypto/ssh/buffer.go
  35. +521 −0 vendor/golang.org/x/crypto/ssh/certs.go
  36. +633 −0 vendor/golang.org/x/crypto/ssh/channel.go
  37. +770 −0 vendor/golang.org/x/crypto/ssh/cipher.go
  38. +278 −0 vendor/golang.org/x/crypto/ssh/client.go
  39. +525 −0 vendor/golang.org/x/crypto/ssh/client_auth.go
  40. +383 −0 vendor/golang.org/x/crypto/ssh/common.go
  41. +143 −0 vendor/golang.org/x/crypto/ssh/connection.go
  42. +21 −0 vendor/golang.org/x/crypto/ssh/doc.go
  43. +646 −0 vendor/golang.org/x/crypto/ssh/handshake.go
  44. +540 −0 vendor/golang.org/x/crypto/ssh/kex.go
  45. +1,035 −0 vendor/golang.org/x/crypto/ssh/keys.go
  46. +61 −0 vendor/golang.org/x/crypto/ssh/mac.go
  47. +766 −0 vendor/golang.org/x/crypto/ssh/messages.go
  48. +330 −0 vendor/golang.org/x/crypto/ssh/mux.go
  49. +593 −0 vendor/golang.org/x/crypto/ssh/server.go
  50. +647 −0 vendor/golang.org/x/crypto/ssh/session.go
  51. +116 −0 vendor/golang.org/x/crypto/ssh/streamlocal.go
  52. +474 −0 vendor/golang.org/x/crypto/ssh/tcpip.go
  53. +353 −0 vendor/golang.org/x/crypto/ssh/transport.go
@@ -73,6 +73,7 @@ type buildOptions struct {
platform string
untrusted bool
secrets []string
ssh []string
}

// dockerfileFromStdin returns true when the user specified that the Dockerfile
@@ -158,6 +159,9 @@ func NewBuildCommand(dockerCli command.Cli) *cobra.Command {

flags.StringArrayVar(&options.secrets, "secret", []string{}, "Secret file to expose to the build (only if BuildKit enabled): id=mysecret,src=/local/secret")
flags.SetAnnotation("secret", "version", []string{"1.39"})

flags.StringArrayVar(&options.ssh, "ssh", []string{}, "SSH agent socket or keys to expose to the build (only if BuildKit enabled) (format: default|<id>[=<socket>|<key>[,<key>]])")
flags.SetAnnotation("ssh", "version", []string{"1.39"})
return cmd
}

@@ -27,6 +27,7 @@ import (
"github.com/moby/buildkit/session/auth/authprovider"
"github.com/moby/buildkit/session/filesync"
"github.com/moby/buildkit/session/secrets/secretsprovider"
"github.com/moby/buildkit/session/sshforward/sshprovider"
"github.com/moby/buildkit/util/appcontext"
"github.com/moby/buildkit/util/progress/progressui"
"github.com/pkg/errors"
@@ -138,6 +139,13 @@ func runBuildBuildKit(dockerCli command.Cli, options buildOptions) error {
}
s.Allow(sp)
}
if len(options.ssh) > 0 {
sshp, err := parseSSHSpecs(options.ssh)
if err != nil {
return errors.Wrapf(err, "could not parse ssh: %v", options.ssh)
}
s.Allow(sshp)
}

eg, ctx := errgroup.WithContext(ctx)

@@ -408,3 +416,26 @@ func parseSecret(value string) (*secretsprovider.FileSource, error) {
}
return &fs, nil
}

func parseSSHSpecs(sl []string) (session.Attachable, error) {
configs := make([]sshprovider.AgentConfig, 0, len(sl))
for _, v := range sl {
c, err := parseSSH(v)
if err != nil {
return nil, err
}
configs = append(configs, *c)
}
return sshprovider.NewSSHAgentProvider(configs)
}

func parseSSH(value string) (*sshprovider.AgentConfig, error) {
parts := strings.SplitN(value, "=", 2)
cfg := sshprovider.AgentConfig{
ID: parts[0],
}
if len(parts) > 1 {
cfg.Paths = strings.Split(parts[1], ",")
}
return &cfg, nil
}
@@ -59,6 +59,7 @@ Options:
Unit is optional and can be `b` (bytes), `k` (kilobytes), `m` (megabytes),
or `g` (gigabytes). If you omit the unit, the system uses bytes.
--squash Squash newly built layers into a single new layer (**Experimental Only**)
--ssh SSH agent socket or keys to expose to the build (only if BuildKit enabled) (format: default|<id>[=<socket>|<key>[,<key>]])
-t, --tag value Name and optionally a tag in the 'name:tag' format (default [])
--target string Set the target build stage to build.
--ulimit value Ulimit options (default [])

Some generated files are not rendered by default. Learn more.

Oops, something went wrong.

Some generated files are not rendered by default. Learn more.

Oops, something went wrong.

Some generated files are not rendered by default. Learn more.

Oops, something went wrong.
Oops, something went wrong.

0 comments on commit db7399a

Please sign in to comment.
You can’t perform that action at this time.