W przededniu nowego naboru na kurs przygotowaliśmy dla was tłumaczenie przydatnego artykułu.

Przezroczyste szyfrowanie danych (Transparent Data Encryption, TDE) pojawiło się w i MySQL już od dłuższego czasu. Ale czy kiedykolwiek zastanawialiście się, jak to działa pod maską i jaki wpływ TDE może mieć na wasz serwer? W tej serii artykułów przyjrzymy się, jak TDE działa wewnętrznie. Zaczniemy od przechowywania kluczy, ponieważ jest to wymagane do działania dowolnego szyfrowania. Następnie szczegółowo omówimy, jak działa szyfrowanie w Percona Server for MySQL/MySQL oraz jakie dodatkowe możliwości oferuje Percona Server for MySQL.
MySQL Keyring
Keyring to wtyczki, które pozwalają serwerowi na żądanie, tworzenie i usuwanie kluczy w lokalnym pliku (keyring_file) lub na zdalnym serwerze (na przykład w HashiCorp Vault). Klucze są zawsze buforowane lokalnie, aby przyspieszyć ich pobieranie.
Wtyczki można podzielić na dwie kategorie:
- Lokalne przechowywanie. Na przykład lokalny plik (nazywamy to lokalnym magazynem kluczy, file-based keyring).
- Zdalne przechowywanie. Na przykład Vault Server (nazywamy to serwerowym magazynem kluczy, server-based keyring).
To rozróżnienie jest ważne, ponieważ różne typy magazynów zachowują się nieco inaczej nie tylko podczas przechowywania i pobierania kluczy, ale także podczas uruchamiania.
Podczas korzystania z lokalnego magazynu, podczas uruchamiania, do pamięci podręcznej ładowane są wszystkie dane magazynu: key id, key user, key type i sam klucz.
W przypadku zdalnego magazynu (na przykład serwera Vault), podczas uruchamiania ładowane są tylko key id i key user, dlatego pobieranie wszystkich kluczy nie opóźnia uruchamiania. Klucze są ładowane leniwie. To znaczy, że sam klucz jest ładowany z Vault dopiero wtedy, gdy jest faktycznie potrzebny. Po załadowaniu klucz jest buforowany w pamięci, aby w przyszłości nie było potrzeby odwoływania się do niego przez połączenia TLS z Vault Server. Przeanalizujmy, jakie informacje znajdują się w magazynie kluczy.
Informacje o kluczu zawierają następujące:
- key id — identyfikator klucza, na przykład:
INNODBKey-764d382a-7324-11e9-ad8f-9cb6d0d5dc99-1 - key type — typ klucza, oparty na używanym algorytmie szyfrowania, możliwe wartości: «AES», «RSA» lub «DSA».
- key length — długość klucza w bajtach, AES: 16, 24 lub 32, RSA 128, 256, 512 i DSA 128, 256 lub 384.
- użytkownik — właściciel klucza. Jeśli klucz jest systemowy, na przykład Master Key, to pole jest puste. Jeśli klucz jest tworzony za pomocą keyring_udf, to pole to oznacza właściciela klucza.
- sam klucz
Klucz jest jednoznacznie identyfikowany przez parę: key_id, user.
Są również różnice w przechowywaniu i usuwaniu kluczy.
Przechowywanie plików działa szybciej. Można by przypuszczać, że przechowywanie kluczy to po prostu jednokrotne zapisanie klucza w pliku, ale to nieprawda — odbywa się tu więcej operacji. Przy każdej modyfikacji przechowywania plików najpierw tworzy się kopię zapasową całej zawartości. Załóżmy, że plik nosi nazwę my_biggest_secrets, wtedy kopia zapasowa będzie nazywała się my_biggest_secrets.backup. Następnie zmienia się pamięć podręczną (dodawane lub usuwane są klucze) i jeśli wszystko zostanie wykonane pomyślnie, pamięć podręczna jest resetowana do pliku. W rzadkich przypadkach, takich jak awaria serwera, można zobaczyć ten plik kopii zapasowej. Plik kopii zapasowej jest usuwany przy następnym ładowaniu kluczy (zwykle po ponownym uruchomieniu serwera).
Podczas zapisywania lub usuwania klucza w przechowywaniu serwerowym, przechowywanie musi połączyć się z serwerem MySQL z poleceniami "wyślij klucz" / "poproś o usunięcie klucza" ("send the key" / "request key deletion").
Wróćmy do prędkości uruchamiania serwera. Oprócz tego, że na szybkość uruchamiania wpływa samo przechowywanie, istnieje także kwestia, ile kluczy z przechowywania musi być uzyskanych podczas uruchamiania. Oczywiście, jest to szczególnie ważne dla przechowywań serwerowych. Przy uruchamianiu serwer sprawdza, jaki klucz jest potrzebny dla zaszyfrowanych tabel / przestrzeni tabel i żąda klucza z przechowywania. Na "czystym" serwerze z Master Key — powinien być jeden Master Key, który należy wyodrębnić z przechowywania. Jednak może być potrzebna większa liczba kluczy, na przykład, gdy na zapasowym serwerze przywracana jest kopia zapasowa z głównego serwera. W takich przypadkach należy przewidzieć rotację Master Key. Temat ten będzie bardziej szczegółowo omawiany w przyszłych artykułach, chociaż tutaj chciałbym zaznaczyć, że serwer korzystający z kilku Master Key może uruchamiać się nieco dłużej, zwłaszcza przy użyciu serwerowego przechowywania kluczy.
Teraz porozmawiajmy jeszcze trochę o keyring_file. Kiedy opracowywałem keyring_file, martwiłem się również, jak sprawdzać zmianę keyring_file podczas pracy serwera. W wersji 5.7 sprawdzenie odbywało się na podstawie statystyk pliku, co nie było idealnym rozwiązaniem, a w wersji 8.0 zostało to zastąpione sumą kontrolną SHA256.
Podczas pierwszego uruchomienia keyring_file obliczana jest statystyka pliku oraz suma kontrolna, które są zapamiętywane przez serwer, a zmiany są stosowane tylko wtedy, gdy się zgadzają. Po zmianie pliku suma kontrolna jest aktualizowana.
Już omówiliśmy wiele kwestii dotyczących magazynów kluczy. Istnieje jednak jeden ważny temat, o którym często zapomina się lub który jest źle rozumiany - podział kluczy między serwery.
Co mam na myśli? Każdy serwer (na przykład Percona Server) w klastrze powinien mieć osobne miejsce na serwerze Vault, w którym Percona Server powinien przechowywać swoje klucze. W każdym Master Key przechowywanym w magazynie znajduje się GUID serwera Percona Server w jego identyfikatorze. Dlaczego to ważne? Wyobraź sobie, że masz tylko jeden Vault Server, a wszystkie Percona Server w klastrze korzystają z tego jedynego Vault Server. Problem wydaje się oczywisty. Gdyby wszystkie Percona Server korzystały z Master Key bez unikalnych identyfikatorów, na przykład id = 1, id = 2 itd., to wszystkie serwery w klastrze korzystałyby z tego samego Master Key. Co zapewnia GUID - rozgraniczenie między serwerami. Po co więc mówić o podziale kluczy między serwerami, jeśli już istnieje unikalny GUID? Jest jeszcze jeden plugin - keyring_udf. Dzięki temu pluginowi użytkownik twojego serwera może przechowywać swoje klucze na serwerze Vault. Problem pojawia się, gdy użytkownik tworzy klucz, na przykład na serwerze server1, a następnie próbuje stworzyć klucz o tym samym identyfikatorze na server2, na przykład:
--server1:
select keyring_key_store('ROB_1','AES',"123456789012345");
1
--1 oznacza pomyślne zakończenie
--server2:
select keyring_key_store('ROB_1','AES',"543210987654321");
1Poczekaj. Oba serwery korzystają z tego samego Vault Server, czy funkcja keyring_key_store nie powinna zakończyć się błędem na serwerze server2? Ciekawe, że jeśli spróbujesz zrobić to samo na jednym serwerze, otrzymasz błąd:
--server1:
select keyring_key_store('ROB_1','AES',"123456789012345");
1
select keyring_key_store('ROB_1','AES',"543210987654321");
0Zgadza się, ROB_1 już istnieje.
Najpierw omówmy drugi przykład. Jak już wcześniej wspomnieliśmy, keyring_vault lub jakakolwiek inna wtyczka magazynująca (keyring) buforuje wszystkie identyfikatory kluczy w pamięci. W ten sposób, po utworzeniu nowego klucza, ROB_1 jest dodawany do server1, a oprócz wysłania tego klucza do Vault, klucz jest także dodawany do bufora. Teraz, gdy próbujemy dodać ten sam klucz po raz drugi, keyring_vault sprawdza, czy ten klucz istnieje w buforze i zgłasza błąd.
W pierwszym przypadku sytuacja jest inna. Na serwerach server1 i server2 są oddzielne bufory. Po dodaniu ROB_1 do buforu kluczy na serwerze server1 oraz w serwerze Vault, bufor kluczy na server2 nie jest synchronizowany. W buforze na server2 nie ma klucza ROB_1. W związku z tym klucz ROB_1 jest zapisywany w keyring_key_store oraz na serwerze Vault, co faktycznie przepisywało (!) poprzednią wartość. Teraz klucz ROB_1 na serwerze Vault ma wartość 543210987654321. Co ciekawe, serwer Vault nie blokuje takich działań i bezproblemowo przepisuje starą wartość.
Teraz widzimy, dlaczego podział na serwery w Vault może być ważny – kiedy używasz keyring_udf i chcesz przechowywać klucze w Vault. Jak zapewnić taki podział na serwerze Vault?
Istnieją dwa sposoby podziału w Vault. Można stworzyć różne punkty montowania dla każdego serwera lub używać różnych ścieżek w jednym punkcie montowania. Najlepiej to zilustrować na przykładach. Zatem, najpierw przyjrzyjmy się oddzielnym punktom montowania:
--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 = (...)Tutaj widać, że server1 i server2 używają różnych punktów montowania. Przy podziale ścieżek konfiguracja będzie wyglądać następująco:
--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 = (...)W tym przypadku oba serwery korzystają z tego samego punktu montowania „mount_point”, ale z różnych ścieżek. Przy tworzeniu pierwszej tajemnicy na serwerze server1 w tej ścieżce serwer Vault automatycznie tworzy katalog „server1”. Dla server2 wszystko jest analogiczne. Gdy usuwasz ostatnią tajemnicę w mount_point/server1 lub mount_point/server2, serwer Vault również usuwa te katalogi. W przypadku, gdy używasz rozdzielenia ścieżek, musisz utworzyć tylko jeden punkt montowania i zmienić pliki konfiguracyjne, aby serwery korzystały z osobnych ścieżek. Punkt montowania można utworzyć za pomocą żądania HTTP. Można to zrobić za pomocą CURL w następujący sposób:
curl -L -H "X-Vault-Token: TOKEN" –cacert VAULT_CA
--data '{"type":"generic"}' --request POST VAULT_URL/v1/sys/mounts/SECRET_MOUNT_POINTWszystkie pola (TOKEN, VAULT_CA, VAULT_URL, SECRET_MOUNT_POINT) odpowiadają parametrom z pliku konfiguracyjnego. Oczywiście można użyć narzędzi Vault, aby zrobić to samo. Ale tak łatwiej zautomatyzować tworzenie punktu montowania. Mam nadzieję, że te informacje będą dla Ciebie przydatne i do zobaczenia w kolejnych artykułach z tej serii.
Czytaj dalej:
Źródło: habr.com
