Merge pull request #6946 from gmmephisto/pr-master-expand-user
communicator/ssh: expand user path for SSH private key
This commit is contained in:
commit
662fbf127b
|
@ -3,7 +3,6 @@ package ecs
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"runtime"
|
||||
|
||||
|
@ -28,10 +27,9 @@ func (s *stepConfigAlicloudKeyPair) Run(_ context.Context, state multistep.State
|
|||
|
||||
if s.Comm.SSHPrivateKeyFile != "" {
|
||||
ui.Say("Using existing SSH private key")
|
||||
privateKeyBytes, err := ioutil.ReadFile(s.Comm.SSHPrivateKeyFile)
|
||||
privateKeyBytes, err := s.Comm.ReadSSHPrivateKeyFile()
|
||||
if err != nil {
|
||||
state.Put("error", fmt.Errorf(
|
||||
"Error loading configured private key file: %s", err))
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ package common
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"runtime"
|
||||
|
||||
|
@ -26,10 +25,9 @@ func (s *StepKeyPair) Run(_ context.Context, state multistep.StateBag) multistep
|
|||
|
||||
if s.Comm.SSHPrivateKeyFile != "" {
|
||||
ui.Say("Using existing SSH private key")
|
||||
privateKeyBytes, err := ioutil.ReadFile(s.Comm.SSHPrivateKeyFile)
|
||||
privateKeyBytes, err := s.Comm.ReadSSHPrivateKeyFile()
|
||||
if err != nil {
|
||||
state.Put("error", fmt.Errorf(
|
||||
"Error loading configured private key file: %s", err))
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
|
|
|
@ -326,7 +326,7 @@ func setSshValues(c *Config) error {
|
|||
}
|
||||
|
||||
if c.Comm.SSHPrivateKeyFile != "" {
|
||||
privateKeyBytes, err := ioutil.ReadFile(c.Comm.SSHPrivateKeyFile)
|
||||
privateKeyBytes, err := c.Comm.ReadSSHPrivateKeyFile()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package cloudstack
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"runtime"
|
||||
|
||||
|
@ -23,10 +22,10 @@ func (s *stepKeypair) Run(_ context.Context, state multistep.StateBag) multistep
|
|||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
if s.Comm.SSHPrivateKeyFile != "" {
|
||||
privateKeyBytes, err := ioutil.ReadFile(s.Comm.SSHPrivateKeyFile)
|
||||
ui.Say("Using existing SSH private key")
|
||||
privateKeyBytes, err := s.Comm.ReadSSHPrivateKeyFile()
|
||||
if err != nil {
|
||||
state.Put("error", fmt.Errorf(
|
||||
"Error loading configured private key file: %s", err))
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
|
@ -29,10 +28,9 @@ func (s *StepCreateSSHKey) Run(_ context.Context, state multistep.StateBag) mult
|
|||
|
||||
if config.Comm.SSHPrivateKeyFile != "" {
|
||||
ui.Say("Using existing SSH private key")
|
||||
privateKeyBytes, err := ioutil.ReadFile(config.Comm.SSHPrivateKeyFile)
|
||||
privateKeyBytes, err := config.Comm.ReadSSHPrivateKeyFile()
|
||||
if err != nil {
|
||||
state.Put("error", fmt.Errorf(
|
||||
"Error loading configured private key file: %s", err))
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
|
|
|
@ -28,10 +28,10 @@ func (s *StepKeyPair) Run(_ context.Context, state multistep.StateBag) multistep
|
|||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
if s.Comm.SSHPrivateKeyFile != "" {
|
||||
privateKeyBytes, err := ioutil.ReadFile(s.Comm.SSHPrivateKeyFile)
|
||||
ui.Say("Using existing SSH private key")
|
||||
privateKeyBytes, err := s.Comm.ReadSSHPrivateKeyFile()
|
||||
if err != nil {
|
||||
state.Put("error", fmt.Errorf(
|
||||
"Error loading configured private key file: %s", err))
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"runtime"
|
||||
|
||||
|
@ -27,9 +26,9 @@ func (s *StepKeyPair) Run(_ context.Context, state multistep.StateBag) multistep
|
|||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
if s.Comm.SSHPrivateKeyFile != "" {
|
||||
privateKeyBytes, err := ioutil.ReadFile(s.Comm.SSHPrivateKeyFile)
|
||||
ui.Say("Using existing SSH private key")
|
||||
privateKeyBytes, err := s.Comm.ReadSSHPrivateKeyFile()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Error loading configured private key file: %s", err)
|
||||
ui.Error(err.Error())
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
|
@ -22,9 +21,9 @@ func (s *StepCreateSSHKey) Run(_ context.Context, state multistep.StateBag) mult
|
|||
c := state.Get("config").(*Config)
|
||||
|
||||
if c.Comm.SSHPrivateKeyFile != "" {
|
||||
pemBytes, err := ioutil.ReadFile(c.Comm.SSHPrivateKeyFile)
|
||||
|
||||
pemBytes, err := c.Comm.ReadSSHPrivateKeyFile()
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"runtime"
|
||||
|
@ -28,10 +27,9 @@ func (s *stepCreateSSHKey) Run(_ context.Context, state multistep.StateBag) mult
|
|||
|
||||
if config.Comm.SSHPrivateKeyFile != "" {
|
||||
ui.Say("Using existing SSH private key")
|
||||
privateKeyBytes, err := ioutil.ReadFile(config.Comm.SSHPrivateKeyFile)
|
||||
privateKeyBytes, err := config.Comm.ReadSSHPrivateKeyFile()
|
||||
if err != nil {
|
||||
state.Put("error", fmt.Errorf(
|
||||
"Error loading configured private key file: %s", err))
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
helperssh "github.com/hashicorp/packer/helper/ssh"
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
"github.com/masterzen/winrm"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
"golang.org/x/crypto/ssh"
|
||||
"golang.org/x/crypto/ssh/agent"
|
||||
)
|
||||
|
@ -27,8 +28,6 @@ type Config struct {
|
|||
SSHPort int `mapstructure:"ssh_port"`
|
||||
SSHUsername string `mapstructure:"ssh_username"`
|
||||
SSHPassword string `mapstructure:"ssh_password"`
|
||||
SSHPublicKey []byte `mapstructure:"ssh_public_key"`
|
||||
SSHPrivateKey []byte `mapstructure:"ssh_private_key"`
|
||||
SSHKeyPairName string `mapstructure:"ssh_keypair_name"`
|
||||
SSHTemporaryKeyPairName string `mapstructure:"temporary_key_pair_name"`
|
||||
SSHClearAuthorizedKeys bool `mapstructure:"ssh_clear_authorized_keys"`
|
||||
|
@ -53,6 +52,9 @@ type Config struct {
|
|||
SSHProxyPassword string `mapstructure:"ssh_proxy_password"`
|
||||
SSHKeepAliveInterval time.Duration `mapstructure:"ssh_keep_alive_interval"`
|
||||
SSHReadWriteTimeout time.Duration `mapstructure:"ssh_read_write_timeout"`
|
||||
// SSH Internals
|
||||
SSHPublicKey []byte
|
||||
SSHPrivateKey []byte
|
||||
|
||||
// WinRM
|
||||
WinRMUser string `mapstructure:"winrm_username"`
|
||||
|
@ -66,6 +68,23 @@ type Config struct {
|
|||
WinRMTransportDecorator func() winrm.Transporter
|
||||
}
|
||||
|
||||
// ReadSSHPrivateKeyFile returns the SSH private key bytes
|
||||
func (c *Config) ReadSSHPrivateKeyFile() ([]byte, error) {
|
||||
var privateKey []byte
|
||||
|
||||
if c.SSHPrivateKeyFile != "" {
|
||||
keyPath, err := homedir.Expand(c.SSHPrivateKeyFile)
|
||||
if err != nil {
|
||||
return privateKey, fmt.Errorf("Error expanding path for SSH private key: %s", err)
|
||||
}
|
||||
privateKey, err = ioutil.ReadFile(keyPath)
|
||||
if err != nil {
|
||||
return privateKey, fmt.Errorf("Error on reading SSH private key: %s", err)
|
||||
}
|
||||
}
|
||||
return privateKey, nil
|
||||
}
|
||||
|
||||
// SSHConfigFunc returns a function that can be used for the SSH communicator
|
||||
// config for connecting to the instance created over SSH using the private key
|
||||
// or password.
|
||||
|
@ -92,12 +111,11 @@ func (c *Config) SSHConfigFunc() func(multistep.StateBag) (*ssh.ClientConfig, er
|
|||
|
||||
var privateKeys [][]byte
|
||||
if c.SSHPrivateKeyFile != "" {
|
||||
// key based auth
|
||||
bytes, err := ioutil.ReadFile(c.SSHPrivateKeyFile)
|
||||
privateKey, err := c.ReadSSHPrivateKeyFile()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error setting up SSH config: %s", err)
|
||||
return nil, err
|
||||
}
|
||||
privateKeys = append(privateKeys, bytes)
|
||||
privateKeys = append(privateKeys, privateKey)
|
||||
}
|
||||
|
||||
// aws,alicloud,cloudstack,digitalOcean,oneAndOne,openstack,oracle & profitbricks key
|
||||
|
@ -112,7 +130,7 @@ func (c *Config) SSHConfigFunc() func(multistep.StateBag) (*ssh.ClientConfig, er
|
|||
for _, key := range privateKeys {
|
||||
signer, err := ssh.ParsePrivateKey(key)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error setting up SSH config: %s", err)
|
||||
return nil, fmt.Errorf("Error on parsing SSH private key: %s", err)
|
||||
}
|
||||
sshConfig.Auth = append(sshConfig.Auth, ssh.PublicKeys(signer))
|
||||
}
|
||||
|
@ -243,10 +261,14 @@ func (c *Config) prepareSSH(ctx *interpolate.Context) []error {
|
|||
}
|
||||
|
||||
if c.SSHPrivateKeyFile != "" {
|
||||
if _, err := os.Stat(c.SSHPrivateKeyFile); err != nil {
|
||||
path, err := homedir.Expand(c.SSHPrivateKeyFile)
|
||||
if err != nil {
|
||||
errs = append(errs, fmt.Errorf(
|
||||
"ssh_private_key_file is invalid: %s", err))
|
||||
} else if _, err := helperssh.FileSigner(c.SSHPrivateKeyFile); err != nil {
|
||||
} else if _, err := os.Stat(path); err != nil {
|
||||
errs = append(errs, fmt.Errorf(
|
||||
"ssh_private_key_file is invalid: %s", err))
|
||||
} else if _, err := helperssh.FileSigner(path); err != nil {
|
||||
errs = append(errs, fmt.Errorf(
|
||||
"ssh_private_key_file is invalid: %s", err))
|
||||
}
|
||||
|
@ -256,6 +278,18 @@ func (c *Config) prepareSSH(ctx *interpolate.Context) []error {
|
|||
if c.SSHBastionPassword == "" && c.SSHBastionPrivateKeyFile == "" {
|
||||
errs = append(errs, errors.New(
|
||||
"ssh_bastion_password or ssh_bastion_private_key_file must be specified"))
|
||||
} else if c.SSHBastionPrivateKeyFile != "" {
|
||||
path, err := homedir.Expand(c.SSHBastionPrivateKeyFile)
|
||||
if err != nil {
|
||||
errs = append(errs, fmt.Errorf(
|
||||
"ssh_bastion_private_key_file is invalid: %s", err))
|
||||
} else if _, err := os.Stat(path); err != nil {
|
||||
errs = append(errs, fmt.Errorf(
|
||||
"ssh_bastion_private_key_file is invalid: %s", err))
|
||||
} else if _, err := helperssh.FileSigner(path); err != nil {
|
||||
errs = append(errs, fmt.Errorf(
|
||||
"ssh_bastion_private_key_file is invalid: %s", err))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ import (
|
|||
"github.com/hashicorp/packer/helper/multistep"
|
||||
helperssh "github.com/hashicorp/packer/helper/ssh"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
gossh "golang.org/x/crypto/ssh"
|
||||
"golang.org/x/crypto/ssh/agent"
|
||||
"golang.org/x/net/proxy"
|
||||
|
@ -226,7 +227,12 @@ func sshBastionConfig(config *Config) (*gossh.ClientConfig, error) {
|
|||
}
|
||||
|
||||
if config.SSHBastionPrivateKeyFile != "" {
|
||||
signer, err := helperssh.FileSigner(config.SSHBastionPrivateKeyFile)
|
||||
path, err := homedir.Expand(config.SSHBastionPrivateKeyFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(
|
||||
"Error expanding path for SSH bastion private key: %s", err)
|
||||
}
|
||||
signer, err := helperssh.FileSigner(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -75,8 +75,9 @@ The SSH communicator has the following options:
|
|||
- `ssh_bastion_port` (number) - The port of the bastion host. Defaults to
|
||||
`22`.
|
||||
|
||||
- `ssh_bastion_private_key_file` (string) - A private key file to use to
|
||||
authenticate with the bastion host.
|
||||
- `ssh_bastion_private_key_file` (string) - Path to a PEM encoded private
|
||||
key file to use to authenticate with the bastion host. The `~` can be used
|
||||
in path and will be expanded to the home directory of current user.
|
||||
|
||||
- `ssh_bastion_username` (string) - The username to connect to the bastion
|
||||
host.
|
||||
|
@ -111,7 +112,8 @@ The SSH communicator has the following options:
|
|||
- `ssh_port` (number) - The port to connect to SSH. This defaults to `22`.
|
||||
|
||||
- `ssh_private_key_file` (string) - Path to a PEM encoded private key file to
|
||||
use to authenticate with SSH.
|
||||
use to authenticate with SSH. The `~` can be used in path and will be
|
||||
expanded to the home directory of current user.
|
||||
|
||||
- `ssh_proxy_host` (string) - A SOCKS proxy host to use for SSH connection
|
||||
|
||||
|
|
Loading…
Reference in New Issue