Kryptering i MySQL: Keystore

I forventning om start af ny tilmelding til kurset "Database" Vi har udarbejdet en oversættelse af en nyttig artikel til dig.

Kryptering i MySQL: Keystore

Transparent Data Encryption (TDE) dukkede op i Percona Server til MySQL og MySQL i et stykke tid. Men har du nogensinde tænkt over, hvordan det fungerer under motorhjelmen, og hvilken indflydelse TDE kan have på din server? I denne serie af artikler vil vi se på, hvordan TDE fungerer internt. Lad os starte med nøgleopbevaring, da dette er nødvendigt for at enhver kryptering kan fungere. Så vil vi se nærmere på, hvordan kryptering fungerer i Percona Server til MySQL/MySQL, og hvilke yderligere funktioner Percona Server til MySQL har.

MySQL nøglering

Nøglering er plugins, der giver serveren mulighed for at forespørge, oprette og slette nøgler i en lokal fil (keyring_file) eller på en ekstern server (såsom HashiCorp Vault). Nøgler gemmes altid lokalt for at fremskynde deres hentning.

Plugins kan opdeles i to kategorier:

  • Lokal opbevaring. For eksempel en lokal fil (vi kalder dette en fil-baseret nøglering).
  • Fjernlagring. For eksempel Vault Server (vi kalder dette en server-baseret nøglering).

Denne adskillelse er vigtig, fordi forskellige typer lagring opfører sig lidt forskelligt, ikke kun når du opbevarer og henter nøgler, men også når du kører dem.

Når du bruger et fillager, bliver hele indholdet af lageret ved opstart indlæst i cachen: nøgle-id, nøglebruger, nøgletype og selve nøglen.

I tilfælde af en server-side butik (såsom Vault Server), er det kun nøgle-id'et og nøglebrugeren, der indlæses ved opstart, så det at få alle nøglerne bremser ikke opstarten. Nøgler indlæses dovent. Det vil sige, at selve nøglen kun indlæses fra Vault, når den faktisk er nødvendig. Når den er downloadet, cachelagres nøglen i hukommelsen, så den ikke skal tilgås via TLS-forbindelser til Vault-serveren i fremtiden. Lad os derefter se på, hvilke oplysninger der er til stede i nøglelageret.

Nøgleoplysningerne indeholder følgende:

  • nøgle id — nøgleidentifikator, for eksempel:
    INNODBKey-764d382a-7324-11e9-ad8f-9cb6d0d5dc99-1
  • nøgletype — nøgletype baseret på den anvendte krypteringsalgoritme, mulige værdier: "AES", "RSA" eller "DSA".
  • nøglelængde — nøglelængde i bytes, AES: 16, 24 eller 32, RSA 128, 256, 512 og DSA 128, 256 eller 384.
  • bruger - ejer af nøglen. Hvis nøglen er system, for eksempel Master Key, så er dette felt tomt. Hvis en nøgle oprettes ved hjælp af keyring_udf, så identificerer dette felt ejeren af ​​nøglen.
  • selve nøglen

Nøglen er entydigt identificeret af parret: key_id, user.

Der er også forskelle i lagring og sletning af nøgler.

Fillagring er hurtigere. Du tror måske, at en nøglebutik simpelthen skriver nøglen til en fil én gang, men nej, der sker mere her. Når der foretages en fillagringsændring, oprettes der først en sikkerhedskopi af alt indhold. Lad os sige, at filen hedder my_biggest_secrets, så vil sikkerhedskopien være my_biggest_secrets.backup. Derefter ændres cachen (nøgler tilføjes eller slettes), og hvis alt lykkes, nulstilles cachen til en fil. I sjældne tilfælde, som f.eks. en serverfejl, kan du se denne sikkerhedskopifil. Sikkerhedskopieringsfilen slettes, næste gang nøglerne indlæses (normalt efter at serveren er genstartet).

Når du gemmer eller sletter en nøgle i et serverlager, skal lageret oprette forbindelse til MySQL-serveren med kommandoerne "send nøglen" / "anmod om nøglesletning".

Lad os vende tilbage til serverens opstartshastighed. Udover at lanceringshastigheden er påvirket af selve hvælvingen, er der også spørgsmålet om, hvor mange nøgler fra hvælvingen, der skal hentes ved opstart. Dette er naturligvis især vigtigt for serverlagring. Ved opstart tjekker serveren, hvilken nøgle der kræves til krypterede tabeller/tablespaces og anmoder om nøglen fra lageret. På en "ren" server med Master Key-kryptering skal der være én Master Key, som skal hentes fra lageret. Der kan dog være behov for et større antal nøgler, for eksempel når backupserveren gendanner en backup fra den primære server. I sådanne tilfælde skal der være mulighed for rotation af hovednøglen. Dette vil blive dækket mere detaljeret i fremtidige artikler, selvom jeg her vil gerne bemærke, at en server, der bruger flere hovednøgler, kan tage lidt længere tid at starte op, især når du bruger et nøglelager på serversiden.

Lad os nu tale lidt mere om keyring_file. Da jeg udviklede keyring_file, var jeg også bekymret over, hvordan man tjekker for nøglering_fil-ændringer, mens serveren kører. I 5.7 blev kontrollen udført på baggrund af filstatistik, hvilket ikke var en ideel løsning, og i 8.0 blev den erstattet med en SHA256 checksum.

Første gang du kører keyring_file, beregnes filstatistik og en kontrolsum, som huskes af serveren, og ændringer anvendes kun, hvis de matcher. Når filen ændres, opdateres kontrolsummen.

Vi har allerede dækket mange spørgsmål om nøglebokse. Der er dog et andet vigtigt emne, som ofte bliver glemt eller misforstået: deling af nøgler på tværs af servere.

Hvad jeg mener? Hver server (for eksempel Percona Server) i klyngen skal have en separat placering på Vault Serveren, hvor Percona Server skal opbevare sine nøgler. Hver hovednøgle, der er gemt i lageret, indeholder Percona-serverens GUID i sin identifikator. Hvorfor er det vigtigt? Forestil dig, at du kun har én Vault-server, og at alle Percona-servere i klyngen bruger den enkelte Vault-server. Problemet synes indlysende. Hvis alle Percona-servere brugte en masternøgle uden unikke identifikatorer, såsom id = 1, id = 2 osv., så ville alle servere i klyngen bruge den samme masternøgle. Hvad GUID'en giver, er skelnen mellem servere. Hvorfor så tale om at dele nøgler mellem servere, hvis der allerede eksisterer en unik GUID? Der er et andet plugin - keyring_udf. Med dette plugin kan din serverbruger gemme deres nøgler på Vault-serveren. Problemet opstår, når en bruger opretter en nøgle på server1, for eksempel, og derefter forsøger at oprette en nøgle med samme ID på server2, for eksempel:

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

Vente. Begge servere bruger den samme Vault Server, burde funktionen keyring_key_store ikke fejle på server2? Interessant nok, hvis du prøver at gøre det samme på én server, vil du modtage en fejlmeddelelse:

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

Det er rigtigt, ROB_1 eksisterer allerede.

Lad os først diskutere det andet eksempel. Som vi sagde tidligere, cacher keyring_vault eller et hvilket som helst andet nøglering-plugin alle nøgle-id'er i hukommelsen. Så efter oprettelse af en ny nøgle tilføjes ROB_1 til server1, og udover at sende denne nøgle til Vault, tilføjes nøglen også til cachen. Nu, når vi forsøger at tilføje den samme nøgle en anden gang, kontrollerer keyring_vault, om nøglen findes i cachen og giver en fejl.

I det første tilfælde er situationen anderledes. Server1 og server2 har separate caches. Efter tilføjelse af ROB_1 til nøglecachen på server1 og Vault-serveren, er nøglecachen på server2 ude af synkronisering. Der er ingen ROB_2 nøgle i cachen på server1. Således skrives ROB_1-nøglen til keyring_key_store og til Vault-serveren, som faktisk overskriver (!) den tidligere værdi. Nu er ROB_1-nøglen på Vault-serveren 543210987654321. Interessant nok blokerer Vault-serveren ikke sådanne handlinger og overskriver nemt den gamle værdi.

Nu kan vi se, hvorfor serverpartitionering i Vault kan være vigtig - når du bruger keyring_udf og vil gemme nøgler i Vault. Hvordan opnår man denne adskillelse på en Vault-server?

Der er to måder at partitionere i Vault på. Du kan oprette forskellige monteringspunkter for hver server eller bruge forskellige stier inden for det samme monteringspunkt. Dette illustreres bedst med eksempler. Så lad os først se på de individuelle monteringspunkter:

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

Her kan du se, at server1 og server2 bruger forskellige monteringspunkter. Når stierne opdeles, vil konfigurationen se sådan ud:

--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 dette tilfælde bruger begge servere det samme monteringspunkt "mount_point", men forskellige stier. Når du opretter den første hemmelighed på server1 ved hjælp af denne sti, opretter Vault-serveren automatisk en "server1"-mappe. For server2 er alt ens. Når du sletter den sidste hemmelighed i mount_point/server1 eller mount_point/server2, sletter Vault-serveren også disse mapper. Hvis du bruger stiadskillelse, skal du kun oprette ét monteringspunkt og ændre konfigurationsfilerne, så serverne bruger separate stier. Et monteringspunkt kan oprettes ved hjælp af en HTTP-anmodning. Ved at bruge CURL kan dette gøres sådan:

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

Alle felter (TOKEN, VAULT_CA, VAULT_URL, SECRET_MOUNT_POINT) svarer til parametrene for konfigurationsfilen. Selvfølgelig kan du bruge Vault-værktøjer til at gøre det samme. Men det er nemmere at automatisere oprettelsen af ​​et monteringspunkt. Jeg håber, du finder denne information nyttig, og vi ses i de næste artikler i denne serie.

Kryptering i MySQL: Keystore

Læs mere:

Kilde: www.habr.com

Tilføj en kommentar