diff --git a/README.md b/README.md index fc36fc580..55b3339e5 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,8 @@ Hardware customization: Provisioning: * `ssh_username` - [**mandatory**] username in guest OS. -* `ssh_password` - [**mandatory**] password in guest OS. +* `ssh_password` - [**mandatory if ssh_private_key_file is not present**] password in guest OS. +* `ssh_private_key_file` - [**mandatory if ssh_password is not present**] password in guest OS. Post-processing: * `shutdown_command` - VMware guest tools are used by default. diff --git a/builder.go b/builder.go index 579c2b9c9..a669abd47 100644 --- a/builder.go +++ b/builder.go @@ -4,12 +4,10 @@ import ( "errors" "github.com/hashicorp/packer/common" - "github.com/hashicorp/packer/packer" - "github.com/mitchellh/multistep" "github.com/hashicorp/packer/helper/communicator" - gossh "golang.org/x/crypto/ssh" - "github.com/hashicorp/packer/communicator/ssh" + "github.com/hashicorp/packer/packer" "github.com/jetbrains-infra/packer-builder-vsphere/driver" + "github.com/mitchellh/multistep" ) type Builder struct { @@ -29,6 +27,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) { state := new(multistep.BasicStateBag) + state.Put("config", b.config) state.Put("hook", hook) state.Put("ui", ui) @@ -45,21 +44,8 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe &StepRun{}, &communicator.StepConnect{ Config: &b.config.Config, - Host: func(state multistep.StateBag) (string, error) { - return state.Get("ip").(string), nil - }, - SSHConfig: func(multistep.StateBag) (*gossh.ClientConfig, error) { - return &gossh.ClientConfig{ - User: b.config.Config.SSHUsername, - Auth: []gossh.AuthMethod{ - gossh.Password(b.config.Config.SSHPassword), - gossh.KeyboardInteractive( - ssh.PasswordKeyboardInteractive(b.config.Config.SSHPassword)), - }, - // TODO: add a proper verification - HostKeyCallback: gossh.InsecureIgnoreHostKey(), - }, nil - }, + Host: commHost, + SSHConfig: sshConfig, }, &common.StepProvision{}, &StepShutdown{ diff --git a/ssh.go b/ssh.go new file mode 100644 index 000000000..4ffdef905 --- /dev/null +++ b/ssh.go @@ -0,0 +1,44 @@ +package main + +import ( + "fmt" + "io/ioutil" + + packerssh "github.com/hashicorp/packer/communicator/ssh" + "github.com/mitchellh/multistep" + "golang.org/x/crypto/ssh" +) + +func commHost(state multistep.StateBag) (string, error) { + return state.Get("ip").(string), nil +} + +func sshConfig(state multistep.StateBag) (*ssh.ClientConfig, error) { + config := state.Get("config").(*Config) + + clientConfig := &ssh.ClientConfig{ + User: config.Config.SSHUsername, + Auth: []ssh.AuthMethod{ + ssh.Password(config.Config.SSHPassword), + ssh.KeyboardInteractive( + packerssh.PasswordKeyboardInteractive(config.Config.SSHPassword)), + }, + HostKeyCallback: ssh.InsecureIgnoreHostKey(), + } + + if config.Config.SSHPrivateKey != "" { + privateKey, err := ioutil.ReadFile(config.Config.SSHPrivateKey) + if err != nil { + return nil, fmt.Errorf("Error loading configured private key file: %s", err) + } + + signer, err := ssh.ParsePrivateKey(privateKey) + if err != nil { + return nil, fmt.Errorf("Error setting up SSH config: %s", err) + } + + clientConfig.Auth = []ssh.AuthMethod{ssh.PublicKeys(signer)} + } + + return clientConfig, nil +}