Making ssh-agent and gpg-agent persistent
From FBSD_tips
This was originally posted on my blog.
A while ago I had to rsync some web files between two servers, and (as usual) I didn’t want the data to be in the clear, so I used rsync’s SSH feature. I needed to run it periodically automatically so I created SSH keys without passphrases.
After talking recently with Aji-Dahaka on IRC, I decided to try doing this again but clean it up and make it a bit more secure by using keys with passphrases. He has ssh-agent start up on login and shut down on logout, but I needed to make this happen in an automated way for the rsync cron script. It turned out to be easier than I thought.
Whenever one starts ssh-agent (or gpg-agent), it spits out some variables for your shell:
> ssh-agent setenv SSH_AUTH_SOCK /tmp/ssh-zwVypTFAFu/agent.78004; setenv SSH_AGENT_PID 78005; echo Agent pid 78005;
These variables are used by ssh-add and other applications to know how to contact the agent, so they need to be present in the shell invoking the process. This means we need to keep these particular variables around somehow for cron to pick up on. I wrote a simple script, ~/bin/ssh-agent, that captures these variables and stores them in a file for later use:
> cat ~/bin/ssh-agent
#!/bin/sh
# Start the agent and set the variables.
eval `ssh-agent -s`
# Set a umask so our agent information is somewhat protected.
umask 077
# Create the csh file
echo "setenv SSH_AUTH_SOCK ${SSH_AUTH_SOCK}" > ${HOME}/.ssh/csh
echo "setenv SSH_AGENT_PID ${SSH_AGENT_PID}" >> ${HOME}/.ssh/csh
# Create the sh file
echo "export SSH_AUTH_SOCK=${SSH_AUTH_SOCK}" > ${HOME}/.ssh/sh
echo "export SSH_AGENT_PID=${SSH_AGENT_PID}" >> ${HOME}/.ssh/sh
Now, in order for this to work, I have to run ~/bin/ssh-agent rather than the normal /usr/bin/ssh-agent, which is something I will need to remember. I suck at remembering things, so if I want I can reorder my $PATH to first check ~/bin. Either way, when I run ~/bin/ssh-agent, it will start the agent and keep the variables in ~/.ssh/<shell> for inclusion in scripts, such as my ~/.cshrc:
> grep ssh ~/.cshrc
source ${HOME}/.ssh/csh
Whenever I log in it will load the variables and I’ll be able to use the same agent with it’s preloaded keys. The same source procedure can be used in cron scripts to “link up with” the currently-running agent. For example, the rsync script I mentioned earlier starts out like this:
#!/bin/sh
. ${HOME}/.ssh/sh
Basically you just source the correct file in your script, before you use SSH. The same method will probably work with gpg-agent but I haven’t tried that yet. This whole process can probably be secured better by validating the parsed lines so one doesn’t execute unwanted commands from the sourced files.
FzZzT 14:22, 9 October 2007 (UTC)
