Ĉifrado en MySQL: Ŝlosilvendejo

Antaŭĝoje de la komenco de nova aliĝo por la kurso "Datumbazo" Ni preparis tradukon de utila artikolo por vi.

Ĉifrado en MySQL: Ŝlosilvendejo

Travidebla Datuma Ĉifrado (TDE) aperis en Percona Servilo por MySQL kaj MySQL dum sufiĉe da tempo. Sed ĉu vi iam pensis pri kiel ĝi funkcias sub la kapuĉo kaj kian efikon povas havi TDE sur via servilo? En ĉi tiu serio de artikoloj ni rigardos kiel TDE funkcias interne. Ni komencu per ŝlosilstokado, ĉar ĉi tio estas postulata por ke iu ĉifrado funkciu. Poste ni rigardos pli detale kiel ĉifrado funkcias en Percona Server por MySQL/MySQL kaj kiajn kromajn funkciojn havas Percona Server por MySQL.

MySQL-Ŝlosilringo

Ŝlosilringo estas aldonaĵoj kiuj permesas al la servilo pridemandi, krei kaj forigi ŝlosilojn en loka dosiero (keyring_file) aŭ sur fora servilo (kiel ekzemple HashiCorp Vault). Ŝlosiloj ĉiam estas konservitaj loke por akceli sian rehavigon.

Kromaĵoj povas esti dividitaj en du kategoriojn:

  • Loka stokado. Ekzemple, loka dosiero (ni nomas tion dosier-bazita ŝlosilringo).
  • Fora stokado. Ekzemple, Vault Server (ni nomas tion servil-bazita ŝlosilringo).

Ĉi tiu disiĝo estas grava ĉar malsamaj specoj de stokado kondutas iomete malsame, ne nur dum stokado kaj reakiro de ŝlosiloj, sed ankaŭ dum rulado de ili.

Kiam oni uzas dosier-stokadon, post ekfunkciigo, la tuta enhavo de la stokado estas ŝarĝita en la kaŝmemoron: ŝlosila id, ŝlosila uzanto, ŝlosila tipo kaj la ŝlosilo mem.

En la kazo de servil-bazita vendejo (kiel ekzemple Vault Server), nur la ŝlosilidentigilo kaj ŝlosila uzanto estas ŝarĝitaj ĉe ekfunkciigo, do ricevi ĉiujn ŝlosilojn ne malrapidigas la ekfunkciigon. Ŝlosiloj estas ŝarĝitaj pigre. Tio estas, la ŝlosilo mem estas ŝarĝita de Vault nur kiam ĝi estas efektive bezonata. Post kiam elŝutite, la ŝlosilo estas konservita en memoro por ke ĝi ne bezonu esti alirita per TLS-konektoj al la Vault-Servilo estonte. Poste, ni rigardu, kiajn informojn troviĝas en la ŝlosila vendejo.

La ŝlosilaj informoj enhavas la jenajn:

  • ŝlosila id — ŝlosila identigilo, ekzemple:
    INNODBKey-764d382a-7324-11e9-ad8f-9cb6d0d5dc99-1
  • ŝlosila tipo — ŝlosiltipo bazita sur la ĉifrada algoritmo uzata, eblaj valoroj: "AES", "RSA" aŭ "DSA".
  • ŝlosila longo — ŝlosillongo en bajtoj, AES: 16, 24 aŭ 32, RSA 128, 256, 512 kaj DSA 128, 256 aŭ 384.
  • surhavi - posedanto de la ŝlosilo. Se la ŝlosilo estas sistemo, ekzemple, Ĉefŝlosilo, tiam ĉi tiu kampo estas malplena. Se ŝlosilo estas kreita per keyring_udf, tiam ĉi tiu kampo identigas la posedanton de la ŝlosilo.
  • la ŝlosilo mem

La ŝlosilo estas unike identigita per la paro: key_id, user.

Estas ankaŭ diferencoj en stokado kaj forigo de ŝlosiloj.

Dosiera stokado estas pli rapida. Vi povus pensi, ke ŝlosilvendejo simple skribas la ŝlosilon al dosiero unufoje, sed ne, okazas pli ĉi tie. Kiam ajn dosiera stokado modifo estas farita, rezerva kopio de ĉiu enhavo unue estas kreita. Ni diru, ke la dosiero nomiĝas my_biggest_secrets, tiam la rezerva kopio estos my_biggest_secrets.backup. Poste, la kaŝmemoro estas ŝanĝita (ŝlosiloj estas aldonitaj aŭ forigitaj) kaj, se ĉio sukcesas, la kaŝmemoro estas restarigita al dosiero. En maloftaj kazoj, kiel servila fiasko, vi eble vidos ĉi tiun rezervan dosieron. La rezerva dosiero estas forigita la venontan fojon kiam la ŝlosiloj estas ŝarĝitaj (kutime post kiam la servilo estas rekomencita).

Konservante aŭ forigante ŝlosilon en servila stokado, la stokado devas konektiĝi al la MySQL-servilo per la komandoj "sendu la ŝlosilon" / "peti ŝlosilon forigon".

Ni revenu al servila startrapideco. Krom la fakto, ke la lanĉa rapideco estas tuŝita de la volbo mem, ekzistas ankaŭ la temo de kiom da ŝlosiloj de la volbo devas esti prenitaj ĉe ekfunkciigo. Kompreneble, ĉi tio estas precipe grava por servila stokado. Ĉe ekfunkciigo, la servilo kontrolas, kiu ŝlosilo estas postulata por ĉifritaj tabeloj/tabelspacoj kaj petas la ŝlosilon de la stokado. Sur "pura" servilo kun ĉifrado de Majstra Ŝlosilo, devas esti unu Ĉefŝlosilo, kiu devas esti prenita el stokado. Tamen, pli granda nombro da ŝlosiloj povas esti postulata, ekzemple, kiam la rezerva servilo restarigas sekurkopion de la primara servilo. En tiaj kazoj, rotacio de la Ĉefŝlosilo devus esti disponigita. Ĉi tio estos pritraktata pli detale en estontaj artikoloj, kvankam ĉi tie mi ŝatus rimarki, ke servilo uzanta plurajn Majstrajn Ŝlosilaĵojn eble daŭros iom pli longe por ekfunkciigi, precipe kiam oni uzas servilflankan ŝlosilvendejon.

Nun ni parolu iom pli pri keyring_file. Kiam mi disvolvis keyring_file, mi ankaŭ zorgis pri kiel kontroli la ŝanĝojn de keyring_file dum la servilo funkcias. En 5.7, la kontrolo estis farita surbaze de dosiero-statistiko, kio ne estis ideala solvo, kaj en 8.0 ĝi estis anstataŭigita per SHA256-kontrolsumo.

La unuan fojon, kiam vi rulas keyring_file, dosiero-statistiko kaj ĉeksumo estas kalkulitaj, kiuj estas memoritaj de la servilo, kaj ŝanĝoj estas aplikataj nur se ili kongruas. Kiam la dosiero ŝanĝiĝas, la ĉeksumo estas ĝisdatigita.

Ni jam kovris multajn demandojn pri ŝlosilaj trezorejoj. Tamen, ekzistas alia grava temo, kiu ofte estas forgesita aŭ miskomprenata: kunhavigi ŝlosilojn tra serviloj.

Kion mi volas diri? Ĉiu servilo (ekzemple, Percona Server) en la areto devas havi apartan lokon sur la Vault Servilo en kiu Percona Server devas konservi siajn ŝlosilojn. Ĉiu Ĉefŝlosilo konservita en la stokado enhavas la GUID de la Percona Servilo ene de sia identigilo. Kial ĝi estas grava? Imagu, ke vi havas nur unu Vault-Servilon kaj ĉiuj Percona-Serviloj en la areto uzas ĉi tiun ununuran Vault-Servilon. La problemo ŝajnas evidenta. Se ĉiuj Percona Serviloj uzus Ĉefŝlosilon sen unikaj identigiloj, kiel id = 1, id = 2, ktp., tiam ĉiuj serviloj en la areto uzus la saman Ĉefŝlosilon. Kion provizas la GUID estas la distingo inter serviloj. Kial do paroli pri kunhavigo de ŝlosiloj inter serviloj se unika GUID jam ekzistas? Estas alia kromaĵo - keyring_udf. Kun ĉi tiu kromaĵo, via servila uzanto povas konservi siajn ŝlosilojn sur la Vault-servilo. La problemo okazas kiam uzanto kreas ŝlosilon ĉe servilo1, ekzemple, kaj poste provas krei ŝlosilon kun la sama identigilo ĉe servilo2, ekzemple:

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

Atendu. Ambaŭ serviloj uzas la saman Vault-Servilon, ĉu la funkcio keyring_key_store ne devus malsukcesi ĉe server2? Kurioze, se vi provas fari la samon sur unu servilo, vi ricevos eraron:

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

Ĝuste, ROB_1 jam ekzistas.

Ni unue diskutu la duan ekzemplon. Kiel ni diris antaŭe, keyring_vault aŭ ajna alia ŝlosilringa kromaĵo konservas ĉiujn ŝlosilajn identigilojn en memoro. Do, post kreado de nova ŝlosilo, ROB_1 estas aldonita al servilo1, kaj krom sendi ĉi tiun ŝlosilon al Vault, la ŝlosilo ankaŭ estas aldonita al la kaŝmemoro. Nun, kiam ni provas aldoni la saman ŝlosilon duan fojon, keyring_vault kontrolas ĉu la ŝlosilo ekzistas en la kaŝmemoro kaj ĵetas eraron.

En la unua kazo la situacio estas malsama. Servilo1 kaj servilo2 havas apartajn kaŝmemorojn. Post aldoni ROB_1 al la ŝlosilkaŝmemoro sur servilo1 kaj la Vault-servilo, la ŝlosilkaŝmemoro sur servilo2 estas malsinkronigita. Ne estas ROB_2-ŝlosilo en la kaŝmemoro sur servilo1. Tiel, la ŝlosilo ROB_1 estas skribita al la keyring_key_store kaj al la Vault-servilo, kiu efektive anstataŭigas (!) la antaŭan valoron. Nun la ŝlosilo ROB_1 sur la Vault-servilo estas 543210987654321. Interese, la Vault-servilo ne blokas tiajn agojn kaj facile anstataŭigas la malnovan valoron.

Nun ni povas vidi kial servildispartigo en Vault povas esti grava - kiam vi uzas keyring_udf kaj volas konservi ŝlosilojn en Vault. Kiel atingi ĉi tiun apartigon sur Vault-servilo?

Estas du manieroj dividi en Vault. Vi povas krei malsamajn muntpunktojn por ĉiu servilo, aŭ uzi malsamajn vojojn ene de la sama muntpunkto. Ĉi tio estas plej bone ilustrita per ekzemploj. Do ni rigardu unue la individuajn muntajn punktojn:

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

Ĉi tie vi povas vidi, ke servilo1 kaj servilo2 uzas malsamajn muntajn punktojn. Disigante la vojojn, la agordo aspektos jene:

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

En ĉi tiu kazo, ambaŭ serviloj uzas la saman muntan punkton "mount_point", sed malsamajn vojojn. Kiam vi kreas la unuan sekreton sur servilo1 uzante ĉi tiun vojon, la Vault-servilo aŭtomate kreas dosierujon "servilo1". Por servilo2 ĉio estas simila. Kiam vi forigas la lastan sekreton en mount_point/server1 aŭ mount_point/server2, la Vault-servilo ankaŭ forigas tiujn dosierujojn. Se vi uzas vojon apartigon, vi devas krei nur unu muntan punkton kaj ŝanĝi la agordajn dosierojn por ke la serviloj uzu apartajn vojojn. Montpunkto povas esti kreita uzante HTTP-peton. Uzante CURL ĉi tio povas esti farita jene:

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

Ĉiuj kampoj (TOKEN, VAULT_CA, VAULT_URL, SECRET_MOUNT_POINT) respondas al la parametroj de la agorda dosiero. Kompreneble, vi povas uzi Vault-servaĵojn por fari la samon. Sed estas pli facile aŭtomatigi la kreadon de munta punkto. Mi esperas, ke vi trovos ĉi tiun informon utila kaj ni vidos vin en la venontaj artikoloj en ĉi tiu serio.

Ĉifrado en MySQL: Ŝlosilvendejo

Legu pli:

fonto: www.habr.com

Aldoni komenton