From c5b8a1069a1192a6dc251945f2ad033b0a4d7245 Mon Sep 17 00:00:00 2001 From: Larry Bordowitz Date: Fri, 10 Mar 2017 08:45:13 -0800 Subject: [PATCH] Add ssh agent to enable SSH-CA authentication. --- builder/openstack/builder.go | 4 +++- builder/openstack/ssh.go | 23 ++++++++++++++++++- .../source/docs/builders/openstack.html.md | 6 +++++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/builder/openstack/builder.go b/builder/openstack/builder.go index ecf37cf73..f0610c989 100644 --- a/builder/openstack/builder.go +++ b/builder/openstack/builder.go @@ -110,7 +110,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe computeClient, b.config.SSHInterface, b.config.SSHIPVersion), - SSHConfig: SSHConfig(b.config.RunConfig.Comm.SSHUsername, + SSHConfig: SSHConfig( + b.config.RunConfig.Comm.SSHAgentAuth, + b.config.RunConfig.Comm.SSHUsername, b.config.RunConfig.Comm.SSHPassword), }, &common.StepProvision{}, diff --git a/builder/openstack/ssh.go b/builder/openstack/ssh.go index a5495eed3..9738c278e 100644 --- a/builder/openstack/ssh.go +++ b/builder/openstack/ssh.go @@ -4,6 +4,8 @@ import ( "errors" "fmt" "log" + "net" + "os" "time" "github.com/gophercloud/gophercloud" @@ -12,6 +14,7 @@ import ( "github.com/mitchellh/multistep" packerssh "github.com/mitchellh/packer/communicator/ssh" "golang.org/x/crypto/ssh" + "golang.org/x/crypto/ssh/agent" ) // CommHost looks up the host for the communicator. @@ -63,8 +66,26 @@ func CommHost( // SSHConfig returns a function that can be used for the SSH communicator // config for connecting to the instance created over SSH using a private key // or a password. -func SSHConfig(username, password string) func(multistep.StateBag) (*ssh.ClientConfig, error) { +func SSHConfig(useAgent bool, username, password string) func(multistep.StateBag) (*ssh.ClientConfig, error) { return func(state multistep.StateBag) (*ssh.ClientConfig, error) { + if useAgent { + authSock := os.Getenv("SSH_AUTH_SOCK") + if authSock == "" { + return nil, fmt.Errorf("SSH_AUTH_SOCK is not set") + } + + sshAgent, err := net.Dial("unix", authSock) + if err != nil { + return nil, fmt.Errorf("Cannot connect to SSH Agent socket %q: %s", authSock, err) + } + + return &ssh.ClientConfig{ + User: username, + Auth: []ssh.AuthMethod{ + ssh.PublicKeysCallback(agent.NewClient(sshAgent).Signers), + }, + }, nil + } privateKey, hasKey := state.GetOk("privateKey") diff --git a/website/source/docs/builders/openstack.html.md b/website/source/docs/builders/openstack.html.md index 486d29e2d..a3920afa5 100644 --- a/website/source/docs/builders/openstack.html.md +++ b/website/source/docs/builders/openstack.html.md @@ -147,6 +147,12 @@ builder. [`ssh_private_key_file`](/docs/templates/communicator.html#ssh_private_key_file) must be specified with this. +- `ssh_agent_auth` (boolean) - If true, the local SSH agent will be used to + authenticate connections to the source instance. No temporary key pair will + be used, and the values of `ssh_password` and `ssh_private_key_file` will + be ignored. Useful for when a temporary keypair can't be used, or when using + a certificate authority for SSH authentication. + - `tenant_id` or `tenant_name` (string) - The tenant ID or name to boot the instance into. Some OpenStack installations require this. If not specified, Packer will use the environment variable `OS_TENANT_NAME`, if set. Tenant