MySQL'de Şifreleme: Anahtar Deposu

Kurs için yeni bir kaydın başlaması beklentisiyle "Veri tabanı" Sizin için faydalı bir makalenin çevirisini hazırladık.

MySQL'de Şifreleme: Anahtar Deposu

Şeffaf Veri Şifreleme (TDE) ortaya çıktı MySQL için Percona Sunucusu ve MySQL'i bir süredir kullanıyorum. Ancak bunun aslında nasıl çalıştığını ve TDE'nin sunucunuz üzerinde ne gibi etkileri olabileceğini hiç düşündünüz mü? Bu makale dizisinde TDE'nin dahili olarak nasıl çalıştığına bakacağız. Herhangi bir şifrelemenin çalışması için gerekli olduğundan, anahtar depolamayla başlayalım. Ardından MySQL/MySQL için Percona Server'da şifrelemenin nasıl çalıştığına ve MySQL için Percona Server'ın hangi ek özelliklere sahip olduğuna daha yakından bakacağız.

MySQL Anahtarlığı

Anahtarlık, sunucunun yerel bir dosyadaki (keyring_file) veya uzak bir sunucudaki (HashiCorp Vault gibi) anahtarları sorgulamasına, oluşturmasına ve silmesine olanak tanıyan eklentilerdir. Anahtarların alınmasını hızlandırmak için anahtarlar her zaman yerel olarak önbelleğe alınır.

Eklentiler iki kategoriye ayrılabilir:

  • Yerel depolama. Örneğin yerel bir dosya (biz buna dosya tabanlı anahtarlık diyoruz).
  • Uzaktan depolama. Örneğin Vault Server (biz buna sunucu tabanlı anahtarlık diyoruz).

Bu ayırma önemlidir çünkü farklı depolama türleri, yalnızca anahtarları saklarken ve alırken değil, aynı zamanda onları çalıştırırken de biraz farklı davranır.

Bir dosya depolama alanı kullanıldığında, başlangıçta depolama alanının tüm içeriği önbelleğe yüklenir: anahtar kimliği, anahtar kullanıcısı, anahtar türü ve anahtarın kendisi.

Sunucu tarafı depolama durumunda (Vault Server gibi), başlangıçta yalnızca anahtar kimliği ve anahtar kullanıcısı yüklenir, bu nedenle tüm anahtarların alınması, başlatmayı yavaşlatmaz. Anahtarlar yavaş yükleniyor. Yani anahtarın kendisi yalnızca gerçekten ihtiyaç duyulduğunda Vault'tan yüklenir. Anahtar indirildikten sonra bellekte önbelleğe alınır, böylece gelecekte Vault Sunucusuna TLS bağlantıları aracılığıyla erişilmesine gerek kalmaz. Sonra, anahtar deposunda hangi bilgilerin mevcut olduğuna bakalım.

Anahtar bilgiler aşağıdakileri içerir:

  • anahtar kimliği — anahtar tanımlayıcı, örneğin:
    INNODBKey-764d382a-7324-11e9-ad8f-9cb6d0d5dc99-1
  • anahtar türü — kullanılan şifreleme algoritmasına dayalı anahtar türü, olası değerler: “AES”, “RSA” veya “DSA”.
  • anahtar uzunluğu — bayt cinsinden anahtar uzunluğu, AES: 16, 24 veya 32, RSA 128, 256, 512 ve DSA 128, 256 veya 384.
  • kullanıcı - anahtarın sahibi. Anahtar sistem ise, örneğin Ana Anahtar, bu alan boştur. Keyring_udf kullanılarak bir anahtar oluşturulmuşsa bu alan, anahtarın sahibini tanımlar.
  • anahtarın kendisi

Anahtar, şu çift tarafından benzersiz bir şekilde tanımlanır: key_id, user.

Anahtarların saklanması ve silinmesinde de farklılıklar vardır.

Dosya depolama daha hızlıdır. Bir anahtar deposunun anahtarı bir dosyaya yalnızca bir kez yazdığını düşünebilirsiniz, ancak hayır, burada daha fazlası oluyor. Dosya depolama alanında bir değişiklik yapıldığında ilk olarak tüm içeriğin yedek bir kopyası oluşturulur. Diyelim ki dosyanın adı my_biggest_secrets, o zaman yedek kopya my_biggest_secrets.backup olacaktır. Daha sonra önbellek değiştirilir (anahtarlar eklenir veya silinir) ve her şey başarılı olursa önbellek bir dosyaya sıfırlanır. Sunucu arızası gibi nadir durumlarda bu yedekleme dosyasını görebilirsiniz. Yedekleme dosyası, anahtarların bir sonraki yüklenmesinde (genellikle sunucu yeniden başlatıldıktan sonra) silinir.

Bir anahtarı sunucu deposuna kaydederken veya silerken, deponun “anahtarı gönder” / “anahtarın silinmesini iste” komutlarıyla MySQL sunucusuna bağlanması gerekir.

Sunucu başlatma hızına geri dönelim. Başlatma hızının kasanın kendisinden etkilenmesine ek olarak, başlangıçta kasadan kaç anahtarın alınması gerektiği sorunu da vardır. Elbette bu özellikle sunucu depolaması için önemlidir. Başlangıçta sunucu, şifrelenmiş tablolar/tablo alanları için hangi anahtarın gerekli olduğunu kontrol eder ve anahtarı depodan ister. Ana Anahtar şifrelemeli "temiz" bir sunucuda, depodan alınması gereken bir Ana Anahtar bulunmalıdır. Ancak, örneğin yedekleme sunucusunun bir yedeği birincil sunucudan geri yüklemesi sırasında daha fazla sayıda anahtar gerekebilir. Bu gibi durumlarda Ana Anahtarın rotasyonu sağlanmalıdır. Bu konu gelecekteki makalelerde daha ayrıntılı olarak ele alınacaktır, ancak burada birden fazla Ana Anahtar kullanan bir sunucunun, özellikle sunucu tarafı anahtar deposu kullanıldığında başlatılmasının biraz daha uzun sürebileceğini belirtmek isterim.

Şimdi keyring_file hakkında biraz daha konuşalım. Keyring_file'ı geliştirirken, sunucu çalışırken keyring_file değişikliklerinin nasıl kontrol edileceği konusunda da endişeleniyordum. 5.7'de kontrol, ideal bir çözüm olmayan dosya istatistiklerine göre gerçekleştirildi ve 8.0'da bunun yerine SHA256 sağlama toplamı kullanıldı.

Keyring_file'ı ilk kez çalıştırdığınızda, sunucu tarafından hatırlanan dosya istatistikleri ve sağlama toplamı hesaplanır ve değişiklikler yalnızca eşleşirse uygulanır. Dosya değiştiğinde sağlama toplamı güncellenir.

Anahtar kasalarıyla ilgili birçok soruyu zaten ele aldık. Ancak sıklıkla unutulan ya da yanlış anlaşılan önemli bir konu daha var: anahtarların sunucular arasında paylaşılması.

Demek istedigim? Kümedeki her sunucunun (örneğin Percona Server), Vault Server'da Percona Server'ın anahtarlarını saklaması gereken ayrı bir konumu olmalıdır. Depolamaya kaydedilen her Ana Anahtar, tanımlayıcısı içinde Percona Sunucusunun GUID'sini içerir. Neden önemlidir? Yalnızca bir Vault Sunucunuz olduğunu ve kümedeki tüm Percona Sunucularının bu tek Vault Sunucusunu kullandığını hayal edin. Sorun açık görünüyor. Tüm Percona Sunucuları, id = 1, id = 2 vb. gibi benzersiz tanımlayıcılar olmayan bir Ana Anahtar kullanıyorsa, kümedeki tüm sunucular aynı Ana Anahtarı kullanır. GUID'in sağladığı şey sunucular arasındaki ayrımdır. Benzersiz bir GUID zaten mevcutsa neden sunucular arasında anahtar paylaşımından bahsedesiniz ki? Başka bir eklenti daha var - keyring_udf. Bu eklenti ile sunucu kullanıcınız anahtarlarını Vault sunucusunda saklayabilir. Sorun, örneğin bir kullanıcı sunucu1'de bir anahtar oluşturduğunda ve ardından sunucu2'de aynı kimliğe sahip bir anahtar oluşturmaya çalıştığında ortaya çıkar; örneğin:

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

Beklemek. Her iki sunucu da aynı Vault Sunucusunu kullanıyor, keyring_key_store işlevinin sunucu2'de başarısız olması gerekmez mi? İlginç bir şekilde, aynı şeyi bir sunucuda yapmaya çalışırsanız bir hata alırsınız:

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

Doğru, ROB_1 zaten mevcut.

Önce ikinci örneği tartışalım. Daha önce de söylediğimiz gibi, keyring_vault veya başka herhangi bir anahtarlık eklentisi, tüm anahtar kimliklerini bellekte önbelleğe alır. Yani yeni bir anahtar oluşturduktan sonra sunucu1'e ROB_1 eklenir ve bu anahtarın Vault'a gönderilmesinin yanı sıra anahtar da önbelleğe eklenir. Artık aynı anahtarı ikinci kez eklemeye çalıştığımızda keyring_vault, anahtarın önbellekte olup olmadığını kontrol ediyor ve hata veriyor.

İlk durumda durum farklıdır. Sunucu1 ve sunucu2'nin ayrı önbellekleri vardır. ROB_1'i sunucu1 ve Vault sunucusundaki anahtar önbelleğine ekledikten sonra sunucu2'deki anahtar önbelleği senkronize değil. Sunucu2'deki önbellekte ROB_1 anahtarı yok. Böylece, ROB_1 anahtarı keyring_key_store'a ve Vault sunucusuna yazılır ve bu da aslında önceki değerin üzerine yazar (!). Artık Vault sunucusundaki ROB_1 anahtarı 543210987654321'dir. İlginçtir ki Vault sunucusu bu tür eylemleri engellemez ve kolayca eski değerin üzerine yazar.

Keyring_udf kullandığınızda ve anahtarları Vault'ta depolamak istediğinizde, Vault'ta sunucu bölümlemenin neden önemli olabileceğini artık görebiliyoruz. Bir Vault sunucusunda bu ayırma nasıl sağlanır?

Vault'u bölmenin iki yolu vardır. Her sunucu için farklı bağlama noktaları oluşturabilir veya aynı bağlama noktası içinde farklı yollar kullanabilirsiniz. Bu en iyi örneklerle gösterilmiştir. O halde önce bireysel bağlama noktalarına bakalım:

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

Burada sunucu1 ve sunucu2'nin farklı bağlama noktaları kullandığını görebilirsiniz. Yolları bölerken konfigürasyon şöyle görünecektir:

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

Bu durumda, her iki sunucu da aynı bağlama noktası olan "mount_point"i ancak farklı yolları kullanır. Bu yolu kullanarak sunucu1 üzerinde ilk gizli diziyi oluşturduğunuzda, Vault sunucusu otomatik olarak bir “sunucu1” dizini oluşturur. Sunucu2 için her şey benzer. Mount_point/server1 veya mount_point/server2'deki son sırrı sildiğinizde, Vault sunucusu bu dizinleri de siler. Yol ayırmayı kullanmanız durumunda, yalnızca bir bağlama noktası oluşturmalı ve yapılandırma dosyalarını, sunucuların ayrı yollar kullanmasını sağlayacak şekilde değiştirmelisiniz. Bir HTTP isteği kullanılarak bir bağlama noktası oluşturulabilir. CURL kullanarak bu şu şekilde yapılabilir:

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

Tüm alanlar (TOKEN, VAULT_CA, VAULT_URL, SECRET_MOUNT_POINT) yapılandırma dosyasının parametrelerine karşılık gelir. Elbette aynısını yapmak için Vault yardımcı programlarını da kullanabilirsiniz. Ancak bir bağlama noktasının oluşturulmasını otomatikleştirmek daha kolaydır. Umarım bu bilgiyi faydalı bulursunuz ve bu serinin sonraki makalelerinde görüşürüz.

MySQL'de Şifreleme: Anahtar Deposu

Daha fazla oku:

Kaynak: habr.com

Yorum ekle