Gestione multi-ambiente con Vault HashiCorp su VPS Linux: secrets per applicazioni PHP

Gestione multi-ambiente con Vault HashiCorp su VPS Linux: secrets per applicazioni PHP

Il 15 luglio 2024 sono stato ingaggiato per un'emergenza di sicurezza da una software house lombarda di 18 dipendenti che gestiva in outsourcing l'infrastruttura IT di una PMI manifatturiera lombarda come cliente. Due giorni prima un junior developer dell'agenzia era stato licenziato dopo un diverbio, e nel processo di revisione degli accessi era emerso un problema grave: le credenziali del database di produzione del cliente - utente MySQL con permessi di scrittura completi - erano hardcoded nel file .env.production committato nel repository GitLab privato dell'agenzia. Il repository era privato ma aveva accesso per otto collaboratori diversi (incluso il junior licenziato), e la policy dell'agenzia non prevedeva rotazione automatica delle credenziali al cessare di un rapporto.

La rotazione manuale delle credenziali del database richiedeva: generazione di una nuova password, aggiornamento del file .env sul server di produzione, deploy del nuovo .env (inevitabilmente committato nel repository, riproducendo il problema), verifica che l'applicazione continuasse a funzionare, aggiornamento delle credenziali negli altri sistemi che accedevano al database (script di backup, tool di monitoring, sistema di reporting esterno). In pratica, la rotazione era così macchinosa che non era mai stata fatta nei 18 mesi precedenti. Il junior licenziato, se avesse voluto farlo, avrebbe avuto accesso completo ai dati del cliente fino alla scadenza delle sue chiavi SSH del server di produzione - che nessuno aveva pianificato di ruotare. Fortunatamente il junior ha restituito le sue credenziali volontariamente e ha firmato un NDA post-separazione, ma l'incidente ha evidenziato una fragilità strutturale nel modello di secrets management dell'agenzia.

In sei giornate distribuite in tre settimane ho implementato HashiCorp Vault come infrastruttura centralizzata di secrets management per l'agenzia, con integrazione nei deploy flow e nelle applicazioni Laravel e Symfony gestite. Al go-live, la rotazione delle credenziali è diventata un'operazione automatica trasparente che avviene ogni 90 giorni senza intervento manuale. Il licenziamento di un collaboratore è diventato un'operazione che richiede un singolo cambio di policy Vault invece di intervenire su decine di sistemi. Il costo consulenziale dell'intervento è stato 8.400 euro. Il valore difensivo in termini di riduzione del rischio operativo è significativo e documentabile in sede di audit.

Questo articolo descrive l'adozione di HashiCorp Vault come backend di secrets management per contesti PMI italiane, basato sull'esperienza di circa 10 progetti simili negli ultimi quattro anni. Il principio guida è uno: Vault è potentissimo ma ha una curva di apprendimento significativa; va adottato con disciplina e con scope realistico rispetto alla dimensione del team. Non è la soluzione per ogni PMI - è la soluzione quando il costo di gestione distribuita dei secrets diventa superiore al costo di introdurre un sistema centralizzato.

Quando HashiCorp Vault si giustifica in una PMI italiana

HashiCorp Vault è un servizio dedicato alla gestione di secrets applicativi - credenziali database, API key di servizi esterni, certificati TLS, token di accesso, chiavi crittografiche. Offre funzionalità avanzate che gli approcci più semplici (file .env, AWS Secrets Manager, GitLab CI variables) non possono eguagliare: secret engines dinamici (generazione automatica di credenziali database univoche per ogni applicazione con TTL breve), rotazione programmata nativa, audit log completo di ogni accesso, policy-based access control granulare, PKI as a Service per emissione certificati interni.

Il costo operativo di Vault è non trascurabile. Richiede un server dedicato (o cluster di 3-5 nodi per alta disponibilità), configurazione iniziale complessa, integrazione applicativa che aggiunge complessità al deploy pipeline, disciplina di uso continuo da parte del team. Per PMI molto piccole (sotto i 10 dipendenti tecnici, sotto i 5 server), l'overhead operativo supera spesso il beneficio. Per PMI medie (15-60 dipendenti tecnici, 10+ server, più clienti gestiti), Vault è tipicamente la scelta giusta.

La documentazione ufficiale HashiCorp Vault copre in dettaglio architettura, configurazione e best practice, ed è il riferimento canonico per implementazioni production-grade. Questo articolo non duplica la documentazione ma si focalizza sulle decisioni operative specifiche per PMI italiane.

Se gestisci un'infrastruttura IT con multiple applicazioni e team distribuito e stai valutando centralizzazione del secrets management, nel mio profilo professionale trovi il dettaglio degli interventi di introduzione Vault in contesti PMI italiane, sempre con valutazione onesta dei trade-off e calibrata sulla reale capacità operativa del team.

Architettura di deploy: single-node vs cluster, dove ospitare, backup

La prima decisione architetturale per Vault in PMI è il modello di deploy. Le opzioni praticabili sono tre. Single-node: un singolo server Vault, configurazione più semplice, adatto quando downtime pianificato è accettabile (finestra di manutenzione di pochi minuti al mese). Lo uso come default per PMI fino a 25 dipendenti tecnici. Cluster 3-nodi con Raft consensus integrato: alta disponibilità, tolleranza a failure di un nodo, complessità operativa moderata. Adatto a PMI che gestiscono molti clienti critici. Managed Vault (HashiCorp Cloud Platform): delega completa a HashiCorp, costo mensile più alto, zero maintenance. Adatto a team che vogliono Vault senza gestire infrastruttura.

Per l'agenzia lombarda ho scelto single-node su un VPS Hetzner CCX23 dedicato (4 vCPU, 16 GB RAM, 160 GB NVMe), costo mensile di 24 euro. Il server è isolato dalle applicazioni - non condivide risorse con VPS applicativi - e accessibile solo dalla rete privata interna (accesso esterno protetto da bastion SSH dedicato). Questa isolation è critica: un compromesso dei server applicativi non deve compromettere Vault.

Il backup di Vault richiede attenzione specifica perché contiene tutti i segreti dell'organizzazione. Il pattern che applico include: snapshot giornaliero del database interno Vault (Raft storage) su storage cifrato separato (Hetzner Storage Box con AES-256), snapshot settimanale offsite (bucket S3 in region diversa), test di restore mensile per verificare che i backup funzionino davvero. Senza disciplina di test periodico, "abbiamo i backup" è spesso scoperta come "abbiamo file di backup corrotti e non lo sapevamo" al momento critico.

Il processo di unseal e root token: i momenti critici operativi

Un aspetto di Vault che confonde sviluppatori all'inizio è il concetto di sealing/unsealing. Vault, per default, si avvia in stato sealed - i dati interni sono cifrati e inaccessibili, anche al processo Vault stesso. Per rendere Vault operativo serve unseal - fornire chiavi crittografiche che Vault usa per decriptare la memoria operativa.

Il pattern standard è Shamir's Secret Sharing: la chiave master Vault viene divisa in N parti (tipicamente 5), ciascuna custodita da persone diverse, e ne servono M (tipicamente 3) per completare l'unseal. Questo meccanismo previene che una singola persona possa avere controllo completo su Vault - serve quorum. Nei deploy moderni, preferisco auto-unseal tramite AWS KMS o Azure Key Vault: Vault usa una chiave esterna (custodita da KMS del cloud provider) per automaticamente unseal al boot, eliminando operazioni manuali e il rischio che le chiavi Shamir vadano perdute.

Il root token è il token iniziale con permessi completi usato per configurare Vault dopo il bootstrap. Il pattern corretto è: usare il root token solo per configurazione iniziale, poi creare policy specifiche e token dedicati per ogni use case, infine revocare il root token per eliminare il rischio di suo uso improprio. In caso di emergenza, un nuovo root token può essere rigenerato tramite procedura che richiede quorum delle chiavi Shamir - sicuro ma non immediato.

Secret engines: KV, Database, PKI, Transit

Vault organizza i secrets in secret engines, ciascuno specializzato per un tipo specifico. Gli engines principali per PMI sono quattro.

Key-Value (KV): storage generico di coppie chiave-valore. Caso d'uso: credenziali statiche che non possono essere generate dinamicamente (API key di provider esterni, password amministrative, token OAuth). Pattern: vault kv put secret/app1/production stripe_api_key=sk_live_..., l'applicazione legge con vault kv get secret/app1/production.

Database: generazione dinamica di credenziali database con TTL configurabile. Caso d'uso principale: l'applicazione non ha credenziali statiche database, ma a ogni avvio richiede a Vault credenziali temporanee con TTL di 24 ore. Vault crea l'utente MySQL/PostgreSQL dinamicamente, lo restituisce all'applicazione, e lo revoca automaticamente alla scadenza del TTL. Questo elimina completamente il rischio di credenziali che sopravvivono a cessazione di personale - ogni credenziale ha vita breve per design.

PKI: emissione di certificati X.509 da una CA privata gestita da Vault. Caso d'uso: certificati per servizi interni (comunicazione mTLS fra microservizi), certificati client per autenticazione alle API interne, certificati SSH per flusso CA centralizzata. Utile quando non si vogliono usare Let's Encrypt pubblici per reti interne.

Transit: Vault agisce come oracolo di cifratura/decifratura - l'applicazione invia dati in chiaro a Vault, Vault restituisce dati cifrati con chiavi gestite internamente (mai esposte all'applicazione). Caso d'uso: crittografia di dati sensibili (numeri di carta, codici fiscali) con gestione chiavi centralizzata e rotazione automatica, pattern complementare ai principi di pseudonimizzazione dati Laravel Symfony per conformità GDPR che ho descritto in un articolo dedicato.

Integrazione applicativa: fetch secrets at boot, caching in memoria

Il pattern di integrazione che applico su applicazioni Laravel e Symfony è fetch at boot: al momento del primo caricamento dell'applicazione (es. prima richiesta HTTP dopo deploy), uno script bash o un early-phase hook PHP si autentica a Vault con AppRole credentials iniettati dal deploy system, recupera i secrets necessari, li inserisce nell'ambiente del processo PHP come variabili $_SERVER. Da quel momento l'applicazione li usa come normali env vars - nessuna modifica al codice applicativo esistente.

Il pattern concreto su Laravel è uno script bin/fetch-secrets.sh invocato dall'entrypoint Docker:

#!/usr/bin/env bash
set -euo pipefail

VAULT_TOKEN=$(vault write -format=json auth/approle/login \
    role_id="$VAULT_ROLE_ID" secret_id="$VAULT_SECRET_ID" \
    | jq -r '.auth.client_token')

export VAULT_TOKEN
SECRETS=$(vault kv get -format=json "secret/myapp/${APP_ENV}")

# inject secrets nell'environment del processo successivo
export DB_PASSWORD=$(echo "$SECRETS" | jq -r '.data.data.db_password')
export STRIPE_KEY=$(echo "$SECRETS" | jq -r '.data.data.stripe_key')
export REDIS_AUTH=$(echo "$SECRETS" | jq -r '.data.data.redis_auth')

exec "$@"

Questo pattern integra con il modello di gestione dei file .env in produzione con pattern sicuri per Laravel e Symfony che ho descritto in un articolo dedicato, dove Vault è il backend che sostituisce il file .env statico.

Policy-based access control: chi può accedere a cosa

Il valore di Vault emerge pienamente con il suo sistema di policy - regole granulari che definiscono chi può leggere o scrivere quali secrets. Il pattern che applico in PMI è policy per applicazione + policy per ruolo umano.

Per l'agenzia lombarda, le policy implementate sono state:

  • app-customer-a: policy che permette lettura di secret/customer-a/*, usata dal server applicativo del cliente A tramite AppRole.
  • developers: policy che permette lettura di secret/*/staging/* e lettura con richiesta esplicita via CLI (audit log pieno) di secret/*/production/*. Usata dagli sviluppatori per accesso interattivo.
  • admin: policy completa, usata solo dai due senior con responsabilità di amministrazione Vault, con MFA obbligatorio.

L'audit log di Vault registra ogni singolo accesso: chi ha letto cosa, quando, da quale IP. Questo audit è critico per compliance (GDPR, NIS2) e per investigation post-incident. In caso di sospetto uso improprio, il log Vault permette di ricostruire esattamente cosa è stato acceduto.

Rotazione automatica: il vero valore operativo di Vault

La funzionalità più trasformativa di Vault per PMI è la rotazione automatica delle credenziali. Vault può rotare le credenziali dei secret KV tramite job scripts programmati, ma il caso più impressionante è il Database secret engine - ogni credenziale database generata ha TTL breve (tipicamente 24 ore), e se una credenziale non viene rinnovata, viene automaticamente revocata.

Il pattern operativo è: l'applicazione al boot richiede credenziali, le usa per la durata del TTL, prima della scadenza le rinnova automaticamente (token renewal). Se l'applicazione smette di rinnovare (crash, deploy di nuova versione che richiede nuove credenziali), le credenziali vecchie scadono e vengono automaticamente revocate da Vault sul database. Risultato: non esistono mai credenziali che sopravvivono oltre il loro uso attivo.

Per l'agenzia lombarda, questo pattern ha risolto strutturalmente il problema dell'incidente di luglio 2024. Quando un collaboratore lascia, le credenziali che aveva uso si sarebbero comunque estinte entro 24 ore senza intervento manuale. Il rischio di credenziali che sopravvivono a cessazione del rapporto è stato eliminato.

Il risultato finale dell'intervento sull'agenzia a dodici mesi dal go-live è stato il seguente. Credenziali database di tutti i 14 clienti gestiti sono passate a generazione dinamica via Vault Database engine con TTL di 24 ore. Numero di operazioni manuali di rotazione credenziali: sceso da "teoricamente mensili ma di fatto mai fatte" a zero (tutto automatico). Audit log centralizzato di ogni accesso a secret: 180.000+ eventi registrati nei 12 mesi, consultabili per investigation. Zero incidenti di esposizione credenziali nei 12 mesi successivi al go-live. Rotazione dell'intera gestione secrets in caso di cessazione collaboratore: ridotta da "operazione complessa che coinvolgeva 30+ sistemi" a "revocation di una singola policy Vault". Costo consulenziale iniziale: 8.400 euro. Costo operativo mensile del server Vault: 24 euro. Beneficio difensivo in ROI puramente preventivo: non quantificabile in numero preciso ma significativo.

Se gestisci un'infrastruttura con multiple applicazioni, multiple clienti, team distribuito e credenziali statiche sparse su file .env o repository git privati, l'introduzione di Vault è uno degli interventi di hardening infrastrutturale con ROI più alto. Non è adatto a contesti molto piccoli dove overhead operativo supera beneficio, ma per PMI medie è quasi sempre giustificato. Se vuoi confrontarti sul tuo caso specifico con una valutazione indipendente del fit di Vault al tuo contesto, contattami per una consulenza preliminare: in una sessione di analisi guidata valutiamo insieme la dimensione della tua gestione secrets attuale, i rischi residui del modello esistente, e una roadmap di adozione Vault calibrata sulla capacità operativa del tuo team.

Ultima modifica: