cloudstack: Add support for ssh_agent_auth
This commit is contained in:
parent
24a53b7ee5
commit
f47c41372e
|
@ -66,9 +66,12 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
|||
},
|
||||
&stepSetupNetworking{},
|
||||
&communicator.StepConnect{
|
||||
Config: &b.config.Comm,
|
||||
Host: commHost,
|
||||
SSHConfig: sshConfig,
|
||||
Config: &b.config.Comm,
|
||||
Host: commHost,
|
||||
SSHConfig: SSHConfig(
|
||||
b.config.Comm.SSHAgentAuth,
|
||||
b.config.Comm.SSHUsername,
|
||||
b.config.Comm.SSHPassword),
|
||||
},
|
||||
&common.StepProvision{},
|
||||
&stepShutdownInstance{},
|
||||
|
|
|
@ -2,12 +2,14 @@ package cloudstack
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
|
||||
packerssh "github.com/hashicorp/packer/communicator/ssh"
|
||||
"github.com/mitchellh/multistep"
|
||||
"github.com/xanzy/go-cloudstack/cloudstack"
|
||||
"golang.org/x/crypto/ssh"
|
||||
"golang.org/x/crypto/ssh/agent"
|
||||
)
|
||||
|
||||
func commHost(state multistep.StateBag) (string, error) {
|
||||
|
@ -26,32 +28,54 @@ func commHost(state multistep.StateBag) (string, error) {
|
|||
return config.hostAddress, nil
|
||||
}
|
||||
|
||||
func sshConfig(state multistep.StateBag) (*ssh.ClientConfig, error) {
|
||||
config := state.Get("config").(*Config)
|
||||
func SSHConfig(useAgent bool, username, password string) func(state 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")
|
||||
}
|
||||
|
||||
clientConfig := &ssh.ClientConfig{
|
||||
User: config.Comm.SSHUsername,
|
||||
Auth: []ssh.AuthMethod{
|
||||
ssh.Password(config.Comm.SSHPassword),
|
||||
ssh.KeyboardInteractive(
|
||||
packerssh.PasswordKeyboardInteractive(config.Comm.SSHPassword)),
|
||||
},
|
||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||
}
|
||||
sshAgent, err := net.Dial("unix", authSock)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Cannot connect to SSH Agent socket %q: %s", authSock, err)
|
||||
}
|
||||
|
||||
if config.Comm.SSHPrivateKey != "" {
|
||||
privateKey, err := ioutil.ReadFile(config.Comm.SSHPrivateKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error loading configured private key file: %s", err)
|
||||
return &ssh.ClientConfig{
|
||||
User: username,
|
||||
Auth: []ssh.AuthMethod{
|
||||
ssh.PublicKeysCallback(agent.NewClient(sshAgent).Signers),
|
||||
},
|
||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
signer, err := ssh.ParsePrivateKey(privateKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error setting up SSH config: %s", err)
|
||||
privateKey, hasKey := state.GetOk("privateKey")
|
||||
|
||||
if hasKey {
|
||||
signer, err := ssh.ParsePrivateKey([]byte(privateKey.(string)))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error setting up SSH config: %s", err)
|
||||
}
|
||||
|
||||
return &ssh.ClientConfig{
|
||||
User: username,
|
||||
Auth: []ssh.AuthMethod{
|
||||
ssh.PublicKeys(signer),
|
||||
},
|
||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||
}, nil
|
||||
|
||||
} else {
|
||||
|
||||
return &ssh.ClientConfig{
|
||||
User: username,
|
||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||
Auth: []ssh.AuthMethod{
|
||||
ssh.Password(password),
|
||||
ssh.KeyboardInteractive(
|
||||
packerssh.PasswordKeyboardInteractive(password)),
|
||||
}}, nil
|
||||
}
|
||||
|
||||
clientConfig.Auth = []ssh.AuthMethod{ssh.PublicKeys(signer)}
|
||||
}
|
||||
|
||||
return clientConfig, nil
|
||||
}
|
||||
|
|
|
@ -22,6 +22,15 @@ func (s *stepPrepareConfig) Run(state multistep.StateBag) multistep.StepAction {
|
|||
var err error
|
||||
var errs *packer.MultiError
|
||||
|
||||
if config.Comm.SSHPrivateKey != "" {
|
||||
privateKey, err := ioutil.ReadFile(config.Comm.SSHPrivateKey)
|
||||
if err != nil {
|
||||
errs = packer.MultiErrorAppend(errs, fmt.Errorf("Error loading configured private key file: %s", err))
|
||||
}
|
||||
|
||||
state.Put("privateKey", privateKey)
|
||||
}
|
||||
|
||||
// First get the project and zone UUID's so we can use them in other calls when needed.
|
||||
if config.Project != "" && !isUUID(config.Project) {
|
||||
config.Project, _, err = client.Project.GetProjectID(config.Project)
|
||||
|
|
|
@ -123,6 +123,13 @@ builder.
|
|||
connecting any provisioners to. If not provided, a temporary public IP
|
||||
address will be associated and released during the Packer run.
|
||||
|
||||
- `ssh_agent_auth` (boolean) - If true, the local SSH agent will be used to
|
||||
authenticate connections to the source instance. No temporary keypair will
|
||||
be created, and the values of `ssh_password` and `ssh_private_key_file` will
|
||||
be ignored. To use this option with a key pair already configured in the source
|
||||
image, leave the `keypair` blank. To associate an existing key pair
|
||||
with the source instance, set the `keypair` field to the name of the key pair.
|
||||
|
||||
- `ssl_no_verify` (boolean) - Set to `true` to skip SSL verification. Defaults
|
||||
to `false`.
|
||||
|
||||
|
|
Loading…
Reference in New Issue