MySQL 中的加密:Keystore

期待新課程開始招生 “數據庫” 我們為您準備了一篇有用文章的翻譯。

MySQL 中的加密:Keystore

透明資料加密(TDE)出現在 用於 MySQL 的 Percona 服務器 和 MySQL 已經有一段時間了。 但是您有沒有想過它在幕後是如何工作的以及 TDE 會對您的伺服器產生什麼影響? 在本系列文章中,我們將了解 TDE 的內部運作原理。 讓我們從密鑰儲存開始,因為這是任何加密工作所必需的。 然後我們將仔細研究 Percona Server for MySQL/MySQL 中的加密工作原理以及 Percona Server for MySQL 具有哪些附加功能。

MySQL 金鑰環

密鑰環是允許伺服器查詢、建立和刪除本機檔案 (keyring_file) 或遠端伺服器(例如 HashiCorp Vault)上的金鑰的插件。 密鑰始終緩存在本地以加快檢索速度。

插件可以分為兩類:

  • 本地儲存。 例如,本地文件(我們稱之為基於文件的密鑰環)。
  • 遠端存儲。 例如,Vault Server(我們稱之為基於伺服器的金鑰環)。

這種分離很重要,因為不同類型的儲存的行為略有不同,不僅在儲存和檢索金鑰時,而且在運行它們時也是如此。

使用檔案儲存時,啟動時,儲存的全部內容都會載入到快取中:金鑰 ID、金鑰使用者、金鑰類型和金鑰本身。

對於基於伺服器的儲存(例如 Vault Server),啟動時僅載入金鑰 ID 和金鑰用戶,因此取得所有金鑰不會減慢啟動速度。 密鑰是延遲載入的。 也就是說,只有在實際需要時才會從 Vault 載入金鑰本身。 下載後,金鑰將緩存在記憶體中,以便將來不需要透過與 Vault 伺服器的 TLS 連接來存取它。 接下來,讓我們看看密鑰儲存中存在哪些資訊。

關鍵訊息包含以下內容:

  • 密鑰 ID — 密鑰標識符,例如:
    INNODBKey-764d382a-7324-11e9-ad8f-9cb6d0d5dc99-1
  • 密鑰類型 — 基於所使用的加密演算法的金鑰類型,可能的值:「AES」、「RSA」或「DSA」。
  • 密鑰長度 — 金鑰長度(以位元組為單位),AES:16、24 或 32,RSA 128、256、512 和 DSA 128、256 或 384。
  • 用戶 - 鑰匙的所有者。 如果密鑰是系統密鑰,例如主密鑰,則此欄位為空。 如果使用 keyring_udf 建立金鑰,則此欄位標識金鑰的擁有者。
  • 鑰匙本身

金鑰由 key_id、user 對唯一識別。

儲存和刪除密鑰也存在差異。

文件儲存速度更快。 您可能認為密鑰儲存只是將密鑰寫入檔案一次,但事實並非如此,這裡還發生了更多事情。 每當進行文件儲存修改時,都會先建立所有內容的備份副本。 假設該檔案名稱為 my_biggest_secrets,則備份副本將為 my_biggest_secrets.backup。 接下來,更改快取(新增或刪除金鑰),如果一切成功,則將快取重設為檔案。 在極少數情況下,例如伺服器故障,您可能會看到此備份檔案。 下次載入金鑰時(通常在伺服器重新啟動後),備份檔案將被刪除。

當在伺服器儲存中儲存或刪除金鑰時,儲存必須使用「傳送金鑰」/「請求刪除金鑰」指令連接到 MySQL 伺服器。

讓我們回到伺服器啟動速度。 除了啟動速度受到Vault本身的影響之外,還有啟動時需要從Vault中檢索多少金鑰的問題。 當然,這對於伺服器儲存尤其重要。 啟動時,伺服器檢查加密表/表空間需要哪個金鑰,並向儲存請求金鑰。 在具有主密鑰加密的「乾淨」伺服器上,必須有一個主密鑰,並且必須從儲存中檢索該主密鑰。 然而,例如,當備份伺服器從主伺服器還原備份時,可能需要更多數量的金鑰。 在這種情況下,應提供主密鑰的輪換。 這將在以後的文章中更詳細地介紹,儘管在這裡我想指出,使用多個主密鑰的伺服器可能需要更長的時間來啟動,特別是在使用伺服器端密鑰儲存時。

現在讓我們多討論一下 keyring_file。 當我開發keyring_file時,我還關心如何在伺服器執行時檢查keyring_file的變更。 在5.7中,檢查是根據文件統計資料進行的,這不是一個理想的解決方案,在8.0中它被替換為SHA256校驗和。

第一次執行 keyring_file 時,將計算檔案統計資料和校驗和,伺服器會記住這些訊息,並且僅在匹配時才應用變更。 當文件更改時,校驗和會更新。

我們已經討論了有關密鑰保管庫的許多問題。 然而,還有一個經常被遺忘或誤解的重要主題:跨伺服器共享金鑰。

我的意思是說? 叢集中的每台伺服器(例如 Percona Server)必須在 Vault Server 上有一個單獨的位置,Percona Server 必須在其中儲存其金鑰。 儲存在儲存中的每個主密鑰在其識別碼中都包含 Percona 伺服器的 GUID。 為什麼它如此重要? 想像一下,您只有一台 Vault 伺服器,而叢集中的所有 Percona 伺服器都使用該一台 Vault 伺服器。 問題似乎很明顯。 如果所有 Percona 伺服器都使用沒有唯一識別碼的主金鑰,例如 id = 1、id = 2 等,那麼叢集中的所有伺服器將使用相同的主密鑰。 GUID提供的是伺服器之間的區分。 如果已經存在唯一的 GUID,為什麼還要談論伺服器之間共享金鑰呢? 還有另一個插件 - keyring_udf。 使用此插件,您的伺服器使用者可以將他們的金鑰儲存在 Vault 伺服器上。 例如,當使用者在 server1 上建立金鑰,然後嘗試在 server2 上建立具有相同 ID 的金鑰時,就會出現此問題,例如:

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

等待。 兩台伺服器都使用相同的 Vault 伺服器,keyring_key_store 函數在 server2 上不會失敗嗎? 有趣的是,如果您嘗試在一台伺服器上執行相同的操作,您將收到錯誤:

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

沒錯,ROB_1 已經存在。

我們先討論第二個例子。 正如我們之前所說,keyring_vault 或任何其他金鑰環插件都會將所有金鑰 ID 快取在記憶體中。 因此,在建立新金鑰後,ROB_1 被加入到 server1 中,除了將該金鑰傳送到 Vault 之外,該金鑰也被加入到快取中。 現在,當我們嘗試第二次新增相同的金鑰時,keyring_vault 會檢查該金鑰是否存在於快取中並拋出錯誤。

在第一種情況下,情況有所不同。 Server1 和 server2 有單獨的快取。 將 ROB_1 新增至 server1 和 Vault 伺服器上的金鑰快取後,server2 上的金鑰快取不同步。 server2 上的快取中沒有 ROB_1 金鑰。 因此,ROB_1 金鑰被寫入 keyring_key_store 和 Vault 伺服器,這實際上會覆寫 (!) 之前的值。 現在 Vault 伺服器上的 ROB_1 金鑰是 543210987654321。有趣的是,Vault 伺服器不會阻止此類操作,並且可以輕鬆覆蓋舊值。

現在我們可以明白為什麼 Vault 中的伺服器分割區很重要 - 當您使用 keyring_udf 並希望在 Vault 中儲存金鑰時。 如何在 Vault 伺服器上實現這種分離?

有兩種方法可以劃分到 Vault 中。 您可以為每個伺服器建立不同的安裝點,或在同一安裝點內使用不同的路徑。 最好用例子來說明這一點。 讓我們先來看看各個掛載點:

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

在這裡您可以看到 server1 和 server2 使用不同的安裝點。 分割路徑時,配置將如下所示:

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

在這種情況下,兩台伺服器使用相同的安裝點“mount_point”,但路徑不同。 當您使用此路徑在 server1 上建立第一個機密時,Vault 伺服器會自動建立一個「server1」目錄。 對 server2 來說一切都是相似的。 當您刪除 mount_point/server1 或 mount_point/server2 中的最後一個機密時,Vault 伺服器也會刪除這些目錄。 如果您使用路徑分離,則必須僅建立一個裝載點並變更配置文件,以便伺服器使用單獨的路徑。 可以使用 HTTP 請求建立安裝點。 使用 CURL 可以這樣完成:

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

所有欄位(TOKEN、VAULT_CA、VAULT_URL、SECRET_MOUNT_POINT)對應設定檔的參數。 當然,您可以使用 Vault 公用程式來執行相同的操作。 但自動建立掛載點會更容易。 我希望這些資訊對您有用,我們將在本系列的下一篇文章中見到您。

MySQL 中的加密:Keystore

閱讀更多:

來源: www.habr.com

添加評論