Šifriranje u MySQL: Keystore

U iščekivanju početka novog upisa za kurs "baza podataka" Za vas smo pripremili prijevod korisnog članka.

Šifriranje u MySQL: Keystore

Transparentno šifriranje podataka (TDE) se pojavilo u Percona server za MySQL i MySQL već neko vrijeme. Ali da li ste ikada razmišljali o tome kako radi ispod haube i kakav uticaj TDE može imati na vaš server? U ovoj seriji članaka ćemo pogledati kako TDE radi interno. Počnimo sa pohranom ključeva, jer je to potrebno da bi bilo koje šifriranje funkcioniralo. Zatim ćemo detaljnije pogledati kako enkripcija funkcionira u Percona Server za MySQL/MySQL i koje dodatne mogućnosti ima Percona Server za MySQL.

MySQL Keyring

Keyring su dodaci koji omogućavaju serveru da traži, kreira i briše ključeve u lokalnoj datoteci (keyring_file) ili na udaljenom serveru (kao što je HashiCorp Vault). Ključevi se uvijek keširaju lokalno kako bi se ubrzalo njihovo preuzimanje.

Dodaci se mogu podijeliti u dvije kategorije:

  • Lokalna pohrana. Na primjer, lokalna datoteka (mi ovo zovemo privjesak za ključeve baziran na fajlovima).
  • Daljinsko skladištenje. Na primjer, Vault Server (mi ovo zovemo privjesak za ključeve baziran na serveru).

Ovo razdvajanje je važno jer se različite vrste pohrane ponašaju malo drugačije, ne samo prilikom pohranjivanja i preuzimanja ključeva, već i prilikom njihovog pokretanja.

Kada koristite skladište datoteka, nakon pokretanja, cijeli sadržaj skladišta se učitava u keš memoriju: ID ključa, korisnik ključa, tip ključa i sam ključ.

U slučaju trgovine na strani servera (kao što je Vault Server), pri pokretanju se učitavaju samo ID ključa i korisnik ključa, tako da preuzimanje svih ključeva ne usporava pokretanje. Ključevi se lijeno učitavaju. Odnosno, sam ključ se učitava iz Vaulta samo kada je zaista potreban. Nakon preuzimanja, ključ se kešira u memoriju tako da mu se u budućnosti ne treba pristupati preko TLS konekcija na Vault Server. 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 — tip ključa zasnovan na korištenom algoritmu šifriranja, moguće vrijednosti: “AES”, “RSA” ili “DSA”.
  • dužina ključa — dužina 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č sistemski, na primjer, glavni ključ, onda je ovo polje prazno. Ako je ključ kreiran pomoću keyring_udf, tada ovo polje identifikuje vlasnika ključa.
  • sam ključ

Ključ je jedinstveno identificiran parom: key_id, korisnik.

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

Pohrana datoteka je brža. Možda mislite da skladište ključeva jednostavno upisuje ključ u datoteku jednom, ali ne, ovdje se događa više. Kad god se napravi modifikacija pohrane datoteka, prvo se kreira sigurnosna kopija cijelog sadržaja. Recimo da se datoteka zove my_biggest_secrets, tada će rezervna kopija biti my_biggest_secrets.backup. Zatim se mijenja keš (ključevi se dodaju ili brišu) i, ako je sve uspješno, keš se resetuje u datoteku. U rijetkim slučajevima, kao što je kvar servera, 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 servera).

Prilikom pohranjivanja ili brisanja ključa u skladištu servera, skladište se mora povezati sa MySQL serverom pomoću naredbi “pošalji ključ” / “zahtjevati brisanje ključa”.

Vratimo se na brzinu pokretanja servera. Pored činjenice da na brzinu pokretanja utiče sam trezor, postoji i pitanje koliko ključeva iz trezora treba preuzeti pri pokretanju. Naravno, ovo je posebno važno za skladištenje na serveru. Prilikom pokretanja, server provjerava koji je ključ potreban za šifrirane tabele/prostore tablica i traži ključ iz skladišta. Na „čistom“ serveru sa šifrovanjem Master Key, mora postojati jedan Master Key, koji se mora preuzeti iz skladišta. Međutim, može biti potreban veći broj ključeva, na primjer, kada rezervni server vraća rezervnu kopiju sa primarnog servera. U takvim slučajevima treba osigurati rotaciju glavnog ključa. Ovo će biti detaljnije pokriveno u budućim člancima, iako bih ovdje želio napomenuti da serveru koji koristi više glavnih ključeva može biti potrebno malo duže da se pokrene, posebno kada se koristi skladište ključeva na strani servera.

Hajde sada da pričamo malo više o keyring_file. Kada sam razvijao keyring_file, također sam se brinuo o tome kako provjeriti promjene u keyring_file dok server radi. U verziji 5.7 provjera je izvršena na osnovu statistike fajla, što nije bilo idealno rješenje, au 8.0 je zamijenjena kontrolnom sumom SHA256.

Kada prvi put pokrenete keyring_file, izračunavaju se statistika datoteke i kontrolni zbroj, koje server pamti, a promjene se primjenjuju samo ako se podudaraju. Kada se datoteka promijeni, kontrolni zbroj se ažurira.

Već smo pokrili mnoga pitanja o trezorima ključeva. Međutim, postoji još jedna važna tema koja se često zaboravlja ili pogrešno razumije: dijeljenje ključeva preko servera.

Ono što mislim? Svaki server (na primjer, Percona Server) u klasteru mora imati zasebnu lokaciju na Vault Serveru u kojoj Percona Server mora pohraniti svoje ključeve. Svaki glavni ključ sačuvan u skladištu sadrži GUID Percona servera unutar svog identifikatora. Zašto je to važno? Zamislite da imate samo jedan Vault server i da svi Percona serveri u klasteru koriste taj jedan Vault server. Problem se čini očiglednim. Ako bi svi Percona serveri koristili glavni ključ bez jedinstvenih identifikatora, kao što su id = 1, id = 2, itd., tada bi svi serveri u klasteru koristili isti glavni ključ. Ono što GUID pruža je razlika između servera. Zašto onda pričati o dijeljenju ključeva između servera ako već postoji jedinstveni GUID? Postoji još jedan dodatak - keyring_udf. Pomoću ovog dodatka, korisnik vašeg servera može pohraniti svoje ključeve na Vault server. Problem se javlja kada korisnik kreira ključ na serveru1, na primjer, a zatim pokuša kreirati ključ sa istim ID-om na serveru2, na primjer:

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

Čekaj. Oba servera koriste isti Vault Server, zar funkcija keyring_key_store ne bi trebala otkazati na serveru2? Zanimljivo, ako pokušate da uradite isto na jednom serveru, dobić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.

Razmotrimo prvo drugi primjer. Kao što smo ranije rekli, keyring_vault ili bilo koji drugi dodatak za ključeve kešira sve ID-ove ključeva u memoriju. Dakle, nakon kreiranja novog ključa, ROB_1 se dodaje na server1, a osim što se ovaj ključ šalje u Vault, ključ se dodaje i u keš memoriju. Sada, kada pokušamo da dodamo isti ključ drugi put, keyring_vault provjerava da li ključ postoji u kešu i ispušta grešku.

U prvom slučaju situacija je drugačija. Server1 i server2 imaju odvojene keš memorije. Nakon dodavanja ROB_1 u predmemoriju ključeva na serveru1 i Vault serveru, keš ključeva na serveru2 nije sinkroniziran. Nema ključa ROB_2 u kešu na serveru1. Dakle, ključ ROB_1 se upisuje u keyring_key_store i na Vault server, koji zapravo prepisuje (!) prethodnu vrijednost. Sada je ključ ROB_1 na serveru trezora 543210987654321. Zanimljivo je da server trezora ne blokira takve radnje i lako prepisuje staru vrijednost.

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

Postoje dva načina za particiju u Vault. Možete kreirati različite tačke montiranja za svaki server ili koristiti različite staze unutar iste tačke montiranja. To je najbolje ilustrovati primjerima. Pogledajmo prvo pojedinačne tač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 tačke montiranja. Prilikom podjele 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 servera koriste istu tačku montiranja "mount_point", ali različite putanje. Kada kreirate prvu tajnu na server1 koristeći ovu stazu, Vault server automatski kreira direktorij “server1”. Za server2 je sve slično. Kada izbrišete posljednju tajnu u mount_point/server1 ili mount_point/server2, server trezora također briše te direktorije. U slučaju da koristite razdvajanje staza, morate kreirati samo jednu tačku montiranja i promijeniti konfiguracijske datoteke tako da serveri koriste odvojene staze. Tačka montiranja može se kreirati korištenjem HTTP zahtjeva. Koristeći CURL ovo se može uraditi 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 Vault uslužne programe da učinite isto. Ali lakše je automatizirati kreiranje točke montiranja. Nadam se da će vam ove informacije biti korisne i vidimo se u sljedećim člancima u ovoj seriji.

Šifriranje u MySQL: Keystore

Čitaj više:

izvor: www.habr.com

Dodajte komentar