教程:在使用随机加密且已启用 enclave 的列上创建和使用索引
适用于: SQL Server 2019 (15.x) 及更高版本 - 仅限 Windows Azure SQL 数据库
本教程将介绍如何在使用含安全 enclave 的 Always Encrypted 中支持的随机加密且已启用 enclave 的列上创建和使用索引。 它将介绍:
- 如何在有权访问保护列的密钥(列主密钥和列加密密钥)时创建索引。
- 如何在无权访问保护列的密钥时创建索引。
先决条件
下载最新版 SQL Server Management Studio (SSMS)。
在执行本教程中的以下步骤之前,请确保已完成开始使用具有安全 enclave 的 Always Encrypted 教程之一。
步骤 1:在数据库中启用加速数据库恢复 (ADR)
注意
此步骤仅适用于 SQL Server。 如果使用的是 Azure SQL 数据库,请跳过此步骤。 Azure SQL 数据库中自动启用 ADR,且不支持禁用它。
Microsoft 强烈建议,先在数据库中启用 ADR,再在使用随机加密且已启用 enclave 的列上创建首个索引。 请参阅含安全 enclave 的 Always Encrypted 中的数据库恢复部分。
关闭在上一教程中使用的任何 SSMS 实例。 关闭 SSMS 时,将会关闭你已打开的数据库连接,这是启用 ADR 的必需操作。
以 sysadmin 身份打开新 SSMS 实例,并连接到 SQL Server 实例,无需为数据库连接启用 Always Encrypted。
- 启动 SSMS。
- 在“连接到服务器”对话框中,指定服务器名称,选择身份验证方法,并指定凭据。
- 选择“选项 >>”,并选择“Always Encrypted”选项卡。
- 务必取消选中“启用 Always Encrypted (列加密)”复选框。
- 选择“连接”。
打开新查询窗口,并执行以下语句来启用 ADR。
ALTER DATABASE ContosoHR SET ACCELERATED_DATABASE_RECOVERY = ON;
步骤 2:在不使用角色分隔的情况下创建和测试索引
这一步将在加密列上创建和测试索引。 你将是一个同时具有以下两个角色的用户:管理数据库的 DBA 和有权访问保护数据的密钥的数据所有者。
打开新 SSMS 实例,并连接到已为数据库连接启用 Always Encrypted 的 SQL Server 实例。
- 启动新 SSMS 实例。
- 在“连接到服务器”对话框中,指定服务器名称,选择身份验证方法,并指定凭据。
- 选择“选项 >>”,并选择“Always Encrypted”选项卡。
- 选中“启用 Always Encrypted (列加密)”和“启用安全 enclave”复选框
- 如果要对数据库使用证明,请选择 enclave 证明协议的值,该值代表你使用的证明服务(主机保护者服务或 Microsoft Azure 证明),并且填写 enclave 证明 URL。 否则,请选择“无”。
- 选择“连接” 。
- 如果系统提示启用 Always Encrypted 查询的参数化,请选择“启用”。
如果系统没有提示启用 Always Encrypted 参数化,请验证它是否已启用。
- 在 SSMS 的主菜单中,选择“工具”。
- 选择“选项...”。
- 导航到“查询执行”>“SQL Server”>“高级”。
- 务必选中“启用 Always Encrypted 参数化”。
- 选择“确定”。
打开查询窗口,并执行下面的语句,以加密“Employees”表中的“LastName”列。 后面的步骤将介绍如何在此列上创建并使用索引。
ALTER TABLE [HR].[Employees] ALTER COLUMN [LastName] [nvarchar](50) COLLATE Latin1_General_BIN2 ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [CEK1], ENCRYPTION_TYPE = Randomized, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NOT NULL; GO ALTER DATABASE SCOPED CONFIGURATION CLEAR PROCEDURE_CACHE; GO
在“LastName”列上创建索引。 由于你是在已启用 Always Encrypted 的情况下连接到数据库,因此 SSMS 内部的客户端驱动程序以透明方式将 CEK1(保护“LastName”列的列加密密钥)提供给创建索引所需的 enclave。
CREATE INDEX IX_LastName ON [HR].[Employees] ([LastName]) INCLUDE ([EmployeeID], [FirstName], [SSN], [Salary]); GO
对“LastName”列运行丰富查询,并验证 SQL Server 是否在执行查询时使用索引。
在同一或新查询窗口中,确保工具栏上的“包括实时查询统计信息”按钮处于启用状态。
执行下面的查询。
DECLARE @LastNamePrefix NVARCHAR(50) = 'Aber%'; SELECT * FROM [HR].[Employees] WHERE [LastName] LIKE @LastNamePrefix; GO
在“实时查询统计信息”选项卡中,观察查询是否使用索引。
步骤 3:在使用角色分隔的情况下创建索引
在这一步中,你将假装为两个不同的用户,在加密列上创建索引。 一个用户是需要创建索引但无权访问密钥的 DBA。 另一个用户是有权访问密钥的数据所有者。
使用未启用 Always Encrypted 的 SSMS 实例来执行下面的语句,以删除“LastName”列上的索引。
DROP INDEX IX_LastName ON [HR].[Employees]; GO
以数据所有者(或有权访问密钥的应用程序)身份,使用 CEK1 填充 enclave 内的缓存。
注意
除非你在步骤 2:在不使用角色分隔的情况下创建和测试索引之后重启了 SQL Server 实例,否则此步骤是多余的,因为 CEK1 已存在于缓存中。 之所以添加它是为了展示数据所有者如何向 enclave 提供密钥(如果 enclave 中尚无的话)。
在已启用 Always Encrypted 的 SSMS 实例中,在查询窗口中执行下面的语句。 此语句将所有已启用 enclave 的列加密密钥都发送到 enclave。 有关详细信息,请参阅 sp_enclave_send_keys。
EXEC sp_enclave_send_keys; GO
作为上述存储过程的替代方法,可以运行对“LastName”列使用 enclave 的 DML 查询。 这只会使用 CEK1 填充 enclave。
DECLARE @LastNamePrefix NVARCHAR(50) = 'Aber%'; SELECT * FROM [HR].[Employees] WHERE [LastName] LIKE @LastNamePrefix; GO
以 DBA 身份创建索引。
在未启用 Always Encrypted 的 SSMS 实例中,在查询窗口中执行下面的语句。
CREATE INDEX IX_LastName ON [HR].[Employees] ([LastName]) INCLUDE ([EmployeeID], [FirstName], [SSN], [Salary]); GO
以数据所有者身份对“LastName”列运行丰富查询,并验证 SQL Server 是否在执行查询时使用索引。
在已启用 Always Encrypted 的 SSMS 实例中,选择现有查询窗口或打开新查询窗口,并确保工具栏上的“包括实时查询统计信息”按钮处于启用状态。
执行下面的查询。
DECLARE @LastNamePrefix NVARCHAR(50) = 'Aber%'; SELECT * FROM [HR].[Employees] WHERE [LastName] LIKE @LastNamePrefix; GO
在“实时查询统计信息”选项卡中,观察查询是否使用索引。
后续步骤
- 教程:使用具有安全 enclave 的 Always Encrypted 开发 .NET 应用程序
- 教程:开发使用具有安全 enclave 的 Always Encrypted 的 .NET Framework 应用程序