commit
8ee6a03748
|
@ -60,6 +60,7 @@ func (p *ResourceProvisioner) copyFiles(conf *helper.SSHConfig, src, dst string)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer config.CleanupConfig()
|
||||||
|
|
||||||
// Wait and retry until we establish the SSH connection
|
// Wait and retry until we establish the SSH connection
|
||||||
var comm *helper.SSHCommunicator
|
var comm *helper.SSHCommunicator
|
||||||
|
|
|
@ -172,16 +172,20 @@ func (p *ResourceProvisioner) runScripts(
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer config.CleanupConfig()
|
||||||
|
|
||||||
o.Output(fmt.Sprintf(
|
o.Output(fmt.Sprintf(
|
||||||
"Connecting to remote host via SSH...\n"+
|
"Connecting to remote host via SSH...\n"+
|
||||||
" Host: %s\n"+
|
" Host: %s\n"+
|
||||||
" User: %s\n"+
|
" User: %s\n"+
|
||||||
" Password: %v\n"+
|
" Password: %v\n"+
|
||||||
" Private key: %v",
|
" Private key: %v"+
|
||||||
|
" SSH Agent: %v",
|
||||||
conf.Host, conf.User,
|
conf.Host, conf.User,
|
||||||
conf.Password != "",
|
conf.Password != "",
|
||||||
conf.KeyFile != ""))
|
conf.KeyFile != "",
|
||||||
|
conf.Agent,
|
||||||
|
))
|
||||||
|
|
||||||
// Wait and retry until we establish the SSH connection
|
// Wait and retry until we establish the SSH connection
|
||||||
var comm *helper.SSHCommunicator
|
var comm *helper.SSHCommunicator
|
||||||
|
|
|
@ -97,6 +97,10 @@ type Config struct {
|
||||||
|
|
||||||
// NoPty, if true, will not request a pty from the remote end.
|
// NoPty, if true, will not request a pty from the remote end.
|
||||||
NoPty bool
|
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
|
// New creates a new packer.Communicator implementation over SSH. This takes
|
||||||
|
|
|
@ -5,12 +5,15 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"golang.org/x/crypto/ssh"
|
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
"github.com/mitchellh/go-homedir"
|
"github.com/mitchellh/go-homedir"
|
||||||
"github.com/mitchellh/mapstructure"
|
"github.com/mitchellh/mapstructure"
|
||||||
|
"golang.org/x/crypto/ssh"
|
||||||
|
"golang.org/x/crypto/ssh/agent"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -37,6 +40,7 @@ type SSHConfig struct {
|
||||||
KeyFile string `mapstructure:"key_file"`
|
KeyFile string `mapstructure:"key_file"`
|
||||||
Host string
|
Host string
|
||||||
Port int
|
Port int
|
||||||
|
Agent bool
|
||||||
Timeout string
|
Timeout string
|
||||||
ScriptPath string `mapstructure:"script_path"`
|
ScriptPath string `mapstructure:"script_path"`
|
||||||
TimeoutVal time.Duration `mapstructure:"-"`
|
TimeoutVal time.Duration `mapstructure:"-"`
|
||||||
|
@ -99,9 +103,32 @@ func safeDuration(dur string, defaultDur time.Duration) time.Duration {
|
||||||
// PrepareConfig is used to turn the *SSHConfig provided into a
|
// PrepareConfig is used to turn the *SSHConfig provided into a
|
||||||
// usable *Config for client initialization.
|
// usable *Config for client initialization.
|
||||||
func PrepareConfig(conf *SSHConfig) (*Config, error) {
|
func PrepareConfig(conf *SSHConfig) (*Config, error) {
|
||||||
|
var conn net.Conn
|
||||||
|
var err error
|
||||||
|
|
||||||
sshConf := &ssh.ClientConfig{
|
sshConf := &ssh.ClientConfig{
|
||||||
User: conf.User,
|
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 != "" {
|
if conf.KeyFile != "" {
|
||||||
fullPath, err := homedir.Expand(conf.KeyFile)
|
fullPath, err := homedir.Expand(conf.KeyFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -142,6 +169,15 @@ func PrepareConfig(conf *SSHConfig) (*Config, error) {
|
||||||
config := &Config{
|
config := &Config{
|
||||||
SSHConfig: sshConf,
|
SSHConfig: sshConf,
|
||||||
Connection: ConnectFunc("tcp", host),
|
Connection: ConnectFunc("tcp", host),
|
||||||
|
SSHAgentConn: conn,
|
||||||
}
|
}
|
||||||
return config, nil
|
return config, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Config) CleanupConfig() error {
|
||||||
|
if c.SSHAgentConn != nil {
|
||||||
|
return c.SSHAgentConn.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -46,6 +46,8 @@ The following arguments are supported:
|
||||||
* `key_file` - The SSH key to use for the connection. This takes preference over the
|
* `key_file` - The SSH key to use for the connection. This takes preference over the
|
||||||
password if provided.
|
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.
|
* `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.
|
* `port` - The port to connect to. This defaults to 22.
|
||||||
|
|
Loading…
Reference in New Issue