在 Azure Synapse Analytics 中实现加密
在此部分中,我们将了解透明数据加密和 TokenLibrary for Apache Spark。
什么是透明数据加密
透明数据加密 (TDE) 是一种加密机制,可帮助你保护 Azure Synapse Analytics。 它将保护 Azure Synapse Analytics 免受恶意脱机活动的威胁。 TDE 以静态加密数据来实现此目的。 TDE 可执行数据库、关联备份和事务日志文件的实时静态加密和解密,你无需更改应用程序。 若要对 Azure Synapse Analytics 使用 TDE,必须手动启用它。
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 还可按需无缝移动和管理密钥,以实现异地复制和还原。
具有自带密钥的透明数据加密,用于客户管理的透明数据加密
如上所述,受透明数据加密保护程序保护的 DEK 也可以使用 Azure Key Vault 中存储的非对称密钥由客户托管(客户管理的透明数据加密)。 这也称为 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。
借助 TokenLibrary for Apache Spark 通过链接服务保护凭据
这是一种用于访问外部源中的数据的常用模式。 除非外部数据源允许匿名访问,否则极有可能需要使用凭据、机密或连接字符串来保护连接。
在 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)
若要获取连接字符串作为映射并分析连接字符串中键的特定值,可查找以下示例:
从连接字符串的键=值对中分析特定值,例如
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)