Tema
Runbook: chiavi di mask (creazione, rotazione, compromissione)
Le chiavi HMAC con cui la transform mask pseudonimizza le colonne.
Chi lo esegue. Chi amministra l'ambiente dell'installazione (
.envo il gestore di segreti). La chiave non passa mai da chat, ticket, mail o repository.
Creare una chiave
Genera 32 byte casuali in base64:
bashopenssl rand -base64 32Deve essere casuale: mai una passphrase o una parola codificata in base64. Una chiave fatta di byte ripetuti viene rifiutata, ma il controllo ferma solo gli errori grossolani.
Scegli un id: minuscole, cifre, underscore singoli in mezzo (
crm,crm_2027). L'id finisce dentro ogni pseudonimo (v1:<id>:<hex>), quindi non si rinomina dopo il primo caricamento.Configura l'ambiente:
bashMASK_KEY_INSTANCES=crm MASK_KEY_CRM_SECRET=<il valore generato>Con una sola chiave basta
MASK_KEY_SECRET, che vale come iddefault.Avvia la pipeline. Una chiave assente, non base64 o più corta di 32 byte ferma la run subito, con un
ConfigErrorche nomina la variabile e mai il valore.
Stessa chiave in tutti gli ambienti che devono fare join fra loro, chiavi diverse dove i dataset non devono essere collegabili (produzione e demo, per esempio).
Ruotare una chiave
Ruotare cambia tutti gli pseudonimi: i dati caricati con la chiave vecchia non fanno più join con quelli nuovi. Va deciso, non fatto di passaggio.
- Crea la chiave nuova con un id nuovo (
crm_2027) e aggiungila alla lista, senza togliere la vecchia:MASK_KEY_INSTANCES=crm,crm_2027. Se la chiave attuale èMASK_KEY_SECRET, senza lista, il suo id èdefaulte i suoi pseudonimi iniziano perv1:default:: la lista diventaMASK_KEY_INSTANCES=default,crm_2027, eMASK_KEY_SECRETresta dov'è. Il segreto deve essere nuovo: due id con lo stesso valore fermano la run con unConfigError. - Cambia la costante dell'id nella pipeline e rilascia.
- Decidi cosa fare dei dati già caricati, che si riconoscono dal prefisso
v1:crm::- ricaricarli dalla sorgente con la chiave nuova, se la sorgente li ha ancora;
- oppure lasciarli, sapendo che i join fra i due periodi non funzionano.
- Quando nessuna pipeline usa più l'id vecchio e i dati vecchi sono stati ricaricati o scaduti, togli la chiave vecchia dall'ambiente.
Se una chiave è compromessa
Chi ha la chiave può ricalcolare lo pseudonimo di un valore noto, e su domini piccoli invertirlo per enumerazione: i dati pseudonimizzati con quella chiave vanno trattati come dati in chiaro.
- Ruota subito (sezione sopra) e togli la chiave vecchia dall'ambiente appena possibile.
- Ricarica o cancella i dati con il prefisso della chiave compromessa, a ogni destinazione.
- Segnala l'accaduto al responsabile della protezione dei dati: può essere una violazione da notificare (GDPR art. 33).
Cosa controllare se qualcosa non torna
| Sintomo | Causa |
|---|---|
MASK_KEY_…_SECRET non è impostata | variabile assente, o id nella lista senza la sua variabile |
… non è base64 valido | valore troncato, con virgolette dentro, o in base64url |
Istanza "x" non configurata per il connettore mask-key | l'id della pipeline non è in MASK_KEY_INSTANCES |
MaskKey "x" è il segnaposto di getSpec() | run() passa maskKeyForSpec invece di loadMaskKeyRegistry().get |
MASK_KEY_SECRET non è impostata, ma MASK_KEY_CRM_SECRET c'è | manca MASK_KEY_INSTANCES=crm: senza la lista si legge solo la chiave default |
… id di chiave non valido | un id con maiuscole, trattini o spazi nella lista o nella pipeline (l'errore non lo cita, di proposito) |
… e … hanno lo stesso valore | due id con lo stesso segreto: genera una chiave nuova per l'id nuovo |
… non è casuale (byte ripetuti) | zeri o una parola ripetuta al posto di una chiave generata |
| Una colonna arriva in chiaro a destinazione | nome sbagliato in columns (refuso, maiuscole): usa onAbsent: "error" |
| Join fra due tabelle che non trova niente | prefissi v1:<id>: diversi, oppure tipi diversi (1 e "1") |

