Choisissez l'identité de ssh-agent par nom de fichier

9

Problème: j'ai 20 à 30 ssh-agentidentités. La plupart des serveurs refusent l'authentification avec Too many failed authentications, car SSH ne me laisse généralement pas essayer 20 clés différentes pour me connecter.

Pour le moment, je spécifie le fichier d'identité pour chaque hôte manuellement, en utilisant la IdentityFileet la IdentitiesOnlydirective, afin que SSH n'essaye qu'un seul fichier de clé, ce qui fonctionne.

Malheureusement, cela cesse de fonctionner dès que les clés d'origine ne sont plus disponibles. ssh-add -lme montre les chemins corrects pour chaque fichier clé, et ils correspondent aux chemins d'accès .ssh/config, mais cela ne fonctionne pas. Apparemment, SSH sélectionne l'indentation par signature de clé publique et non par nom de fichier, ce qui signifie que les fichiers d'origine doivent être disponibles pour que SSH puisse extraire la clé publique.

Il y a deux problèmes avec ceci:

  • il cesse de fonctionner dès que je débranche le lecteur flash en maintenant les touches
  • cela rend le transfert d'agent inutile car les fichiers de clés ne sont pas disponibles sur l'hôte distant

Bien sûr, je pouvais extraire les clés publiques de mes fichiers d'identité et les stocker sur mon ordinateur et sur chaque ordinateur distant auquel je me connecte habituellement. Cependant, cela ne semble pas être une solution souhaitable.

Ce dont j'ai besoin est une possibilité de sélectionner une identité de ssh-agent par nom de fichier, afin que je puisse facilement sélectionner la bonne clé en utilisant .ssh/configou en passant -i /path/to/original/key, même sur un hôte distant dans lequel je me suis connecté. Ce serait encore mieux si je pouvais "surnommer" les clés afin que je n'ai même pas besoin de spécifier le chemin complet.

leoluk
la source
1
Pourquoi avez-vous besoin de nombreuses identités ssh? Si c'est pour éviter qu'une clé privée compromise ne donne accès à tous vos comptes, alors pourquoi les conservez-vous tous sur une seule clé USB? Ce n'est pas la première fois que j'entends parler de problèmes liés à la gestion de plusieurs identités ssh, mais je n'ai jamais eu la chance de demander pourquoi elles étaient nécessaires.
Dmitri Chubarov
Je n'ai jamais dit qu'ils étaient tous sur un seul lecteur flash.
leoluk
3
@DmitriChubarov Une application possible pour plusieurs identités ssh est un authorized_keysfichier qui, selon la clé utilisée, exécute différentes commandes, sans jamais permettre un accès direct au shell.
Tobias Kienzler

Réponses:

8

Je suppose que je vais devoir répondre à ma propre question, car il ne semble pas y avoir de moyen de demander une identité par nom de fichier.

J'ai écrit un script Python rapide et sale qui crée un fichier de clé publique .ssh/fingerprintspour chaque clé détenue par l'agent. Je peux alors spécifier ce fichier, qui ne contient pas de clé secrète, en utilisant IdentityFileet SSH choisira la bonne identité de l'agent SSH. Fonctionne parfaitement bien et me permet d'utiliser l'agent pour autant de clés privées que je souhaite.

#!/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()
leoluk
la source
Beau travail, je vais essayer bientôt
Tobias Kienzler
3

Courir

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

sur la machine distante pour générer automatiquement tous les fichiers de clé publique (en supposant que les clés publiques de votre .ssh/configsont nommées privateKeyFileName.pubet qu'aucun chemin incohérent n'est impliqué). Appelez chown $USER .ssh/*pour votre sudocas.

Tobias Kienzler
la source
1

Reprenant de la solution acceptée, et en supposant que vous voulez juste réutiliser l'identité utilisée pour accéder au serveur initial, alors quelque chose comme:

Host github.com
    IdentitiesOnly yes
    IdentityFile ~/.ssh/authorized_keys

est suffisant.

cagney
la source
ça ne marche pas pour moi. Lorsque le fichier d'identité n'a qu'une seule clé publique - cela fonctionne, mais pas lorsqu'il est multiple.
ygrek