28

I want to put ssh-add /path/to/special_key at the top of a script. This works fine, but it always prompts for the passphrase. This is strange, and a little annoying, as it still asks for the passphrase even when ssh-add -l shows the key has already been added.

Is there a way to tell it: "add this key and ask the passphrase if not already been added, otherwise do nothing" ?

Darren Cook
  • 984
  • 2
  • 9
  • 19

5 Answers5

31

I don't see any options to ssh-add that help achieve your desired result, but it's pretty easy to work around this, given that you're concerned with one key in particular.

First, grab the fingerprint for your special_key:

ssh-keygen -lf /path/to/special_key  | awk '{print $2}'

Let's say this fingerprint looks like 6d:98:ed:8c:07:07:fe:57:bb:19:12:89:5a:c4:bf:25

Then, at the top of your script, use ssh-add -l to check whether that key is loaded, before prompting to add it:

ssh-add -l |grep -q 6d:98:ed:8c:07:07:fe:57:bb:19:12:89:5a:c4:bf:25 || ssh-add /path/to/special_key

You can fold all this together into one line if you wish:

ssh-add -l |grep -q `ssh-keygen -lf /path/to/special_key  | awk '{print $2}'` || ssh-add /path/to/special_key
Lars Rohrbach
  • 5,143
  • 2
  • 20
  • 24
  • The one-liner is working nicely, thanks! – Darren Cook Jun 01 '14 at 02:09
  • 3
    I find this simplified one-liner to be a bit more comprehensible, and preferable since it avoids `ssh-keygen` (after all, I don't want to generate any keys), instead using the key path: `ssh-add -l | grep -q 'path/to/key' || ssh-add /path/to/key` – mattsilver Jan 17 '17 at 14:58
  • 1
    `ssh-keygen` in the answer does not generate a key - same as `ssh-add -l` in your example does not actually add anything. Flags modify the behaviour of the commands so it does not exactly match the name. Note that these versions functionally differ - if checking by path and the key at that path changes, your version would not pick it up. The version in the answer would also detect existing key no matter where it was loaded from. – Richlv May 15 '19 at 11:18
5

There is no direct way to check using just ssh-add but you can make use of ssh-keygen and some scripting to check.

$ if  ssh-add -l | \
    grep -q "$(ssh-keygen -lf /path/to/special_key | awk '{print $2}')"; \
    then echo yes; \
    else echo no; \
  fi

The above would then print yes if the fingerprint represented by the file /path/to/special_key was present in ssh-add -l's output.

Example

$ if  ssh-add -l | \
    grep -q "$(ssh-keygen -lf /path/to/special_key | awk '{print $2}')"; \
    then echo yes; \
    else echo no; \
  fi
yes

Where the contents of output from ssh-keygen -lf /path/to/special_key looks like this:

$ ssh-keygen -lf /path/to/special_key
2048 8a:6a:5a:44:20:c8:3a:da:ab:dd:1c:12:2c:e4:20:0c  dev-servers (RSA)

And we're using `awk '{print $2}' to select just the 2nd column, which contains the fingerprint, i.e.:

8a:6a:5a:44:20:c8:3a:da:ab:dd:1c:12:2c:e4:20:0c

References

slm
  • 363,520
  • 117
  • 767
  • 871
5

You might have particular reasons to be using ssh-add explicitly, but if you just want "I want to be prompted for my passphrase the first time I use the key, but not after that," openssh has a simpler solution:

Put AddKeysToAgent yes in your .ssh/config file.

Nate
  • 193
  • 1
  • 4
1

I know this is an old question but I needed the answer today, and this was the right question. But maybe due to old key format - ssh-keygen answer variations wouldn't function for my case. Here's a variation using just the output from "ssh-add -l", which just lists out all managed keys. This will be checking if my path-to-my-key is a substring within that result. If so, all's good, otherwise add the key.

PATH_TO_MY_KEY="/path/to/special_key"
if [[ "$(ssh-add -l)" == *"${PATH_TO_MY_KEY}"* ]]; then 
        echo "Key is ready managed in ssh-agent "
else  
        echo "adding key for ${PATH_TO_MY_KEY} "
        ssh-add ${PATH_TO_MY_KEY} 
fi
Pete Kelley
  • 111
  • 3
0

ssh-add --apple-use-keychain FILE worked fine for me on Mac.
It still shows "Identity added: " lines but doesn't ask for passphrase.

From man page:

--apple-use-keychain When adding identities, each passphrase will also be stored in the user's keychain. When removing identities with -d, each passphrase will be removed from it.

Stephen Kitt
  • 411,918
  • 54
  • 1,065
  • 1,164
Ivan
  • 101
  • 2