Merge pull request #4956 from rickard-von-essen/null-ssh-agent

builder/null: Support SSH Agent Auth
This commit is contained in:
Rickard von Essen 2017-06-02 12:58:55 +02:00 committed by GitHub
commit 254bd95ad7
3 changed files with 30 additions and 5 deletions

View File

@ -32,6 +32,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
Config: &b.config.CommConfig, Config: &b.config.CommConfig,
Host: CommHost(b.config.CommConfig.Host()), Host: CommHost(b.config.CommConfig.Host()),
SSHConfig: SSHConfig( SSHConfig: SSHConfig(
b.config.CommConfig.SSHAgentAuth,
b.config.CommConfig.SSHUsername, b.config.CommConfig.SSHUsername,
b.config.CommConfig.SSHPassword, b.config.CommConfig.SSHPassword,
b.config.CommConfig.SSHPrivateKey), b.config.CommConfig.SSHPrivateKey),

View File

@ -41,14 +41,16 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
fmt.Errorf("a Username must be specified, please reference your communicator documentation")) fmt.Errorf("a Username must be specified, please reference your communicator documentation"))
} }
if c.CommConfig.Password() == "" && c.CommConfig.SSHPrivateKey == "" { if !c.CommConfig.SSHAgentAuth && c.CommConfig.Password() == "" && c.CommConfig.SSHPrivateKey == "" {
errs = packer.MultiErrorAppend(errs, errs = packer.MultiErrorAppend(errs,
fmt.Errorf("one authentication method must be specified, please reference your communicator documentation")) fmt.Errorf("one authentication method must be specified, please reference your communicator documentation"))
} }
if c.CommConfig.SSHPassword != "" && c.CommConfig.SSHPrivateKey != "" { if (c.CommConfig.SSHAgentAuth &&
(c.CommConfig.SSHPassword != "" || c.CommConfig.SSHPrivateKey != "")) ||
(c.CommConfig.SSHPassword != "" && c.CommConfig.SSHPrivateKey != "") {
errs = packer.MultiErrorAppend(errs, errs = packer.MultiErrorAppend(errs,
fmt.Errorf("only one of ssh_password and ssh_private_key_file must be specified")) fmt.Errorf("only one of ssh_agent_auth, ssh_password, and ssh_private_key_file must be specified"))
} }
if errs != nil && len(errs.Errors) > 0 { if errs != nil && len(errs.Errors) > 0 {

View File

@ -2,10 +2,14 @@ package null
import ( import (
"fmt" "fmt"
"io/ioutil"
"net"
"os"
"github.com/hashicorp/packer/communicator/ssh" "github.com/hashicorp/packer/communicator/ssh"
"github.com/mitchellh/multistep" "github.com/mitchellh/multistep"
gossh "golang.org/x/crypto/ssh" gossh "golang.org/x/crypto/ssh"
"io/ioutil" "golang.org/x/crypto/ssh/agent"
) )
func CommHost(host string) func(multistep.StateBag) (string, error) { func CommHost(host string) func(multistep.StateBag) (string, error) {
@ -17,8 +21,26 @@ func CommHost(host string) func(multistep.StateBag) (string, error) {
// SSHConfig returns a function that can be used for the SSH communicator // SSHConfig returns a function that can be used for the SSH communicator
// config for connecting to the specified host via SSH // config for connecting to the specified host via SSH
// private_key_file has precedence over password! // private_key_file has precedence over password!
func SSHConfig(username string, password string, privateKeyFile string) func(multistep.StateBag) (*gossh.ClientConfig, error) { func SSHConfig(useAgent bool, username string, password string, privateKeyFile string) func(multistep.StateBag) (*gossh.ClientConfig, error) {
return func(state multistep.StateBag) (*gossh.ClientConfig, error) { return func(state multistep.StateBag) (*gossh.ClientConfig, error) {
if useAgent {
authSock := os.Getenv("SSH_AUTH_SOCK")
if authSock == "" {
return nil, fmt.Errorf("SSH_AUTH_SOCK is not set")
}
sshAgent, err := net.Dial("unix", authSock)
if err != nil {
return nil, fmt.Errorf("Cannot connect to SSH Agent socket %q: %s", authSock, err)
}
return &gossh.ClientConfig{
User: username,
Auth: []gossh.AuthMethod{
gossh.PublicKeysCallback(agent.NewClient(sshAgent).Signers),
},
}, nil
}
if privateKeyFile != "" { if privateKeyFile != "" {
// key based auth // key based auth