Crittografia dei nostri backup: arrivare a quel traguardo

Pubblicato: 2017-09-02

Nota: questo post di ingegneria è stato scritto dalla nostra amministratore del database, Silvia Botros. Dai un'occhiata ad alcuni dei suoi altri post DBA qui.

Un anno fa, SendGrid stava lavorando duramente per ottenere la certificazione SOC2. Tutti erano coinvolti. C'erano storie su quasi tutte le bacheche dei team di consegna con un tag SOC2 poiché stavamo tutti cercando di ottenere la certificazione entro la fine del terzo trimestre. Come puoi immaginare, essendo il responsabile dei database, c'era sicuramente del lavoro da fare per quella parte dello stack.

Nella mia lista delle attività per questa impresa a livello aziendale c'era la certezza che i nostri backup fossero crittografati. Dal momento che la mia area di familiarità sono gli strumenti DBA e sapendo che xtrabackup di Percona ha già il supporto per la crittografia, era prevedibile che sarei andato a quello come primo tentativo in questa attività.

Nel testare questo approccio avevo nel mirino alcune cose importanti:

  • Ovviamente, il backup doveva essere crittografato
  • Il sovraccarico per la creazione del backup doveva essere noto e accettabile
  • Il sovraccarico per la decrittografia del backup al momento del ripristino doveva essere noto e accettabile

Ciò significava che prima dovevo essere in grado di monitorare quanto tempo impiegano i miei backup.

Monitoraggio del tempo di backup

SendGrid utilizza Graphite per le sue metriche di infrastruttura e mentre la stragrande maggioranza viene inviata tramite Sensu, Graphite è abbastanza facile da inviare le metriche direttamente tramite linee bash, molto conveniente poiché gli script di backup sono in bash. Nota che l'invio diretto delle metriche a Graphite non è super scalabile, ma poiché questi backup vengono eseguiti al massimo una volta all'ora, andava bene per le mie esigenze.

Quella parte si è rivelata relativamente facile.

Per spiegare cosa è successo in quell'ultima riga, invio a Graphite il percorso della metrica che sto inviando (assicurati che sia univoca), il valore della metrica, quindi l'ora corrente in formato epoch. Netcat è quello che ho deciso di usare per semplicità, e gli do un timeout di 1 secondo perché, altrimenti, non uscirà mai. L'"URL di grafite" è il nostro endpoint DNS per la grafite nel data center.

Ora che avevo una linea di base con cui confrontare, eravamo pronti per iniziare a testare i metodi di crittografia.

Seguendo la documentazione dettagliata di Percona su come farlo, ho iniziato creando una chiave. Se leggi attentamente quella pagina della documentazione, potresti realizzare qualcosa.

Questa chiave deve essere passata direttamente allo strumento di backup ed è la stessa chiave che può decrittografare lo snapshot. Si chiama crittografia simmetrica ed è, per natura della stessa chiave in entrambe le direzioni, meno sicura della crittografia asimmetrica. Ho deciso di continuare a testare per vedere se la semplicità rende ancora questo un approccio praticabile.

I test con DB molto piccoli, poche centinaia di MB, hanno avuto successo. Lo strumento funziona come previsto e documentato, ma si trattava più di un test funzionale e la vera domanda era "qual è l'entità della penalizzazione della crittografia sui nostri DB più grandi?" Le istanze più legacy di SendGrid erano cresciute fino a dimensioni da 1-2 TB a una singola bestia da 18 TB. Quello che avrei usato per le istanze piccole doveva essere operativamente accettabile anche per quelle più grandi.

È qui che i test e i benchmark sono diventati interessanti

Il mio primo soggetto di prova di dimensioni considerevoli è un database che abbiamo da 1 TB su disco. Molto rapidamente ho riscontrato un problema imprevisto. Con impostazioni di crittografia minime (1 thread, dimensioni dei blocchi predefinite), ho visto i backup fallire con questo errore:

All'epoca, questi database utilizzavano 512 MB come dimensione del file di registro delle transazioni, e questo è un cluster abbastanza occupato, quindi quei file ruotavano quasi ogni minuto. Normalmente, questo sarebbe evidente nelle prestazioni del DB, ma è stato per lo più mascherato dalla meraviglia delle unità a stato solido. Sembra che non impostare alcun thread di crittografia parallela (leggi: usane uno) significa che passiamo così tanto tempo a crittografare i file `.ibd` che i roll di redo log di innodb da sotto di noi stavano interrompendo il backup.

Quindi, proviamo di nuovo con un numero di thread di crittografia. Come primo tentativo, ho provato con 50 thread. Il trucco qui è trovare il punto debole della crittografia veloce senza competere con la CPU. Ho anche aumentato la dimensione di `ib_logfiles` a 1 GB ciascuno.

Questo è stato un test di maggior successo che sono stato felice di far fermentare durante la notte. Per le prime notti, le cose sembravano buone. Era ora di fare un backup che non crescesse troppo, ma il carico medio del box durante il processo di backup mostrava sicuramente i passaggi aggiunti.

Tuttavia, quando sono passato al test dei ripristini, ho scoperto che il processo di ripristino degli stessi backup, dopo l'aggiunta della crittografia, era aumentato da 60 a 280 minuti, il che significa una grave penalizzazione del tempo di ripristino promesso in caso di disastro.

Dovevamo riportarlo a un lasso di tempo più ragionevole.

È qui che brillava il lavoro di squadra e soluzioni più semplici ai problemi. Uno dei membri del nostro team InfoSec ha deciso di vedere se questa soluzione può essere semplificata. Quindi ha fatto altri test ed è tornato con qualcosa di più semplice e sicuro. Non avevo ancora imparato a conoscere gpg2 e quindi questo è diventato un esercizio di apprendimento anche per me.

La cosa buona di gpg2 è che supporta la crittografia asimmetrica. Creiamo una coppia di chiavi dove ci sono parti private e pubbliche. La parte pubblica viene utilizzata per crittografare qualsiasi flusso o file che decidi di alimentare gpg2 e il segreto privato può essere utilizzato per decrittografare.

La modifica ai nostri script di backup per aggiungere la crittografia distillata a questo. Alcuni argomenti sono stati rimossi per facilitare la lettura:

D'altra parte, durante il ripristino di un backup, dobbiamo semplicemente assicurarci che una chiave segreta accettabile sia nel keyring dell'host e quindi utilizzare questo comando:

Dato che anche io ero nuovo di gpg2, questa è diventata un'opportunità di apprendimento per me. Colin, il nostro fantastico membro del team InfoSec, ha continuato a testare backup e ripristini utilizzando gpg2 fino a quando non ha confermato che l'utilizzo di gpg2 presenta molteplici vantaggi rispetto all'utilizzo della compressione incorporata di xtrabackup, tra cui:

  • Era asimmetrico
  • La sua gestione segreta per la decrittazione è ruotata in modo relativamente semplice (più su questo sotto)
  • È indipendente dallo strumento, il che significa che qualsiasi altro tipo di backup che non utilizza xtrabackup potrebbe utilizzare lo stesso metodo
  • Stava usando più core per la decrittazione che ci ha dato tempi di ripristino migliori

Sempre margini di miglioramento

Un punto in cui vedo ancora margini di miglioramento è il modo in cui gestiamo il segreto in grado di decrittografare questi file. Al momento, li abbiamo nella nostra soluzione di gestione delle password aziendali, ma ottenerli da lì, quindi utilizzarli per testare i backup è un processo manuale. Il prossimo passo nel nostro piano è implementare Vault di Hashicorp e usarlo per estrarre senza problemi e sugli host designati la chiave segreta per la decrittazione, quindi rimuoverla dall'anello locale in modo che sia facilmente disponibile per i test automatizzati e sia ancora protetta.

In definitiva, abbiamo ottenuto che tutti i nostri backup del database siano conformi alle nostre esigenze SOC2 in tempo senza sacrificare le prestazioni di backup o lo SLA per il ripristino di emergenza. Mi sono divertito molto a lavorare su questo compito con il nostro team di InfoSec e ne sono uscito imparando nuovi strumenti. Inoltre, è sempre bello quando la soluzione più semplice finisce per essere la più adatta al proprio compito.