Skip to content

Commit

Permalink
Merge pull request #1208 from tarrant/master
Browse files Browse the repository at this point in the history
Add support for SSH Agent
  • Loading branch information
mitchellh committed Apr 2, 2015
2 parents 2721f62 + f68c9ee commit 8ee6a03
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 5 deletions.
1 change: 1 addition & 0 deletions builtin/provisioners/file/resource_provisioner.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ func (p *ResourceProvisioner) copyFiles(conf *helper.SSHConfig, src, dst string)
if err != nil {
return err
}
defer config.CleanupConfig()

// Wait and retry until we establish the SSH connection
var comm *helper.SSHCommunicator
Expand Down
8 changes: 6 additions & 2 deletions builtin/provisioners/remote-exec/resource_provisioner.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,16 +172,20 @@ func (p *ResourceProvisioner) runScripts(
if err != nil {
return err
}
defer config.CleanupConfig()

o.Output(fmt.Sprintf(
"Connecting to remote host via SSH...\n"+
" Host: %s\n"+
" User: %s\n"+
" Password: %v\n"+
" Private key: %v",
" Private key: %v"+
" SSH Agent: %v",
conf.Host, conf.User,
conf.Password != "",
conf.KeyFile != ""))
conf.KeyFile != "",
conf.Agent,
))

// Wait and retry until we establish the SSH connection
var comm *helper.SSHCommunicator
Expand Down
4 changes: 4 additions & 0 deletions helper/ssh/communicator.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ type Config struct {

// NoPty, if true, will not request a pty from the remote end.
NoPty bool

// SSHAgentConn is a pointer to the UNIX connection for talking with the
// ssh-agent.
SSHAgentConn net.Conn
}

// New creates a new packer.Communicator implementation over SSH. This takes
Expand Down
42 changes: 39 additions & 3 deletions helper/ssh/provisioner.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@ import (
"fmt"
"io/ioutil"
"log"
"net"
"os"
"time"

"golang.org/x/crypto/ssh"
"github.com/hashicorp/terraform/terraform"
"github.com/mitchellh/go-homedir"
"github.com/mitchellh/mapstructure"
"golang.org/x/crypto/ssh"
"golang.org/x/crypto/ssh/agent"
)

const (
Expand All @@ -37,6 +40,7 @@ type SSHConfig struct {
KeyFile string `mapstructure:"key_file"`
Host string
Port int
Agent bool
Timeout string
ScriptPath string `mapstructure:"script_path"`
TimeoutVal time.Duration `mapstructure:"-"`
Expand Down Expand Up @@ -99,9 +103,32 @@ func safeDuration(dur string, defaultDur time.Duration) time.Duration {
// PrepareConfig is used to turn the *SSHConfig provided into a
// usable *Config for client initialization.
func PrepareConfig(conf *SSHConfig) (*Config, error) {
var conn net.Conn
var err error

sshConf := &ssh.ClientConfig{
User: conf.User,
}
if conf.Agent {
sshAuthSock := os.Getenv("SSH_AUTH_SOCK")

if sshAuthSock == "" {
return nil, fmt.Errorf("SSH Requested but SSH_AUTH_SOCK not-specified")
}

conn, err = net.Dial("unix", sshAuthSock)
if err != nil {
return nil, fmt.Errorf("Error connecting to SSH_AUTH_SOCK: %v", err)
}
// I need to close this but, later after all connections have been made
// defer conn.Close()
signers, err := agent.NewClient(conn).Signers()
if err != nil {
return nil, fmt.Errorf("Error getting keys from ssh agent: %v", err)
}

sshConf.Auth = append(sshConf.Auth, ssh.PublicKeys(signers...))
}
if conf.KeyFile != "" {
fullPath, err := homedir.Expand(conf.KeyFile)
if err != nil {
Expand Down Expand Up @@ -140,8 +167,17 @@ func PrepareConfig(conf *SSHConfig) (*Config, error) {
}
host := fmt.Sprintf("%s:%d", conf.Host, conf.Port)
config := &Config{
SSHConfig: sshConf,
Connection: ConnectFunc("tcp", host),
SSHConfig: sshConf,
Connection: ConnectFunc("tcp", host),
SSHAgentConn: conn,
}
return config, nil
}

func (c *Config) CleanupConfig() error {
if c.SSHAgentConn != nil {
return c.SSHAgentConn.Close()
}

return nil
}
2 changes: 2 additions & 0 deletions website/source/docs/provisioners/connection.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ The following arguments are supported:
* `key_file` - The SSH key to use for the connection. This takes preference over the
password if provided.

* `agent` - Set to true to enable using ssh-agent to authenticate.

* `host` - The address of the resource to connect to. This is provided by the provider.

* `port` - The port to connect to. This defaults to 22.
Expand Down

0 comments on commit 8ee6a03

Please sign in to comment.