diff --git a/CLAUDE.md b/CLAUDE.md index c68a0cd..2a8735b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -119,7 +119,8 @@ spiegala in una riga la prima volta. dal campo di testo della scheda `AWS > Nome Cognome`; crea l'accesso a Gitea, configura git, genera la chiave SSH e la carica sul suo profilo Gitea (da lì la prende l'amministratore: **non va mandata a nessuno**), - scrive i nomi dei server in `~/.ssh/config`. Gitea viene prima apposta: è lui a dire chi è la persona. Se sul PC + scrive i nomi dei server in `~/.ssh/config` e le loro chiavi in + `~/.ssh/known_hosts` (da `server.known_hosts`). Gitea viene prima apposta: è lui a dire chi è la persona. Se sul PC c'è già una chiave AWS **di un altro** (rimasta da chi lo usava, o copiata da un collega), lo script lo dice e chiede la sua: dille di avvisare l'amministratore, perché quella chiave va disattivata. Una chiave altrui @@ -158,4 +159,10 @@ Dillo alla persona, invece di farle scoprire un rosso inspiegabile: `~/.ssh/config` ci sono `oto-production` (la macchina nuova, dietro la VPN come staging, utente `admin.produzione`) e `oto-production-old` (quella dove girano ancora i siti). Chi ha il ruolo di rilascio entra in tutte e - due; per gli altri sono gialle tutte e due, ed è normale. + due; per gli altri sono gialle tutte e due, ed è normale. Giallo vuol + dire solo "il server non accetta la tua chiave": se una riga è rossa il + ruolo non c'entra, e `verifica.sh` dice cosa fare (di solito rilanciare + `configura.sh`, che registra le chiavi dei server). Se ssh chiede *Are you + sure you want to continue connecting?*, non far rispondere `yes` alla + cieca: le chiavi giuste sono in `server.known_hosts`, e le registra + `configura.sh`. diff --git a/configura.sh b/configura.sh index 69344fb..6eda04e 100755 --- a/configura.sh +++ b/configura.sh @@ -1,6 +1,6 @@ #!/bin/bash # -# PREPARA IL PC: accesso Gitea, accesso AWS, git, chiave SSH, nomi dei server. +# PREPARA IL PC: accesso Gitea, accesso AWS, git, chiave SSH, nomi e chiavi dei server. # # ./configura.sh # @@ -229,6 +229,23 @@ BLOCCO="$BLOCCO$FINE_BLOCCO" && mv "$CONFIG.nuovo" "$CONFIG" && chmod 600 "$CONFIG" ok "ssh $STAGING_NOME, ssh $PRODUZIONE_NOME e ssh $PRODUZIONE_VECCHIA_NOME: configurati" +# -------------------------------------------------------------------------- +titolo "5. Chiavi dei server in ~/.ssh/known_hosts" +# -------------------------------------------------------------------------- +# Quelle di server.known_hosts, lette sulle macchine: cosi' il primo +# collegamento non chiede "Are you sure you want to continue connecting?", +# e la risposta non dipende da chi e' in mezzo alla rete quel giorno. Quelle +# che c'erano per gli stessi nomi si tolgono prima (ssh-keygen ne lascia una +# copia in known_hosts.old): una vecchia rimasta li' farebbe dire a ssh che +# il server e' cambiato. +NOTI="$HOME/.ssh/known_hosts" +touch "$NOTI" && chmod 600 "$NOTI" +for H in $(grep -v '^#' server.known_hosts | awk 'NF {print $1}' | sort -u) ; do + ssh-keygen -R "$H" -f "$NOTI" > /dev/null 2>&1 +done +grep -v '^#' server.known_hosts | awk 'NF' >> "$NOTI" +ok "chiavi di $STAGING_NOME, $PRODUZIONE_NOME e $PRODUZIONE_VECCHIA_NOME registrate" + # -------------------------------------------------------------------------- titolo "Fatto" # -------------------------------------------------------------------------- diff --git a/server.known_hosts b/server.known_hosts new file mode 100644 index 0000000..e6f897f --- /dev/null +++ b/server.known_hosts @@ -0,0 +1,22 @@ +# Le chiavi dei tre server, lette sulle macchine stesse (/etc/ssh/ssh_host_*_key.pub) +# l'08/10/2026. configura.sh le scrive in ~/.ssh/known_hosts: senza, il primo +# collegamento chiede "Are you sure you want to continue connecting?" e +# verifica.sh, che non puo' rispondere, dice "non entri" anche a chi la chiave +# sul server ce l'ha. Se un server viene reinstallato, qui vanno quelle nuove. +# +# Il nome e' lo HostName di comune.sh, non il nome corto: e' quello che ssh cerca. + +# oto-staging +10.110.185.10 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEdXcmBdVpVzOeRBU7qG22eKxeqrupuhc/vQhlz3hATP +10.110.185.10 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBD6WAf8go/g6PPmAoNTbz53Khg/wFa3da6BPwnJj/bALJ0QBsmd0Dx7f446oQEia7CMGbAAKRjRdNgbSOaI3LNc= +10.110.185.10 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC5j0lk5bMjFDBzqzsh20sF2C/h8kkmekxI/QxsZxSlWT1WFnHCNa3GC0umSQmPKjoZF639dZUDsbE/3UbrwJICD03arQGlClEu/i7ct6eWPhPT71vtH0BAUcjYKWK9dst5dAG4cd1mGP2hCtYTGMXo7KnzPprUTHVytf3KOcRydwlaRchFhxXnzPBVaaIAAvF7++ZNq0krRvw3X5G1tOPCSViiR1w7jmeX/UiDaS/4avJ4TXzqDQG56C1VG/iAxjeImJLQxQAkQMz+J6RG+g7kDGlSpiO8COFLyqgfgDjVV2ZUDqgZdrVb6HOwnIx2eqRCvsRA1G7HHuYp1tECZEkUToGx0P4D9ee38FwKXJ34cslOtz494ZCKF9vvd99602WKQxudNZxKv6/gXdVeBS2UjLVCYfCX+aSvOGJBCheC8sy4dDTeeO9keGV/KfIHRQy27Lgr7tswBabASjTHiOFZvbAeETWi9wtwb0Eyg3PYZ3KAnc+zNx5maqeLnJxQ+9M= + +# oto-production +10.110.137.20 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAx5QWSl3YsMGEerqfYRhrXSy5PIdiHQW5rf/yiiLZhv +10.110.137.20 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBB41d5/XnLsNI4dYfx9IRnSOsFnazb6EvsLRKCotxSgXmrp7Ds+6cnoSB141+Tgj9xNA6NrfI3XuCfLQw1ZQYXw= +10.110.137.20 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCb1sVTJkOoPfUQvZv2TNRNXr180OYO+Ua2yLeDFRpqxevgGiQz7amDcrW1M2ouokkI8YTDBc6bzMXLrWRRI34gTZHe9jYp9kEs+G+1XZnsd2fVoKY7Ix7dV33IRPb4qXb9KT4k9XgnygCRSrjhQNtjO6aFy0IfGWZF75jxDeRs3AWs0bllrJ1TMX91sCxlaYvUkehDqkavocpl4praiQDXnwdDFKiqGfQAFhcTLVfBetNIBx+T1Fvu/8FA24rogVcECkqdxO8PKpEA90rwQt0KwzIqHVcrbxP9vKlddX37spf4wSeJMo/T7w7iU5b1q5PKhxgWxHCRP9Hf09laYdDAiwZs1F9Sv6KWbVGKzhkQvVZF1nzWfPPo9UeyRDRpF5TORi0eeXUem2LprG/msJG1AJX7K0GN4QyuozzQqQr5NKFY7JjlxWS5Q+pZKCvJdaJU6Tvtc8oE8qtIerjdnCnz9eE3bfjPnMwmsPh8dSyGSK97g49Z/W8YWnug96CYCnU= + +# oto-production-old +vps-production.oto-farm.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKjqHPAj0yN1PdWbIvJPAc1i/M2fGE6LH9W0ggNOqUda +vps-production.oto-farm.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBKCfOvVGQPwctSwrTEPalC8fdhAawKVOlv/uIfIljZTCxX25+u7vw2+NlYhq7ETrSQvLAzaf3cOlbu2/qXUB3OA= +vps-production.oto-farm.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDtikmWxIRAi73fvYXxyqji84qkSt3G2Psqe+ynnwe0iQ6bvf0elYU4HOIdta7MtJjAiRHeXkH7hvlAorXL9+nagzA+2AVs2YM0rF4mTQO6thpUOPh0U7kHAj7WAJMjogJBJ3wA9A1N1VMHdOPc1trK7OTGJ6BCFKVjglsaBh2n/v5Hl4wpTORTpXNbwpxBfr9TtXtqYb/csSURi2LZEewkLZFrWkKyhHWTmiSSHl8QEjgf+/hoafXeAJ7bxv0lZ2h5QGuyV6KN3A9lQ4omFE+2ug+pqQH31Xn934W5Bwt6QI/yjOjcwn4yMKr2wfQRk85qkIESovmH3I2g8ivY8cB3y358cBsz1LMQ2+NJlzbvVrqDAFLPAgBPNeU442bosvX92gIgXWRxhwHjoCc1/BaoyNidPw7aQ6teDb0HicwKfXAAaS9pamhMjdqz4uGiC0iiPbhrxUX/UOviTh8Oy4AniHFxSj3Afs1k5JBNUotXc2o2ZOsuj3Sy4XCUTZtj6LE= diff --git a/verifica.sh b/verifica.sh index e0c4b24..487bbd6 100755 --- a/verifica.sh +++ b/verifica.sh @@ -68,33 +68,48 @@ porta_aperta () { kill "$sveglia" 2> /dev/null return "$esito" } +# Un tentativo, e il motivo se non si entra: "non entri" da solo faceva +# pensare ai ruoli anche quando mancava la chiave del server su questo PC. +# Esce 0 se si entra, 1 se e' la chiave tua, 2 se e' altro (scritto in MOTIVO). +entra () { + local errore + errore="$(ssh -o BatchMode=yes -o ConnectTimeout=8 "$1" true 2>&1 > /dev/null)" && return 0 + case "$errore" in + *"Permission denied"*) return 1 ;; + *"Host key verification failed"*|*"IDENTIFICATION HAS CHANGED"*) + MOTIVO="questo PC non ha la chiave giusta del server: rilancia ./configura.sh, che la registra" ;; + *"Connection closed"*|*"Connection reset"*) + MOTIVO="il server ha chiuso la connessione: dopo troppi tentativi sbagliati la chiude per qualche minuto, aspetta e rilancia" ;; + *) MOTIVO="ssh dice: $(printf '%s\n' "$errore" | grep -v '^\*\*' | tail -1)" ;; + esac + return 2 +} if porta_aperta "$STAGING_HOST" 22 ; then ok "VPN attiva (staging raggiungibile)" - if ssh -o BatchMode=yes -o ConnectTimeout=8 "$STAGING_NOME" true 2> /dev/null ; then - ok "entri su staging ($STAGING_NOME)" - else - rosso "staging non accetta la tua chiave: l'amministratore deve ancora aggiungerla" - fi + entra "$STAGING_NOME" ; ESITO=$? + if [ "$ESITO" = "0" ] ; then ok "entri su staging ($STAGING_NOME)" + elif [ "$ESITO" = "1" ] ; then rosso "staging non accetta la tua chiave: l'amministratore deve ancora aggiungerla" + else rosso "staging ($STAGING_NOME): $MOTIVO" ; fi else rosso "staging non raggiungibile: la VPN e' accesa?" fi # Le produzioni sono due finche' i siti non sono migrati tutti. La nuova sta # dietro la stessa VPN di staging. Un tentativo solo per macchina: la nuova # chiude le porte per un po' a chi sbaglia il login piu' volte di fila. +# Solo il rifiuto della chiave dipende dal ruolo: il resto si sistema da qui. +NON_AUTORIZZATO="il server non accetta la tua chiave (normale se non hai il ruolo di rilascio; se ce l'hai, chiedi a chi amministra di aggiungerla)" if porta_aperta "$PRODUZIONE_HOST" 22 ; then - if ssh -o BatchMode=yes -o ConnectTimeout=8 "$PRODUZIONE_NOME" true 2> /dev/null ; then - ok "entri in produzione ($PRODUZIONE_NOME)" - else - attento "produzione ($PRODUZIONE_NOME): non entri (normale se non hai il ruolo di rilascio, o se la tua chiave non e' ancora stata aggiunta)" - fi + entra "$PRODUZIONE_NOME" ; ESITO=$? + if [ "$ESITO" = "0" ] ; then ok "entri in produzione ($PRODUZIONE_NOME)" + elif [ "$ESITO" = "1" ] ; then attento "produzione ($PRODUZIONE_NOME): $NON_AUTORIZZATO" + else rosso "produzione ($PRODUZIONE_NOME): $MOTIVO" ; fi else attento "produzione ($PRODUZIONE_NOME): non raggiungibile (sta dietro la VPN, come staging)" fi -if ssh -o BatchMode=yes -o ConnectTimeout=8 "$PRODUZIONE_VECCHIA_NOME" true 2> /dev/null ; then - ok "entri nella produzione vecchia ($PRODUZIONE_VECCHIA_NOME)" -else - attento "produzione vecchia ($PRODUZIONE_VECCHIA_NOME): non entri (normale se non hai il ruolo di rilascio, o se la tua chiave non e' ancora stata aggiunta)" -fi +entra "$PRODUZIONE_VECCHIA_NOME" ; ESITO=$? +if [ "$ESITO" = "0" ] ; then ok "entri nella produzione vecchia ($PRODUZIONE_VECCHIA_NOME)" +elif [ "$ESITO" = "1" ] ; then attento "produzione vecchia ($PRODUZIONE_VECCHIA_NOME): $NON_AUTORIZZATO" +else rosso "produzione vecchia ($PRODUZIONE_VECCHIA_NOME): $MOTIVO" ; fi titolo "Risultato" if [ "$ROSSI" = "0" ] ; then