diff --git a/CLAUDE.md b/CLAUDE.md index 9b1a1c2..1905162 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,82 +1,112 @@ # Istruzioni per Claude: preparare il PC di chi arriva -Chi apre questo repository è una persona **nuova in OTO**, spesso non -tecnica, al primo giorno. Il tuo compito: portarla da "ho solo le password -provvisorie" a "`./verifica.sh` è tutto verde e ho scaricato i miei -progetti". Parla semplice, un passo alla volta, e controlla ogni passo prima -di passare al successivo. +Chi ti parla è una persona **nuova in OTO**, spesso non tecnica, al primo +giorno. Ti ha scritto qualcosa come «prepara il mio PC per OTO» e ha in mano +solo le password provvisorie che le ha mandato l'amministratore. **Il lavoro +lo fai tu**: installi i programmi, lanci i controlli, le dici cosa cliccare. +Lei fa solo quello che tu non puoi fare: i login nel browser, e scrivere i +propri segreti nel terminale. Parla semplice, un passo alla volta, e controlla +ogni passo prima del successivo. La spiegazione per le persone sta in `https://servizi.oto-farm.com/nuovo-collaboratore.html`: non contraddirla. ## Regole che non si negoziano -1. **Mai un segreto in chat.** Token Gitea, chiave e segreto AWS, password, - chiavi private: non chiederli e, se la persona li incolla, dille di - rigenerarli (un token finito in chat va considerato esposto). I segreti - li chiede `configura.sh` nel terminale, con l'input nascosto. -2. **Gli script che chiedono qualcosa li lancia la persona**, in un suo - terminale, non tu: tu non puoi rispondere al posto suo a un prompt - nascosto. Tu lanci solo `./verifica.sh` e i comandi di sola lettura. -3. **Non creare accessi e non chiederli.** Utenti AWS, utenti Gitea, VPN, - chiavi sui server li crea un amministratore (con gli script di `_OTO_IT`). - Se manca qualcosa, dillo con precisione ("serve che l'amministratore ti - aggiunga al repository X") e vai avanti col resto. +1. **Mai un segreto in chat.** Password, chiavi AWS, token, chiavi private: + non chiederli. Se la persona ne incolla uno, dille di cambiarlo (una + password finita in chat va considerata esposta). I segreti li chiede + `configura.sh` nel terminale, con l'input nascosto. +2. **`configura.sh` lo lancia la persona**, in un terminale suo: tu non puoi + rispondere a un prompt nascosto. Diglielo con le parole giuste per dove + lavora (vedi sotto). Tu lanci tutto il resto: installazioni, `verifica.sh`, + `progetti.sh`, i comandi di sola lettura. +3. **Non creare accessi e non chiederli.** Utenti AWS e Gitea, VPN, chiavi + sui server li crea un amministratore. Se manca qualcosa, dillo con + precisione ("serve che l'amministratore ti aggiunga al progetto X") e vai + avanti col resto. 4. **Un "accesso negato" di AWS non è un guasto**: è il ruolo della persona. Lo dici e prosegui. 5. **Non copiare file da altri PC** e non proporlo: se a un progetto manca un segreto, va messo su AWS SSM da un amministratore. -## Prima domanda: qual è il suo caso +## Dove sei -Chiedilo subito, con parole semplici, perché cambia quanti passi servono: +- **Visual Studio Code con l'estensione Claude Code**, oppure **l'app Claude + nella scheda Code**: lavori sul PC vero, puoi installare. Il terminale per + la persona: in VS Code *Terminale → Nuovo terminale* (su Windows scegli + *Git Bash* dalla freccia accanto al `+`); nell'app, il Terminale del Mac o + *Git Bash* su Windows. +- **Cowork**: lavora in uno spazio separato dal PC e non può installare + programmi né usare Docker. Diglielo e falle aprire VS Code o la scheda Code. + +Capisci da solo se sei su Windows o su Mac (`uname -s`, `$OS`): non chiederlo. + +## Prima domanda: qual è il suo caso - **modifica testi e immagini solo dal pannello** (o dall'area di amministrazione di WordPress/Drupal): non le serve niente di questo - repository. Diglielo e fermati: le basta l'utente del pannello. -- **crea o modifica pagine con Claude, senza scrivere codice**: servono AWS, - Gitea e Claude. **Salta VPN e chiave SSH** (passi 5 e 6): servono solo per - pubblicare siti Drupal o WordPress. `verifica.sh` segnerà rossi VPN e SSH: - dille che per lei è normale. + repository. Diglielo e fermati. +- **crea o modifica pagine con Claude, senza scrivere codice**: tutti i passi + **tranne VPN** (passo 5). `verifica.sh` segnerà rossi VPN e staging: dille + che per lei è normale. - **sviluppa**: tutti i passi. -Con chi non sviluppa niente gergo: se una parola tecnica serve (token, -terminale, push), spiegala in una riga la prima volta che la usi. +Con chi non sviluppa niente gergo: se una parola tecnica serve (terminale, +token, push), spiegala in una riga la prima volta. ## L'ordine -1. **Programmi**: `./verifica.sh` dice cosa manca tra git, Docker, AWS CLI. - Guida l'installazione per il sistema della persona (Linux, macOS o - Windows con WSL). -2. **AWS**, nel browser: entrare nella console con la password provvisoria, - sceglierne una nuova, attivare l'MFA, poi *nome in alto a destra → - Security credentials → Create access key* (uso: CLI). Poi nel terminale - `aws configure`, con regione `eu-central-1`. Controllo: - `aws sts get-caller-identity` deve mostrare `nome.cognome`. -3. **Gitea**, nel browser: cambiare la password provvisoria, poi - *Impostazioni → Applicazioni → Genera token* con permesso di scrittura - sui repository. -4. **`./configura.sh`**, nel terminale della persona: salva il token Gitea, - configura git, genera la chiave SSH, scrive i nomi dei server in - `~/.ssh/config`. -5. **La chiave SSH pubblica**: `configura.sh` la stampa. La persona la manda - all'amministratore (si può mandare in chat: è la parte pubblica). Ribadisci - che il file **senza** `.pub` non esce dal PC. -6. **VPN**: importare il file ricevuto (Linux: *Impostazioni → Rete → VPN → - + → Importa da file*). +1. **Programmi.** Servono git, la AWS CLI, Docker, curl e ssh. Installa + quello che manca: + - **Windows**: `winget install -e --id Git.Git`, `Amazon.AWSCLI`, + `Docker.DockerDesktop`. Docker vuole WSL2: `wsl --install`, poi un + riavvio. Windows chiederà conferma (finestra *Sì/No*): avvisa prima che + arriva e che va cliccato *Sì*. Dopo un'installazione il `PATH` nuovo lo + vede solo un terminale nuovo. + - **Mac**: prima Homebrew. Il suo installatore chiede la password del Mac, + quindi quel comando lo lancia la persona nel Terminale: + `/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"`. + Poi tu: `brew install git awscli` e `brew install --cask docker`. + - Docker Desktop va **aperto una volta** a mano e le condizioni accettate: + finché non lo si fa, `docker info` non risponde. +2. **Questo repository sul PC**, se ci stai parlando da un link e non da + dentro la cartella: `git clone https://git.oto-farm.com/admin/_OTO_IT_onboard.git + ~/Work/workspace/oto/_OTO_IT_onboard` (è pubblico, non ha segreti) e da lì + continui. +3. **I login nel browser**, li fa lei: + - **AWS** (indirizzo e password provvisoria nel messaggio dell'amministratore): + scegliere la password nuova, attivare l'MFA (*il suo nome in alto a destra + → Security credentials → Assign MFA device*, con un'app sul telefono), poi + nella stessa pagina *Create access key*, uso *Command Line Interface*. + **Lasciare aperta la pagina**: la chiave segreta si vede una volta sola. + - **Gitea** (`https://git.oto-farm.com`): entrare con la password provvisoria + e sceglierne una nuova. Nient'altro: il token lo crea lo script. +4. **`./configura.sh`**, nel terminale della persona. Chiede i due pezzi della + chiave AWS e utente e password di Gitea; 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`. Poi fa chiudere la pagina di AWS. +5. **VPN** (solo chi sviluppa): installare il client e importare il file + arrivato dal fornitore. +6. **Dirlo all'amministratore**: «ho finito la configurazione». È il segnale + per mettere la sua chiave SSH sui server; finché non lo fa, staging resta + rosso. 7. **`./verifica.sh`**: tutto verde, o un elenco preciso di cosa manca e a chi chiederlo. -8. **`./progetti.sh`**: scarica i progetti che la persona vede su Gitea. - Poi, in ogni progetto: `./start.sh` per i progetti con pannello, - `bin/local-init.sh` per Drupal e WordPress. Il resto lo spiega il - `CLAUDE.md` di quel progetto. +8. **`./progetti.sh`**: scarica i progetti che la persona vede su Gitea (lo + lanci tu con i nomi: `./progetti.sh nome1 nome2`). Poi, in ogni progetto: + `./start.sh` per i progetti con pannello, `bin/local-init.sh` per Drupal e + WordPress. Il resto lo spiega il `CLAUDE.md` di quel progetto. -## Stato al 29/09/2026: cosa non è ancora pronto +## Stato al 30/09/2026: cosa non è ancora pronto Dillo alla persona, invece di farle scoprire un rosso inspiegabile: -- **le chiavi SSH personali non sono ancora installate sui server**: il - controllo SSH resterà rosso finché l'amministratore non aggiunge la sua; +- **questo percorso non è ancora stato fatto da nessuno su Windows o su Mac**: + gli script sono bash (su Windows girano in Git Bash) e sono stati provati su + Linux. Se qualcosa non va, scrivi con precisione cosa è successo: serve per + correggerlo; - **alcuni progetti non hanno ancora tutti i segreti su SSM**: in locale qualcosa può mancare; - la produzione nuova non esiste ancora: in `~/.ssh/config` c'è quella vecchia. diff --git a/README.md b/README.md index ec9b3e1..5069110 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,30 @@ # Primo giorno in OTO: preparare il PC Questo repository serve una volta sola: prepara il tuo PC per lavorare sui -progetti OTO. Non contiene segreti. I segreti dei progetti li scaricano i -progetti stessi da AWS, con il tuo accesso personale. - -La spiegazione completa (cosa sono i quattro accessi, chi li crea, cosa fai -quando qualcuno se ne va) è sul portale dei servizi, alla voce **Chi arriva → -Accessi e primo giorno**: `https://servizi.oto-farm.com/nuovo-collaboratore.html`. - -## Prima di iniziare ti servono - -Te li manda l'amministratore: - -- la **password provvisoria di AWS** (utente `nome.cognome`); -- la **password provvisoria di Gitea**, con cui hai scaricato questo repository; -- il **file della VPN**, che arriva dal fornitore della VPN. - -Sul PC ti servono installati **git**, **Docker**, la **AWS CLI** e -**Claude Code**. +progetti OTO. È pubblico e non contiene segreti: i segreti dei progetti li +scaricano i progetti stessi da AWS, con il tuo accesso personale. ## Come si usa -```bash -git clone https://git.oto-farm.com/admin/_OTO_IT_onboard.git -cd _OTO_IT_onboard -claude -``` +1. Installa **Visual Studio Code** e, dentro, l'estensione **Claude Code** + (oppure l'app **Claude**, scheda *Code*). Entra con l'invito di Claude. +2. Scrivi a Claude: -e a Claude scrivi: **«configura la mia postazione»**. Ti guida passo per passo -e controlla ogni passo. + > Prepara il mio PC per OTO: https://git.oto-farm.com/admin/_OTO_IT_onboard -Se preferisci fare da solo: +Il resto lo fa Claude: installa i programmi e ti dice cosa cliccare. Tu fai i +login nel browser e scrivi le tue chiavi nel terminale quando te lo chiede. + +## Una regola + +**Password, chiavi e token non si scrivono mai in chat, nemmeno a Claude.** +Quando serve un segreto, `configura.sh` lo chiede nel terminale senza +mostrarlo a schermo. + +La spiegazione completa è su +`https://servizi.oto-farm.com/nuovo-collaboratore.html`. + +## Senza Claude ```bash ./configura.sh # chiede quello che serve, una cosa per volta @@ -38,11 +32,5 @@ Se preferisci fare da solo: ./progetti.sh # scarica i progetti a cui hai accesso ``` -Puoi rilanciarli quante volte vuoi: quello che è già a posto non viene -toccato. - -## Una regola - -**Token, password e chiavi private non si scrivono mai in chat, nemmeno a -Claude.** Quando serve un segreto, `configura.sh` lo chiede nel terminale senza -mostrarlo a schermo. +Si possono rilanciare quante volte si vuole: quello che è già a posto non +viene toccato. diff --git a/configura.sh b/configura.sh index 01d5c2a..b883b8d 100755 --- a/configura.sh +++ b/configura.sh @@ -1,11 +1,12 @@ #!/bin/bash # -# PREPARA IL PC: token Gitea, git, chiave SSH, nomi dei server. +# PREPARA IL PC: accesso AWS, accesso Gitea, git, chiave SSH, nomi dei server. # # ./configura.sh # -# Si lancia nel proprio terminale (chiede il token Gitea con l'input -# nascosto). Si puo' rilanciare: quello che e' gia' a posto non viene toccato. +# Si lancia nel proprio terminale: chiede le chiavi AWS e la password Gitea +# 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 @@ -15,36 +16,70 @@ cd "$(dirname "$0")" || exit 1 # -------------------------------------------------------------------------- titolo "1. AWS" # -------------------------------------------------------------------------- +# La chiave di accesso la crea la persona dalla console (Security +# credentials → Create access key): qui la si incolla una volta e finisce in +# ~/.aws/credentials, dove la leggono la AWS CLI e gli script dei progetti. 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 ok "accesso AWS: ${IDENTITA##*/}" else - attento "AWS non ancora configurato. Nel terminale:" - echo " aws configure (regione: $AWS_REGIONE)" - echo " con la chiave che crei dalla console AWS (Security credentials)." + echo " Serve la tua chiave di accesso AWS, due pezzi. La crei nella console AWS:" + echo " il tuo nome in alto a destra → Security credentials → Create access key (uso: CLI)." + 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:]')" + 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 + ok "accesso AWS: ${IDENTITA##*/}" + else + male "AWS non accetta questa chiave: controlla di aver copiato i due pezzi interi, o creane un'altra." + fi fi # -------------------------------------------------------------------------- titolo "2. 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. +# Gitea rifiuta la password provvisoria finche' non la si cambia nel browser. UTENTE="$(utente_gitea)" if [ -n "$UTENTE" ] ; then ok "token Gitea gia' salvato (utente $UTENTE)" else - echo " Incolla il token Gitea (Impostazioni → Applicazioni → Genera token)." - echo " Non si vede mentre lo incolli, ed e' normale." - read -r -s -p " Token: " TOKEN ; echo - TOKEN="$(printf '%s' "$TOKEN" | tr -d '[:space:]')" - mkdir -p "$(dirname "$TOKEN_GITEA_FILE")" - chmod 700 "$(dirname "$TOKEN_GITEA_FILE")" - ( umask 077 ; printf '%s\n' "$TOKEN" > "$TOKEN_GITEA_FILE" ) - UTENTE="$(utente_gitea)" - if [ -n "$UTENTE" ] ; then - ok "token valido, salvato in $TOKEN_GITEA_FILE (utente $UTENTE)" + echo " Se non l'hai ancora fatto, entra su $GITEA_URL e cambia la password provvisoria." + read -r -p " Il tuo utente Gitea (nome.cognome): " UTENTE_DATO + read -r -s -p " La tua password Gitea (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\",\"read: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 provvisoria: entra su $GITEA_URL, cambiala e rilancia." + elif [ "$CODICE" = "401" ] ; then + male "utente o password sbagliati: rilancia e riprova." else - rm -f "$TOKEN_GITEA_FILE" - male "Gitea non accetta questo token: controlla di averlo copiato intero, o generane un altro." + male "Gitea non ha creato l'accesso (HTTP ${CODICE:-nessuna risposta}): rilancia, o chiedi all'amministratore." fi fi @@ -75,12 +110,26 @@ else ssh-keygen -q -t ed25519 -f "$CHIAVE_SSH" -C "$COMMENTO" -N "" \ && ok "chiave creata: $CHIAVE_SSH" fi -if [ -f "$CHIAVE_SSH.pub" ] ; then - echo - echo " Manda all'amministratore QUESTA riga (e' la parte pubblica, si puo' mandare in chat):" - echo - echo " $(cat "$CHIAVE_SSH.pub")" - echo +# 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 diff --git a/verifica.sh b/verifica.sh index e2187f0..ceaef17 100755 --- a/verifica.sh +++ b/verifica.sh @@ -54,8 +54,15 @@ if [ -f "$CHIAVE_SSH" ] ; then ok "$CHIAVE_SSH" ; else rosso "chiave mancante: r titolo "VPN e server" # La VPN si riconosce da una cosa sola: staging, che sta su rete privata, -# risponde sulla porta SSH. -if timeout 5 bash -c "exec 3<>/dev/tcp/$STAGING_HOST/22" 2> /dev/null ; then +# risponde sulla porta SSH. Niente `timeout`: sul Mac non c'e'. +porta_aperta () { + bash -c "exec 3<>/dev/tcp/$1/$2" 2> /dev/null & local pid=$! + ( sleep 5 ; kill "$pid" 2> /dev/null ) & local sveglia=$! + wait "$pid" 2> /dev/null ; local esito=$? + kill "$sveglia" 2> /dev/null + return "$esito" +} +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)"