Git 30
🔀 Git & GitHub · Modulo 5 · Lezione 30
Secrets e variabili d’ambiente 🔐
Gestire credenziali · GitHub Secrets · Variabili di repository · Sicurezza nelle pipeline
🔐 Il workflow ha bisogno di una API key per fare deploy. Dove la metti? Non nel codice — chiunque la vedrebbe. Non in un file di configurazione committato — finirebbe nella storia di Git per sempre. La soluzione: i GitHub Secrets, un vault crittografato integrato nel repository. I secrets vengono iniettati nel workflow a runtime e non sono mai visibili nei log. In questa lezione impari a gestire credenziali e configurazioni in modo sicuro.
🎯 Obiettivi della lezione
- Capire perché le credenziali non vanno mai nel codice
- Creare e usare GitHub Secrets nei workflow
- Creare e usare variabili di repository (non segrete)
- Capire la differenza tra secrets e variabili
- Usare i secrets in modo sicuro nei workflow
- Conoscere le best practice di sicurezza per le pipeline
📖 1. Teoria
1.1 — Il problema: credenziali nel codice
const API_KEY = “sk-a1b2c3d4e5f6”;
const DB_PASSWORD = “SuperSegreto123”;
# .env committato nel repo
API_KEY=sk-a1b2c3d4e5f6
DB_PASSWORD=SuperSegreto123
env:
API_KEY: ${{ secrets.API_KEY }}
# Il valore non è nel codice.
# È nel vault crittografato di GitHub.
# Viene iniettato a runtime.
# Non appare mai nei log.
⚠️ Se hai già committato una credenziale per errore: cambiare il file e ricommittare NON basta — il valore resta nella storia di Git. Devi: 1) revocare immediatamente la credenziale (genera una nuova API key), 2) usare git filter-branch o BFG Repo-Cleaner per rimuoverla dalla storia. La prevenzione è molto più semplice della cura.
1.2 — Secrets vs Variabili di repository
| Secrets | Variables | |
|---|---|---|
| Crittografati | Sì — una volta salvati, non puoi più vederli | No — visibili a chi ha accesso alle settings |
| Nei log | Mascherati con *** automaticamente | Visibili nei log |
| Accesso nel workflow | ${{ secrets.NOME }} | ${{ vars.NOME }} |
| Quando usarli | API key, token, password, chiavi SSH | URL del server, nome del progetto, versione, flag on/off |
| Dove configurarli | Settings → Secrets and variables → Actions → Secrets | Settings → Secrets and variables → Actions → Variables |
1.3 — Creare un secret
API_KEY, DEPLOY_TOKEN).${{ secrets.API_KEY }}.1.4 — Usare secrets e variabili nel workflow
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
– uses: actions/checkout@v4
– name: Info progetto
env:
NOME_PROGETTO: ${{ vars.NOME_PROGETTO }} ← variabile (non segreta)
AMBIENTE: ${{ vars.AMBIENTE }}
run: echo “Deploying $NOME_PROGETTO in $AMBIENTE”
– name: Deploy con token
env:
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }} ← secret (crittografato)
run: |
echo “Autenticazione con token…”
# Il token è disponibile come $DEPLOY_TOKEN
# Ma nei log appare come ***
echo “Token: $DEPLOY_TOKEN” ← nei log: “Token: ***”
📌 GitHub maschera automaticamente i secrets nei log. Se un comando stampa il valore di un secret (es. echo $DEPLOY_TOKEN), nei log appare ***. Questo impedisce che le credenziali vengano esposte accidentalmente. Ma attenzione: se codifichi il secret (es. base64), il valore codificato potrebbe non essere mascherato — evita manipolazioni non necessarie.
1.5 — Livelli di secrets: repository, environment, organization
| Livello | Dove si crea | Chi ne ha accesso | Caso d’uso |
|---|---|---|---|
| Repository ⭐ | Settings del singolo repo | Tutti i workflow di quel repo | API key specifica del progetto |
| Environment | Settings → Environments | Solo job che dichiarano quell’environment | Credenziali diverse per staging e produzione |
| Organization | Settings dell’organizzazione | Tutti i repo dell’organizzazione (o un sottoinsieme) | Credenziali condivise tra più progetti |
1.6 — Il token GITHUB_TOKEN: il secret automatico
GitHub fornisce automaticamente un token speciale chiamato GITHUB_TOKEN a ogni workflow. Non devi crearlo — è già disponibile come ${{ secrets.GITHUB_TOKEN }}. Serve per interagire con il repository stesso: creare release, commentare PR, pushare tag.
– name: Commenta la PR
if: github.event_name == ‘pull_request’
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: ‘✅ Tutti i test passati! Pronto per la review.’
})
1.7 — Best practice di sicurezza per le pipeline
permissions: write-all — specifica esattamente cosa serve.actions/checkout@v4 (tag) o meglio actions/checkout@abc123 (hash del commit) — non @main che può cambiare.💻 2. Esempi guidati
Esempio A — Creare secret e variabile, usarli nel workflow
MIO_SECRET. Value: valore-segreto-123. Add secret.NOME_PROGETTO. Value: Sito Classe 4A. Add variable.name: Demo secrets e variabili
on: workflow_dispatch ← manuale per test
jobs:
demo:
runs-on: ubuntu-latest
steps:
– name: Mostra variabile (visibile nei log)
run: echo “Progetto: ${{ vars.NOME_PROGETTO }}”
# Log: “Progetto: Sito Classe 4A”
– name: Mostra secret (mascherato nei log)
env:
IL_SECRET: ${{ secrets.MIO_SECRET }}
run: echo “Secret: $IL_SECRET”
# Log: “Secret: ***”
– name: Verifica che il secret esiste
env:
IL_SECRET: ${{ secrets.MIO_SECRET }}
run: |
if [ -z “$IL_SECRET” ]; then
echo “❌ Secret non configurato!”
exit 1
else
echo “✅ Secret presente (lunghezza: ${#IL_SECRET} caratteri)”
fi
Esempio B — Uso pratico: notifica con webhook
# Il WEBHOOK_URL è un secret (contiene un token)
– name: Notifica deploy completato
if: success()
env:
WEBHOOK: ${{ secrets.WEBHOOK_URL }}
run: |
curl -X POST “$WEBHOOK” \
-H “Content-Type: application/json” \
-d “{\”text\”: \”🚀 Deploy completato da ${{ github.actor }}\”}”
🏋️ 3. Esercizi
🟢 Esercizio 1 — Primo secret e variabile (Facile)
TEST_SECRET con valore CiaoSono Segreto.b) Crea una variabile:
PROGETTO con valore Il mio progetto.c) Crea il workflow dell’Esempio A (
workflow_dispatch).d) Avvia manualmente il workflow: Actions → “Demo secrets” → “Run workflow”.
e) Nei log: la variabile appare in chiaro? Il secret appare come
***?
🔵 Esercizio 2 — Secret mancante (Medio)
API_KEY… ma non creare il secret.b) Esegui il workflow. Cosa succede? (Il secret sarà una stringa vuota — il workflow potrebbe non fallire!)
c) Aggiungi uno step che verifica che il secret non sia vuoto (come nell’Esempio A, con
-z).d) Riesegui. Ora il workflow fallisce con un messaggio chiaro.
e) Crea il secret
API_KEY con un valore. Riesegui. Ora passa.
🟠 Esercizio 3 — Proteggi il .env (Medio)
.env in locale con: API_KEY=chiave-di-test.b) Verifica che
.env sia nel .gitignore. Se non c’è, aggiungilo.c) Fai
git status: il file .env non deve apparire tra i file da committare.d) Aggiungi uno step al tuo workflow CI che verifica che nessun file .env sia stato committato:
test ! -f .env || (echo "❌ .env trovato nel repo!" && exit 1)e) Committa e pusha. Il check passa? (Deve passare perché .env è nel gitignore.)
🟣 Esercizio 4 — Pipeline sicura completa (Difficile)
a) Crea le variabili:
PROGETTO (nome progetto), AMBIENTE (“produzione”).b) Crea i secrets:
DEPLOY_TOKEN (un valore di test).c) Job 1 — security: verifica che non ci siano file .env, cerca credenziali hardcoded nel codice con
grep.d) Job 2 — test: esegui i test. Usa la variabile
PROGETTO nel messaggio.e) Job 3 — deploy:
needs: [security, test]. Usa il secret DEPLOY_TOKEN. Solo su main. Verifica che il token non sia vuoto prima di procedere.f) Stampa un riepilogo: “Deploy di $PROGETTO in $AMBIENTE completato da ${{ github.actor }}”.
❓ 4. Quiz di verifica
1. Perché non devi mai committare credenziali nel repository?
Mostra risposta
Perché una volta committate, le credenziali restano nella storia di Git per sempre — anche se le rimuovi nel commit successivo, sono ancora accessibili con git log o git show. Se il repository è pubblico, chiunque può trovarle. Anche in repository privati, tutti i collaboratori le vedono. Esistono bot automatici che scansionano GitHub alla ricerca di credenziali esposte. L’unica soluzione dopo un commit accidentale è revocare la credenziale e rigenerarla. Prevenire (con secrets e .gitignore) è molto più semplice che curare.
2. Qual è la differenza tra ${{ secrets.X }} e ${{ vars.X }}?
Mostra risposta
secrets.X accede a un secret crittografato: il valore non è mai visibile (nemmeno nelle settings dopo il salvataggio) e viene mascherato con *** nei log. vars.X accede a una variabile di repository non crittografata: il valore è visibile nelle settings e appare in chiaro nei log. Usa secrets per dati sensibili (password, token, chiavi API) e variabili per configurazioni normali (nome progetto, URL, versioni).
3. Cos’è il GITHUB_TOKEN e a cosa serve?
Mostra risposta
È un token di autenticazione generato automaticamente da GitHub per ogni esecuzione di workflow. Non devi crearlo — è già disponibile come ${{ secrets.GITHUB_TOKEN }}. Serve per interagire con il repository corrente: creare release, commentare PR, gestire label, fare deploy su Pages. Ha permessi limitati al repository corrente e scade alla fine dell’esecuzione del workflow. È il modo più sicuro per autenticarsi con l’API di GitHub dall’interno di un workflow.
4. Cosa succede se un workflow usa ${{ secrets.X }} ma il secret X non esiste?
Mostra risposta
Il valore sarà una stringa vuota, non un errore. Il workflow non fallisce automaticamente — lo step viene eseguito con una variabile vuota. Questo può causare errori silenziosi (es. un’API call senza token che fallisce con un messaggio criptico). Per questo è importante aggiungere uno step di verifica: if [ -z "$MIO_SECRET" ]; then echo "Secret mancante!" && exit 1; fi. Questo fa fallire il workflow con un messaggio chiaro se il secret non è configurato.
5. Le PR da fork hanno accesso ai secrets del repository originale?
Mostra risposta
No — ed è una protezione intenzionale. Se un utente fa fork del tuo repository e apre una PR, il workflow che gira per quella PR non ha accesso ai tuoi secrets. Questo impedisce a un fork malevolo di creare un workflow che stampa o invia i tuoi secrets a un server esterno. È il motivo per cui i workflow su pull_request da fork hanno permessi molto limitati. I secrets sono disponibili solo per workflow attivati da collaboratori diretti del repository.
6. Perché è meglio iniettare un secret a livello di step piuttosto che di workflow?
Mostra risposta
Per il principio del minimo privilegio. Se inietti il secret a livello di workflow (env: globale), tutti gli step di tutti i job lo hanno disponibile — anche quelli che non ne hanno bisogno, come lo step di checkout o di linting. Se uno di quegli step ha una vulnerabilità, il secret potrebbe essere esposto. Iniettandolo solo nello step specifico che lo usa (es. lo step di deploy), limiti la superficie di attacco. Solo quel singolo step vede il secret.
📚 Riepilogo della lezione
- Mai credenziali nel codice — una volta committate, restano per sempre nella storia di Git
- Secrets = crittografati, mascherati nei log →
${{ secrets.NOME }} - Variables = configurazioni non segrete →
${{ vars.NOME }} - Dove crearli: Settings → Secrets and variables → Actions
- GITHUB_TOKEN: token automatico per interagire con il repo corrente
- 3 livelli: repository (progetto) · environment (staging/prod) · organization (multi-repo)
- Secret mancante = stringa vuota — verifica sempre che non sia vuoto
- PR da fork non hanno accesso ai secrets (protezione intenzionale)
- 7 regole: minimo privilegio, pinna versioni, inietta solo dove serve, .env nel gitignore
🎉 Congratulazioni! Hai completato il Modulo 5 — Automazione e CI/CD. Sai creare workflow, scrivere test automatici, fare deploy su GitHub Pages, integrare linter, e gestire credenziali in modo sicuro. Hai una pipeline CI/CD funzionante: push → lint → test → deploy. Dal prossimo modulo si entra nel mondo pratico degli studenti.
Prossima lezione →
Lezione 31 — Setup ambiente personale
Configurare il computer dello studente per lavorare con Git e GitHub.
SSH, editor, alias, personalizzazione del terminale.
Corso Git & GitHub · Per studenti e insegnanti · Lezione 30 di 45