Verschlüsselung in MySQL: Keystore

In Erwartung des Beginns einer neuen Einschreibung für den Kurs "Datenbank" Wir haben eine Übersetzung eines nützlichen Artikels für Sie vorbereitet.

Verschlüsselung in MySQL: Keystore

Transparent Data Encryption (TDE) erschien in Percona-Server für MySQL und MySQL schon seit geraumer Zeit. Aber haben Sie schon einmal darüber nachgedacht, wie es unter der Haube funktioniert und welche Auswirkungen TDE auf Ihren Server haben kann? In dieser Artikelserie schauen wir uns an, wie TDE intern funktioniert. Beginnen wir mit der Schlüsselspeicherung, da diese für das Funktionieren jeglicher Verschlüsselung erforderlich ist. Anschließend schauen wir uns genauer an, wie die Verschlüsselung in Percona Server für MySQL/MySQL funktioniert und welche zusätzlichen Funktionen Percona Server für MySQL bietet.

MySQL-Schlüsselring

Schlüsselringe sind Plugins, die es dem Server ermöglichen, Schlüssel in einer lokalen Datei (keyring_file) oder auf einem Remote-Server (z. B. HashiCorp Vault) abzufragen, zu erstellen und zu löschen. Schlüssel werden immer lokal zwischengespeichert, um ihren Abruf zu beschleunigen.

Plugins können in zwei Kategorien unterteilt werden:

  • Lokaler Speicher. Zum Beispiel eine lokale Datei (wir nennen dies einen dateibasierten Schlüsselbund).
  • Remote-Speicher. Zum Beispiel Vault Server (wir nennen dies einen serverbasierten Schlüsselbund).

Diese Trennung ist wichtig, da sich verschiedene Speichertypen etwas unterschiedlich verhalten, nicht nur beim Speichern und Abrufen von Schlüsseln, sondern auch bei deren Ausführung.

Bei Verwendung eines Dateispeichers wird beim Start der gesamte Inhalt des Speichers in den Cache geladen: Schlüssel-ID, Schlüsselbenutzer, Schlüsseltyp und der Schlüssel selbst.

Bei einem serverbasierten Speicher (z. B. Vault Server) werden beim Start nur die Schlüssel-ID und der Schlüsselbenutzer geladen, sodass der Erhalt aller Schlüssel den Start nicht verlangsamt. Schlüssel werden träge geladen. Das heißt, der Schlüssel selbst wird nur dann aus Vault geladen, wenn er tatsächlich benötigt wird. Nach dem Herunterladen wird der Schlüssel im Speicher zwischengespeichert, sodass in Zukunft nicht mehr über TLS-Verbindungen zum Vault-Server auf ihn zugegriffen werden muss. Schauen wir uns als Nächstes an, welche Informationen im Schlüsselspeicher vorhanden sind.

Die Kerninformationen enthalten Folgendes:

  • Schlüssel-ID — Schlüsselkennung, zum Beispiel:
    INNODBKey-764d382a-7324-11e9-ad8f-9cb6d0d5dc99-1
  • Schlüsselart — Schlüsseltyp basierend auf dem verwendeten Verschlüsselungsalgorithmus, mögliche Werte: „AES“, „RSA“ oder „DSA“.
  • Schlüssellänge — Schlüssellänge in Bytes, AES: 16, 24 oder 32, RSA 128, 256, 512 und DSA 128, 256 oder 384.
  • Benutzer - Besitzer des Schlüssels. Wenn es sich bei dem Schlüssel um einen Systemschlüssel handelt, beispielsweise um einen Hauptschlüssel, ist dieses Feld leer. Wenn ein Schlüssel mit keyring_udf erstellt wird, identifiziert dieses Feld den Eigentümer des Schlüssels.
  • der Schlüssel selbst

Der Schlüssel wird durch das Paar „key_id, user“ eindeutig identifiziert.

Auch beim Speichern und Löschen von Schlüsseln gibt es Unterschiede.

Die Dateispeicherung ist schneller. Man könnte denken, dass ein Schlüsselspeicher einfach nur einmal den Schlüssel in eine Datei schreibt, aber nein, hier passiert noch mehr. Bei jeder Änderung des Dateispeichers wird zunächst eine Sicherungskopie aller Inhalte erstellt. Nehmen wir an, die Datei heißt my_biggest_secrets, dann heißt die Sicherungskopie my_biggest_secrets.backup. Als nächstes wird der Cache geändert (Schlüssel werden hinzugefügt oder gelöscht) und wenn alles erfolgreich ist, wird der Cache auf eine Datei zurückgesetzt. In seltenen Fällen, beispielsweise bei einem Serverausfall, wird diese Sicherungsdatei möglicherweise angezeigt. Die Sicherungsdatei wird beim nächsten Laden der Schlüssel gelöscht (normalerweise nach dem Neustart des Servers).

Beim Speichern oder Löschen eines Schlüssels in einem Serverspeicher muss sich der Speicher mit den Befehlen „Schlüssel senden“ / „Schlüssellöschung anfordern“ mit dem MySQL-Server verbinden.

Kommen wir zurück zur Startgeschwindigkeit des Servers. Neben der Tatsache, dass die Startgeschwindigkeit vom Tresor selbst beeinflusst wird, stellt sich auch die Frage, wie viele Schlüssel beim Start aus dem Tresor abgerufen werden müssen. Dies ist natürlich besonders wichtig für Serverspeicher. Beim Start prüft der Server, welcher Schlüssel für verschlüsselte Tabellen/Tablespaces benötigt wird und fordert den Schlüssel vom Speicher an. Auf einem „sauberen“ Server mit Master-Key-Verschlüsselung muss es einen Master-Schlüssel geben, der aus dem Speicher abgerufen werden muss. Allerdings kann eine größere Anzahl von Schlüsseln erforderlich sein, beispielsweise wenn der Sicherungsserver eine Sicherung vom Primärserver wiederherstellt. In solchen Fällen sollte eine Rotation des Hauptschlüssels vorgesehen sein. Dies wird in zukünftigen Artikeln ausführlicher behandelt, allerdings möchte ich an dieser Stelle darauf hinweisen, dass der Start eines Servers, der mehrere Hauptschlüssel verwendet, etwas länger dauern kann, insbesondere wenn ein serverseitiger Schlüsselspeicher verwendet wird.

Lassen Sie uns nun etwas mehr über keyring_file sprechen. Als ich „keyring_file“ entwickelte, machte ich mir auch Gedanken darüber, wie ich nach Änderungen an „keyring_file“ suchen kann, während der Server läuft. In 5.7 wurde die Prüfung auf Basis von Dateistatistiken durchgeführt, was keine ideale Lösung war, und in 8.0 wurde sie durch eine SHA256-Prüfsumme ersetzt.

Wenn Sie keyring_file zum ersten Mal ausführen, werden Dateistatistiken und eine Prüfsumme berechnet, die vom Server gespeichert werden, und Änderungen werden nur angewendet, wenn sie übereinstimmen. Wenn sich die Datei ändert, wird die Prüfsumme aktualisiert.

Wir haben bereits viele Fragen zu Schlüsseltresoren beantwortet. Es gibt jedoch noch ein weiteres wichtiges Thema, das oft vergessen oder missverstanden wird: die gemeinsame Nutzung von Schlüsseln zwischen Servern.

Was ich meine? Jeder Server (z. B. Percona Server) im Cluster muss über einen separaten Speicherort auf dem Vault Server verfügen, an dem Percona Server seine Schlüssel speichern muss. Jeder im Speicher gespeicherte Hauptschlüssel enthält in seiner Kennung die GUID des Percona-Servers. Warum ist es wichtig? Stellen Sie sich vor, Sie haben nur einen Vault-Server und alle Percona-Server im Cluster verwenden diesen einzelnen Vault-Server. Das Problem scheint offensichtlich. Wenn alle Percona-Server einen Hauptschlüssel ohne eindeutige Kennungen wie ID = 1, ID = 2 usw. verwenden würden, würden alle Server im Cluster denselben Hauptschlüssel verwenden. Die GUID ermöglicht die Unterscheidung zwischen Servern. Warum dann über die gemeinsame Nutzung von Schlüsseln zwischen Servern sprechen, wenn bereits eine eindeutige GUID vorhanden ist? Es gibt ein weiteres Plugin – keyring_udf. Mit diesem Plugin kann Ihr Serverbenutzer seine Schlüssel auf dem Vault-Server speichern. Das Problem tritt auf, wenn ein Benutzer beispielsweise einen Schlüssel auf Server1 erstellt und dann versucht, einen Schlüssel mit derselben ID auf Server2 zu erstellen, beispielsweise:

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

Warten. Beide Server verwenden denselben Vault-Server. Sollte die Funktion keyring_key_store nicht auf Server2 fehlschlagen? Interessanterweise erhalten Sie eine Fehlermeldung, wenn Sie versuchen, dasselbe auf einem Server zu tun:

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

Das ist richtig, ROB_1 existiert bereits.

Lassen Sie uns zunächst das zweite Beispiel besprechen. Wie bereits erwähnt, speichert keyring_vault oder jedes andere Schlüsselbund-Plugin alle Schlüssel-IDs im Speicher. Nach dem Erstellen eines neuen Schlüssels wird ROB_1 zu Server1 hinzugefügt und zusätzlich zum Senden dieses Schlüssels an Vault wird der Schlüssel auch zum Cache hinzugefügt. Wenn wir nun versuchen, denselben Schlüssel ein zweites Mal hinzuzufügen, prüft keyring_vault, ob der Schlüssel im Cache vorhanden ist, und gibt einen Fehler aus.

Im ersten Fall ist die Situation anders. Server1 und Server2 verfügen über separate Caches. Nach dem Hinzufügen von ROB_1 zum Schlüsselcache auf Server1 und dem Vault-Server ist der Schlüsselcache auf Server2 nicht synchron. Es gibt keinen ROB_2-Schlüssel im Cache auf Server1. Somit wird der ROB_1-Schlüssel in den keyring_key_store und auf den Vault-Server geschrieben, der tatsächlich den vorherigen Wert überschreibt (!). Jetzt ist der ROB_1-Schlüssel auf dem Vault-Server gleich 543210987654321. Interessanterweise blockiert der Vault-Server solche Aktionen nicht und überschreibt problemlos den alten Wert.

Jetzt können wir sehen, warum die Serverpartitionierung in Vault wichtig sein kann – wenn Sie keyring_udf verwenden und Schlüssel in Vault speichern möchten. Wie erreicht man diese Trennung auf einem Vault-Server?

Es gibt zwei Möglichkeiten zur Partitionierung in Vault. Sie können für jeden Server unterschiedliche Mount-Punkte erstellen oder unterschiedliche Pfade innerhalb desselben Mount-Punkts verwenden. Dies lässt sich am besten anhand von Beispielen veranschaulichen. Schauen wir uns also zunächst die einzelnen Mount-Punkte an:

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

Hier können Sie sehen, dass Server1 und Server2 unterschiedliche Mount-Punkte verwenden. Bei der Aufteilung der Pfade sieht die Konfiguration folgendermaßen aus:

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

In diesem Fall verwenden beide Server denselben Mountpunkt „mount_point“, aber unterschiedliche Pfade. Wenn Sie über diesen Pfad das erste Geheimnis auf Server1 erstellen, erstellt der Vault-Server automatisch ein Verzeichnis „server1“. Für Server2 ist alles ähnlich. Wenn Sie das letzte Geheimnis in mount_point/server1 oder mount_point/server2 löschen, löscht der Vault-Server auch diese Verzeichnisse. Falls Sie die Pfadtrennung verwenden, sollten Sie nur einen Einhängepunkt erstellen und die Konfigurationsdateien so ändern, dass die Server separate Pfade verwenden. Ein Mount-Punkt kann über eine HTTP-Anfrage erstellt werden. Mit CURL kann dies folgendermaßen erfolgen:

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

Alle Felder (TOKEN, VAULT_CA, VAULT_URL, SECRET_MOUNT_POINT) entsprechen den Parametern der Konfigurationsdatei. Natürlich können Sie dazu auch Vault-Dienstprogramme verwenden. Es ist jedoch einfacher, die Erstellung eines Mount-Punkts zu automatisieren. Ich hoffe, dass Sie diese Informationen nützlich finden und wir sehen uns in den nächsten Artikeln dieser Serie.

Verschlüsselung in MySQL: Keystore

Weiterlesen:

Source: habr.com

Kommentar hinzufügen