Kryptering i MySQL: Keystore

I väntan på start av ny anmälan till kursen "Databas" Vi har förberett en översättning av en användbar artikel åt dig.

Kryptering i MySQL: Keystore

Transparent Data Encryption (TDE) dök upp i Percona Server för MySQL och MySQL under ganska lång tid. Men har du någonsin tänkt på hur det fungerar under huven och vilken inverkan TDE kan ha på din server? I den här artikelserien ska vi titta på hur TDE fungerar internt. Låt oss börja med nyckellagring, eftersom detta krävs för att all kryptering ska fungera. Sedan ska vi titta närmare på hur kryptering fungerar i Percona Server för MySQL/MySQL och vilka ytterligare funktioner Percona Server för MySQL har.

MySQL nyckelring

Nyckelring är plugins som låter servern fråga, skapa och ta bort nycklar i en lokal fil (keyring_file) eller på en fjärrserver (som HashiCorp Vault). Nycklar cachelagras alltid lokalt för att påskynda hämtningen.

Plugins kan delas in i två kategorier:

  • Lokalt utrymme. Till exempel en lokal fil (vi kallar detta en filbaserad nyckelring).
  • Fjärrlagring. Till exempel Vault Server (vi kallar detta en serverbaserad nyckelring).

Denna separation är viktig eftersom olika typer av lagring beter sig lite olika, inte bara när du lagrar och hämtar nycklar, utan även när du kör dem.

När du använder en fillagring, vid uppstart, laddas hela innehållet i lagringen in i cachen: nyckel-id, nyckelanvändare, nyckeltyp och själva nyckeln.

I fallet med en server-side store (som Vault Server) laddas bara nyckel-id och nyckelanvändare vid start, så att få alla nycklar saktar inte upp start. Nycklar laddas lat. Det vill säga att själva nyckeln laddas från Vault endast när den faktiskt behövs. När nyckeln har laddats ned cachelagras den i minnet så att den inte behöver nås via TLS-anslutningar till Vault Server i framtiden. Låt oss sedan titta på vilken information som finns i nyckelarkivet.

Nyckelinformationen innehåller följande:

  • nyckel-id — nyckelidentifierare, till exempel:
    INNODBKey-764d382a-7324-11e9-ad8f-9cb6d0d5dc99-1
  • Nyckeltyp — Nyckeltyp baserad på den använda krypteringsalgoritmen, möjliga värden: "AES", "RSA" eller "DSA".
  • nyckellängd — nyckellängd i byte, AES: 16, 24 eller 32, RSA 128, 256, 512 och DSA 128, 256 eller 384.
  • användare - nyckelns ägare. Om nyckeln är system, till exempel Master Key, är detta fält tomt. Om en nyckel skapas med nyckelring_udf, identifierar detta fält ägaren till nyckeln.
  • själva nyckeln

Nyckeln identifieras unikt av paret: key_id, user.

Det finns också skillnader i att lagra och radera nycklar.

Fillagring är snabbare. Du kanske tror att en nyckelbutik helt enkelt skriver nyckeln till en fil en gång, men nej, det händer mer här. Närhelst en fillagringsändring görs skapas först en säkerhetskopia av allt innehåll. Låt oss säga att filen heter my_biggest_secrets, då kommer säkerhetskopian att vara my_biggest_secrets.backup. Därefter ändras cachen (nycklar läggs till eller tas bort) och om allt lyckas återställs cachen till en fil. I sällsynta fall, till exempel ett serverfel, kan du se denna säkerhetskopia. Säkerhetskopieringsfilen raderas nästa gång nycklarna laddas (vanligtvis efter att servern har startat om).

När du sparar eller tar bort en nyckel i en serverlagring måste lagringen ansluta till MySQL-servern med kommandona "skicka nyckel" / "begär nyckelborttagning".

Låt oss gå tillbaka till serverns starthastighet. Utöver att lanseringshastigheten påverkas av själva valvet så finns det också frågan om hur många nycklar från valvet som behöver hämtas vid uppstart. Detta är naturligtvis särskilt viktigt för serverlagring. Vid uppstart kontrollerar servern vilken nyckel som krävs för krypterade tabeller/tabellutrymmen och begär nyckeln från lagringen. På en "ren" server med Master Key-kryptering måste det finnas en Master Key, som måste hämtas från lagringen. Ett större antal nycklar kan dock krävas, till exempel när backupservern återställer en backup från den primära servern. I sådana fall bör rotation av huvudnyckeln tillhandahållas. Detta kommer att behandlas mer i detalj i framtida artiklar, även om jag här skulle vilja notera att en server som använder flera huvudnycklar kan ta lite längre tid att starta upp, särskilt när du använder ett nyckellager på serversidan.

Låt oss nu prata lite mer om keyring_file. När jag utvecklade keyring_file var jag också bekymrad över hur jag skulle leta efter förändringar av keyring_file medan servern körs. I 5.7 utfördes kontrollen baserat på filstatistik, vilket inte var en idealisk lösning, och i 8.0 ersattes den med en SHA256-kontrollsumma.

Första gången du kör keyring_file beräknas filstatistik och en kontrollsumma, som kommer ihåg av servern, och ändringar tillämpas endast om de matchar. När filen ändras uppdateras kontrollsumman.

Vi har redan täckt många frågor om nyckelvalv. Det finns dock ett annat viktigt ämne som ofta glöms bort eller missförstås: att dela nycklar över servrar.

Vad jag menar? Varje server (till exempel Percona Server) i klustret måste ha en separat plats på Vault Server där Percona Server måste lagra sina nycklar. Varje huvudnyckel som sparas i lagringen innehåller GUID för Percona-servern i dess identifierare. Varför är det viktigt? Föreställ dig att du bara har en Vault-server och alla Percona-servrar i klustret använder den enda Vault-servern. Problemet verkar uppenbart. Om alla Percona-servrar använde en huvudnyckel utan unika identifierare, såsom id = 1, id = 2, etc., skulle alla servrar i klustret använda samma huvudnyckel. Vad GUID tillhandahåller är skillnaden mellan servrar. Varför då prata om att dela nycklar mellan servrar om en unik GUID redan finns? Det finns ett annat plugin - keyring_udf. Med denna plugin kan din serveranvändare lagra sina nycklar på Vault-servern. Problemet uppstår när en användare skapar en nyckel på server1, till exempel, och sedan försöker skapa en nyckel med samma ID på server2, till exempel:

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

Vänta. Båda servrarna använder samma Vault Server, borde inte keyring_key_store-funktionen misslyckas på server2? Intressant nog, om du försöker göra samma sak på en server får du ett felmeddelande:

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

Det stämmer, ROB_1 finns redan.

Låt oss diskutera det andra exemplet först. Som vi sa tidigare, cachelagrar keyring_vault eller något annat nyckelringsplugin alla nyckel-ID:n i minnet. Så, efter att ha skapat en ny nyckel, läggs ROB_1 till server1, och förutom att skicka denna nyckel till Vault, läggs nyckeln också till i cachen. Nu, när vi försöker lägga till samma nyckel en andra gång, kontrollerar keyring_vault om nyckeln finns i cachen och ger ett fel.

I det första fallet är situationen annorlunda. Server1 och server2 har separata cachar. Efter att ha lagt till ROB_1 till nyckelcachen på server1 och Vault-servern är nyckelcachen på server2 inte synkroniserad. Det finns ingen ROB_2-nyckel i cachen på server1. Således skrivs ROB_1-nyckeln till keyring_key_store och till Vault-servern, som faktiskt skriver över (!) det tidigare värdet. Nu är ROB_1-nyckeln på Vault-servern 543210987654321. Intressant nog blockerar inte Vault-servern sådana åtgärder och skriver över det gamla värdet.

Nu kan vi se varför serverpartitionering i Vault kan vara viktigt - när du använder keyring_udf och vill lagra nycklar i Vault. Hur uppnår man denna separation på en Vault-server?

Det finns två sätt att partitionera i Vault. Du kan skapa olika monteringspunkter för varje server eller använda olika vägar inom samma monteringspunkt. Detta illustreras bäst med exempel. Så låt oss titta på de individuella monteringspunkterna först:

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

Här kan du se att server1 och server2 använder olika monteringspunkter. När du delar upp sökvägarna kommer konfigurationen att se ut så här:

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

I det här fallet använder båda servrarna samma monteringspunkt "mount_point", men olika sökvägar. När du skapar den första hemligheten på server1 med den här sökvägen, skapar Vault-servern automatiskt en "server1"-katalog. För server2 är allt liknande. När du tar bort den sista hemligheten i mount_point/server1 eller mount_point/server2, tar Vault-servern också bort dessa kataloger. Om du använder sökvägsseparering måste du bara skapa en monteringspunkt och ändra konfigurationsfilerna så att servrarna använder separata sökvägar. En monteringspunkt kan skapas med hjälp av en HTTP-begäran. Med CURL kan detta göras så här:

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

Alla fält (TOKEN, VAULT_CA, VAULT_URL, SECRET_MOUNT_POINT) motsvarar parametrarna för konfigurationsfilen. Naturligtvis kan du använda Vault-verktyg för att göra detsamma. Men det är lättare att automatisera skapandet av en monteringspunkt. Jag hoppas att du tycker att denna information är användbar och att vi ses i nästa artiklar i den här serien.

Kryptering i MySQL: Keystore

Läs mer:

Källa: will.com

Lägg en kommentar