SSH key forwarding with Chef deploy from git
January 30, 2014 in DevopsSeveral 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
- First it SSHs with the “admin” user
- Then it switches to root to run
chef-solo
- Then it switches to the app user to run
git pull
- Then it switches to the app user to run
- Then it switches to root to run
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.
Liked the post? Treat me to a coffee