Database di audit presso The Grid
Pubblicato: 2018-09-29Poiché SendGrid è diventata di recente una società quotata in borsa, dovevamo disporre di registri di controllo completi di tutte le modifiche a un sottoinsieme dei nostri database. Questo sottoinsieme includeva alcune piccole istanze che non registravano un volume di traffico elevato, ma anche alcuni dei nostri cluster meno recenti che sono fondamentali per il tempo di attività del nostro portale clienti e il flusso di registrazione.
Ciò ha influito anche su alcuni datastore che richiedevano tempi di attività elevati ed era auspicabile un'implementazione online (senza tempi di inattività per le scritture). Con una scadenza esterna a portata di mano e conoscendo la portata del progetto, abbiamo deciso di fare un piano.
In fase di progettazione, abbiamo individuato alcune domande aperte a cui avevamo bisogno di risposte:
- Quali opzioni abbiamo per quanto riguarda il software in grado di farlo?
- Quale impatto sulle prestazioni è previsto e quanto possiamo testarlo in anticipo?
- Possiamo farlo senza tempi di inattività per la disponibilità in scrittura?
Scelte, scelte
In SendGrid, seguiamo un processo di progettazione per qualsiasi progetto di grandi dimensioni o multi-team. Questo progetto ha coinvolto una serie di team come stakeholder, tra cui:
- L'audit interno in quanto team incaricato di definire quale archivio dati rientra nell'ambito di questo controllo di conformità e per la raccolta di prove giunge al momento dell'audit
- InfoSec come il team che doveva analizzare e gestire la risposta agli incidenti derivata da questi registri di controllo del database
- DB Ops come il team che scrive il codice che distribuisce, gestisce e ottimizza questa nuova funzionalità per i database nell'ambito
Ho deciso di scrivere questo progetto e assicurarmi che fosse esaminato da tutte le parti interessate e approvato dal nostro team di architettura. Anche se un paio di anni fa avevo svolto alcune ricerche sull'argomento della registrazione di audit in MySQL e avevo un'idea di come fosse il panorama delle opzioni, non volevo affrontare il progetto con pregiudizi e volevo comunque indagare su più di uno opzione e fornire a tutti un solido caso del perché dovremmo scegliere una soluzione piuttosto che un'altra.
Questo progetto era insolito in quanto lo stavo scrivendo contemporaneamente mentre indagavo su quale sarebbe stata la soluzione alle esigenze aziendali. Quindi sapevo che molti dettagli sarebbero stati compilati mentre facevamo delle ricerche.
Le nostre opzioni erano:
- Plugin di controllo Percona
- Mcafee MySQL Audit
Sebbene queste non siano le uniche opzioni sul mercato, abbiamo ritenuto che fossero le più vicine alle nostre pratiche di scala e devops per giustificare l'inclusione nell'effettiva cottura. Altre opzioni commerciali sul mercato non hanno superato tale limite per essere incluse nel benchmark.
Quest'ultima era una soluzione più recente aperta solo di recente da Mcafee ed era abbastanza intrigante da esaminare perché affermava di supportare il filtraggio a livello di tabella che il plug-in Percona non faceva. Dal momento che sapevamo che uno dei nostri cluster di ambito doveva effettivamente controllare circa 24 tabelle su un totale di 300, questa sembrava essere una funzionalità abbastanza preziosa da rendere il plug-in Mcafee un contendente.
D'altra parte, il plug-in Percona Audit era la soluzione open source più utilizzata per questa funzionalità. Viene integrato ma disabilitato in Percona Server, che già utilizziamo. Tuttavia, non fornisce il filtraggio degli eventi a livello di tabella, il che significava che dovevamo farlo al di fuori del livello del database.
Sfornare
Con l'aiuto del nostro team di partner di Pythian, abbiamo iniziato il confronto di cottura. All'inizio, abbiamo confrontato come installare e ottimizzare ciascuna opzione. Il team ha rapidamente stabilito che avevamo un compromesso tra le mani. Sebbene il plug-in Mcafee supportasse i filtri delle tabelle in modo nativo, non supportava l'uso di rsyslog come metodo per lo streaming dei suoi eventi. Ciò significava che se dovessimo usarlo avremmo dovuto scrivere i file localmente su disco e gestire l'invio allo stack di monitoraggio.
Ciò non è stato ritenuto desiderabile in quanto molto probabilmente aumenterebbe la penalizzazione delle prestazioni dell'utilizzo del plug-in di audit. Scrivere gli eventi di controllo in locale e poi leggerli di nuovo con un processo separato sottrae capacità IOPS dal nostro traffico di produzione effettivo e aumenta il rischio per le istanze del database poiché significa che dobbiamo gestire la dimensione di questi file sul disco per evitare che si gonfino e causino il database tempo di inattività.
D'altra parte del compromesso c'era il plugin Percona. Supporta l'invio degli eventi a syslog in modo nativo ma non offre filtri di tabella. Sapevamo che ciò significava che i cluster più occupati nell'ambito invieranno un gran numero di eventi, la maggior parte dei quali non provengono effettivamente dalle tabelle che vogliamo controllare. Ciò presentava un rischio per il livello syslog-receive/logstash dello stack di monitoraggio di InfoSec. Dal momento che DB ops non ha accesso a ciò, significava che il successo di questo progetto era uno sforzo di proprietà condivisa.
Alla fine, abbiamo deciso di utilizzare la soluzione con meno parti mobili e di pianificare la nostra implementazione per sapere il prima possibile se logstash doveva essere ridimensionato per gestire il filtraggio di migliaia di eventi al secondo. Quindi è stata presa la decisione di andare avanti con il plug-in di audit di Percona.
Pianificazione della distribuzione
Ambito di installazione
Abbiamo deciso di semplificare questa distribuzione installando e abilitando il plug-in su tutti i nodi in un determinato cluster, eliminando la necessità di orchestrare l'attivazione o disattivazione della funzione di controllo quando il nodo writer in un cluster cambia. Non abbiamo avuto alcuna preoccupazione per il flusso di replica che causa eventi duplicati quando viene applicata una modifica perché il plug-in, in base alla progettazione, non registra le modifiche del flusso di replica.
Nessun tempo di inattività
Volevamo che si trattasse di una distribuzione senza interruzioni senza tempi di inattività nei cluster interessati. Ciò ridurrebbe notevolmente la quantità di pianificazione e orchestrazione che avremmo bisogno di fare con i team di consegna che utilizzano questi cluster e ridurrebbe notevolmente l'impatto sui clienti. Ma volevamo anche che il plug-in inviasse i suoi eventi a rsyslog, su una struttura specifica, con una configurazione personalizzata che avrebbe inviato gli eventi al server di aggregazione syslog del team di InfoSec. Alcune di queste configurazioni sono documentate come non dinamiche da Percona e ciò presentava la possibilità che ogni istanza nell'ambito di questo progetto subisse dei tempi di inattività quando riavviamo l'istanza mysql con il plug-in di controllo richiesto config.
Abbiamo iniziato a testare diversi ordini operativi nella distribuzione del plug-in con un'istanza di test dedicata nel nostro ambiente di staging e siamo stati in grado di dimostrare che se la nostra gestione della configurazione disponesse inizialmente tutte le configurazioni necessarie, quindi eseguiva il comando di caricamento del plug -in, il comando sarebbe avviare con la configurazione desiderata.
Ciò si è rivelato fondamentale sia per semplificare il piano per il completamento di questo progetto sia per ridurre i tempi di rilascio in produzione, facendoci guadagnare tempo per ottimizzare il filtraggio degli eventi e collaborare con il team di sicurezza sull'analisi e il rilevamento.
Usa la gestione della configurazione
Utilizziamo i libri di cucina dello chef per gestire i nostri database, quindi ovviamente abbiamo pianificato di utilizzare lo chef per distribuire, ottimizzare e monitorare il plug-in di audit. Ma poiché questo doveva essere abilitato solo in un sottoinsieme dei nostri cluster, ciò significava che avevamo bisogno di un modo per controllare dove era abilitato in modo da non ingombrare il nostro archivio di log con dati non pertinenti al nostro obiettivo aziendale qui.

Per la gestione dei database MySQL, utilizziamo un modello di ricettario wrapper per gestire la configurazione. Un libro di cucina "di base" di base definisce la maggior parte di come dovrebbe apparire l'istanza del database, quindi un libro di cucina per cluster lo avvolge per modificare gli attributi o aggiungere la configurazione se pertinente al cluster specifico. Quel design ha reso facile aggiungere la maggior parte del codice che avrebbe creato i file di configurazione necessari, quindi caricare il plug-in in una nuova ricetta che possiamo quindi attivare e disattivare in base a un attributo chef. Abbiamo anche deciso, data la portata della modifica che stavamo apportando, che ciò garantisse il rilascio di questo codice come una nuova versione minore del ricettario.
Ci siamo anche assicurati che lo chef rimuovesse tutti i relativi controlli sensu e disattivi lo streaming di audit quando l'attributo era impostato su false. Questo per garantire che lo chef possa fare la cosa giusta se un cluster non è più compreso nell'ambito o deve essere interrotto per qualsiasi motivo intermittente, quindi non è necessario modificare manualmente un nodo per riflettere la modifica dell'attributo.
Monitoraggio
Non puoi dichiarare il successo di qualcosa che non stai monitorando. Ma anche il monitoraggio è più che schiaffeggiare alcuni controlli sensu senza pensare a quali casi di errore stiamo monitorando e quale azione ci aspettiamo in risposta a questi controlli che un giorno falliscono. Quindi ho deciso di pianificare il monitoraggio in questa pipeline con 2 cose in mente
- Dobbiamo essere tutti d'accordo sull'ambito di proprietà esplicito in questo sistema, soprattutto perché si trova a cavallo delle responsabilità di 2 squadre con rotazioni di guardia separate
- Eventuali nuovi controlli aggiunti per questo devono essere forniti con un runbook a cui ci colleghiamo nel controllo, che spieghi in cosa non riesce questo controllo e come risolverlo
Date queste 2 regole, ho provveduto ad aggiungere controlli molto specifici. A questo punto, ho pensato di aggiungere anche un controllo "sintetico" end-to-end, ma da allora mi sono astenuto dal farlo poiché un controllo end-to-end qui non sarebbe riuscito a dirci esattamente quale parte del sistema ha fallito, il che significa che avremmo avuto difficoltà tempo anche impaginando la squadra giusta con esso. E non sono un sostenitore del paging delle persone di notte "per ogni evenienza"
Abbiamo deciso di monitorare quanto segue:
- Controlla la configurazione di mysql live del plug-in di controllo per assicurarti che
- Il plug-in era in stato attivo
- Audit_log_policy è stato impostato su QUERIES
Questo controllo conferma che un DB nell'ambito non ha avuto la sua configurazione modificata al volo poiché queste impostazioni sono dinamiche e potrebbero cambiare al di fuori del file my.cnf su disco .
- Controlla la porta su cui inviamo i log allo stack di monitoraggio per assicurarti che i dati scorrano. Fondamentalmente, assicurandosi che l'altra estremità del flusso syslog funzioni. Questo controllo viene gestito come ciò che senso chiama un controllo aggregato in modo da non eseguire egregiamente il paging del team di InfoSec
Ostacoli lungo il percorso
Verifica la configurazione del plug-in
Una delle iterazioni iniziali di questo progetto intendeva sfruttare la funzionalità audit_log_exclude_commands per limitare gli eventi che emettiamo alla sola manipolazione dei dati o dello schema. Abbiamo subito appreso che l'elenco su cui si basa questa configurazione è molto più lungo di quanto ci si aspetterebbe.
configurazione di rsyslog
Ecco qualcosa che non sapevo prima di questo progetto. La configurazione di Rsyslog è quasi la sua lingua. Per esempio:
- Utilizzare un secondo @ davanti alla destinazione remota per inviare i registri su TCP anziché su UDP. Volevamo utilizzare questa struttura per dare un po' più di garanzia sulla consegna dei registri.
- rsyslog ha una pagina dedicata su come configurarlo per un inoltro affidabile, che si è rivelato davvero utile per un principiante dello strumento come me.
- rsyslog, per impostazione predefinita, trasmetterà i suoi dati anche a /var/log/messages, cosa indesiderabile nel mio caso perché si tratta di MOLTI eventi. Se devi fare in modo che la struttura che stai utilizzando NON lo faccia, devi aggiungere local5.* ~ alla fine della tua configurazione
Esercitazione antincendio
Parlerò più avanti delle implicazioni sulle prestazioni per i database nell'ambito, ma poiché rsyslog veniva utilizzato come parte cruciale per questo progetto, dovevamo anche eseguire un'esercitazione antincendio su come si sarebbe comportato rsyslog quando la sua destinazione remota non è disponibile o non risponde. Il modo migliore per farlo era causare l'interruzione di tale comunicazione utilizzando le regole iptables in produzione su uno dei database nell'ambito che sapevamo avesse un'elevata velocità effettiva delle transazioni e quindi un grande volume di eventi di controllo al secondo. Ecco come è andata a finire quell'esercitazione antincendio.
- Verificare che gli eventi di controllo fluiscano sulla porta TCP designata
- Usa una regola iptables per eliminare tutto il traffico su quella porta /sbin/iptables -A OUTPUT -p tcp –dport {PORT-NUMBER-HERE} -j DROP
- Controlla l'attività di scrittura del disco e i file nella WorkDirectory configurata nella configurazione di rsyslog. I nomi dei file saranno basati su ActionQueueFileName della struttura che riceve questi eventi
Come previsto, i file hanno iniziato lo spooling in questa directory. Abbiamo riscontrato un picco nell'attività degli IOP del disco. Una volta che la dimensione del numero di file che definiva il nome della coda è stata sommata al valore di ActionQueueMaxDiskSpace , rsyslog ha interrotto la creazione di questi file, gli IOP del disco si sono normalizzati ed era chiaro che ora stavamo eliminando gli eventi sul pavimento nel livello rsyslog. Ciò che è stato più impressionante da vedere è che dopo aver rimosso la regola potable, rsyslog ha inviato nuovamente lo spooling su disco di tutti gli eventi, quindi non abbiamo avuto perdite di eventi per il nostro archivio di analisi fintanto che non abbiamo superato la dimensione dello spool. Abbiamo imparato alcune cose sulla base di quell'esperimento
- rsyslog si comporta come documentato. Sempre meglio dimostrarlo con esperimenti di prima mano
- Molto probabilmente dovremo definire uno spazio su disco di coda diverso per cluster a seconda del volume di eventi che ciascuno genera. Poiché l'accodamento su disco aggiunge rischi alla capacità degli IOP e alla capacità del disco, è una cosa che dovremo rivedere periodicamente e riesaminare
Nel prossimo post parlerò di quali sono state le nostre osservazioni dopo aver distribuito questo progetto alla produzione e di cosa lo ha reso il più possibile non dirompente per la produzione.
