在 Azure Synapse Analytics 中實作加密
在本節中,我們將逐步解說 Apache Spark 的透明資料加密和 TokenLibrary。
什麼是透明資料加密
透明資料加密 (TDE) 是一種加密機制,可協助您保護 Azure Synapse Analytics。 其會保護 Azure Synapse Analytics 以抵禦惡意離線活動的威脅。 TDE 的做法是將待用資料加密。 TDE 能對資料庫、相關聯的備份,以及待用的交易記錄檔執行即時加密和解密,而不需變更應用程式。 為了將 TDE 使用於 Azure Synapse Analytics,您必須手動加以啟用。
TDE 的做法是即時在頁面層級執行資料的 I/O 加密和解密。 當頁面讀入記憶體時,就會解密。 其會在寫入磁片前進行加密。 TDE 會使用稱為資料庫加密金鑰 (DEK) 的對稱金鑰來加密整個資料庫儲存體。 當您啟動資料庫時,會解密已加密的資料庫加密金鑰。 接著會使用 DEK 以在 SQL Server 資料庫引擎中解密和重新加密資料庫檔案。 DEK 受到透明資料加密保護裝置的保護。 此保護裝置可以是服務管理的憑證 (稱為服務管理的透明資料加密),或是儲存在 Azure Key Vault 中的非對稱金鑰 (客戶管理的透明資料加密)。
請務必瞭解,對 Azure Synapse Analytics 而言,此 TDE 保護裝置設定於伺服器層級。 由會由附加或對應至該伺服器的所有資料庫繼承。 伺服器一詞同時指伺服器與執行個體。
服務管理的透明資料加密
如上所述,透明加密保護裝置所保護的 DEK 可以是服務管理的憑證,我們稱為服務受控 TDE。 當您在 Azure 中查看時,該預設設定表示 DEK 受到每部採用加密演算法 AES256 的伺服器特有的內建憑證所保護。 當資料庫處於異地複寫的關聯性時,主要資料庫和異地次要資料庫都會受到主要資料庫的父伺服器金鑰保護。 如果兩個資料庫連線到相同的伺服器,則也會具有相同的內建 AES 256 憑證。 Microsoft 會自動輪替憑證,以符合內部安全性原則。 根金鑰是由 Microsoft 內部秘密存放區所保護。 Microsoft 也會視異地複寫和還原的需要順暢地移動和管理金鑰。
「自備金鑰」的透明資料加密適用於客戶管理的透明資料加密
如上所述,藉由攜帶 Azure Key Vault 中儲存的非對稱金鑰 (客戶管理的透明資料加密),透明資料加密保護裝置所保護的 DEK 也可以由客戶管理。 這也稱為 TDE 的自備金鑰 (BYOK) 支援。 當這是您適用的案例時,加密 DEK 的 TDE 保護裝置是由客戶管理的非對稱金鑰。 這會儲存至您自己和受控的 Azure Key Vault。 Azure Key Vault 是 Azure 的雲端式外部金鑰管理系統。 此受控金鑰永遠不會離開金鑰保存庫。 TDE 保護裝置可由金鑰保存庫所產生。 另一個選項是將 TDE 保護裝置從內部部署硬體安全模組 (HSM) 裝置傳送至金鑰保存庫。 Azure Synapse Analytics 必須獲得客戶擁有的金鑰保存庫權限,才能將 DEK 解密和加密。 如果撤銷了伺服器對金鑰保存庫的權限,將無法存取資料庫,且所有資料都會加密。
使用 TDE 的 Azure Key Vault 整合,您即可控制金鑰管理工作,例如金鑰輪替、金鑰備份和金鑰權限。 當您使用 Azure Key Vault 功能時,也可讓您在所有 TDE 保護裝置上進行稽核與報告。 使用 Key Vault 的原因在於其為您提供中央金鑰管理系統,其中會運用嚴密監視的 HSM。 其也可讓您劃分金鑰和資料的管理職責,以符合安全性原則的規範。
在 Azure 入口網站中管理透明資料加密。
針對 Azure Synapse Analytics,您可以在使用 Azure 系統管理員或參與者帳戶登入之後,在 Azure 入口網站中管理資料庫的 TDE。 在您的使用者資料庫之下可以找到 TDE 設定。
預設會使用服務管理的 TDE,因此會自動為包含該資料庫的伺服器產生 TDE 憑證。
移動透明資料加密保護的資料庫
在某些使用案例中,您需要移動以 TDE 保護的資料庫。 在 Azure 中,不需要將資料庫解密。 目標將會繼承來源資料庫或主要資料庫上的 TDE 設定。 Azure 中有些繼承 TDE 的作業如下:
- 異地復原
- 自助式時間點還原
- 還原已刪除的資料庫
- 使用中的地理複寫
- 建立資料庫複本
- 將備份檔案還原至 Azure SQL 受控執行個體
如果您匯出受 TDE 保護的資料庫,則匯出的內容不會加密。 這會儲存在未加密的 BACPAC 檔案中。 當新資料庫中的 bacpac 檔案匯入完成後,您就必須確定保護此 BACPAC 檔案,並立即啟用 TDE。
搭配適用於 Apache Spark 的 TokenLibrary 透過連結服務保護您的認證
從外部來源存取資料是很常見的模式。 除非外部資料源允許匿名存取,否則您很可能需要使用認證、祕密或連接字串來保護您的連線。
在 Azure Synapse Analytics 中,藉由提供連結服務來簡化整合程序。 如此一來,連線詳細資料即可儲存在連結服務或 Azure Key Vault 中。 若已建立連結服務,Apache Spark 即可參考連結服務,以在您的程式碼中套用連線資訊。 當您想要從 Azure Synapse Analytics 工作區內的 Azure Data Lake Storage Gen 2 存取檔案時,其會使用 AAD 傳遞進行驗證。 因此,不需要使用 TokenLibrary。 不過,若要連線到其他連結服務,您可以直接呼叫 TokenLibrary。
您可以在下面找到範例:若要連線到其他連結服務,您可以藉由擷取連接字串來直接呼叫 TokenLibrary。 若要取出連接字串,請使用 getConnectionString 函式,並傳入連結服務名稱。
// Scala
// retrieve connectionstring from TokenLibrary
import com.microsoft.azure.synapse.tokenlibrary.TokenLibrary
val connectionString: String = TokenLibrary.getConnectionString("<LINKED SERVICE NAME>")
println(connectionString)
# Python
# retrieve connectionstring from TokenLibrary
from pyspark.sql import SparkSession
sc = SparkSession.builder.getOrCreate()
token_library = sc._jvm.com.microsoft.azure.synapse.tokenlibrary.TokenLibrary
connection_string = token_library.getConnectionString("<LINKED SERVICE NAME>")
print(connection_string)
如果您想要取得連接字串作為對應,並從連接字串的金鑰中剖析特定值,則可以尋找下面的範例:
若要剖析連接字串中 key=value 配對的特定值,例如
DefaultEndpointsProtocol=https;AccountName=<AccountName>;AccountKey=<AccountKey>
使用 getConnectionStringAsMap 函式並傳遞機碼以傳回值。
// Linked services can be used for storing and retreiving credentials (e.g, account key)
// Example connection string (for storage): "DefaultEndpointsProtocol=https;AccountName=<accountname>;AccountKey=<accountkey>"
import com.microsoft.azure.synapse.tokenlibrary.TokenLibrary
val accountKey: String = TokenLibrary.getConnectionStringAsMap("<LINKED SERVICE NAME">).get("<KEY NAME>")
println(accountKey)
# Linked services can be used for storing and retreiving credentials (e.g, account key)
# Example connection string (for storage): "DefaultEndpointsProtocol=https;AccountName=<accountname>;AccountKey=<accountkey>"
from pyspark.sql import SparkSession
sc = SparkSession.builder.getOrCreate()
token_library = sc._jvm.com.microsoft.azure.synapse.tokenlibrary.TokenLibrary
accountKey = token_library.getConnectionStringAsMap("<LINKED SERVICE NAME>").get("<KEY NAME>")
print(accountKey)