Cosa vedi
In uno script con BatchMode=yes, o senza un terminale su cui chiedere, c'è una sola riga:
Host key verification failed.
Con StrictHostKeyChecking=yes sopra c'è anche il motivo:
No ED25519 host key is known for server and you have requested strict checking.
Host key verification failed.
Git aggiunge righe sue, che non vogliono dire che il repository manca:
Host key verification failed.
fatal: Could not read from remote repository.
Capire in quale caso sei
Esegui questo con lo stesso utente che esegue il comando che fallisce:
ssh-keygen -F server
Per un server su un'altra porta, la voce è salvata con le parentesi quadre:
ssh-keygen -F '[server]:2222'
- Nessun output: l'host è sconosciuto a questo utente. Vedi causa 1 e causa 2.
- Viene stampata una riga e l'errore mostra il grande avviso REMOTE HOST IDENTIFICATION HAS CHANGED: vedi causa 3.
Causa 1: il server non è in known_hosts
In un terminale, SSH ti chiederebbe di confermare l'impronta. BatchMode=yes vieta le domande, e un job senza terminale non ha nessuno a cui chiedere, quindi SSH fallisce. Aggiungi la chiave in anticipo.
Raccogli la chiave e confrontala con quella sul server prima di fidarti:
ssh-keyscan -t ed25519 server > server.hostkey
ssh-keygen -lf server.hostkey
Sul server stesso, o da una console del tuo provider:
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
Se le due impronte coincidono, installa la chiave:
mkdir -p ~/.ssh && chmod 700 ~/.ssh
cat server.hostkey >> ~/.ssh/known_hosts
Per una porta diversa dalla 22, usa ssh-keyscan -p 2222 -t ed25519 server. ssh-keyscan da solo non prova nulla, perché accetta qualunque cosa risponda a quell'indirizzo. È il confronto a renderlo sicuro. I servizi di hosting pubblicano le loro impronte, per esempio GitHub nella pagina indicata nelle fonti.
In CI
Salva la riga verificata come variabile di CI e scrivila all'inizio del job, invece di fare la scansione a ogni esecuzione:
mkdir -p ~/.ssh && chmod 700 ~/.ssh
printf '%s\n' "$KNOWN_HOSTS" >> ~/.ssh/known_hosts
accept-new e no
StrictHostKeyChecking=accept-new salva una chiave mai vista prima e rifiuta comunque una chiave cambiata. Si fida della prima connessione senza verificarla, un compromesso accettabile per una macchina usa e getta su una rete di cui ti fidi. Evita StrictHostKeyChecking=no: lascia proseguire la connessione anche quando la chiave è cambiata, cioè proprio la situazione per cui esiste questo controllo.
Cosa contiene ogni riga del file: known_hosts spiegato.
Causa 2: un altro utente o un altro HOME
known_hosts appartiene a un utente. Funziona nel tuo terminale e fallisce nel job quando il job gira come qualcun altro: sudo ssh usa il file di root, e cron, le build Docker e i runner di CI hanno una loro cartella home, spesso vuota a ogni esecuzione.
whoami
echo "$HOME"
ssh -G server | grep -iE '^(userknownhostsfile|stricthostkeychecking) '
L'ultimo comando stampa quali file SSH leggerà per quell'host, senza connettersi. Installa la chiave per quell'utente, oppure indica al job un file che controlli tu:
ssh -o UserKnownHostsFile=/path/to/known_hosts -o BatchMode=yes user@server true
Causa 3: la chiave salvata è diversa
L'output inizia allora con questo avviso, e le ultime due righe sono:
Host key for server has changed and you have requested strict checking.
Host key verification failed.
Una reinstallazione o un nuovo server allo stesso indirizzo è il motivo più comune, ma è anche l'aspetto di un'intercettazione. accept-new non la supera. Confronta le impronte come mostrato sopra e solo dopo rimuovi la vecchia voce:
ssh-keygen -R server
Con github.com succede spesso: GitHub ha sostituito la sua chiave host RSA a marzo 2023, quindi una vecchia riga salvata ora fallisce. Rimuovila con ssh-keygen -R github.com, poi aggiungi le chiavi che GitHub pubblica, dalla pagina nelle fonti.
Altro su questo caso in REMOTE HOST IDENTIFICATION HAS CHANGED.
Domande
Cosa significa Host key verification failed?
SSH non ha potuto confermare l'identità del server e si è fermato. O il server non è in known_hosts e nessuno poteva rispondere alla domanda, o la sua chiave è diversa da quella salvata.
StrictHostKeyChecking=no è una soluzione sicura in CI?
No. Accetta anche una chiave cambiata. Installa la chiave verificata in known_hosts, oppure usa accept-new su macchine usa e getta in una rete di cui ti fidi.
Perché funziona nel mio terminale ma fallisce in cron?
known_hosts appartiene a un utente. Cron, sudo e i runner di CI usano un altro utente o un'altra home, dove la voce salvata non c'è.
Perché git dice Host key verification failed con GitHub?
O github.com non è in known_hosts per l'utente che esegue git, o c'è ancora una riga RSA salvata prima di marzo 2023. Rimuovila con ssh-keygen -R github.com e aggiungi le chiavi dalla pagina dei fingerprint di GitHub.
Fonti
- ssh_config(5), StrictHostKeyChecking
- ssh-keyscan(1), manuale OpenBSD
- ssh-keygen(1), manuale OpenBSD
- Impronte delle chiavi SSH di GitHub