Enkripcija u MySQL: Keystore

U iščekivanju početka novih upisa na tečaj "Baza podataka" Za vas smo pripremili prijevod korisnog članka.

Enkripcija u MySQL: Keystore

Transparent Data Encryption (TDE) pojavio se u Percona poslužitelj za MySQL i MySQL već neko vrijeme. Ali jeste li ikada razmišljali o tome kako funkcionira ispod haube i kakav utjecaj TDE može imati na vaš poslužitelj? U ovoj seriji članaka pogledat ćemo kako TDE radi interno. Počnimo s pohranjivanjem ključeva, budući da je to potrebno za bilo koje šifriranje. Zatim ćemo pobliže pogledati kako funkcionira enkripcija u Percona Serveru za MySQL/MySQL i koje dodatne značajke ima Percona Server za MySQL.

MySQL privjesak za ključeve

Keyring su dodaci koji poslužitelju omogućuju postavljanje upita, stvaranje i brisanje ključeva u lokalnoj datoteci (keyring_file) ili na udaljenom poslužitelju (kao što je HashiCorp Vault). Ključevi se uvijek lokalno predmemoriraju kako bi se ubrzalo njihovo dohvaćanje.

Dodaci se mogu podijeliti u dvije kategorije:

  • Lokalna pohrana. Na primjer, lokalna datoteka (ovo zovemo privjesak ključeva temeljen na datotekama).
  • Udaljena pohrana. Na primjer, Vault Server (ovo zovemo privjesak ključeva temeljen na poslužitelju).

Ovo odvajanje je važno jer se različite vrste pohrane ponašaju malo drugačije, ne samo kada pohranjuju i dohvaćaju ključeve, već i kada ih izvode.

Kada koristite pohranu datoteka, nakon pokretanja, cijeli sadržaj pohrane se učitava u predmemoriju: ID ključa, korisnik ključa, vrsta ključa i sam ključ.

U slučaju pohrane na strani poslužitelja (kao što je Vault Server), pri pokretanju se učitavaju samo ID ključa i korisnik ključa, tako da dobivanje svih ključeva ne usporava pokretanje. Ključevi se lijeno učitavaju. Odnosno, sam ključ se učitava iz Vaulta samo kada je stvarno potreban. Nakon preuzimanja, ključ se predmemorira u memoriji tako da mu se u budućnosti ne mora pristupati putem TLS veza s Vault Serverom. Zatim, pogledajmo koje su informacije prisutne u spremištu ključeva.

Ključne informacije sadrže sljedeće:

  • ID ključa — identifikator ključa, na primjer:
    INNODBKey-764d382a-7324-11e9-ad8f-9cb6d0d5dc99-1
  • tip ključa — vrsta ključa na temelju korištenog algoritma šifriranja, moguće vrijednosti: „AES“, „RSA“ ili „DSA“.
  • duljina ključa — duljina ključa u bajtovima, AES: 16, 24 ili 32, RSA 128, 256, 512 i DSA 128, 256 ili 384.
  • korisnik - vlasnik ključa. Ako je ključ sustav, na primjer, Glavni ključ, tada je ovo polje prazno. Ako je ključ kreiran pomoću keyring_udf, tada ovo polje identificira vlasnika ključa.
  • sam ključ

Ključ je jedinstveno identificiran parom: key_id, user.

Također postoje razlike u pohranjivanju i brisanju ključeva.

Pohranjivanje datoteka je brže. Možda mislite da pohrana ključeva jednostavno jednom zapisuje ključ u datoteku, ali ne, ovdje se događa nešto više. Kad god se izvrši izmjena pohrane datoteke, prvo se stvara sigurnosna kopija cijelog sadržaja. Recimo da se datoteka zove my_biggest_secrets, tada će sigurnosna kopija biti my_biggest_secrets.backup. Zatim se mijenja predmemorija (ključevi se dodaju ili brišu) i, ako je sve uspješno, predmemorija se vraća na datoteku. U rijetkim slučajevima, kao što je kvar poslužitelja, možete vidjeti ovu datoteku sigurnosne kopije. Datoteka sigurnosne kopije se briše sljedeći put kada se ključevi učitaju (obično nakon ponovnog pokretanja poslužitelja).

Prilikom spremanja ili brisanja ključa u pohranu poslužitelja, pohrana se mora povezati s MySQL poslužiteljem s naredbama “pošalji ključ” / “zatraži brisanje ključa”.

Vratimo se brzini pokretanja poslužitelja. Osim činjenice da na brzinu pokretanja utječe sam trezor, postoji i pitanje koliko ključeva iz trezora treba dohvatiti pri pokretanju. Naravno, ovo je posebno važno za pohranu na poslužitelju. Prilikom pokretanja poslužitelj provjerava koji je ključ potreban za šifrirane tablice/prostore tablica i traži ključ iz pohrane. Na "čistom" poslužitelju s enkripcijom glavnog ključa mora postojati jedan glavni ključ koji se mora dohvatiti iz pohrane. Međutim, može biti potreban veći broj ključeva, na primjer, kada rezervni poslužitelj vraća sigurnosnu kopiju s primarnog poslužitelja. U takvim slučajevima treba osigurati rotaciju glavnog ključa. Ovo će biti detaljnije obrađeno u budućim člancima, iako bih ovdje želio napomenuti da poslužitelju koji koristi više glavnih ključeva može trebati malo više vremena da se pokrene, posebno kada se koristi pohrana ključeva na strani poslužitelja.

Sada razgovarajmo još malo o keyring_file. Kad sam razvijao keyring_file, također sam se brinuo o tome kako provjeriti promjene keyring_filea dok poslužitelj radi. U 5.7 provjera se vršila na temelju statistike datoteka, što nije bilo idealno rješenje, au 8.0 je zamijenjeno SHA256 kontrolnim zbrojem.

Kada prvi put pokrenete keyring_file, izračunava se statistika datoteke i kontrolni zbroj, koje poslužitelj pamti, a promjene se primjenjuju samo ako odgovaraju. Kada se datoteka promijeni, kontrolni zbroj se ažurira.

Već smo obradili mnoga pitanja o trezorima ključeva. Međutim, postoji još jedna važna tema koja se često zaboravlja ili krivo shvaća: dijeljenje ključeva između poslužitelja.

Što mislim? Svaki poslužitelj (na primjer, Percona poslužitelj) u klasteru mora imati zasebnu lokaciju na Vault poslužitelju u kojem Percona poslužitelj mora pohraniti svoje ključeve. Svaki glavni ključ spremljen u pohrani sadrži GUID Percona poslužitelja unutar svog identifikatora. Zašto je to važno? Zamislite da imate samo jedan Vault Server i da svi Percona poslužitelji u klasteru koriste taj jedan Vault Server. Problem se čini očitim. Kad bi svi Percona poslužitelji koristili glavni ključ bez jedinstvenih identifikatora, kao što su id = 1, id = 2 itd., tada bi svi poslužitelji u klasteru koristili isti glavni ključ. Ono što GUID pruža je razlika između poslužitelja. Zašto onda govoriti o dijeljenju ključeva između poslužitelja ako jedinstveni GUID već postoji? Postoji još jedan dodatak - keyring_udf. Pomoću ovog dodatka korisnik vašeg poslužitelja može pohraniti svoje ključeve na poslužitelj trezora. Problem se javlja kada korisnik kreira ključ na poslužitelju1, na primjer, a zatim pokuša stvoriti ključ s istim ID-om na poslužitelju2, na primjer:

--server1:
select keyring_key_store('ROB_1','AES',"123456789012345");
1
--1 значит успешное завершение
--server2:
select keyring_key_store('ROB_1','AES',"543210987654321");
1

Čekati. Oba poslužitelja koriste isti Vault Server, ne bi li funkcija keyring_key_store trebala pasti na poslužitelju2? Zanimljivo, ako pokušate učiniti isto na jednom poslužitelju, dobit ćete grešku:

--server1:
select keyring_key_store('ROB_1','AES',"123456789012345");
1
select keyring_key_store('ROB_1','AES',"543210987654321");
0

Tako je, ROB_1 već postoji.

Raspravimo prvo o drugom primjeru. Kao što smo ranije rekli, keyring_vault ili bilo koji drugi dodatak za ključeve sprema sve ID-ove ključeva u memoriju. Dakle, nakon kreiranja novog ključa, ROB_1 se dodaje na server1, a osim što ovaj ključ šalje Vaultu, ključ se također dodaje u predmemoriju. Sada, kada pokušamo dodati isti ključ drugi put, keyring_vault provjerava postoji li ključ u predmemorij i javlja pogrešku.

U prvom slučaju situacija je drugačija. Server1 i server2 imaju odvojene predmemorije. Nakon dodavanja ROB_1 u predmemoriju ključeva na poslužitelju1 i Vault poslužitelju, predmemorija ključeva na poslužitelju2 nije sinkronizirana. Ne postoji ključ ROB_2 u predmemorij na poslužitelju1. Stoga se ključ ROB_1 zapisuje u keyring_key_store i na Vault poslužitelj, koji zapravo prepisuje (!) prethodnu vrijednost. Sada je ključ ROB_1 na Vault poslužitelju 543210987654321. Zanimljivo je da Vault poslužitelj ne blokira takve radnje i lako prepisuje staru vrijednost.

Sada možemo vidjeti zašto particioniranje poslužitelja u Vaultu može biti važno - kada koristite keyring_udf i želite pohraniti ključeve u Vault. Kako postići ovo odvajanje na Vault poslužitelju?

Postoje dva načina particioniranja u Vault. Možete stvoriti različite točke montiranja za svaki poslužitelj ili koristiti različite staze unutar iste točke montiranja. To je najbolje ilustrirati primjerima. Dakle, pogledajmo prvo pojedinačne točke montiranja:

--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 = (...)

Ovdje možete vidjeti da server1 i server2 koriste različite točke montiranja. Prilikom dijeljenja staza konfiguracija će izgledati ovako:

--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 = (...)

U ovom slučaju, oba poslužitelja koriste istu točku montiranja "mount_point", ali različite staze. Kada stvorite prvu tajnu na poslužitelju1 pomoću ove staze, Vault poslužitelj automatski stvara direktorij "poslužitelj1". Za server2 sve je slično. Kada izbrišete posljednju tajnu u mount_point/server1 ili mount_point/server2, Vault poslužitelj također briše te direktorije. U slučaju da koristite odvajanje staza, morate stvoriti samo jednu točku montiranja i promijeniti konfiguracijske datoteke tako da poslužitelji koriste zasebne staze. Točka montiranja može se stvoriti pomoću HTTP zahtjeva. Koristeći CURL ovo se može učiniti ovako:

curl -L -H "X-Vault-Token: TOKEN" –cacert VAULT_CA
--data '{"type":"generic"}' --request POST VAULT_URL/v1/sys/mounts/SECRET_MOUNT_POINT

Sva polja (TOKEN, VAULT_CA, VAULT_URL, SECRET_MOUNT_POINT) odgovaraju parametrima konfiguracijske datoteke. Naravno, možete koristiti pomoćne programe Vault da učinite isto. Ali lakše je automatizirati stvaranje točke montiranja. Nadam se da će vam ove informacije biti korisne i vidimo se u sljedećim člancima u ovoj seriji.

Enkripcija u MySQL: Keystore

Čitaj više:

Izvor: www.habr.com

Dodajte komentar