Uoči početka novog upisa na kurs pripremili smo za vas prevod korisnog članka.

Transparentno šifriranje podataka (Transparent Data Encryption, TDE) uvedeno je u i MySQL već dugo. Ali jeste li se ikad zapitali kako to funkcioniše ispod haube i koji uticaj TDE može imati na vaš server? U ovoj seriji članaka razmotrićemo kako TDE funkcioniše unutra. Počećemo s skladištenjem ključeva, jer je to neophodno za funkcionisanje svakog šifriranja. Zatim ćemo detaljno razmotriti kako šifriranje funkcioniše u Percona Server za MySQL/MYSQL i koje dodatne mogućnosti postoje u Percona Server za MySQL.
MySQL Keyring
Keyring je plugin koji omogućava serveru da zahteva, kreira i briše ključeve u lokalnoj datoteci (keyring_file) ili na udaljenom serveru (npr. u HashiCorp Vault-u). Ključevi se uvek keširaju lokalno za brži pristup.
Plugin možemo podeliti u dve kategorije:
- Lokalno skladište. Na primer, lokalna datoteka (ovo nazivamo skladištem ključeva zasnovano na datoteci, file-based keyring).
- Udaljeno skladište. Na primer Vault Server (ovo nazivamo skladištem ključeva zasnovano na serveru, server-based keyring).
Ova podela je važna jer se različiti tipovi skladišta ponašaju malo drugačije ne samo pri skladištenju i dobijanju ključeva, već i pri pokretanju.
Kada koristite skladište zasnovano na datoteci, prilikom pokretanja se kešira sav sadržaj skladišta: key id, key user, key type i sam ključ.
U slučaju skladišta zasnovanog na serveru (npr. Vault server), prilikom pokretanja se kešira samo key id i key user, stoga preuzimanje svih ključeva ne usporava pokretanje. Ključevi se učitavaju lenjo. To znači da se ključ preuzima iz Vault-a samo kada zaista zatreba. Nakon preuzimanja, ključ se kešira u memoriji kako ne bi bilo potrebe da se u budućnosti obraća za njim putem TLS veza prema Vault Server-u. Sada ćemo razmotriti koju informaciju skladište ključeva sadrži.
Informacije o ključu sadrže sledeće:
- key id — identifikator ključa, na primer:
INNODBKey-764d382a-7324-11e9-ad8f-9cb6d0d5dc99-1 - key type — tip ključa, zasnovan na korišćenom algoritmu šifriranja, moguće vrednosti: „AES“, „RSA“ ili „DSA“.
- key length — dužina ključa u bajtovima, AES: 16, 24 ili 32; RSA: 128, 256, 512 i DSA: 128, 256 ili 384.
- uporabnik — lastnik ključa. Če je ključ sistemski, na primer, Master Key, je to polje prazno. Če se ključ ustvari z uporabo keyring_udf, to polje označuje lastnika ključa.
- sam ključ
Ključ se nedvoumno identificira s parom: key_id, user.
Obstajajo tudi razlike v shranjevanju in brisanja ključev.
Datotečno shranjevanje deluje hitreje. Lahko bi domnevali, da je shranjevanje ključev preprosto enkratno beleženje ključa v datoteko, vendar ni tako — tukaj poteka več operacij. Pri vsaki spremembi datotečnega shranjevanja se najprej ustvari varnostna kopija vsebine. Recimo, da se datoteka imenuje my_biggest_secrets, potem bo varnostna kopija my_biggest_secrets.backup. Nato se spremeni predpomnilnik (dodajo ali odstranijo se ključi) in, če je vse uspešno, se predpomnilnik zapiše v datoteko. V redkih primerih, kot je napaka strežnika, lahko vidite to varnostno kopijo. Varnostna kopija se odstrani ob naslednjem nalaganju ključev (ponavadi po ponovnem zagonu strežnika).
Pri shranjevanju ali brisanju ključa v strežniškem shranjevanju se mora shranjevanje povezati s strežnikom MySQL s ukazi "pošlji ključ" / "zahtevaj brisanje ključa" ("send the key" / "request key deletion").
Poglejmo nazaj na hitrost zagona strežnika. Poleg tega, da na hitrost zagona vpliva samo shranjevanje, je tudi vprašanje, koliko ključev iz shranjevanja je treba pridobiti ob zagonu. Seveda je to še posebej pomembno za strežniška shranjevanja. Ob zagonu strežnik preveri, kateri ključ je potreben za šifrirane tabele / tabelarna prostora in zahteva ključ iz shranjevanja. Na "čistem" strežniku s šifriranjem Master Key mora biti en Master Key, ki ga je treba pridobiti iz shranjevanja. Vendar pa je lahko potreben tudi večji števil ključev, na primer, ko se na rezervnem strežniku obnavlja varnostna kopija iz glavnega strežnika. V takih primerih je treba predvideti rotacijo Master Key. O tem bo več govorjeno v prihodnjih člankih, čeprav bi rad opozoril, da se strežnik, ki uporablja več Master Key, lahko zažene nekoliko dlje, zlasti ob uporabi strežnega shranjevanja ključev.
Zdaj pa se pogovoriva še malo o keyring_file. Ko sem razvil keyring_file, me je skrbelo tudi, kako preveriti spremembo keyring_file med delovanjem strežnika. V 5.7 je bila preverba izvedena na podlagi statistike datoteke, kar ni bilo idealna rešitev, in v 8.0 je bila zamenjana s kontrolno vsoto SHA256.
Ob prvem zagonu keyring_file se izračuna statistika datoteke in kontrolna vsota, ki ju strežnik zapomni, in spremembe se uporabijo le, če se ujemajo. Ob spremembi datoteke se kontrolna vsota posodobi.
Že smo obravnavali mnoge zadeve glede skladišč ključev. Vendar pa je še ena pomembna tema, ki jo pogosto pozabljamo ali napačno razumemo — ločitev ključev po strežnikih.
Kaj mislim s tem? Vsak strežnik (na primer, Percona Server) v klastru mora imeti ločen prostor na strežniku Vault, kjer mora Percona Server hraniti svoje ključe. V vsakem Master Key, shranjenem v skladišču, je GUID strežnika Percona Server znotraj svojega identifikatorja. Zakaj je to pomembno? Predstavljajte si, da imate le en Vault Server in vsi Percona Serverji v klastru uporabljajo ta edini Vault Server. Težava se zdi očitna. Če bi vsi Percona Serverji uporabljali Master Key brez edinstvenih identifikatorjev, na primer, id = 1, id = 2 itd., bi vsi strežniki v klastru uporabljali isti Master Key. Kar zagotavlja GUID — ločitev med strežniki. Zakaj torej govoriti o ločitvi ključev med strežniki, če že obstaja edinstven GUID? Obstaja še en vtičnik — keyring_udf. S pomočjo tega vtičnika lahko uporabnik vašega strežnika hrani svoje ključe na strežniku Vault. Težava se pojavi, ko uporabnik ustvari ključ, na primer, na strežniku server1, nato pa poskuša ustvariti ključa z enakim identifikatorjem na server2, na primer:
--server1:
select keyring_key_store('ROB_1','AES',"123456789012345");
1
--1 pomeni uspešno dokončanje
--server2:
select keyring_key_store('ROB_1','AES',"543210987654321");
1Počakajte. Obe strežniki uporabljata isti Vault Server, ali ne bi morala funkcija keyring_key_store končati s napako na strežniku server2? Zanimivo je, da če poskusite narediti isto na enem strežniku, boste dobili napako:
--server1:
select keyring_key_store('ROB_1','AES',"123456789012345");
1
select keyring_key_store('ROB_1','AES',"543210987654321");
0Prav, ROB_1 že obstaja.
Najprej se pogovorimo o drugem primeru. Kot smo že prej omenili, keyring_vault ali kateri koli drug vtičnik shrambe (keyring) predpomni vse identifikatorje ključev v pomnilniku. Tako, po tem, ko je bilo ustvarjeno novo ključe, ROB_1 dodano na server1, in poleg pošiljanja tega ključa v Vault, se ključ tudi doda v predpomnilnik. Zdaj, ko poskušamo dodati enak ključ drugič, keyring_vault preveri, ali ta ključ obstaja v predpomnilniku, in izda napako.
V prvem primeru je situacija drugačna. Na strežnikih server1 in server2 so ločeni predpomnilniki. Po dodajanju ROB_1 v predpomnilnik ključev na strežniku server1 in strežniku Vault, se predpomnilnik ključev na server2 ne sinhronizira. V predpomnilniku na server2 ni ključa ROB_1. Tako se ključ ROB_1 shrani v keyring_key_store in na strežniku Vault, kar dejansko prepisuje (!) prejšnjo vrednost. Sedaj je ključ ROB_1 na strežniku Vault enak 543210987654321. Zanimivo je, da strežnik Vault ne blokira takšnih dejanj in preprosto prepisuje staro vrednost.
Zdaj vidimo, zakaj je razdelitev po strežnikih na Vaultu lahko pomembna — kadar uporabljate keyring_udf in želite shraniti ključe v Vault. Kako zagotoviti takšno razdelitev na strežniku Vault?
Obstajata dva načina za razdelitev na Vault. Lahko ustvarite različne točke montaže za vsak strežnik ali uporabite različne poti znotraj ene točke montaže. Najbolje bo to pokazati na primerih. Torej, najprej poglejmo ločene točke montaže:
--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 = (...)Tukaj je razvidno, da server1 in server2 uporabljata različne točke montaže. Pri razdelitvi poti bo konfiguracija videti takole:
--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 = (...)V tem primeru oba strežnika uporabljata isto točko montaže "mount_point", vendar različne poti. Ko ustvarite prvo skrivnost na strežniku server1 po tej poti, strežnik Vault samodejno ustvari imenik "server1". Za server2 je vse enako. Ko izbrišete zadnjo skrivnost v mount_point/server1 ali mount_point/server2, strežnik Vault prav tako izbriše te imenike. V primeru, da uporabljate razdelitev poti, morate ustvariti le eno točko montaže in spremeniti konfiguracijske datoteke, da strežniki uporabljajo ločene poti. Točko montaže lahko ustvarite s pomočjo HTTP zahtevka. S CURL to lahko storite takole:
curl -L -H "X-Vault-Token: TOKEN" –cacert VAULT_CA
--data '{"type":"generic"}' --request POST VAULT_URL/v1/sys/mounts/SECRET_MOUNT_POINTVsa polja (TOKEN, VAULT_CA, VAULT_URL, SECRET_MOUNT_POINT) ustrezajo parametrom konfiguracijske datoteke. Seveda lahko uporabite orodja Vault, da naredite isto. A tako je preprosteje avtomatizirati ustvarjanje točke montaže. Upam, da vam bo ta informacija koristna in se vidimo v naslednjih člankih te serije.
Preberi več:
Izvor: habr.com
