Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

Problem: I have some 20-30 ssh-agent identities. Most servers refuse authentication with Too many failed authentications, as SSH usually won't let me try 20 different keys to log in.

At the moment, I am specifying the identity file for every host manually, using the IdentityFile and the IdentitiesOnly directive, so that SSH will only try one key file, which works.

Unfortunately, this stops working as soon as the original keys aren't available anymore. ssh-add -l shows me the correct paths for every key file, and they match with the paths in .ssh/config, but it doesn't work. Apparently, SSH selects the indentity by public key signature and not by file name, which means that the original files have to be available so that SSH can extract the public key.

There are two problems with this:

  • it stops working as soon as I unplug the flash drive holding the keys
  • it renders agent forwarding useless as the key files aren't available on the remote host

Of course, I could extract the public keys from my identity files and store them on my computer, and on every remote computer I usually log into. This doesn't looks like a desirable solution, though.

What I need is a possibility to select an identity from ssh-agent by file name, so that I can easily select the right key using .ssh/config or by passing -i /path/to/original/key, even on a remote host I SSH'd into. It would be even better if I could "nickname" the keys so that I don't even have to specify the full path.

share|improve this question
1  
Why do you need many ssh identities? If it is to avoid one compromised private key giving access to all your accounts, then why do you hold all of them on a single flash drive? It is not the first time I hear of problems related to managing multiple ssh identities but never had a chance to ask why they are needed. –  Dmitri Chubarov Jun 24 '12 at 12:07
    
Never said all of them are on one flash drive. –  leoluk Jun 24 '12 at 13:14
2  
@DmitriChubarov One possible application for multiple ssh identities is a authorized_keys file that, depending on the key used, executes different commands, without ever permitting direct shell access. –  Tobias Kienzler Oct 17 '12 at 17:47
add comment

2 Answers

up vote 2 down vote accepted

Guess I'll have to answer my own question, as there doesn't seem to be any way to request an identity by file name.

I wrote a quick-and-dirty Python scripts which creates a public key file in .ssh/fingerprints for every key the agent holds. I can then specify this file, which contains no secret key, using IdentityFile and SSH will pick the right identity from the SSH agent. Works perfectly fine, and allows me to use the agent for as many private keys I wish.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""Dumps all public keys held by ssh-agent and stores them in ~/.ssh/fingerprints/, so that
they can be identified using the IdentityFile directive.

"""

import sys, os
import stat
import re
import envoy

RE_MATCH_FILENAME = re.compile(r'([^\\/:*?"<>|\r\n]+)\.\w{2,}$', re.IGNORECASE)

if os.getuid() == 0:
    USERNAME = os.environ['SUDO_USER']
else:
    USERNAME = os.environ['USER']

def error(message):
    print "Error:", message
    sys.exit(1)

def main():
    keylist = envoy.run('ssh-add -L').std_out.strip('\n').split('\n')

    if len(keylist) < 1:
        error("SSH-Agent holds no indentities")

    for key in keylist:
        crypto, ckey, name = key.split(' ')
        filename = os.path.join(os.environ['HOME'], '.ssh/fingerprints',
                  RE_MATCH_FILENAME.search(name).group(1)+'.pub')

        with open(filename, 'w') as f:
            print "Writing %s ..." % filename
            f.write(key)

        envoy.run('chmod 600 %s' % filename)
        envoy.run('chown %s %s' % (USERNAME, filename))


if __name__ == '__main__':
    main()
share|improve this answer
    
Nice job, I'll try this soon –  Tobias Kienzler Oct 17 '12 at 18:53
add comment

Run

ssh-add -L | gawk ' { print $2 > $3 ".pub" } '

on the remote machine to automatically generate all the public key files (assuming the public keys in your .ssh/config are named privateKeyFileName.pub and no inconsitent paths are involved). Call chown $USER .ssh/* for your sudo case.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.