In attesa dell'avvio di un nuovo ciclo di corsi abbiamo preparato per voi la traduzione di un articolo utile.

La crittografia trasparente dei dati (Transparent Data Encryption, TDE) è disponibile in e MySQL da molto tempo. Ma ti sei mai chiesto come funziona dietro le quinte e quale impatto possa avere TDE sul tuo server? In questa serie di articoli esamineremo come TDE funziona internamente. Iniziamo con l'archiviazione delle chiavi, poiché è necessaria per qualsiasi tipo di crittografia. Successivamente, esamineremo in dettaglio come funziona la crittografia in Percona Server for MySQL/MySQL e quali funzionalità aggiuntive offre Percona Server for MySQL.
MySQL Keyring
Keyring è un plugin che consente al server di richiedere, creare ed eliminare chiavi in un file locale (keyring_file) o su un server remoto (ad esempio, in HashiCorp Vault). Le chiavi vengono sempre memorizzate nella cache localmente per accelerare il loro recupero.
I plugin possono essere suddivisi in due categorie:
- Archiviazione locale. Ad esempio, un file locale (lo definiamo archivio delle chiavi basato su file, file-based keyring).
- Archiviazione remota. Ad esempio, Vault Server (lo definiamo archivio delle chiavi basato su server, server-based keyring).
Questa distinzione è importante, poiché diversi tipi di archiviazione si comportano in modo leggermente diverso non solo durante la memorizzazione e il recupero delle chiavi, ma anche durante l'avvio.
Quando si utilizza un archivio basato su file, al momento dell'avvio viene caricato nella cache l'intero contenuto dell'archivio: id chiave, utente chiave, tipo chiave e la chiave stessa.
Nel caso di un archivio basato su server (ad esempio, un server Vault), al momento dell'avvio vengono caricati solo l'id chiave e l'utente chiave, quindi il recupero di tutte le chiavi non rallenta l'avvio. Le chiavi vengono caricate in modo pigro. Cioè, la chiave stessa viene caricata da Vault solo quando è effettivamente necessaria. Dopo il caricamento, la chiave viene memorizzata nella cache nella memoria, in modo da non doverla richiedere nuovamente tramite connessioni TLS al Vault Server. Successivamente, vedremo quali informazioni sono presenti nell'archivio delle chiavi.
Le informazioni sulla chiave contengono quanto segue:
- id chiave — identificatore della chiave, ad esempio:
INNODBKey-764d382a-7324-11e9-ad8f-9cb6d0d5dc99-1 - tipo chiave — tipo di chiave, basato sull'algoritmo di crittografia utilizzato, i valori possibili sono: «AES», «RSA» o «DSA».
- lunghezza chiave — lunghezza della chiave in byte, AES: 16, 24 o 32, RSA 128, 256, 512 e DSA 128, 256 o 384.
- user — proprietario della chiave. Se la chiave è di sistema, ad esempio, Master Key, questo campo è vuoto. Se la chiave è creata tramite keyring_udf, questo campo indica il proprietario della chiave.
- la chiave stessa
La chiave è univocamente identificata dalla coppia: key_id, user.
Ci sono anche differenze nel salvataggio e nella rimozione delle chiavi.
Il repository file funziona più velocemente. Si potrebbe presumere che il repository delle chiavi sia una semplice registrazione della chiave in un file, ma non è così: ci sono più operazioni in corso. In caso di qualsiasi modifica al repository file, viene prima creato un backup di tutto il contenuto. Supponiamo che il file si chiami my_biggest_secrets, quindi il backup sarà my_biggest_secrets.backup. Successivamente, viene modificata la cache (vengono aggiunte o rimosse chiavi) e, se tutto va a buon fine, la cache viene scritta nel file. In rari casi, come un guasto del server, potresti vedere questo file di backup. Il file di backup viene eliminato al successivo caricamento delle chiavi (di solito dopo il riavvio del server).
Quando si salva o si rimuove una chiave nel repository del server, il repository deve connettersi al server MySQL con i comandi "inviare chiave" / "richiedere cancellazione chiave" ("send the key" / "request key deletion").
Torniamo alla velocità di avvio del server. Oltre al fatto che la velocità di avvio è influenzata dal repository stesso, c'è anche la questione di quante chiavi dal repository devono essere recuperate all'avvio. Certamente, questo è particolarmente importante per i repository server. Durante l'avvio, il server verifica quale chiave è necessaria per le tabelle / tablespace crittografati e richiede la chiave dal repository. Su un server "pulito" con Master Key — la crittografia deve esserci un'unica Master Key che deve essere estratta dal repository. Tuttavia, potrebbe essere necessaria un numero maggiore di chiavi, ad esempio quando un server di backup ripristina un backup dal server principale. In questi casi, deve essere prevista una rotazione della Master Key. Questo sarà approfondito in articoli futuri, anche se qui vorrei sottolineare che un server che utilizza più Master Key potrebbe avviarsi leggermente più a lungo, soprattutto quando si utilizza un repository di chiavi server.
Ora parliamo ancora un po' di keyring_file. Quando ho sviluppato keyring_file, mi preoccupava anche come controllare le modifiche a keyring_file durante il funzionamento del server. Nella versione 5.7, il controllo veniva effettuato sulla base delle statistiche del file, il che non era una soluzione ideale, e nella versione 8.0 è stato sostituito con un checksum SHA256.
All'avvio di keyring_file, vengono calcolate le statistiche del file e il checksum, che vengono memorizzati dal server, e le modifiche vengono applicate solo se coincidono. Quando il file viene modificato, il checksum viene aggiornato.
Abbiamo già esaminato molte problematiche relative ai vault delle chiavi. Tuttavia, c'è un altro argomento importante che spesso viene dimenticato o frainteso: la separazione delle chiavi tra i server.
Cosa intendo? Ogni server (ad esempio, Percona Server) in un cluster deve avere uno spazio separato sul server Vault, in cui Percona Server deve memorizzare le proprie chiavi. In ogni Master Key memorizzato nel vault è contenuto il GUID del server Percona Server all'interno del proprio identificatore. Perché è importante? Immagina di avere un solo Server Vault e tutti i Percona Server nel cluster utilizzano quest'unico Server Vault. Il problema sembra ovvio. Se tutti i Percona Server utilizzassero un Master Key senza identificatori unici, ad esempio, id = 1, id = 2 e così via, tutti i server nel cluster utilizzerebbero lo stesso Master Key. Ciò che fornisce il GUID è la separazione tra i server. Perché allora parlare di separazione delle chiavi tra i server, se esiste già un GUID unico? C'è un altro plugin: keyring_udf. Con questo plugin, l'utente del tuo server può memorizzare le proprie chiavi sul server Vault. Il problema sorge quando l'utente crea una chiave, ad esempio, sul server server1, e poi cerca di crearne una con lo stesso identificatore su server2, ad esempio:
--server1:
select keyring_key_store('ROB_1','AES',"123456789012345");
1
--1 significa completamento con successo
--server2:
select keyring_key_store('ROB_1','AES',"543210987654321");
1Aspetta. Entrambi i server utilizzano lo stesso Server Vault, non dovrebbe la funzione keyring_key_store terminare con un errore sul server server2? È interessante notare che se provi a fare lo stesso su un singolo server, otterrai un errore:
--server1:
select keyring_key_store('ROB_1','AES',"123456789012345");
1
select keyring_key_store('ROB_1','AES',"543210987654321");
0Esatto, ROB_1 esiste già.
Iniziamo discutendo il secondo esempio. Come abbiamo già detto in precedenza, keyring_vault o qualsiasi altro plugin di archiviazione (keyring) memorizza nella cache tutti gli identificatori delle chiavi in memoria. Pertanto, dopo aver creato una nuova chiave, ROB_1 viene aggiunta a server1 e, oltre all'invio di questa chiave a Vault, la chiave viene anche aggiunta alla cache. Ora, quando proviamo ad aggiungere la stessa chiave per la seconda volta, keyring_vault controlla se questa chiave esiste nella cache e restituisce un errore.
Nel primo caso la situazione è diversa. I server server1 e server2 hanno cache separate. Dopo aver aggiunto ROB_1 nella cache delle chiavi sul server server1 e sul server Vault, la cache delle chiavi su server2 non è sincronizzata. Nella cache su server2 non c'è la chiave ROB_1. Pertanto, la chiave ROB_1 viene scritta in keyring_key_store e nel server Vault, il che effettivamente sovrascrive (!) il valore precedente. Ora la chiave ROB_1 sul server Vault è uguale a 543210987654321. È interessante notare che il server Vault non blocca tali operazioni e sovrascrive tranquillamente il valore precedente.
Ora vediamo perché la separazione per server su Vault può essere importante — quando si utilizza keyring_udf e si desidera memorizzare le chiavi in Vault. Come garantire tale separazione sul server Vault?
Ci sono due modi per separare su Vault. Si possono creare diversi punti di montaggio per ciascun server o utilizzare percorsi diversi all'interno di un unico punto di montaggio. È meglio mostrarlo con degli esempi. Quindi, iniziamo a guardare prima i punti di montaggio separati:
--server1:
vault_url = http://127.0.0.1:8200
secret_mount_point = server1_mount
token = (...)
vault_ca = (...)
--server2:
vault_url = http://127.0.0.1:8200
secret_mount_point = sever2_mount
token = (...)
vault_ca = (...)Qui si può vedere che server1 e server2 utilizzano punti di montaggio diversi. Quando si separano i percorsi, la configurazione apparirà come segue:
--server1:
vault_url = http://127.0.0.1:8200
secret_mount_point = mount_point/server1
token = (...)
vault_ca = (...)
--server2:
vault_url = http://127.0.0.1:8200
secret_mount_point = mount_point/sever2
token = (...)
vault_ca = (...)In questo caso, entrambi i server utilizzano lo stesso punto di montaggio "mount_point", ma percorsi diversi. Quando si crea il primo segreto sul server server1 tramite questo percorso, il server Vault crea automaticamente la directory "server1". Per server2 è tutto analogo. Quando si elimina l'ultimo segreto in mount_point/server1 o mount_point/server2, il server Vault elimina anche queste directory. Se si utilizza la separazione dei percorsi, è necessario creare solo un punto di montaggio e modificare i file di configurazione affinché i server utilizzino percorsi separati. Il punto di montaggio può essere creato tramite una richiesta HTTP. Con CURL si può fare in questo modo:
curl -L -H "X-Vault-Token: TOKEN" –cacert VAULT_CA
--data '{"type":"generic"}' --request POST VAULT_URL/v1/sys/mounts/SECRET_MOUNT_POINTTutti i campi (TOKEN, VAULT_CA, VAULT_URL, SECRET_MOUNT_POINT) corrispondono ai parametri del file di configurazione. Naturalmente, è possibile utilizzare gli strumenti di Vault per fare la stessa cosa. Ma è più semplice automatizzare la creazione del punto di montaggio. Spero che queste informazioni siano utili e ci vediamo nei prossimi articoli di questa serie.
Leggi anche:
Fonte: habr.com
