Re: Can ssh add keys to ssh-agent?

On Mon, Mar 23, 2009 at 05:47:12PM +0000, Hari Sekhon wrote:
My shells all use a unified agent which only triggers once the first
time I need to ssh (or if the agent is killed/restart or my key was not
already loaded for some reason etc..)

I don't see any way to do this that isn't a horrible hack involving
parsing the output of "ps" or your operating system's equivalent (such
as /proc). ssh-agent is intended to be run as the ancestor of all the
processes of your session (e.g. eval `ssh-agent -s` in your .xsession or
.profile file), so that they all inherit the same environment variables
pointing to the same agent.

If ssh-agent isn't already running at the time your ssh command is
triggered, then you're (potentially) going to have multiple xterms
running around with no SSH_AUTH* variables set. If you try to detect
the presence or absence of an agent running under your UID using some
ps/pgrep hackery, not only do you get the error-prone-ness of parsing
process names (processes can change their own names, invoke other
processes under pseudonyms, etc.), but you also create a race condition.

Consider something like this (bash syntax):

ssh() {
if ! pgrep -u $LOGNAME ssh-agent >/dev/null; then
# Agent is not running
eval $(ssh-agent -s)
ssh-add -L >/dev/null 2>&1
if [ $? = 1 ]; then
# Agent running, but no key loaded
command ssh "$@"
unset -f ssh

Looks good at first glance, right? But consider two xterms started
without a parent agent, so that they have no SSH_AUTH* variables, etc.
You start an "ssh" command in each one. Each one runs the pgrep, sees
there's no agent running under your name, and then runs ssh-agent -s to
set one up. Now you've got two agents, and two shells with different
environment variables pointing to the different agents. Not to mention
two ssh-add passphrase prompts, which is the thing you were trying to
avoid all along.

I wouldn't recommend anything other than putting eval $(ssh-agent -s) or
its equivalent into your primary login session file (.xinitrc or .xsession
or .profile or .login or whatever makes sense for your login). You can
then either do an ssh-add at that time (which is what I do, personally),
or you could write an override function like this (again, bash syntax):

ssh() {
ssh-add -L >/dev/null 2>&1
[ $? = 1 ] && ssh-add
command ssh "$@"
unset -f ssh

Since this doesn't involving checking for an agent, you avoid the
multiple-agent race condition I pointed out earlier. There's still
a race condition when you check whether the key is already loaded,
but the worst you can do here is get an extra passphrase prompt,
which is relatively harmless.