Lezione 30 di 35

Git 30

🔀 Git & GitHub · Modulo 5 · Lezione 30

Secrets e variabili d’ambiente 🔐

Gestire credenziali · GitHub Secrets · Variabili di repository · Sicurezza nelle pipeline

⏱️ Durata stimata: 60–75 min 📊 Livello: Avanzato (Modulo 5) 🔧 Strumenti: GitHub (interfaccia web) · Terminale 📋 Prerequisiti: Lezioni 25–29 (workflow CI/CD)

🔐 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

❌ Mai fare questo
// script.js
const API_KEY = “sk-a1b2c3d4e5f6”;
const DB_PASSWORD = “SuperSegreto123”;

# .env committato nel repo
API_KEY=sk-a1b2c3d4e5f6
DB_PASSWORD=SuperSegreto123
Chiunque cloni il repo vede le credenziali. Se il repo è pubblico, il mondo intero le vede. Una volta committate, restano nella storia di Git per sempre — anche se le rimuovi dopo.
✅ Usa i secrets
# Nel workflow:
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.
Le credenziali sono al sicuro. Solo il workflow le vede, solo a runtime, solo in quel job.

⚠️ 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
La regola è semplice
Se qualcuno non dovrebbe vederlo →
Secret. Password, token API, chiavi private, credenziali di deploy, webhook URL con token.
Se è una configurazione normale →
Variable. Nome del progetto, URL del sito, versione di Node, flag feature on/off.

1.3 — Creare un secret

PASSO 1
Repository → Settings → nel menu a sinistra: “Secrets and variables” → “Actions”.
PASSO 2
Tab “Secrets” → “New repository secret”.
PASSO 3
Name: il nome del secret, tutto maiuscolo con underscore (es. API_KEY, DEPLOY_TOKEN).
PASSO 4
Secret: il valore (la API key, la password…). Una volta salvato, non potrai più vederlo — solo aggiornarlo o cancellarlo.
PASSO 5
Clicca “Add secret”. Il secret è disponibile nei workflow con ${{ secrets.API_KEY }}.

1.4 — Usare secrets e variabili nel workflow

name: Deploy con secrets
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
Per i progetti scolastici, i repository secrets sono sufficienti. Gli environment e organization secrets sono utili per organizzazioni più grandi.

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.

# Esempio: creare un commento automatico su una PR
– 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.’
})
Cosa può fare GITHUB_TOKEN
✅ Può
Leggere/scrivere il repository corrente. Creare release, commenti, label. Gestire PR e issue. Fare deploy su Pages (con permissions).
❌ Non può
Accedere ad altri repository. Chiamare API esterne. Modificare le settings del repo. Creare o cancellare repository.

1.7 — Best practice di sicurezza per le pipeline

Le 7 regole della sicurezza nelle pipeline
1
Mai credenziali nel codice. Nemmeno nel .env committato. Usa secrets per tutto ciò che è sensibile.
2
Minimo privilegio. Dai al workflow solo i permessi che servono. Non usare permissions: write-all — specifica esattamente cosa serve.
3
Pinna le versioni delle actions. Usa actions/checkout@v4 (tag) o meglio actions/checkout@abc123 (hash del commit) — non @main che può cambiare.
4
Non passare secrets a step che non ne hanno bisogno. Inietta il secret solo nello step specifico, non a livello di workflow.
5
Attenzione ai fork. Le PR da fork non hanno accesso ai secrets del repository originale — è una protezione intenzionale. Un fork malevolo non può rubare i tuoi secrets.
6
Aggiungi .env al .gitignore. Se usi file .env in locale per lo sviluppo, assicurati che non vengano committati.
7
Ruota le credenziali regolarmente. Cambia le API key periodicamente. Se sospetti una compromissione, ruota immediatamente.

💻 2. Esempi guidati

Esempio A — Creare secret e variabile, usarli nel workflow

1
Settings → Secrets and variables → Actions → Secrets → “New repository secret”. Name: MIO_SECRET. Value: valore-segreto-123. Add secret.
2
Tab Variables → “New repository variable”. Name: NOME_PROGETTO. Value: Sito Classe 4A. Add variable.
3
Crea il workflow che li usa (sotto).
# File: .github/workflows/secrets-demo.yml

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

# Scenario: inviare una notifica quando il deploy è completato
# 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)

a) Crea un repository secret: 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)

a) Crea un workflow che usa un secret chiamato 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)

a) Crea un file .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)

Costruisci una pipeline CI/CD con gestione completa dei secrets:

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

Cosa hai imparato oggi:
  • 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