I controlli nella sezione 14 di 21-compliance.md che un auditor chiede per nome. Questa pagina è la procedura; i record che produce sono la prova.
Le chiavi
Ogni credenziale archiviata è sigillata con una chiave di cifratura dati (DEK) nuova.
La DEK è avvolta dalla chiave master (la KEK), e il riferimento della chiave master
è conservato accanto (key_ref, oppure il riferimento dentro un valore impacchettato). Ruotare
la chiave master riavvolge le DEK. Non decifra né ricifra mai una credenziale.
| Impostazione | Significato |
|---|---|
QUIRE_MASTER_KEY |
La chiave master corrente: 32 byte, base64. Ogni nuovo segreto è avvolto sotto di essa |
QUIRE_MASTER_KEY_VERSION |
La sua etichetta di versione. v1 se non impostata. Alzala ogni volta che cambi la chiave |
QUIRE_MASTER_KEY_RETIRED |
Chiavi precedenti sotto cui potrebbero ancora trovarsi segreti archiviati, come v1=<base64>,v0=<base64>. Lettura, mai scrittura |
Il livello web, il worker e il comando bun run kek:rotate leggono le stesse tre
impostazioni. Devono avere tutte gli stessi valori, altrimenti una non può aprire ciò che
un’altra ha sigillato.
Senza QUIRE_MASTER_KEY ciascun sottosistema conserva la chiave che deriva da
QUIRE_SECRET_KEY. Funziona, la pagina Stato del sistema la mostra come degradata, e
resta leggibile dopo aver impostato una chiave master, ed è così che la prima rotazione
sposta tutto fuori da essa. Chiunque possa leggere l’ambiente del processo può decifrare
ogni credenziale archiviata, quindi un’installazione di produzione dovrebbe avere una chiave master,
conservata in un archivio di segreti e non nello stesso backup del database.
Rotazione
L’età della chiave è mostrata in Console piattaforma, Sicurezza, Chiave master, e come metrica
quire.secrets.master_key.age (giorni). La programmazione giornaliera platform.key_age (03:41 UTC)
scrive una voce promemoria nella catena di audit della piattaforma quando la chiave compie 365
giorni, e di nuovo ogni 30 giorni finché non viene ruotata. Ruota al promemoria, e ogni volta che una chiave potrebbe essere stata esposta.
- Genera la nuova chiave:
openssl rand -base64 32. - Imposta
QUIRE_MASTER_KEYsu di essa eQUIRE_MASTER_KEY_VERSIONsulla prossima etichetta (v2). Sposta la vecchia chiave inQUIRE_MASTER_KEY_RETIREDcomev1=<old base64>. Conserva una copia di entrambe altrove rispetto a questo host. - Distribuisci il livello web e il worker con le nuove impostazioni. I nuovi segreti sono ora
avvolti sotto
env:QUIRE_MASTER_KEY:v2; quelli vecchi si aprono ancora tramite la chiave ritirata. - Richiedi la rotazione, con la motivazione che resterà nella traccia di audit:
- nella console: Sicurezza, Chiave master, Ruota la chiave master; oppure
- su una shell con lo stesso ambiente:
bun run kek:rotate request --reason "Annual rotation, ticket SEC-114".
- Il worker riavvolge una fetta al minuto (la programmazione
platform.key_rotationdello scheduler) e riprende dopo un riavvio. Per finirla in una sola seduta:bun run kek:rotate run. Seguila conbun run kek:rotate status. - Quando il record mostra che la rotazione è completata con zero irrisolti e zero
falliti, rimuovi la chiave ritirata da
QUIRE_MASTER_KEY_RETIREDe ridistribuisci. Fino ad allora conservala: un valore che non è stato possibile spostare è ancora avvolto sotto la vecchia chiave.
Cosa percorre il job
Ogni archivio che contiene una DEK avvolta: quelli in SEALED_STORES
(apps/worker/src/key-rotation.ts). Gli archivi del database di controllo sono percorsi sul
database di controllo; gli archivi delle organizzazioni sono percorsi un’organizzazione alla volta sotto
sicurezza a livello di riga, nel database che contiene l’organizzazione, così un tenant
fissato a un database dedicato viene ruotato in quel database. Un test fallisce quando lo
schema acquisisce una colonna con chiave avvolta che l’elenco non nomina, e un altro quando
la revisione delle credenziali classifica una colonna sigillata che l’elenco manca.
Il record
ops.key_rotation: una riga per rotazione, con motivazione, chi l’ha richiesta, stato e totali (riavvolti, già aggiornati, irrisolti, falliti).ops.key_rotation_progress: una riga per archivio e ambito una volta percorso, con i riferimenti di chiave non leggibili e quanti valori si trovavano sotto ciascuno. Una rotazione ripresa salta questi.- Catena di audit della piattaforma:
platform/key_rotation_request(con la motivazione), unaplatform/key_rotation_storeper archivio con i suoi conteggi, eplatform/key_rotation_completeoppureplatform/key_rotation_fail;platform/key_age_reminderper il promemoria. - Metriche:
quire.secrets.master_key.ageequire.secrets.rewrap.outstanding(valori che l’ultima rotazione non ha potuto spostare).
Quando i valori sono irrisolti
Un valore irrisolto è avvolto sotto un riferimento di chiave che questa installazione non
possiede, oppure non è nella forma promessa dalla sua colonna. Il record di avanzamento nomina il
riferimento (ad esempio env:QUIRE_MASTER_KEY:v0 (unreadable)). Ripristina quella chiave
in QUIRE_MASTER_KEY_RETIRED ed esegui un’altra rotazione, oppure, se la chiave è persa
per sempre, chiedi all’amministratore dell’organizzazione di inserire di nuovo la credenziale:
essa verrà sigillata sotto la chiave corrente. Le rotazioni fallite mostrano il loro errore sul
record; correggi la causa e richiedi di nuovo.
Chiavi di firma
Separate dalla chiave master: ciascuna organizzazione firma i propri token OpenID Connect
e messaggi LTI con la propria chiave RSA, pubblicata in /.well-known/jwks.json.
Qui nulla richiede un operatore. La programmazione oraria platform.signing_keys
pubblica un successore sette giorni prima che i novanta della chiave corrente scadano, una settimana
dopo il successore inizia a firmare e la vecchia chiave diventa in ritiro, e novanta
giorni dopo la vecchia chiave viene eliminata e lascia il set di chiavi. Ogni passaggio è una
voce platform/signing_key_advance sulla catena di audit della piattaforma.
Per sostituire prima la chiave di un’organizzazione, ad esempio dopo un’esposizione:
- nella console: Sicurezza, Chiave master, Pubblica una nuova chiave di firma (serve
platform/keys_manage); oppure - su una shell con l’ambiente del worker:
bun run kek:rotate signing-keys rotate --tenant <slug or id> --reason "Key exposed, INC-3310".bun run kek:rotate signing-keys statuselenca le chiavi di ogni organizzazione per fase.
La nuova chiave viene pubblicata subito e inizia a firmare dopo sette giorni, quando la
chiave corrente va in ritiro. La settimana è intenzionale: le parti fidate memorizzano il set di chiavi,
e una sovrapposizione più breve fa fallire ogni strumento in una volta sola. La chiave in ritiro resta nel set di chiavi
per altri novanta giorni così i token già firmati continuano a verificarsi; se
l’esposizione richiede che smetta di essere attendibile prima, eliminare la sua riga è una modifica
effettuata con l’accesso database proprio dell’operatore sotto un record di modifica (l’accesso di
emergenza è di sola lettura), e i token firmati con essa falliscono poi la verifica. La
rotazione forzata è platform/signing_key_rotate nella catena di audit, con la
motivazione. Il worker necessita delle stesse impostazioni QUIRE_MASTER_KEY del livello web per
avvolgere la nuova chiave; bun run kek:rotate per la chiave master riavvolge le chiavi di firma
con tutto il resto (oauth_signing_key è in SEALED_STORES).
Accesso di emergenza alla produzione
Nessuno detiene un accesso permanente alla produzione. Quando qualcosa non può attendere, un proprietario emette una concessione di emergenza: Console piattaforma, Sicurezza, Accesso di emergenza.
- Una concessione ha un ambito (un’organizzazione, oppure il registro della piattaforma), una motivazione di almeno 20 caratteri che nomina l’incidente o il ticket, e una finestra da 5 a 240 minuti. Scade da sola: viene verificata contro l’orologio a ogni istruzione.
- Può essere emessa al proprietario che la emette, oppure a un altro proprietario (il modulo a due persone).
Solo la persona a cui è stata emessa può usarla. Emettere richiede
platform/break_glass_issuee usare richiedeplatform/break_glass_use; entrambi sono riservati ai proprietari per impostazione predefinita. - Le istruzioni girano tramite il gateway, non su un login database: sola lettura, una alla volta, confinate all’organizzazione o al registro di controllo, con timeout di cinque secondi e al massimo 500 righe. I valori binari sono mostrati per dimensione.
- La catena di audit della piattaforma registra l’emissione (con la motivazione), la revoca,
ogni istruzione prima che giri (
platform/break_glass_statement, quelle rifiutate con esitodenied) e ogni risultato (platform/break_glass_result).ops.break_glass_statementcontiene gli id delle voci di audit, così il record di emissione si unisce alle sue voci di audit. - Le scritture non sono offerte. Una modifica che non può attendere una release usa l’accesso database proprio dell’operatore sotto un proprio record di modifica, fuori da questo prodotto, e il record dovrebbe citare il riferimento di incidente usato qui.
Perché non emettere credenziali database: un login Postgres sopravvive alla sessione che l’ha chiesto, aggira la sicurezza a livello di riga su cui l’applicazione fa affidamento, e non può scrivere nella catena di audit di questo prodotto, così le sue istruzioni sarebbero verificate solo fin dove qualcuno ha spedito il registro del server. Il gateway rende la traccia di audit una proprietà dell’accesso anziché una pratica attorno a esso.
Per rispondere a una richiesta di audit: elenca le concessioni del periodo (Accesso di emergenza),
apri la cronologia di una concessione per le sue istruzioni e gli id delle voci di audit, e leggi quelle
voci sulla catena di audit della piattaforma (bun run audit:verify --platform prova che la
catena è integra).