静态加密概念和配置指南
重要
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 平台支持这种方法。 它是大数据群集部署的最佳做法。 本文不介绍卷加密。 若要了解如何正确地对用于 SQL Server 大数据群集的卷进行加密,请参阅 Kubernetes 平台或设备文档。
- 应用程序级别加密。 这种体系结构是指,在数据写入磁盘之前由处理数据的应用程序进行的数据加密。 在公开卷的情况下,攻击者无法在其他地方还原数据项目,除非目标系统也配置了相同的加密密钥。
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 实例
- 系统生成的证书安装在 SQL Server Pod 上,以便与 TDE 命令一起使用。 系统管理的证书命名标准是
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 分层装载。
静态加密管理
以下列表包含静态加密管理功能:
- 使用标准 T-SQL 命令,可进行 SQL Server TDE 管理。
- 使用
azdata
命令,可进行 HDFS 加密区域和 HDFS 密钥管理。 - 使用操作笔记本可执行以下管理功能:
- HDFS 密钥备份和恢复
- HDFS 密钥删除
配置指南
在 SQL Server 大数据群集的新部署期间,自 CU8 起,静态加密将默认启用和配置。 也就是说:
- 大数据群集 KMS 组件部署在控制器中,并生成一组默认的密钥和证书。
- SQL Server 是在启用 TDE 的情况下部署的,证书由控制器安装。
- 适用于 HDFS 的 Hadoop KMS 配置为与大数据群集 KMS 交互,以执行加密操作。 HDFS 加密区域已经配置好,可供使用。
上一部分中所述的要求和默认行为都适用。
如果是执行 SQL Server 大数据群集 CU8+ 的新部署或直接升级到 CU9,则无需执行其他步骤。
升级方案
在现有群集上,升级过程不会强制对未加密的用户数据进行新的加密,也不会对其重新加密。 此行为是专门设计的,每个组件需要考虑以下问题:
SQL Server
- SQL Server 主实例。 升级过程不会影响任何主实例数据库和已安装的 TDE 证书。 我们建议在升级过程之前备份你的数据库和手动安装的 TDE 证书。 我们还建议将这些项目存储在大数据群集之外。
- 计算池和存储池。 这些数据库是系统管理的,具有不稳定性,将在群集升级后重新创建并自动加密。
- 数据池。 升级不会影响数据池的 SQL Server 实例部分中的数据库。
HDFS
升级过程不会触及加密区域以外的 HDFS 文件和文件夹。
从 CU8 或更早版本升级到 CU9
无需执行其他步骤。
从 CU6 或更早版本升级到 CU8
注意
在升级到 SQL Server 大数据群集 CU8 之前,请对数据执行完整备份。
不会配置加密区域。 不会将 Hadoop KMS 组件配置为使用大数据群集 KMS。 若要在升级后配置和启用 HDFS 加密区域,请按照下一部分中的说明操作。
升级到 CU8 后启用 HDFS 加密区域
如果已将群集升级到 CU8 (azdata upgrade
),并且想要启用 HDFS 加密区域,可使用以下两种选项:
- 执行名为 SOP0128 - 在大数据群集中启用 HDFS 加密区域的 Azure Data Studio 操作笔记本,以执行配置。
- 运行脚本,如下所示。
要求:
- Active Directory 集成群集。
- 在 AD 模式下配置并记录到群集中的 Azure Data CLI (
azdata
)。
若要重新配置具有加密区域支持的群集,请遵循以下过程。
使用
azdata
执行升级后,保存以下脚本。脚本执行要求:
- 这两个脚本应位于同一个目录中。
- 用于 Kubernetes 的 PATH 配置文件上的
kubectl
位于文件夹 $HOME/.kube 中。
应将此脚本命名为 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 大数据群集 的详细信息,请参阅以下概述: