Marco Laterza, amministratore, si e' visto dire "produzione: non entri (normale se non hai il ruolo di rilascio...)" con la chiave gia' sul server: al suo PC mancava la chiave host della macchina nuova, e con BatchMode=yes ssh rifiuta un host sconosciuto senza provare la chiave. configura.sh scrive in ~/.ssh/known_hosts le chiavi di server.known_hosts, lette sulle tre macchine l'08/10/2026, togliendo prima quelle vecchie per gli stessi nomi. verifica.sh legge l'errore di ssh: giallo solo se il server rifiuta la chiave personale, rosso con il rimedio per chiave host mancante o cambiata e per il blocco dopo troppi tentativi. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
253 lines
13 KiB
Bash
Executable File
253 lines
13 KiB
Bash
Executable File
#!/bin/bash
|
|
#
|
|
# PREPARA IL PC: accesso Gitea, accesso AWS, git, chiave SSH, nomi e chiavi dei server.
|
|
#
|
|
# ./configura.sh
|
|
#
|
|
# Si lancia nel proprio terminale: chiede la password Gitea e la chiave AWS
|
|
# con l'input nascosto, e un assistente AI non puo' rispondere al posto tuo.
|
|
# Si puo' rilanciare: quello che e' gia' a posto non viene toccato.
|
|
# Non crea accessi: quelli li crea un amministratore, qui si usano.
|
|
|
|
set -u
|
|
cd "$(dirname "$0")" || exit 1
|
|
. ./comune.sh
|
|
|
|
# --------------------------------------------------------------------------
|
|
titolo "1. Gitea"
|
|
# --------------------------------------------------------------------------
|
|
# Alla persona si chiede la password, non un token: il token lo crea lo
|
|
# script con l'API di Gitea, cosi' non c'e' da cercarlo fra le impostazioni.
|
|
# La password e' nella scheda LastPass "Gitea > nome.cognome", condivisa da
|
|
# chi amministra (nella mail non c'e', apposta): dal 07/10/2026 Gitea non
|
|
# obbliga piu' a cambiarla. Chi e' stato creato prima invece deve ancora
|
|
# cambiarla nel browser, e Gitea gli risponde 403: lo si dice sotto.
|
|
UTENTE="$(utente_gitea)"
|
|
# I token creati prima del 07/10/2026 hanno read:organization e non
|
|
# write:organization, che serve a creare i progetti nell'organizzazione oto.
|
|
# Lo si chiede a Gitea con una creazione volutamente incompleta (senza nome):
|
|
# a un token senza lo scope risponde 403 citandolo, a uno giusto 422, e in
|
|
# nessuno dei due casi crea niente. Il token vecchio si mette da parte e se ne
|
|
# crea uno nuovo qui sotto; quello vecchio si cancella dal proprio profilo.
|
|
if [ -n "$UTENTE" ] && curl -s --max-time 10 -X POST -H "Authorization: token $(token_gitea)" \
|
|
-H 'Content-Type: application/json' -d '{}' "$GITEA_URL/api/v1/orgs/oto/repos" \
|
|
| grep -q 'write:organization' ; then
|
|
mv "$TOKEN_GITEA_FILE" "$TOKEN_GITEA_FILE.vecchio"
|
|
attento "il token Gitea salvato non puo' creare progetti nell'organizzazione: ne creo uno nuovo"
|
|
echo " (quello vecchio, in $TOKEN_GITEA_FILE.vecchio, cancellalo dal tuo profilo Gitea:"
|
|
echo " Impostazioni -> Applicazioni)"
|
|
UTENTE=""
|
|
fi
|
|
if [ -n "$UTENTE" ] ; then
|
|
ok "token Gitea gia' salvato (utente $UTENTE)"
|
|
else
|
|
echo " L'utente Gitea e' nella mail \"I tuoi accessi OTO\" che ti ha mandato chi"
|
|
echo " amministra. La password no: e' su LastPass, nella scheda \"Gitea > nome.cognome\""
|
|
echo " col tuo utente (per esempio \"Gitea > sara.locatelli\"), campo Password."
|
|
read -r -p " Il tuo utente Gitea (dalla mail, riga utente Gitea): " UTENTE_DATO
|
|
read -r -s -p " La tua password Gitea, dalla scheda LastPass \"Gitea > $UTENTE_DATO\" (non si vede, ed e' normale): " PASSWORD ; echo
|
|
# utente:password passano a curl da stdin, non dalla riga di comando
|
|
# (che chiunque sul PC vede con ps). Virgolette e \ vanno protette.
|
|
PASSWORD_CURL="$(printf '%s:%s' "$UTENTE_DATO" "$PASSWORD" | sed 's/[\\"]/\\&/g')"
|
|
NOME_TOKEN="oto-$(hostname | tr -dc 'A-Za-z0-9-' | head -c 20)-$(date +%Y%m%d%H%M%S)"
|
|
RISPOSTA="$(printf 'user = "%s"\n' "$PASSWORD_CURL" \
|
|
| curl -s --max-time 15 -K - -w '\n%{http_code}' -X POST \
|
|
-H 'Content-Type: application/json' \
|
|
-d "{\"name\":\"$NOME_TOKEN\",\"scopes\":[\"write:repository\",\"write:user\",\"write:organization\"]}" \
|
|
"$GITEA_URL/api/v1/users/$UTENTE_DATO/tokens")"
|
|
unset PASSWORD PASSWORD_CURL
|
|
CODICE="${RISPOSTA##*$'\n'}"
|
|
TOKEN="$(printf '%s' "${RISPOSTA%$'\n'*}" | sed -n 's/.*"sha1":"\([^"]*\)".*/\1/p')"
|
|
if [ "$CODICE" = "201" ] && [ -n "$TOKEN" ] ; then
|
|
mkdir -p "$(dirname "$TOKEN_GITEA_FILE")"
|
|
chmod 700 "$(dirname "$TOKEN_GITEA_FILE")"
|
|
( umask 077 ; printf '%s\n' "$TOKEN" > "$TOKEN_GITEA_FILE" )
|
|
unset TOKEN
|
|
UTENTE="$(utente_gitea)"
|
|
ok "accesso Gitea salvato in $TOKEN_GITEA_FILE (utente $UTENTE)"
|
|
elif [ "$CODICE" = "403" ] ; then
|
|
male "Gitea chiede prima di cambiare la password: entra su $GITEA_URL (Sign in), scegline una nuova, salvala su LastPass e rilancia."
|
|
elif [ "$CODICE" = "401" ] ; then
|
|
male "utente o password sbagliati: rilancia e riprova."
|
|
else
|
|
male "Gitea non ha creato l'accesso (HTTP ${CODICE:-nessuna risposta}): rilancia, o chiedi all'amministratore."
|
|
fi
|
|
fi
|
|
|
|
# git: chi sei, e come si ricorda le credenziali. Il token vale anche come
|
|
# password per git: lo si scrive una volta in ~/.git-credentials.
|
|
if [ -n "$UTENTE" ] ; then
|
|
[ -n "$(git config --global user.name)" ] || git config --global user.name "$UTENTE"
|
|
if [ -z "$(git config --global user.email)" ] ; then
|
|
read -r -p " La tua email di lavoro, quella @oto.agency (firma le tue modifiche al codice): " EMAIL
|
|
[ -n "$EMAIL" ] && git config --global user.email "$EMAIL"
|
|
fi
|
|
[ -n "$(git config --global credential.helper)" ] || git config --global credential.helper store
|
|
CREDENZIALI="$HOME/.git-credentials"
|
|
if ! grep -q "@$GITEA_HOST" "$CREDENZIALI" 2> /dev/null ; then
|
|
( umask 077 ; printf 'https://%s:%s@%s\n' "$UTENTE" "$(token_gitea)" "$GITEA_HOST" >> "$CREDENZIALI" )
|
|
fi
|
|
ok "git configurato ($(git config --global user.name) <$(git config --global user.email)>)"
|
|
fi
|
|
|
|
# --------------------------------------------------------------------------
|
|
titolo "2. AWS"
|
|
# --------------------------------------------------------------------------
|
|
# La chiave di accesso la crea chi amministra insieme all'utente, e la
|
|
# persona la trova su LastPass, nel campo di testo della scheda
|
|
# "AWS > Nome Cognome": qui la si incolla
|
|
# una volta e finisce in ~/.aws/credentials, dove la leggono la AWS CLI e gli
|
|
# script dei progetti. Se non ce l'ha (e' arrivata prima, o l'ha persa), se
|
|
# ne crea una dalla console: la strada e' scritta qui sotto.
|
|
#
|
|
# Viene dopo Gitea apposta: e' Gitea, con la password, a dire chi e' la
|
|
# persona. Una chiave gia' presente sul PC non basta a dirlo: puo' essere
|
|
# rimasta da chi lo usava prima, o copiata da un collega, e allora tutto
|
|
# quello che la persona fa su AWS risulterebbe fatto da un altro.
|
|
chiedi_chiave_aws () {
|
|
echo " Serve la tua chiave di accesso AWS, due pezzi: Access key ID e Secret access key."
|
|
# Il nome della scheda e' quello per esteso: sara.locatelli -> Sara Locatelli.
|
|
SCHEDA_AWS="AWS > $(printf '%s' "${UTENTE:-nome.cognome}" | awk -F. '{for (i = 1; i <= NF; i++) printf "%s%s", (i > 1 ? " " : ""), toupper(substr($i, 1, 1)) substr($i, 2)}')"
|
|
echo " Non sono nella mail: li trovi su LastPass, nella scheda \"$SCHEDA_AWS\" che ti"
|
|
echo " ha condiviso chi amministra, nel campo di testo (righe Access key ID e Secret"
|
|
echo " access key). Se li' non c'e', la crei tu nella console AWS:"
|
|
echo " 1. entra su $AWS_CONSOLE (IAM user, utente, password e"
|
|
echo " codice a due fattori dalla stessa scheda LastPass);"
|
|
echo " 2. il tuo nome in alto a destra → Security credentials;"
|
|
echo " 3. riquadro Access keys → Create access key → Command Line Interface (CLI),"
|
|
echo " spunta la conferma → Next → Create access key."
|
|
echo " I due pezzi sono nella pagina che si apre (Retrieve access keys): la Secret"
|
|
echo " si vede cliccando Show, e una volta sola. Se hai chiuso quella pagina,"
|
|
echo " cancella la chiave dallo stesso riquadro e creane un'altra."
|
|
echo " Non si vede mentre la incolli, ed e' normale."
|
|
read -r -s -p " Access key ID (inizia con AKIA): " CHIAVE_ID ; echo
|
|
read -r -s -p " Secret access key: " CHIAVE_SEGRETA ; echo
|
|
CHIAVE_ID="$(printf '%s' "$CHIAVE_ID" | tr -d '[:space:]')"
|
|
CHIAVE_SEGRETA="$(printf '%s' "$CHIAVE_SEGRETA" | tr -d '[:space:]')"
|
|
if [ -z "$CHIAVE_ID" ] || [ -z "$CHIAVE_SEGRETA" ] ; then
|
|
male "chiave non inserita: rilancia quando ce l'hai." ; unset CHIAVE_SEGRETA ; return 1
|
|
fi
|
|
aws configure set aws_access_key_id "$CHIAVE_ID"
|
|
aws configure set aws_secret_access_key "$CHIAVE_SEGRETA"
|
|
aws configure set region "$AWS_REGIONE"
|
|
unset CHIAVE_SEGRETA
|
|
if ! IDENTITA="$(aws sts get-caller-identity --query Arn --output text 2> /dev/null)" ; then
|
|
male "AWS non accetta questa chiave: controlla di aver copiato i due pezzi interi, senza scambiarli, e rilancia."
|
|
elif [ -n "$UTENTE" ] && [ "${IDENTITA##*/}" != "$UTENTE" ] ; then
|
|
male "questa chiave e' di ${IDENTITA##*/}, non tua ($UTENTE): usa quella della tua scheda LastPass \"$SCHEDA_AWS\", e rilancia."
|
|
else
|
|
ok "accesso AWS: ${IDENTITA##*/}"
|
|
fi
|
|
}
|
|
|
|
if ! c_e aws ; then
|
|
male "AWS CLI non installata: installala e rilancia questo script."
|
|
elif IDENTITA="$(aws sts get-caller-identity --query Arn --output text 2> /dev/null)" ; then
|
|
if [ -z "$UTENTE" ] || [ "${IDENTITA##*/}" = "$UTENTE" ] ; then
|
|
ok "accesso AWS: ${IDENTITA##*/}"
|
|
else
|
|
attento "su questo PC c'e' gia' una chiave AWS, ma e' di ${IDENTITA##*/}, non tua ($UTENTE)."
|
|
echo " Usandola, tutto quello che fai su AWS risulterebbe fatto da ${IDENTITA##*/}."
|
|
echo " La sostituisco con la tua. Avvisa l'amministratore: quella chiave e' uscita"
|
|
echo " dal PC di ${IDENTITA##*/} e va disattivata."
|
|
chiedi_chiave_aws
|
|
fi
|
|
else
|
|
chiedi_chiave_aws
|
|
fi
|
|
|
|
# --------------------------------------------------------------------------
|
|
titolo "3. Chiave SSH"
|
|
# --------------------------------------------------------------------------
|
|
if [ -f "$CHIAVE_SSH" ] ; then
|
|
ok "chiave gia' presente: $CHIAVE_SSH"
|
|
else
|
|
mkdir -p "$HOME/.ssh" && chmod 700 "$HOME/.ssh"
|
|
COMMENTO="${UTENTE:-$(whoami)}@oto"
|
|
ssh-keygen -q -t ed25519 -f "$CHIAVE_SSH" -C "$COMMENTO" -N "" \
|
|
&& ok "chiave creata: $CHIAVE_SSH"
|
|
fi
|
|
# La parte pubblica va sul proprio profilo Gitea: e' da li' che
|
|
# l'amministratore la prende per metterla sui server, senza che la persona
|
|
# debba mandarla a nessuno.
|
|
if [ -f "$CHIAVE_SSH.pub" ] && [ -n "$UTENTE" ] ; then
|
|
PUBBLICA="$(awk '{print $1" "$2}' "$CHIAVE_SSH.pub")"
|
|
if curl -s --max-time 10 -H "Authorization: token $(token_gitea)" "$GITEA_URL/api/v1/user/keys" \
|
|
| grep -qF "${PUBBLICA#* }" ; then
|
|
ok "chiave pubblica gia' sul tuo profilo Gitea"
|
|
else
|
|
CODICE="$(curl -s -o /dev/null --max-time 10 -w '%{http_code}' -X POST \
|
|
-H "Authorization: token $(token_gitea)" -H 'Content-Type: application/json' \
|
|
-d "{\"title\":\"oto $(hostname | tr -dc 'A-Za-z0-9-')\",\"key\":\"$PUBBLICA\"}" \
|
|
"$GITEA_URL/api/v1/user/keys")"
|
|
if [ "$CODICE" = "201" ] ; then
|
|
ok "chiave pubblica caricata sul tuo profilo Gitea: l'amministratore la prende da li'"
|
|
else
|
|
attento "non riesco a caricare la chiave su Gitea (HTTP $CODICE). Manda all'amministratore questa riga, e' la parte pubblica:"
|
|
echo " $(cat "$CHIAVE_SSH.pub")"
|
|
fi
|
|
fi
|
|
echo " Il file $CHIAVE_SSH, senza .pub, non esce mai da questo PC."
|
|
fi
|
|
|
|
# --------------------------------------------------------------------------
|
|
titolo "4. Nomi dei server in ~/.ssh/config"
|
|
# --------------------------------------------------------------------------
|
|
# Un blocco fra due segni, riscritto intero a ogni giro: cosi' quando cambia
|
|
# un server basta rilanciare. Un nome gia' definito fuori dal blocco non si
|
|
# tocca (e' una configurazione tua).
|
|
CONFIG="$HOME/.ssh/config"
|
|
touch "$CONFIG" && chmod 600 "$CONFIG"
|
|
INIZIO="# >>> OTO (scritto da _OTO_IT_onboard/configura.sh) >>>"
|
|
FINE_BLOCCO="# <<< OTO <<<"
|
|
# Confronto esatto, non una regex: il segno contiene "/" e "(".
|
|
FUORI="$(awk -v i="$INIZIO" -v f="$FINE_BLOCCO" '$0 == i {dentro=1; next} $0 == f {dentro=0; next} !dentro' "$CONFIG")"
|
|
|
|
# La chiave con ~ e non col percorso intero: su Windows Git Bash scriverebbe
|
|
# /c/Users/..., che l'OpenSSH di Windows (quello di VS Code) non capisce.
|
|
CHIAVE_CONFIG="~${CHIAVE_SSH#"$HOME"}"
|
|
BLOCCO="$INIZIO"
|
|
for VOCE in "$STAGING_NOME $STAGING_HOST $STAGING_UTENTE" \
|
|
"$PRODUZIONE_NOME $PRODUZIONE_HOST $PRODUZIONE_UTENTE" \
|
|
"$PRODUZIONE_VECCHIA_NOME $PRODUZIONE_VECCHIA_HOST $PRODUZIONE_VECCHIA_UTENTE" ; do
|
|
set -- $VOCE
|
|
if printf '%s\n' "$FUORI" | grep -qE "^Host[[:space:]]+$1([[:space:]]|\$)" ; then
|
|
attento "$1 e' gia' definito in $CONFIG: lo lascio com'e'"
|
|
continue
|
|
fi
|
|
BLOCCO="$BLOCCO
|
|
Host $1
|
|
HostName $2
|
|
User $3
|
|
IdentitiesOnly yes
|
|
IdentityFile $CHIAVE_CONFIG
|
|
"
|
|
done
|
|
BLOCCO="$BLOCCO$FINE_BLOCCO"
|
|
|
|
{ printf '%s\n' "$FUORI" | sed -e :a -e '/^\n*$/{$d;N;ba' -e '}' ; echo ; printf '%s\n' "$BLOCCO" ; } > "$CONFIG.nuovo" \
|
|
&& 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"
|
|
# --------------------------------------------------------------------------
|
|
echo " Ora: se su LastPass hai la scheda \"OTO > VPN HK ${UTENTE:-nome.cognome}\", accendi la VPN (file e credenziali sono li'); poi torna da Claude."
|