Krüpteerimine MySQL-is: võtmehoidla

Kursusele uue registreerimise ootuses "Andmebaas" Oleme teile koostanud kasuliku artikli tõlke.

Krüpteerimine MySQL-is: võtmehoidla

aastal ilmus Transparent Data Encryption (TDE). Percona server MySQL-i jaoks ja MySQL-i juba mõnda aega. Kuid kas olete kunagi mõelnud, kuidas see kapoti all töötab ja millist mõju võib TDE teie serverile avaldada? Selles artiklite sarjas vaatleme, kuidas TDE sisemiselt töötab. Alustame võtme salvestamisest, kuna see on vajalik igasuguse krüptimise toimimiseks. Seejärel vaatame lähemalt, kuidas Percona Server for MySQL/MySQL krüptimine töötab ja millised lisafunktsioonid Percona Server for MySQL-il on.

MySQL võtmehoidja

Võtmehoidja on pistikprogrammid, mis võimaldavad serveril teha päringuid, luua ja kustutada võtmeid kohalikus failis (keyring_file) või kaugserveris (nt HashiCorp Vault). Võtmed salvestatakse alati kohalikku vahemällu, et kiirendada nende otsimist.

Pluginad võib jagada kahte kategooriasse:

  • Kohalik salvestusruum. Näiteks kohalik fail (nimetame seda failipõhiseks võtmehoidjaks).
  • Kaugsalvestusruum. Näiteks Vault Server (nimetame seda serveripõhiseks võtmehoidjaks).

See eraldamine on oluline, kuna erinevat tüüpi salvestusruumid käituvad veidi erinevalt mitte ainult võtmete salvestamisel ja hankimisel, vaid ka nende käitamisel.

Failimälu kasutamisel laaditakse käivitamisel kogu salvestusruumi sisu vahemällu: võtme ID, võtme kasutaja, võtme tüüp ja võti ise.

Serveripoolse poe (nt Vault Server) puhul laaditakse käivitamisel ainult võtme ID ja võtmekasutaja, nii et kõigi võtmete hankimine ei aeglusta käivitamist. Võtmeid laetakse laisalt. See tähendab, et võti laaditakse Vaultist ainult siis, kui seda tegelikult vaja on. Pärast allalaadimist salvestatakse võti vahemällu, nii et sellele ei pea tulevikus Vault Serveriga TLS-ühenduste kaudu juurde pääsema. Järgmisena vaatame, milline teave võtmehoidlas on.

Põhiteave sisaldab järgmist:

  • võtme ID — võtme identifikaator, näiteks:
    INNODBKey-764d382a-7324-11e9-ad8f-9cb6d0d5dc99-1
  • võtme tüüp — kasutataval krüpteerimisalgoritmil põhinev võtme tüüp, võimalikud väärtused: “AES”, “RSA” või “DSA”.
  • võtme pikkus — võtme pikkus baitides, AES: 16, 24 või 32, RSA 128, 256, 512 ja DSA 128, 256 või 384.
  • kasutaja - võtme omanik. Kui võtmeks on süsteemne võti, näiteks põhivõti, siis on see väli tühi. Kui võti luuakse võtmerõngas_udf abil, identifitseerib see väli võtme omaniku.
  • võti ise

Võti identifitseerib unikaalselt paar: võtme_id, kasutaja.

Erinevused on ka võtmete salvestamisel ja kustutamisel.

Failide salvestamine on kiirem. Võib arvata, et võtmehoidja kirjutab võtme lihtsalt faili üks kord, kuid ei, siin toimub rohkem. Alati, kui faili salvestamisel tehakse muudatusi, luuakse esmalt kogu sisust varukoopia. Oletame, et faili nimi on my_biggest_secrets, siis on varukoopiaks my_biggest_secrets.backup. Järgmisena muudetakse vahemälu (lisatakse või kustutatakse võtmed) ja kui kõik õnnestub, lähtestatakse vahemälu failiks. Harvadel juhtudel, näiteks serveri rikke korral, võite näha seda varukoopiafaili. Varundusfail kustutatakse järgmisel võtmete laadimisel (tavaliselt pärast serveri taaskäivitamist).

Võtme salvestamisel või kustutamisel serveri salvestusruumis peab salvestusruum looma ühenduse MySQL-serveriga käskudega “send the key” / “request key deletion”.

Pöördume tagasi serveri käivituskiiruse juurde. Lisaks sellele, et käivituskiirust mõjutab varahoidla ise, on probleem ka selles, kui palju võtmeid varahoidlast käivitamisel tuleb hankida. Loomulikult on see eriti oluline serveri salvestusruumi jaoks. Käivitamisel kontrollib server, millist võtit on krüptitud tabelite/tabeliruumide jaoks vaja, ja küsib võtit salvestusruumist. Peavõtme krüptimisega "puhtal" serveril peab olema üks põhivõti, mis tuleb salvestusruumist alla laadida. Siiski võib olla vajalik suurem arv võtmeid, näiteks kui varuserver taastab varukoopiat esmasest serverist. Sellistel juhtudel tuleks tagada peavõtme pöörlemine. Seda käsitletakse üksikasjalikumalt tulevastes artiklites, kuigi siinkohal tahaksin märkida, et mitut peavõtit kasutava serveri käivitamine võib võtta veidi kauem aega, eriti kui kasutatakse serveripoolset võtmehoidjat.

Räägime nüüd natuke lähemalt võtmerõnga_failist. Keyring_file'i arendades muretsesin ka selle pärast, kuidas serveri töötamise ajal faili võtmerõnga_faili muudatusi kontrollida. 5.7-s tehti kontroll failistatistika põhjal, mis ei olnud ideaalne lahendus ja 8.0-s asendati see SHA256 kontrollsummaga.

Keyring_file esmakordsel käivitamisel arvutatakse faili statistika ja kontrollsumma, mille server jätab meelde ning muudatusi rakendatakse ainult siis, kui need ühtivad. Kui fail muutub, värskendatakse kontrollsummat.

Oleme juba käsitlenud palju võtmehoidlaid puudutavaid küsimusi. Siiski on veel üks oluline teema, mida sageli unustatakse või mõistetakse valesti: võtmete jagamine serverite vahel.

Mida ma mõtlen? Igal klastri serveril (näiteks Percona serveril) peab Vault Serveris olema eraldi asukoht, kuhu Percona Server oma võtmed salvestama. Iga salvestusruumi salvestatud põhivõti sisaldab oma identifikaatoris Percona serveri GUID-i. Miks see oluline on? Kujutage ette, et teil on ainult üks Vault Server ja kõik klastris olevad Percona serverid kasutavad seda ühte Vault serverit. Probleem tundub ilmne. Kui kõik Percona serverid kasutaksid peavõtit ilma unikaalsete identifikaatoriteta (nt id = 1, id = 2 jne), siis kasutaksid kõik klastri serverid sama peavõtit. See, mida GUID pakub, on serverite erinevus. Miks siis rääkida võtmete jagamisest serverite vahel, kui kordumatu GUID on juba olemas? On veel üks pistikprogramm - keyring_udf. Selle pistikprogrammi abil saab teie serveri kasutaja salvestada oma võtmed Vault serverisse. Probleem ilmneb siis, kui kasutaja loob võtme serveris 1 ja seejärel proovib luua sama ID-ga võtit serveris 2, näiteks:

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

Oota. Mõlemad serverid kasutavad sama Vault Serverit. Kas funktsioon keyring_key_store ei peaks serveris2 ebaõnnestuma? Huvitav on see, et kui proovite sama teha ühes serveris, kuvatakse tõrketeade:

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

See on õige, ROB_1 on juba olemas.

Arutleme kõigepealt teise näite üle. Nagu me varem ütlesime, salvestab keyring_vault või mõni muu võtmehoidja pistikprogramm kõik mällu võtme ID-d. Seega lisatakse pärast uue võtme loomist serverisse ROB_1 ja lisaks selle võtme saatmisele Vaulti lisatakse võti ka vahemällu. Nüüd, kui proovime sama võtit teist korda lisada, kontrollib keyring_vault, kas võti on vahemälus olemas, ja annab veateate.

Esimesel juhul on olukord erinev. Server1 ja server2 omavad eraldi vahemälu. Pärast ROB_1 lisamist serveri 1 võtme vahemällu ja Vault serverisse on serveri 2 võtme vahemälu sünkroonist väljas. Server2 vahemälus pole võtit ROB_1. Seega kirjutatakse võti ROB_1 võtmehoidja_võtmepoodi ja Vault serverisse, mis tegelikult kirjutab (!) eelmise väärtuse üle. Nüüd on Vault serveri võti ROB_1 543210987654321. Huvitaval kombel ei blokeeri Vault server selliseid toiminguid ja kirjutab vana väärtuse kergesti üle.

Nüüd näeme, miks võib serveri partitsioonide eraldamine Vaultis olla oluline – kui kasutate võtmerõngas_udf-i ja soovite võtmeid Vaultis salvestada. Kuidas seda eraldamist Vaulti serveris saavutada?

Vaulti jagamiseks on kaks võimalust. Saate luua iga serveri jaoks erinevad ühenduspunktid või kasutada samas ühenduspunktis erinevaid teid. Seda on kõige paremini illustreeritud näidetega. Nii et vaatame kõigepealt üksikuid kinnituspunkte:

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

Siin näete, et server1 ja server2 kasutavad erinevaid ühenduspunkte. Radade jagamisel näeb konfiguratsioon välja järgmine:

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

Sel juhul kasutavad mõlemad serverid sama ühenduspunkti "mount_point", kuid erinevaid teid. Kui loote selle tee abil serveris1 esimese saladuse, loob Vault server automaatselt serveri1 kataloogi. Server2 puhul on kõik sarnane. Kui kustutate viimase saladuse kaustas mount_point/server1 või mount_point/server2, kustutab Vault server ka need kataloogid. Kui kasutate tee eraldamist, peate looma ainult ühe ühenduspunkti ja muutma konfiguratsioonifaile nii, et serverid kasutaksid eraldi teid. Ühenduspunkti saab luua HTTP päringu abil. CURL-i kasutades saab seda teha järgmiselt:

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

Kõik väljad (TOKEN, VAULT_CA, VAULT_URL, SECRET_MOUNT_POINT) vastavad konfiguratsioonifaili parameetritele. Muidugi saate sama tegemiseks kasutada Vault utiliite. Kuid kinnituspunkti loomist on lihtsam automatiseerida. Loodan, et see teave on teile kasulik ja näeme teid selle sarja järgmistes artiklites.

Krüpteerimine MySQL-is: võtmehoidla

Loe rohkem:

Allikas: www.habr.com

Lisa kommentaar