Ce que vous voyez
Dans un script avec BatchMode=yes, ou sans terminal pour poser la question, il n'y a qu'une seule ligne :
Host key verification failed.
Avec StrictHostKeyChecking=yes, une raison s'affiche au-dessus :
No ED25519 host key is known for server and you have requested strict checking.
Host key verification failed.
Git ajoute ses propres lignes, qui ne signifient pas que le dépôt est introuvable :
Host key verification failed.
fatal: Could not read from remote repository.
Déterminer de quel cas il s'agit
Lancez ceci avec le même utilisateur que la commande qui échoue :
ssh-keygen -F server
Pour un serveur sur un autre port, l'entrée est enregistrée avec des crochets :
ssh-keygen -F '[server]:2222'
- Aucune sortie : l'hôte est inconnu de cet utilisateur. Voir la cause 1 et la cause 2.
- Une ligne s'affiche, et l'erreur montre un grand avertissement REMOTE HOST IDENTIFICATION HAS CHANGED : voir la cause 3.
Cause 1 : le serveur n'est pas dans known_hosts
Dans un terminal, SSH vous demanderait de confirmer l'empreinte. BatchMode=yes interdit les questions, et une tâche sans terminal n'a personne à qui demander : SSH échoue donc. Ajoutez la clé à l'avance.
Récupérez la clé, puis comparez-la avec celle du serveur avant de lui faire confiance :
ssh-keyscan -t ed25519 server > server.hostkey
ssh-keygen -lf server.hostkey
Sur le serveur lui-même, ou depuis une console fournie par votre hébergeur :
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
Si les deux empreintes correspondent, installez la clé :
mkdir -p ~/.ssh && chmod 700 ~/.ssh
cat server.hostkey >> ~/.ssh/known_hosts
Pour un port autre que 22, utilisez ssh-keyscan -p 2222 -t ed25519 server. ssh-keyscan seul ne prouve rien, car il accepte tout ce qui répond à cette adresse. C'est la comparaison qui rend l'opération sûre. Les hébergeurs publient leurs empreintes, par exemple GitHub dans la page indiquée dans les sources.
En CI
Enregistrez la ligne vérifiée dans une variable de CI et écrivez-la au début du job, plutôt que de scanner à chaque exécution :
mkdir -p ~/.ssh && chmod 700 ~/.ssh
printf '%s\n' "$KNOWN_HOSTS" >> ~/.ssh/known_hosts
accept-new et no
StrictHostKeyChecking=accept-new enregistre une clé jamais vue et refuse toujours une clé qui a changé. Il fait confiance à la première connexion sans vérification, ce qui est un compromis acceptable pour une machine jetable sur un réseau de confiance. Évitez StrictHostKeyChecking=no : il laisse aussi la connexion se poursuivre quand la clé a changé, c'est-à-dire dans la situation pour laquelle cette vérification existe.
Ce que contient chaque ligne du fichier : known_hosts expliqué.
Cause 2 : un autre utilisateur ou un autre HOME
known_hosts appartient à un utilisateur. Il fonctionne dans votre terminal et échoue dans la tâche quand celle-ci s'exécute sous un autre compte : sudo ssh utilise le fichier de root, et cron, les builds Docker et les runners de CI ont leur propre dossier personnel, souvent vide à chaque exécution.
whoami
echo "$HOME"
ssh -G server | grep -iE '^(userknownhostsfile|stricthostkeychecking) '
La dernière commande affiche les fichiers que SSH lira pour cet hôte, sans se connecter. Installez la clé pour cet utilisateur, ou indiquez à la tâche un fichier que vous contrôlez :
ssh -o UserKnownHostsFile=/path/to/known_hosts -o BatchMode=yes user@server true
Cause 3 : la clé enregistrée est différente
La sortie commence alors par cet avertissement, et les deux dernières lignes sont :
Host key for server has changed and you have requested strict checking.
Host key verification failed.
Une réinstallation ou un nouveau serveur à la même adresse est la raison la plus courante, mais c'est aussi à cela que ressemble une interception. accept-new ne permet pas de passer outre. Comparez les empreintes comme indiqué plus haut, et seulement ensuite supprimez l'ancienne entrée :
ssh-keygen -R server
Avec github.com, c'est fréquent : GitHub a remplacé sa clé d'hôte RSA en mars 2023, donc une ancienne ligne enregistrée échoue maintenant. Supprimez-la avec ssh-keygen -R github.com, puis ajoutez les clés que GitHub publie, depuis la page citée dans les sources.
Plus de détails sur ce cas dans REMOTE HOST IDENTIFICATION HAS CHANGED.
Questions
Que signifie Host key verification failed ?
SSH n'a pas pu confirmer l'identité du serveur et s'est arrêté. Soit le serveur n'est pas dans known_hosts et personne ne pouvait répondre à la question, soit sa clé diffère de celle enregistrée.
StrictHostKeyChecking=no est-il une solution sûre en CI ?
Non. Il accepte aussi une clé modifiée. Installez la clé vérifiée dans known_hosts, ou utilisez accept-new sur des machines jetables dans un réseau de confiance.
Pourquoi cela marche dans mon terminal mais échoue dans cron ?
known_hosts appartient à un utilisateur. Cron, sudo et les runners de CI utilisent un autre utilisateur ou un autre dossier personnel, où l'entrée enregistrée n'existe pas.
Pourquoi git affiche Host key verification failed avec GitHub ?
Soit github.com n'est pas dans known_hosts pour l'utilisateur qui lance git, soit une ligne RSA enregistrée avant mars 2023 s'y trouve encore. Supprimez-la avec ssh-keygen -R github.com et ajoutez les clés de la page des empreintes de GitHub.
Sources
- ssh_config(5), StrictHostKeyChecking
- ssh-keyscan(1), manuel OpenBSD
- ssh-keygen(1), manuel OpenBSD
- Empreintes des clés SSH de GitHub