Dopo aver già ottenuto nel primo capitolo una panoramica approfondita dell’intero ecosistema delle Secrets Engines, ci immergiamo ora nella quotidianità di ogni cluster Vault. La Key / Value (KV) Secrets Engine è il cavallo di battaglia per tutte le situazioni in cui è necessario archiviare in modo sicuro dei segreti, versionarli e recuperarli successivamente in maniera mirata.
Sebbene Vault sia noto soprattutto per le sue capacità dinamiche, in ogni ambiente reale esiste una considerevole quantità di valori statici - a partire dalle chiavi API di servizi SaaS esterni, passando per le password di account di servizio senza scadenza, fino ad arrivare ai pacchetti di certificati per sistemi legacy. Senza uno storage Key/Value robusto, questi dati continuerebbero spesso a circolare in modo incontrollato in file di testo, repository Git, sistemi CI o persino in fogli Excel. Proprio questo viene evitato dalla Key/Value Secrets Engine.
In questo sottocapitolo daremo uno sguardo pratico a
- come viene attivata una Key/Value Secrets Engine,
- quali considerazioni influenzano la scelta del percorso di mount e
- come progettare una struttura gerarchica che sia comprensibile anche tra cinque anni.
Nei sottocapitoli seguenti a partire dalla parte 2b, esamineremo poi diversi aspetti della Key/Value Secrets Engine - tra cui le differenze tra le due varianti del KV-Store, l’esecuzione degli upgrade dalla vecchia alla nuova versione, come scrivere e leggere dati, come gestire i metadati e come versionare, eliminare e ripristinare i segreti memorizzati.
Che cos’è la Key / Value Secrets Engine?
La Key/Value Secrets Engine (o più brevemente KV Engine) risponde a una domanda semplice ma onnipresente:
Dove possiamo conservare segreti immutabili in modo che siano protetti da occhi indiscreti, registrati in modo a prova di revisione e allo stesso tempo facilmente accessibili per pipeline di integrazione, utenti umani e applicazioni?
Dal punto di vista tecnico, si tratta di un archivio Key/Value transazionale e cifrato, che cripta tutti i dati in modo trasparente con AES a 256 bit prima che vengano salvati nel backend di storage.
Ogni operazione di lettura o scrittura viene registrata senza lacune dal sottosistema di audit di Vault, permettendo così di ricostruire in modo preciso chi ha avuto accesso a quale percorso e quando.
Per i team che finora hanno utilizzato soluzioni Cloud KMS o Parameter Store, la KV Engine rappresenta spesso il primo punto di contatto con Vault, poiché offre un modello dati familiare ma con funzionalità di sicurezza e automazione nettamente superiori.
Due versioni, due filosofie
Un dettaglio che genera spesso confusione: esistono due varianti di questa Engine.
- Versione 1 (kv): La variante classica, non versionata
- Versione 2 (kv-v2): La variante moderna, versionata
La versione 1, internamente chiamata semplicemente “kv”, memorizza esattamente una versione corrente per ogni voce. Una sovrascrittura elimina in modo irreversibile i vecchi dati. Questo comportamento era perfettamente adeguato nei primi tempi di Vault, ma oggi non soddisfa più i requisiti di conformità.
La versione 2, configurabile con il nome kv-v2 o tramite il parametro ‑version=2, mantiene invece una cronologia completa per ogni voce. Ogni modifica a una coppia Key/Value genera una nuova revisione, che può essere recuperata o ripristinata in un secondo momento. È inoltre possibile eseguire eliminazioni soft con un periodo di conservazione definito, prima che un valore venga cancellato definitivamente.
Nelle installazioni moderne, si dovrebbe quindi utilizzare esclusivamente la variante v2. La v1 viene utilizzata solo quando carichi di lavoro legacy dipendono da un’API stabile e non possono essere convertiti nel breve periodo.
Oltre alla semplice versionatura, la v2 introduce ulteriori funzionalità: ogni voce può, ad esempio, essere protetta con un indice Check-and-Set opzionale, che impedisce i cosiddetti Blind Writes. Inoltre, è possibile limitare server-side il numero massimo di revisioni conservate, per mantenere sotto controllo il consumo di spazio e il traffico di replica.
Ai fini dell’esame di certificazione è importante sapere che un upgrade da v1 a v2 non avviene automaticamente. Il processo di migrazione deve essere avviato attivamente e richiede ACL adeguate e, se coinvolge decine di applicazioni, eventualmente un piano multi-step. Cambiano anche i percorsi API, il che significa che eventuali script e applicazioni devono essere adattati in caso di migrazione da v1 a v2.
Importante per la pratica: Nelle nuove implementazioni dovrebbe essere utilizzata quasi esclusivamente la Versione 2. La Versione 1 è considerata obsoleta e viene utilizzata solo in scenari legacy specifici.
Modalità di accesso e integrazione
Come per tutte le componenti di Vault, sono disponibili tre modalità principali di interazione.
- UI: Per un utilizzo interattivo e una visione rapida, ideale per lavori Ad-hoc veloci in ambienti di sviluppo e demo. Poiché ciò non è sufficiente per ambienti di produzione, in questa serie di articoli non approfondiremo l’interfaccia grafica.
- CLI: Per amministratori e scripting. La CLI è l’equivalente adatto alla produzione dei clic del mouse nella UI. I nostri esempi di codice utilizzano la CLI.
- API: Per l'automazione e l'integrazione in pipeline e applicazioni.
L’utilizzo dell’API tramite Infrastructure-as-Code è lo standard per gli ambienti di produzione. Un job di build può, ad esempio, richiedere un nuovo token immediatamente prima del deployment e poi recuperare il secret desiderato tramite una semplice richiesta GET dal percorso KV apps/payment/prod/api_key.
Per carichi di lavoro come le applicazioni, è consigliato l’uso del Vault Agent, che mette a disposizione i dati in file temporanei e rinnova autonomamente i token di accesso dell’applicazione. Grazie a questa flessibilità, la KV Engine si adatta praticamente a ogni workflow, senza compromettere gli obiettivi centrali di sicurezza.
Sicurezza come principio progettuale
Tutti i dati nella KV Engine vengono cifrati prima di essere salvati. Di conseguenza, per auditor o team operativi non ha importanza se il backend fisico è un filesystem locale, un cluster Consul (standard fino a pochi anni fa) o il backend Raft integrato (attuale standard). Anche uno storage compromesso non è in grado di ricostruire il contenuto in chiaro.
Vault gestisce i diritti di accesso tramite il proprio sistema di policy. Singoli percorsi possono essere protetti con regole di policy basate su permessi come read, create, update o delete. Uno scenario tipico di produzione prevede che gli sviluppatori abbiano diritti di sola lettura su un percorso come apps/*/prod, mentre solo il team di operations può scrivere in quell’area.
Assegnando speciali capabilities come list è possibile impedire che occhi indiscreti vengano a conoscenza dell’esistenza di percorsi subordinati.
Come ulteriore livello di sicurezza, possono essere impiegati Token Tiers o Control Groups, ad esempio per subordinare azioni particolarmente sensibili a un’approvazione multi-fattore.
Attivazione pratica
L’attivazione di una KV Engine avviene, come mostrato nella Parte 1, tramite il comando vault secrets enable <engine>.
Non appena viene definito il punto di mount, questo assume il ruolo di namespace - completamente isolato dalle altre Engines. È importante ricordare che una rinomina successiva è possibile solo tramite vault secrets move e può richiedere ampie modifiche alle policy.
Attivare la Versione 1
# Attivazione standard di KV v1
$ vault secrets enable kv
Success! Enabled the kv secrets engine at: kv/
# Attivazione su un percorso personalizzato
$ vault secrets enable -path=legacy-secrets kv
Success! Enabled the kv secrets engine at: legacy-secrets/
Attivare la Versione 2
# Metodo 1: Specifica esplicita di kv-v2 $ vault secrets enable kv-v2 Success! Enabled the kv-v2 secrets engine at: kv-v2/ # Metodo 2: Versione come parametro \$ vault secrets enable -path=secrets -version=2 kv Success! Enabled the kv-v2 secrets engine at: secrets/
Suggerimenti professionali dalla pratica
1. Ogni mount dovrebbe essere immediatamente corredato da una descrizione, in modo che i colleghi sappiano ancora tra sei mesi a cosa servisse.
2. Nei mount v2 produttivi conviene impostare l’opzione max_versions non appena si ha chiarezza su quante revisioni siano effettivamente necessarie. In settori regolamentati, dove è richiesta una conservazione decennale, il valore va calcolato di conseguenza.
3. Consiglio di impostare il parametro cas_required su true, per attivare il meccanismo Check-and-Set ed escludere sovrascritture parallele accidentali. In tal caso, ogni operazione di scrittura su un Secret (ossia create, update o patch) deve includere anche il parametro cas. Il parametro cas funge da controllo di versione: un’operazione di scrittura va a buon fine solo se il valore cas corrisponde alla versione attuale del Secret. In questo modo si ha il controllo sulle scritture concorrenti dei Secret.
Rilevamento della versione
Proprio negli ambienti di grandi dimensioni sorge spesso la domanda su quali punti di mount siano già configurati con la KV Engine v2. Il seguente comando fornisce la risposta nella colonna »Options«.
$ vault secrets list --detailed Path Type Accessor Description Options ---- ---- -------- ----------- ------- cubbyhole/ cubbyhole cubbyhole_abc123 [...] map[] kv/ kv kv_def456 [...] map[] secrets/ kv kv_ghi789 [...] map[version:2]
Sì, avete ragione: bisogna prima saperlo.
Se manca la voce version:2 all’interno di map[], si tratta di un’istanza v1.
Negli script di automazione è consigliabile eseguire il parsing di questo output in modo leggibile dalla macchina per cercare version:2 e non limitarsi a controllare il nome del percorso. Infatti, non solo il nome del percorso (Mountpoint) di una KV Engine è liberamente assegnabile, ma è anche possibile per un utente denominare una KV Engine v1 con il nome kv‑v2.
Concetto di percorso e isolamento
Ogni KV Engine attivata costituisce un proprio namespace. Ciò significa:
- Case-Sensitivity: I percorsi kv/ e KV/ sono diversi e completamente indipendenti, poiché Vault fa distinzione tra maiuscole e minuscole.
- Nessuna sovrapposizione: Un mount su secrets/ impedisce mount aggiuntivi su percorsi subordinati come secrets/sub/. In questo modo si evita che due team scrivano accidentalmente negli stessi directory, ad esempio a causa di malintesi nella suddivisione dei namespaces.
- Isolamento completo: In background, ogni Engine riceve un percorso UUID generato casualmente, che funziona come un chroot. Anche se un mount venisse compromesso, non avrebbe accesso ai dati di altre Engines.
Strutturazione dei Secrets
Una convenzione di naming ordinata garantisce percorsi di accesso brevi, responsabilità chiare e, in definitiva, meno richieste di supporto. Un modello spesso utilizzato è »//<secret‑group>/«. Nella pratica potrebbe apparire così:
apps/ └── aws/ ├── prod/ │ ├── user: dbadmin │ ├── password: P@ssw0rd │ └── api_key: b93md83mdmapw └── dev/ ├── cert: -----BEGIN CERTIFICATE----- └── key: -----BEGIN PRIVATE KEY-----
La directory creata apps/aws/ funge solo da contenitore, non contiene alcun secret. Solo i nodi più profondi contengono le effettive coppie chiave-valore.
Il vantaggio di questa gerarchia è la semplicità nella delega dei diritti. Un team di sviluppo potrebbe ricevere il permesso di read su tutti i percorsi contenenti dev nel nome, mentre il team Ops mantiene diritti di scrittura globali per la produzione all’interno del namespace assegnato (i namespaces sono istanze virtuali e isolate di Vault all’interno di Vault Enterprise).
Modello di autorizzazione
Per lavorare con la KV Engine sono necessarie cinque diverse autorizzazioni, chiamate Capabilities:
- create: Creare nuovi secrets (sovrascrive quelli esistenti in v1)
- update: Modificare secrets esistenti (rilevante solo per v2)
- read: Leggere i secrets (ritornati in chiaro)
- delete: Eliminare secrets, in modalità soft o hard
- list: Elencare i secrets disponibili in un percorso (solo le chiavi, non i valori)
Queste capabilities vengono assegnate tramite policies – un argomento che approfondiremo in un articolo successivo. Per ora basti sapere che le policies combinano questi permessi e li associano a Token Roles. In questo modo si può consentire a un sistema CI di scrivere nei percorsi come apps/build durante la fase di build, ma di avere solo accesso in lettura su apps//prod durante il job di release.
Prospettive
In questo articolo abbiamo conosciuto le basi della Key/Value Secrets Engine e compreso le principali differenze tra Versione 1 e Versione 2.
Nel prossimo capitolo entreremo più nel dettaglio dell’utilizzo pratico: come memorizzare, leggere e gestire i secrets? Quali sono le best practice per la struttura dei percorsi? E come sfruttare al meglio la versioning della KV v2?
Restate con noi - si passa alla pratica!