Enable ssh agent forwarding #1066

This commit is contained in:
Mark Peek 2015-06-13 17:15:49 -07:00
parent 74b9da5b23
commit b2f8eb68e8
3 changed files with 79 additions and 0 deletions

View File

@ -17,6 +17,8 @@ FEATURES:
being built. This should be used for template-relative paths. [GH-54] being built. This should be used for template-relative paths. [GH-54]
* **Disable SSH:** Set `communicator` to "none" in any builder to disable SSH * **Disable SSH:** Set `communicator` to "none" in any builder to disable SSH
connections. Note that provisioners won't work if this is done. [GH-1591] connections. Note that provisioners won't work if this is done. [GH-1591]
* **SSH Agent Forwarding:** SSH Agent Forwarding will now be enabled
to allow access to remote servers such as private git repos. [GH-1066]
IMPROVEMENTS: IMPROVEMENTS:

View File

@ -7,6 +7,7 @@ import (
"fmt" "fmt"
"github.com/mitchellh/packer/packer" "github.com/mitchellh/packer/packer"
"golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh"
"golang.org/x/crypto/ssh/agent"
"io" "io"
"io/ioutil" "io/ioutil"
"log" "log"
@ -226,10 +227,59 @@ func (c *comm) reconnect() (err error) {
if sshConn != nil { if sshConn != nil {
c.client = ssh.NewClient(sshConn, sshChan, req) c.client = ssh.NewClient(sshConn, sshChan, req)
} }
c.connectToAgent()
return return
} }
func (c *comm) connectToAgent() {
if c.client == nil {
return
}
// open connection to the local agent
socketLocation := os.Getenv("SSH_AUTH_SOCK")
if socketLocation == "" {
log.Printf("no local agent socket")
return
}
agentConn, err := net.Dial("unix", socketLocation)
if err != nil {
log.Printf("could not connect to local agent socket: %s", socketLocation)
return
}
// create agent and add in auth
forwardingAgent := agent.NewClient(agentConn)
if forwardingAgent == nil {
log.Printf("could not create agent client")
agentConn.Close()
return
}
// add callback for forwarding agent to SSH config
// XXX - might want to handle reconnects appending multiple callbacks
auth := ssh.PublicKeysCallback(forwardingAgent.Signers)
c.config.SSHConfig.Auth = append(c.config.SSHConfig.Auth, auth)
agent.ForwardToAgent(c.client, forwardingAgent)
// Setup a session to request agent forwarding
session, err := c.newSession()
if err != nil {
return
}
defer session.Close()
err = agent.RequestAgentForwarding(session)
if err != nil {
log.Printf("RequestAgentForwarding:", err)
return
}
log.Printf("agent forwarding enabled")
return
}
func (c *comm) scpSession(scpCommand string, f func(io.Writer, *bufio.Reader) error) error { func (c *comm) scpSession(scpCommand string, f func(io.Writer, *bufio.Reader) error) error {
session, err := c.newSession() session, err := c.newSession()
if err != nil { if err != nil {

View File

@ -146,6 +146,33 @@ on reboot or in your shell script. For example, on Gentoo:
/etc/init.d/net.eth0 stop /etc/init.d/net.eth0 stop
``` ```
## SSH Agent Forwarding
Some provisioning requires connecting to remote SSH servers from within the
packer instance. The below example is for pulling code from a private git
repository utilizing openssh on the client. Make sure you are running
`ssh-agent` and add your git repo ssh keys into it using `ssh-add /path/to/key`.
When the packer instance needs access to the ssh keys the agent will forward
the request back to your `ssh-agent`.
Note: when provisioning via git you should add the git server keys into
the `~/.ssh/known_hosts` file otherwise the git command could hang awaiting
input. This can be done by copying the file in via the
[file provisioner](/docs/provisioners/file.html) (more secure)
or using `ssh-keyscan` to populate the file (less secure). An example of the
latter accessing github would be:
```
{
"type": "shell",
"inline": [
"sudo apt-get install -y git",
"ssh-keyscan github.com >> ~/.ssh/known_hosts",
"git clone git@github.com:exampleorg/myprivaterepo.git"
]
}
```
## Troubleshooting ## Troubleshooting
*My shell script doesn't work correctly on Ubuntu* *My shell script doesn't work correctly on Ubuntu*