Kryptering i MySQL: Keystore

I påvente av oppstart av ny påmelding til kurset "Database" Vi har utarbeidet en oversettelse av en nyttig artikkel for deg.

Kryptering i MySQL: Keystore

Transparent Data Encryption (TDE) dukket opp i Percona Server for MySQL og MySQL i ganske lang tid. Men har du noen gang tenkt på hvordan det fungerer under panseret og hvilken innvirkning TDE kan ha på serveren din? I denne artikkelserien skal vi se på hvordan TDE fungerer internt. La oss starte med nøkkellagring, siden dette er nødvendig for at eventuell kryptering skal fungere. Deretter skal vi se nærmere på hvordan kryptering fungerer i Percona Server for MySQL/MySQL og hvilke tilleggsfunksjoner Percona Server for MySQL har.

MySQL nøkkelring

Nøkkelring er plugins som lar serveren spørre etter, opprette og slette nøkler i en lokal fil (keyring_file) eller på en ekstern server (som HashiCorp Vault). Nøkler bufres alltid lokalt for å fremskynde gjenfinningen.

Plugins kan deles inn i to kategorier:

  • Lokal lagring. For eksempel en lokal fil (vi kaller dette en filbasert nøkkelring).
  • Fjernlagring. For eksempel Vault Server (vi kaller dette en serverbasert nøkkelring).

Denne separasjonen er viktig fordi forskjellige typer lagring oppfører seg litt forskjellig, ikke bare når du lagrer og henter nøkler, men også når du kjører dem.

Når du bruker en fillagring, ved oppstart, lastes hele innholdet av lagringen inn i hurtigbufferen: nøkkel-ID, nøkkelbruker, nøkkeltype og selve nøkkelen.

Når det gjelder en butikk på serversiden (som Vault Server), lastes bare nøkkel-ID og nøkkelbruker ved oppstart, så det å få alle nøklene bremser ikke oppstarten. Nøkler lastes dovent. Det vil si at selve nøkkelen lastes fra Vault kun når den faktisk er nødvendig. Når den er lastet ned, bufres nøkkelen i minnet, slik at den ikke trenger å være tilgjengelig via TLS-tilkoblinger til Vault Server i fremtiden. La oss deretter se på hvilken informasjon som finnes i nøkkellageret.

Nøkkelinformasjonen inneholder følgende:

  • nøkkel id – nøkkelidentifikator, for eksempel:
    INNODBKey-764d382a-7324-11e9-ad8f-9cb6d0d5dc99-1
  • nøkkeltype – nøkkeltype basert på krypteringsalgoritmen som brukes, mulige verdier: «AES», «RSA» eller «DSA».
  • nøkkel lengde — nøkkellengde i byte, AES: 16, 24 eller 32, RSA 128, 256, 512 og DSA 128, 256 eller 384.
  • bruker - eier av nøkkelen. Hvis nøkkelen er system, for eksempel hovednøkkel, er dette feltet tomt. Hvis en nøkkel opprettes ved hjelp av keyring_udf, identifiserer dette feltet eieren av nøkkelen.
  • selve nøkkelen

Nøkkelen identifiseres unikt av paret: key_id, user.

Det er også forskjeller i lagring og sletting av nøkler.

Fillagring er raskere. Du tror kanskje at en nøkkelbutikk bare skriver nøkkelen til en fil én gang, men nei, det skjer mer her. Hver gang en modifikasjon av fillagring gjøres, opprettes først en sikkerhetskopi av alt innhold. La oss si at filen heter my_biggest_secrets, så vil sikkerhetskopien være my_biggest_secrets.backup. Deretter endres cachen (nøkler legges til eller slettes), og hvis alt er vellykket, tilbakestilles cachen til en fil. I sjeldne tilfeller, for eksempel en serverfeil, kan du se denne sikkerhetskopifilen. Sikkerhetskopien slettes neste gang nøklene lastes (vanligvis etter at serveren er startet på nytt).

Når du lagrer eller sletter en nøkkel i en serverlagring, må lagringen kobles til MySQL-serveren med kommandoene "send nøkkelen" / "be om nøkkelsletting".

La oss gå tilbake til serverens oppstartshastighet. I tillegg til at lanseringshastigheten påvirkes av selve hvelvet, er det også spørsmålet om hvor mange nøkler fra hvelvet som må hentes ved oppstart. Dette er selvfølgelig spesielt viktig for serverlagring. Ved oppstart sjekker serveren hvilken nøkkel som kreves for krypterte tabeller/tabellplasser og ber om nøkkelen fra lageret. På en "ren" server med hovednøkkelkryptering må det være én hovednøkkel, som må hentes fra lagring. Det kan imidlertid være nødvendig med et større antall nøkler, for eksempel når backupserveren gjenoppretter en sikkerhetskopi fra primærserveren. I slike tilfeller bør rotasjon av hovednøkkelen gis. Dette vil bli dekket mer detaljert i fremtidige artikler, selv om jeg her vil merke meg at en server som bruker flere hovednøkler kan ta litt lengre tid å starte opp, spesielt når du bruker et nøkkellager på serversiden.

La oss nå snakke litt mer om keyring_file. Da jeg utviklet keyring_file, var jeg også bekymret for hvordan jeg kunne se etter endringer i keyring_file mens serveren kjører. I 5.7 ble kontrollen utført basert på filstatistikk, noe som ikke var en ideell løsning, og i 8.0 ble den erstattet med en SHA256 sjekksum.

Første gang du kjører keyring_file, beregnes filstatistikk og en kontrollsum, som huskes av serveren, og endringer blir bare brukt hvis de stemmer overens. Når filen endres, oppdateres sjekksummen.

Vi har allerede dekket mange spørsmål om nøkkelhvelv. Det er imidlertid et annet viktig tema som ofte blir glemt eller misforstått: deling av nøkler på tvers av servere.

Hva jeg mener? Hver server (for eksempel Percona Server) i klyngen må ha en egen plassering på Vault Server der Percona Server må lagre nøklene sine. Hver hovednøkkel som er lagret i lagringen inneholder GUIDen til Percona-serveren i sin identifikator. Hvorfor er det viktig? Tenk deg at du bare har én Vault-server og alle Percona-servere i klyngen bruker den eneste Vault-serveren. Problemet virker åpenbart. Hvis alle Percona-servere brukte en hovednøkkel uten unike identifikatorer, slik som id = 1, id = 2, osv., ville alle serverne i klyngen bruke samme hovednøkkel. Det GUID gir er skillet mellom servere. Hvorfor da snakke om å dele nøkler mellom servere hvis en unik GUID allerede eksisterer? Det er en annen plugin - keyring_udf. Med denne plugin-en kan serverbrukeren lagre nøklene sine på Vault-serveren. Problemet oppstår når en bruker oppretter en nøkkel på server1, for eksempel, og deretter prøver å opprette en nøkkel 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 serverne bruker den samme Vault-serveren, burde ikke nøkkelring_nøkkel_butikk-funksjonen mislykkes på server2? Interessant nok, hvis du prøver å gjøre det samme på én server, vil du få en feilmelding:

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

Det stemmer, ROB_1 eksisterer allerede.

La oss diskutere det andre eksemplet først. Som vi sa tidligere, bufrer keyring_vault eller en annen nøkkelring-plugin alle nøkkel-ID-er i minnet. Så, etter å ha opprettet en ny nøkkel, legges ROB_1 til server1, og i tillegg til å sende denne nøkkelen til Vault, legges nøkkelen også til cachen. Nå, når vi prøver å legge til den samme nøkkelen en gang til, sjekker keyring_vault om nøkkelen finnes i hurtigbufferen og gir en feil.

I det første tilfellet er situasjonen annerledes. Server1 og server2 har separate cacher. Etter å ha lagt til ROB_1 i nøkkelbufferen på server1 og Vault-serveren, er nøkkelbufferen på server2 ikke synkronisert. Det er ingen ROB_2-nøkkel i hurtigbufferen på server1. Dermed blir ROB_1-nøkkelen skrevet til keyring_key_store og til Vault-serveren, som faktisk overskriver (!) den forrige verdien. Nå er ROB_1-nøkkelen på Vault-serveren 543210987654321. Interessant nok blokkerer ikke Vault-serveren slike handlinger og overskriver enkelt den gamle verdien.

Nå kan vi se hvorfor serverpartisjonering i Vault kan være viktig - når du bruker keyring_udf og ønsker å lagre nøkler i Vault. Hvordan oppnå denne separasjonen på en Vault-server?

Det er to måter å partisjonere inn i Vault. Du kan opprette forskjellige monteringspunkter for hver server, eller bruke forskjellige baner innenfor samme monteringspunkt. Dette illustreres best med eksempler. Så la oss først se på de individuelle monteringspunktene:

--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 bruker forskjellige monteringspunkter. Når du deler opp banene, vil konfigurasjonen se slik ut:

--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 tilfellet bruker begge serverne det samme monteringspunktet "mount_point", men forskjellige stier. Når du oppretter den første hemmeligheten på server1 ved å bruke denne banen, oppretter Vault-serveren automatisk en "server1"-katalog. For server2 er alt likt. Når du sletter den siste hemmeligheten i mount_point/server1 eller mount_point/server2, sletter Vault-serveren også disse katalogene. I tilfelle du bruker baneseparasjon, må du bare opprette ett monteringspunkt og endre konfigurasjonsfilene slik at serverne bruker separate baner. Et monteringspunkt kan opprettes ved hjelp av en HTTP-forespørsel. Ved å bruke CURL kan dette gjøres slik:

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

Alle feltene (TOKEN, VAULT_CA, VAULT_URL, SECRET_MOUNT_POINT) tilsvarer parameterne til konfigurasjonsfilen. Selvfølgelig kan du bruke Vault-verktøy for å gjøre det samme. Men det er lettere å automatisere opprettelsen av et monteringspunkt. Jeg håper du finner denne informasjonen nyttig, og vi ses i de neste artiklene i denne serien.

Kryptering i MySQL: Keystore

Les mer:

Kilde: www.habr.com

Legg til en kommentar