SSH key forwarding with Chef deploy from git

January 30, 2014 Chef deployment knife-solo SSH

Several months ago I migrated my deploy scheme to use the Chef deploy resource instead of Capistrano. I’m also using knife-solo and not Chef server.

One of the hurdles with the deploy was that I couldn’t use ssh-agent to forward SSH keys from my local machine, because of the way Chef works. The SSH keys are used to pull source code from Git repositories. Storing sensitive SSH keys on the application server, that is - let’s not kid ourselves - full of holes, is madness.

How Chef (knife-solo) changes users

How ssh-agent works

SSH-Agent needs two things to operate: a Unix socket and $SSH_AUTH_SOCK that stores the socket’s path. The app user needs access to both of these.

The solution

The first part of the solution was root_ssh_agent - this is a cookbook that gives root access to the socket. (I’m assuming you are already forwarding keys from the local machine.)

The second part is making the socket available to the deploy process. Instead of passing variables around - and because I needed to configure git access further, setting a custom port for SSH - I decided to use a git wrapper script:

execute "chmod -R 0777 $(dirname $SSH_AUTH_SOCK)"

# Wrapper to access git repos on git.todo.in.ua
execute "create git wrapper" do
  command 'echo "#!/bin/bash\nSSH_AUTH_SOCK=$SSH_AUTH_SOCK ssh -o StrictHostKeyChecking=no -p 1234 \$1 \$2\n" >/usr/local/bin/git-wrapper;'
end

execute "git wrapper ownership" do
  command 'chown root:root /usr/local/bin/git-wrapper;chmod 0755 /usr/local/bin/git-wrapper'
end

This code doesn’t use the file resource because it needs to get the value of $SSH_AUTH_SOCK at runtime.

Finally, tell the deploy resource to use the wrapper script:

deploy_revision "myapp" do
  ssh_wrapper "/usr/local/bin/git-wrapper"
  # rest of the configuration
end

The wrapper will only be valid during the deploy as the socket is closed at the end of the session.

Buy Me a Coffee at ko-fi.com