重要
Microsoft SQL Server 2019 大数据群集附加产品将停用。 对 SQL Server 2019 大数据群集的支持将于 2025 年 2 月 28 日结束。 具有软件保障的 SQL Server 2019 的所有现有用户都将在平台上获得完全支持,在此之前,该软件将继续通过 SQL Server 累积更新进行维护。 有关详细信息,请参阅公告博客文章和 Microsoft SQL Server 平台上的大数据选项。
从MICROSOFT SQL Server 2019 CU8 大数据群集开始,静态加密功能可用于向平台中存储的所有数据提供应用程序级加密。 本指南介绍大数据群集静态加密功能集的概念、体系结构和配置。
SQL Server 大数据群集将数据存储在以下位置:
- SQL Server 主实例。
- HDFS。 由存储池和 Spark 使用。
有两种方法可以透明加密 SQL Server 大数据群集中的数据:
- 卷加密。 Kubernetes 平台支持此方法。 这是大数据群集部署的最佳做法。 本文不涉及卷加密。 请参阅 Kubernetes 平台或设备文档,了解如何正确加密用于 SQL Server 大数据群集的卷。
- 应用程序级加密。 此体系结构是指应用程序在将数据写入磁盘之前处理数据的加密。 如果卷公开,攻击者将无法在其他位置还原数据项目,除非目标系统也配置了相同的加密密钥。
SQL Server 大数据群集的静态加密功能集支持 SQL Server 和 HDFS 组件应用程序级加密的核心方案。
此功能提供以下功能:
- 系统管理的静态加密。 此功能在 CU8+ 中可用。
- 用户管理的静态加密,也称为自带密钥(BYOK)。 SQL Server 2019 CU8 中引入了由服务管理的集成。 SQL Server 2019 CU11+ 中引入了外部密钥提供程序集成。
有关详细信息,请参阅 SQL Server 大数据群集中的密钥版本。
密钥定义
SQL Server 大数据群集密钥管理服务 (KMS)
负责管理 SQL Server 大数据群集静态加密功能的密钥和证书的控制器托管服务。 该服务支持以下功能:
- 安全管理和存储用于静态加密的密钥和证书。
- Hadoop KMS 兼容性。 KMS 充当大数据群集上的 HDFS 组件的密钥管理服务。
- SQL Server 透明数据加密 (TDE) 证书管理。
系统管理的密钥
大数据群集 KMS 服务管理 SQL Server 和 HDFS 的所有密钥和证书
用户定义的密钥
要由大数据群集 KMS 管理的用户定义的密钥,通常称为自带密钥。 SQL Server 大数据群集支持用于 SQL Server 和 HDFS 组件加密的密钥的自定义定义。 大数据群集 KMS 管理这些密钥。
谨慎
SQL Server 主实例继承 SQL Server TDE 功能。 但是,不支持将自定义密钥从文件手动加载到 Pod 中,在 SQL Server 上注册这些密钥并将其用于 TDE。 大数据群集 KMS 不会管理这些密钥。 这种情况可能导致数据库不可读。 若要正确使用外部提供的密钥,请使用本文中所述的“外部提供程序”功能。
外部供应商
支持将加密操作委托给与大数据群集 KMS 兼容的外部密钥解决方案。 SQL Server 2019 CU11+ 支持此功能。 启用此功能后,加密的根密钥托管在大数据群集控制器外部。
SQL Server 大数据群集上的静态加密
大数据群集 KMS 控制器服务为系统管理的密钥和外部提供程序控制的密钥提供支持,以实现 SQL Server 和 HDFS 上的静态数据加密。
这些密钥和证书由服务管理。 本文提供有关如何与服务交互的操作指导。
此功能集引入了大数据群集 KMS 控制器服务,为 SQL Server 和 HDFS 上的静态数据加密提供系统管理的密钥和证书。 这些密钥和证书由服务管理。 本文提供有关如何与服务交互的操作指导。
- SQL Server 实例使用已建立的 透明数据加密(TDE) 功能。
- HDFS 在每个 Pod 中使用本机 Hadoop KMS 来与控制器上的大数据群集 KMS 交互。 此方法支持 HDFS 加密区域,这些区域在 HDFS 上提供安全路径。
SQL Server 实例
- 系统生成的证书安装在要用于 TDE 命令的 SQL Server Pod 上。 系统管理的证书命名标准为
TDECertificate
+timestamp
。 例如,TDECertificate2020_09_15_22_46_27
。 - 主实例大数据群集预配的数据库和用户数据库不会自动加密。 数据库管理员可以使用已安装的证书来加密任何数据库。
- 使用系统生成的证书自动加密计算池和存储池。
- 尽管从技术上可以使用 T-SQL
EXECUTE AT
命令进行数据池加密,但目前不建议使用和不支持数据池加密。 使用此方法加密数据池数据库可能无效,加密可能未在所需状态下发生。 此方法还会为下一版本创建不兼容的升级路径。 - SQL Server 密钥轮换是使用标准 T-SQL 管理命令实现的。 有关详细信息,请参阅 SQL Server 大数据群集透明数据加密(TDE)静态使用指南。
- 加密监视通过适用于 TDE 的现有标准 SQL Server DMV 进行。
- 支持将启用 TDE 的数据库备份和还原到集群中。
- 支持高可用性。 如果 SQL Server 的主实例上的数据库已加密,则数据库的所有次要副本也会加密。
HDFS 加密区域
- 需要 Active Directory 集成才能为 HDFS 启用加密区域。
- 在 Hadoop KMS 中预配系统生成的密钥。 键名称为
securelakekey
. 在 CU8 上,默认密钥为 256 位,我们支持 256 位 AES 加密。 - 在名为 /securelake 的路径上使用上述系统生成的密钥预配默认加密区域。
- 用户可以使用本指南中提供的特定说明创建其他密钥和加密区域。 用户能够在创建密钥期间选择密钥大小 128、192 或 256。
- HDFS 加密区域的密钥轮换操作是通过使用
azdata
来实现的。 有关详细信息,请参阅 SQL Server 大数据群集 HDFS 加密区域使用指南。 - 不支持在加密区域顶部装载 HDFS 分层。
静态加密管理
以下列表包含静态加密的管理功能:
- SQL Server TDE 管理是使用标准 T-SQL 命令执行的。
-
HDFS 加密区域 和 HDFS 密钥管理是使用
azdata
命令执行的。 - 以下管理功能是使用 运作笔记本执行的:
- HDFS 密钥备份和恢复
- HDFS 密钥删除
配置指南
在SQL Server 大数据群集的新部署期间,从 CU8 起,默认情况下会启用和配置数据静态加密。 也就是说:
- 大数据群集 KMS 组件部署在控制器中,并生成一组默认密钥和证书。
- SQL Server 已启用 TDE 部署,并且由控制器安装证书。
- Hadoop KMS for HDFS 配置为与大数据群集 KMS 对接,以便进行加密操作。 HDFS 加密区域已配置并可供使用。
上一部分所述的要求和默认行为适用。
如果执行 SQL Server 大数据群集 CU8 的全新部署或直接升级到 CU9,则无需执行其他步骤。
升级方案
在现有群集上,升级过程不会对尚未加密的用户数据强制实施新的加密或重新加密。 此行为是设计造成的,每个组件需要考虑以下问题:
SQL Server
- SQL Server 主实例。 升级过程不会影响任何主实例数据库和已安装的 TDE 证书。 建议在升级过程之前备份数据库和手动安装的 TDE 证书。 我们还建议将这些工件存储在大数据群集之外。
- 计算和存储池。 这些数据库是系统管理的、易失性的,在群集升级时重新创建并自动加密。
- 数据池。 升级不会影响数据池的 SQL Server 实例中的数据库。
HDFS(Hadoop分布式文件系统)
升级过程不会接触加密区域外的 HDFS 文件和文件夹。
从 CU8 或更早版本升级到 CU9
无需执行其他步骤。
从 CU6 或更早版本升级到 CU8
谨慎
在升级到 SQL Server 大数据群集 CU8 之前,请执行数据的完整备份。
不会配置加密区域。 Hadoop KMS 组件不会配置为使用大数据群集 KMS。 若要在升级后配置和启用 HDFS 加密区域,请按照下一部分中的说明进行作。
升级到 CU8 后启用 HDFS 加密区域
如果将群集升级到 CU8(azdata upgrade
)并且想要启用 HDFS 加密区域,有两个选项:
- 执行 Azure Data Studio 的操作笔记本 名为 SOP0128 - 启用大数据群集中的 HDFS 加密区域 以进行配置。
- 运行脚本,如下所示。
要求:
- Active Directory 集成群集。
- 在 AD 模式下配置并记录到群集中的 Azure Data CLI (
azdata
)。
按照此过程重新配置支持加密区域的群集。
在执行
azdata
升级后,请保存以下脚本。脚本执行要求:
- 这两个脚本应位于同一目录中。
-
kubectl
$HOME /.kube 文件夹中 Kubernetes 的 PATH 配置文件。
此脚本应命名 为 run-key-provider-patch.sh:
#!/bin/bash if [[ -z "${BDC_DOMAIN}" ]]; then echo "BDC_DOMAIN environment variable with the ___domain name of the cluster is not defined." exit 1 fi if [[ -z "${BDC_CLUSTER_NS}" ]]; then echo "BDC_CLUSTER_NS environment variable with the cluster namespace is not defined." exit 1 fi kubectl get configmaps -n test diff <(kubectl get configmaps mssql-hadoop-storage-0-configmap -n $BDC_CLUSTER_NS -o json | ./updatekeyprovider.py) <(kubectl get configmaps mssql-hadoop-storage-0-configmap -n $BDC_CLUSTER_NS -o json | python -m json.tool) diff <(kubectl get configmaps mssql-hadoop-sparkhead-configmap -n $BDC_CLUSTER_NS -o json | ./updatekeyprovider.py) <(kubectl get configmaps mssql-hadoop-sparkhead-configmap -n $BDC_CLUSTER_NS -o json | python -m json.tool) # Replace the config maps. # kubectl replace -n $BDC_CLUSTER_NS -o json -f <(kubectl get configmaps mssql-hadoop-storage-0-configmap -n $BDC_CLUSTER_NS -o json | ./updatekeyprovider.py) kubectl replace -n $BDC_CLUSTER_NS -o json -f <(kubectl get configmaps mssql-hadoop-sparkhead-configmap -n $BDC_CLUSTER_NS -o json | ./updatekeyprovider.py) # Restart the pods which need to have the necessary changes with the core-site.xml kubectl delete pods -n $BDC_CLUSTER_NS nmnode-0-0 kubectl delete pods -n $BDC_CLUSTER_NS storage-0-0 kubectl delete pods -n $BDC_CLUSTER_NS storage-0-1 # Wait for sometime for pods to restart # sleep 300 # Check for the KMS process status. # kubectl exec -n $BDC_CLUSTER_NS -c hadoop nmnode-0-0 -- bash -c 'ps aux | grep kms' kubectl exec -n $BDC_CLUSTER_NS -c hadoop storage-0-0 -- bash -c 'ps aux | grep kms' kubectl exec -n $BDC_CLUSTER_NS -c hadoop storage-0-1 -- bash -c 'ps aux | grep kms'
此脚本应命名 为 updatekeyprovider.py:
#!/usr/bin/env python3 import json import re import sys import xml.etree.ElementTree as ET import os class CommentedTreeBuilder(ET.TreeBuilder): def comment(self, data): self.start(ET.Comment, {}) self.data(data) self.end(ET.Comment) domain_name = os.environ['BDC_DOMAIN'] parser = ET.XMLParser(target=CommentedTreeBuilder()) core_site = 'core-site.xml' j = json.load(sys.stdin) cs = j['data'][core_site] csxml = ET.fromstring(cs, parser=parser) props = [prop.find('value').text for prop in csxml.findall( "./property/name/..[name='hadoop.security.key.provider.path']")] kms_provider_path='' for x in range(5): if len(kms_provider_path) != 0: kms_provider_path = kms_provider_path + ';' kms_provider_path = kms_provider_path + 'nmnode-0-0.' + domain_name if len(props) == 0: prop = ET.SubElement(csxml, 'property') name = ET.SubElement(prop, 'name') name.text = 'hadoop.security.key.provider.path' value = ET.SubElement(prop, 'value') value.text = 'kms://https@' + kms_provider_path + ':9600/kms' cs = ET.tostring(csxml, encoding='utf-8').decode('utf-8') j['data'][core_site] = cs kms_site = 'kms-site.xml.tmpl' ks = j['data'][kms_site] kp_uri_regex = re.compile('(<name>hadoop.kms.key.provider.uri</name>\s*<value>\s*)(.*)(\s*</value>)', re.MULTILINE) def replace_uri(match_obj): key_provider_uri = 'bdc://https@hdfsvault-svc.' + domain_name if match_obj.group(2) == 'jceks://file@/var/run/secrets/keystores/kms/kms.jceks' or match_obj.group(2) == key_provider_uri: return match_obj.group(1) + key_provider_uri + match_obj.group(3) return match_obj.group(0) ks = kp_uri_regex.sub(replace_uri, ks) j['data'][kms_site] = ks print(json.dumps(j, indent=4, sort_keys=True))
使用相应的参数运行 run-key-provider-patch.sh 。
外部提供商的配置
如前几节所述,SQL Server 2019 CU8+ 大数据群集部署默认使用系统管理的密钥启用静态加密功能。 为了使外部密钥提供程序能够保护 SQL Server 和 HDFS 加密的根密钥,请参阅 SQL Server 大数据群集中的外部密钥提供程序。
后续步骤
若要详细了解如何在 SQL Server 大数据群集上使用密钥版本,请参阅 SQL Server 大数据群集中的密钥版本。
若要详细了解如何有效地使用静态加密 SQL Server 大数据群集,请参阅以下文章:
若要了解有关 SQL Server 大数据群集 的详细信息,请参阅以下概述: