Salta al contenuto principale

4 - Gestione dei Segreti nelle Pipeline CI/CD

Best practices per la gestione sicura di secrets, API keys e credenziali nelle pipeline CI/CD: GitHub Secrets, Vault e environment variables.

Cosa ne pensi di questo articolo?

4 - Gestione dei Segreti nelle Pipeline CI/CD
DevOps FrontendFoto:Nimit KansagraPexels

In Breve

Best practices per la gestione sicura di secrets, API keys e credenziali nelle pipeline CI/CD: GitHub Secrets, Vault e environment variables.

Introduzione: perchè la Gestione dei Segreti e Critica

Una singola API key esposta in un repository pubblico può costare migliaia di euro in pochi minuti. Bot automatizzati scandagliano costantemente GitHub alla ricerca di credenziali committate per errore: chiavi AWS, token Firebase, password di database. La gestione dei segreti non e un optional nella pipeline CI/CD, e una necessità assoluta.

In questo articolo esploreremo in profondità come gestire i segreti in modo sicuro nelle pipeline CI/CD, partendo da GitHub Secrets fino ad arrivare a soluzioni enterprise come HashiCorp Vault. Ogni strategia viene illustrata con esempi pratici specifici per applicazioni Angular.

Cosa Imparerai in Questo Articolo

  • perchè la gestione dei segreti e fondamentale per la sicurezza
  • Come funzionano GitHub Secrets (repository, environment, organization)
  • La differenza tra variabili d'ambiente e segreti
  • Come gestire la sicurezza dei file .env
  • La differenza tra segreti runtime e build-time
  • Strategie di rotazione dei segreti
  • Soluzioni vault: HashiCorp Vault, AWS Secrets Manager, GCP Secret Manager
  • Come prevenire il leak di segreti con git-secrets e pre-commit hook
  • Best practice per audit trail e compliance

1. GitHub Secrets: La Base della Gestione Segreti

GitHub offre tre livelli di segreti, ognuno con un ambito di visibilità diverso. Comprendere quando usare ciascun livello e fondamentale per una gestione efficace.

Livelli di GitHub Secrets

Livello Ambito Caso d'Uso Chi Può Accedere
Repository Singolo repository API key specifiche del progetto Tutti i workflow del repo
Environment Ambiente specifico (staging, production) Credenziali di produzione Solo workflow con environment specificato
Organization Tutti i repository dell'organizzazione Token condivisi (npm, Docker Hub) Repository selezionati dall'admin

Configurare i Segreti nel Repository

Per aggiungere un segreto al repository, vai su Settings > Secrets and variables > Actions > New repository secret. Ecco come usarli nei workflow:


# Accedere ai segreti del repository
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Deploy to Firebase
        env:
          FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }}
        run: firebase deploy --token "$FIREBASE_TOKEN"

      # I segreti vengono automaticamente mascherati nei log
      - name: Debug (il segreto viene mostrato come ***)
        run: echo "Token is ${{ secrets.FIREBASE_TOKEN }}"
      

Segreti per Ambiente

I segreti per ambiente sono la scelta migliore per separare le credenziali di staging e produzione. Richiedono la keyword environment nel job:


# Segreti per ambiente
jobs:
  deploy-staging:
    runs-on: ubuntu-latest
    environment: staging
    steps:
      - name: Deploy to staging
        env:
          # Usa il segreto dell'ambiente "staging"
          API_KEY: ${{ secrets.API_KEY }}
          DEPLOY_URL: ${{ vars.DEPLOY_URL }}
        run: |
          echo "Deploying to $DEPLOY_URL"
          firebase deploy --token "${{ secrets.FIREBASE_TOKEN }}"

  deploy-production:
    runs-on: ubuntu-latest
    environment: production
    needs: deploy-staging
    steps:
      - name: Deploy to production
        env:
          # Usa il segreto dell'ambiente "production" (diverso!)
          API_KEY: ${{ secrets.API_KEY }}
        run: firebase deploy --token "${{ secrets.FIREBASE_TOKEN }}"
      

Protezione degli Ambienti di Produzione

Configura sempre le Environment Protection Rules per l'ambiente production: richiedi l'approvazione manuale di un reviewer prima del deploy, limita i branch che possono deployare a production (solo main), e abilita il timer di attesa per avere un buffer di sicurezza.

2. Variabili d'Ambiente vs Segreti

E importante distinguere tra variabili d'ambiente e segreti. GitHub Actions supporta entrambi ma con caratteristiche diverse:

Variabili vs Segreti

Caratteristica Variables (vars) Secrets (secrets)
Visibilità nei log Visibili in chiaro Mascherati con ***
Crittografia No Si (Libsodium sealed box)
Leggibili dopo la creazione Si No (solo sovrascrivibili)
Uso tipico URL, nomi ambiente, feature flags Token, password, chiavi API

# Esempio: variabili vs segreti
jobs:
  build:
    runs-on: ubuntu-latest
    environment: production
    env:
      # Variabili: configurazione non sensibile
      API_URL: ${{ vars.API_URL }}
      APP_NAME: ${{ vars.APP_NAME }}
      ENABLE_ANALYTICS: ${{ vars.ENABLE_ANALYTICS }}
    steps:
      - uses: actions/checkout@v4
      - name: Build with environment config
        env:
          # Segreti: informazioni sensibili
          FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }}
          ANALYTICS_KEY: ${{ secrets.ANALYTICS_KEY }}
        run: |
          echo "Building for $API_URL"
          npm run build -- --configuration=production
      

3. Sicurezza dei File .env

I file .env sono comodi per lo sviluppo locale ma rappresentano un rischio significativo se gestiti male. Ecco le regole fondamentali:

Struttura Raccomandata


# Struttura dei file .env nel progetto
project/
  .env                 # MAI committato (in .gitignore)
  .env.example         # Template SENZA valori reali (committato)
  .env.development     # Valori di sviluppo (opzionale, in .gitignore)
  .env.production      # MAI committato, MAI nel repository
      

# .env.example - Template committato nel repository
# Copiare in .env e compilare con i valori reali
API_URL=https://api.example.com
FIREBASE_PROJECT_ID=your-project-id
ANALYTICS_ID=
SECRET_KEY=

# .env - File locale (DEVE essere in .gitignore)
API_URL=https://api.example.com
FIREBASE_PROJECT_ID=my-actual-project
ANALYTICS_ID=G-XXXXXXXXXX
SECRET_KEY=super-secret-value-123
      

Regola d'Oro per .gitignore


# .gitignore - Escludere SEMPRE i file .env
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
.env.production

# Ma NON escludere il template
!.env.example
      

4. Segreti Runtime vs Build-Time

Per le applicazioni Angular, e cruciale capire la differenza tra segreti disponibili al momento della build e segreti disponibili a runtime. Angular e un framework frontend: tutto ciò che viene incluso nel bundle e visibile nel browser.

Regola Fondamentale per il Frontend

Mai includere segreti nel bundle frontend. Qualsiasi valore presente nei file environment.ts di Angular e visibile a chiunque apra gli strumenti sviluppatore del browser. Le API key pubbliche (come Google Maps o Google Analytics) sono accettabili, ma token privati, chiavi di crittografia e password non devono mai essere nel codice frontend.


// environment.ts - Cosa e sicuro e cosa NO

// SICURO: chiavi pubbliche con restrizioni di dominio
export const environment = {
  production: true,
  apiUrl: 'https://api.example.com',
  googleMapsKey: 'AIza...',  // OK: limitata per dominio nella console Google
  analyticsId: 'G-XXXXX',   // OK: e un identificatore pubblico
  sentryDsn: 'https://xxx@sentry.io/123',  // OK: limitata per dominio
};

// MAI FARE QUESTO:
// firebaseAdminKey: 'xxxxx',    // PERICOLOSO: accesso admin completo
// stripeSecretKey: 'sk_xxxxx',  // PERICOLOSO: accesso ai pagamenti
// dbPassword: 'password123',     // PERICOLOSO: accesso al database
      

Gestire Build-Time Secrets nella Pipeline


# Iniettare valori sicuri al build time
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'

      # Sostituire i placeholder nell'environment file
      - name: Configure environment
        run: |
          cat > src/environments/environment.prod.ts << 'ENVEOF'
          export const environment = {
            production: true,
            apiUrl: '${{ vars.API_URL }}',
            analyticsId: '${{ vars.ANALYTICS_ID }}',
          };
          ENVEOF

      - run: npm ci
      - run: npx ng build --configuration=production
      

5. Rotazione dei Segreti

La rotazione periodica dei segreti e una pratica di sicurezza fondamentale. Anche se un segreto non e stato compromesso, la rotazione riduce la finestra di esposizione in caso di leak non rilevato.

Piano di Rotazione Consigliato

Tipo di Segreto Frequenza Motivo
Token di deploy (Firebase, Vercel) Ogni 90 giorni Accesso alle risorse di produzione
API key di servizi terzi Ogni 180 giorni Rischio di compromissione nel tempo
Token npm/Docker Hub Ogni 90 giorni Accesso alla pubblicazione di pacchetti
Service Account JSON Ogni 365 giorni Credenziali di lungo termine
Segreto compromesso Immediatamente Emergenza di sicurezza

# Workflow per promemoria di rotazione
name: Secret Rotation Reminder

on:
  schedule:
    - cron: '0 9 1 */3 *'  # Primo giorno di ogni trimestre

jobs:
  remind:
    runs-on: ubuntu-latest
    steps:
      - name: Check secret age
        run: |
          echo "Reminder: E il momento di ruotare i segreti del repository."
          echo "Segreti da controllare:"
          echo "- FIREBASE_SERVICE_ACCOUNT"
          echo "- NPM_TOKEN"
          echo "- DOCKER_HUB_TOKEN"
          echo "Vai su Settings > Secrets per aggiornare i valori."

      - name: Create GitHub Issue
        uses: actions/github-script@v7
        with:
          script: |
            github.rest.issues.create({
              owner: context.repo.owner,
              repo: context.repo.repo,
              title: 'Rotazione trimestrale dei segreti',
              body: 'E il momento di ruotare i segreti CI/CD.',
              labels: ['security', 'maintenance']
            });
      

6. Soluzioni Vault Enterprise

Per organizzazioni con requisiti di sicurezza avanzati, GitHub Secrets potrebbe non essere sufficiente. Le soluzioni vault offrono funzionalità aggiuntive come audit dettagliato, rotazione automatica e crittografia avanzata.

HashiCorp Vault


# Integrare HashiCorp Vault con GitHub Actions
jobs:
  deploy:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read
    steps:
      - name: Import Secrets from Vault
        uses: hashicorp/vault-action@v3
        with:
          url: https://vault.example.com
          method: jwt
          role: github-actions
          secrets: |
            secret/data/production/firebase token | FIREBASE_TOKEN ;
            secret/data/production/api key | API_KEY ;

      - name: Use imported secrets
        run: |
          echo "Firebase token is available as env var"
          firebase deploy --token "$FIREBASE_TOKEN"
      

Confronto Soluzioni Vault

Vault Solutions a Confronto

Caratteristica GitHub Secrets HashiCorp Vault AWS Secrets Manager GCP Secret Manager
Costo Gratuito Self-hosted o Cloud Pay-per-use Pay-per-use
Rotazione automatica No Si Si Si
Audit log Limitato Completo CloudTrail Cloud Audit
Complessità Bassa Alta Media Media
Ideale per Piccoli team Enterprise Ecosistema AWS Ecosistema GCP

7. Prevenire il Leak di Segreti

La prevenzione e più efficace della cura. Ecco gli strumenti e le pratiche per impedire che i segreti finiscano nel repository.

git-secrets: Scansione Pre-Commit


# Installare git-secrets
# macOS
brew install git-secrets

# Linux
git clone https://github.com/awslabs/git-secrets.git
cd git-secrets && make install

# Configurare nel repository
cd my-project
git secrets --install
git secrets --register-aws

# Aggiungere pattern personalizzati
git secrets --add 'FIREBASE_TOKEN[=:]\s*[A-Za-z0-9]+'
git secrets --add 'sk_live_[A-Za-z0-9]+'
git secrets --add 'AIza[0-9A-Za-z\\-_]{35}'

# Scansionare il repository esistente
git secrets --scan
      

Pre-Commit Hook con Husky


# Installare husky
npm install -D husky
npx husky init

# Creare il pre-commit hook
cat > .husky/pre-commit << 'HOOKEOF'
#!/bin/sh

# Controllare che nessun segreto venga committato
echo "Checking for secrets..."

# Pattern comuni di segreti
PATTERNS=(
  'AKIA[0-9A-Z]{16}'           # AWS Access Key
  'sk_live_[a-zA-Z0-9]+'       # Stripe Secret Key
  'AIza[0-9A-Za-z\-_]{35}'     # Google API Key
  'ghp_[a-zA-Z0-9]{36}'        # GitHub Personal Token
  'xox[bpoas]-[a-zA-Z0-9-]+'   # Slack Token
)

for pattern in "${PATTERNS[@]}"; do
  if git diff --cached --name-only -z | xargs -0 grep -lP "$pattern" 2>/dev/null; then
    echo "ERRORE: Possibile segreto rilevato!"
    echo "Pattern: $pattern"
    exit 1
  fi
done

echo "Nessun segreto rilevato."
HOOKEOF

chmod +x .husky/pre-commit
      

GitHub Secret Scanning

GitHub offre anche una funzionalità integrata di Secret Scanning che rileva automaticamente pattern noti di segreti nei commit push. Per i repository pubblici e attiva di default; per i repository privati, e disponibile con GitHub Advanced Security.

8. Audit Trail e Compliance

Per organizzazioni con requisiti di compliance (SOC 2, GDPR, ISO 27001), e necessario mantenere un registro di chi accede ai segreti e quando:


# Workflow con logging dettagliato
jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: production
    steps:
      - name: Log deployment attempt
        run: |
          echo "=== DEPLOYMENT AUDIT LOG ==="
          echo "Timestamp: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
          echo "Actor: ${{ github.actor }}"
          echo "Ref: ${{ github.ref }}"
          echo "SHA: ${{ github.sha }}"
          echo "Workflow: ${{ github.workflow }}"
          echo "Run ID: ${{ github.run_id }}"
          echo "Environment: production"
          echo "==========================="

      - name: Deploy
        run: firebase deploy --token "${{ secrets.FIREBASE_TOKEN }}"

      - name: Log deployment result
        if: always()
        run: |
          echo "Deploy status: ${{ job.status }}"
      

Checklist Sicurezza dei Segreti

  • Tutti i file .env sono nel .gitignore
  • Esiste un file .env.example senza valori reali
  • I segreti di produzione usano GitHub Environment Secrets
  • L'ambiente production ha le protection rules attive
  • I pre-commit hook controllano i pattern di segreti
  • La rotazione dei segreti e pianificata trimestralmente
  • Il team sa cosa fare in caso di leak (procedura di emergenza)
  • Nessun segreto privato e presente nel codice frontend

Conclusione

La gestione dei segreti e un aspetto della sicurezza che non si può trascurare. In questo articolo abbiamo esplorato l'intero spettro delle soluzioni: da GitHub Secrets per i piccoli team, ai vault enterprise per le organizzazioni con requisiti di compliance avanzati.

I principi fondamentali da ricordare sono: mai committare segreti nel repository, usare livelli di ambiente per separare staging e produzione, implementare pre-commit hook per la prevenzione, pianificare la rotazione regolare dei segreti, e tenere sempre una procedura di emergenza pronta in caso di leak.

Nel prossimo articolo ci concentreremo sulle performance: configureremo performance budgets e Lighthouse CI nella pipeline per garantire che ogni deploy mantenga standard di qualità elevati.

Domande frequenti

Qual è il rischio più grande se una API key viene esposta in un repository pubblico?

Il rischio più grande è quello di essere scoperti e utilizzati da bot automatizzati, che possono causare danni significativi in pochi minuti.

Come si configurano i segreti nel repository su GitHub?

Per aggiungere un segreto al repository, vai su Settings > Secrets and variables > Actions > New repository secret.

Qual è la differenza tra variabili d'ambiente e segreti in GitHub Actions?

Le variabili d'ambiente sono visibili a tutti i job di una pipeline, mentre i segreti sono accessibili solo ai job specificati con la keyword "secrets".

Perché è importante non includere segreti nel bundle frontend delle applicazioni Angular?

Perché tutto ciò che viene incluso nel bundle è visibile nel browser degli utenti e rappresenta un rischio significativo per la sicurezza.

Fonti e approfondimenti

Prova Questi Strumenti

Strumenti gratuiti correlati a questo argomento.

Commenti

Caricamento commenti...

Accedi per commentare

Discuti questo articolo nella community

Unisciti al gruppo Telegram per discutere con altri sviluppatori, fare domande e condividere le tue esperienze.

Ti è piaciuto questo articolo?

Esplora altri contenuti sul blog o scopri i miei progetti