Azure AI 搜索使用 Azure 管理的密钥自动加密静态数据。 如果需要另一层加密或撤销密钥并关闭对内容的访问权限,可以使用在 Azure Key Vault 中创建和管理的密钥。 本文介绍如何设置客户管理的密钥(CMK)加密。
可以使用 Azure Key Vault 或 Azure Key Vault 托管 HSM(硬件安全模块)存储密钥。 Azure Key Vault 管理的 HSM 是经过 FIPS 140-2 第 3 级验证的 HSM。 HSM 支持是 Azure AI 搜索中的新增功能。 若要迁移到 HSM, 请轮换密钥 并选择托管 HSM 进行存储。
重要
CMK 加密不可逆。 可以轮换密钥并更改 CMK 配置,但索引加密在索引的生存期内持续。 CMK 加密后,仅当搜索服务有权访问密钥时,才能访问索引。 如果通过删除或更改角色分配来撤销对密钥的访问权限,则索引不可用,且在删除索引或还原对密钥的访问权限之前,服务将无法缩放。 如果删除或轮换密钥,则最新密钥最多缓存 60 分钟。
CMK 加密的对象
CMK 加密适用于创建单个对象时。 这意味着无法加密已经存在的对象。 每次将对象保存到磁盘时,就会进行 CMK 加密,无论是用于静态数据(长期存储),还是用于临时缓存的数据(短期存储)。 使用 CMK 时,磁盘永远不会看到未加密的数据。
可加密的对象包括索引、同义词列表、索引器、数据源和技能组。 加密的计算开销高于解密,因此只会加密敏感内容。
加密对以下内容执行:
索引和同义词列表中的所有内容。
索引器、数据源、技能集和矢量器中的敏感内容。 敏感内容是指连接字符串、说明、标识、密钥和用户输入。 例如,技能组有 Azure 认知服务密钥,而某些技能接受用户输入,例如自定义实体。 在这两种情况下,密钥和用户输入都经过加密。 对外部资源(例如 Azure 数据源或 Azure OpenAI 模型)的任何引用也都经过加密。
如果需要跨搜索服务使用 CMK,请设置强制策略。
先决条件
可计费层(任何区域中的“基本”层或更高层)上的 Azure AI 搜索。
Azure Key Vault 和已启用 软删除 和 清除保护 的密钥保管库。 或者是 Azure Key Vault 托管 HSM。 此资源可以位于任何订阅中,但它必须与 Azure AI 搜索位于同一租户中。
能够为密钥访问设置权限并分配角色。 若要创建密钥,必须是 Azure Key Vault 中的 Key Vault 加密官 或 Azure Key Vault 托管 HSM 中的 托管 HSM 加密官。
若要分配角色,你必须是订阅 所有者、 用户访问管理员、 基于角色的访问控制管理员,或者分配到具有 Microsoft.Authorization/roleAssignments/write 权限的自定义角色。
步骤 1:创建加密密钥
使用 Azure Key Vault 或 Azure Key Vault 托管 HSM 创建密钥。 Azure AI 搜索加密支持大小为 2048、3072 和 4096 的 RSA 密钥。 有关支持的密钥类型详细信息,请参阅关于密钥。
建议在开始之前查看 这些提示 。
必需的作是 Wrap、 Unwrap、 Encrypt 和 Decrypt。
- Azure Key Vault
- 托管 HSM
可以使用 Azure 门户、Azure CLI 或 Azure PowerShell 来创建密钥保管库。
步骤 2:创建安全主体
创建一个安全主体供搜索服务用于访问加密密钥。 可以使用托管标识和角色分配,也可以注册应用程序并让搜索服务针对请求提供应用程序 ID。
建议使用托管标识和角色。 可以使用系统托管标识或用户托管标识。 托管标识使搜索服务能够通过 Microsoft Entra ID 进行身份验证,而无需在代码中存储凭据(ApplicationID 或 ApplicationSecret)。 此类托管标识的生命周期与只能具有一个系统分配托管标识的搜索服务的生命周期相关联。 若要详细了解托管标识工作原理,请参阅什么是 Azure 资源托管标识?。
为搜索服务启用系统分配的托管标识。 这是一项两步操作:启用并保存。
步骤 3:授予权限
如果将搜索服务配置为使用托管标识,请分配授予其对加密密钥访问权限的角色。
建议选择基于角色的访问控制,而不是访问策略权限模型。 有关详细信息或迁移步骤,请从 Azure 基于角色的访问控制(Azure RBAC)与访问策略(旧版)开始。
登录到 Azure 门户并查找密钥保管库。
选择“访问控制 (IAM)”,然后选择“添加角色分配”。
选择一个角色:
- 在 Azure Key Vault 上,选择 “Key Vault 加密服务加密用户”。
- 在托管 HSM 上,选择“托管 HSM 加密服务加密用户”。
依次选择托管标识和成员,然后选择搜索服务的托管标识。 如果是在本地进行测试,请同时将此角色分配给自己。
选择“查看 + 分配”。
等待几分钟,以便角色分配正常运行。
步骤 4:加密内容
创建或更新对象时发生加密。 可以将 Azure 门户用于所选对象。 对于任何对象,请使用 搜索 REST API 或 Azure SDK。 查看本文中的 Python 示例 ,了解如何以编程方式加密内容。
在 Azure 门户中创建新对象时,可以在密钥保管库中指定预定义的客户管理的密钥。 Azure 门户允许为以下项启用 CMK 加密:
- 索引
- 数据源
- 索引器
使用 Azure 门户的要求是必须存在密钥保管库和密钥,并且已完成前面的步骤,获得了对密钥的授权访问。
在 Azure 门户中,技能组在 JSON 视图中定义。 使用 REST API 示例中所示的 JSON 在技能组上提供客户管理的密钥。
登录到 Azure 门户 并打开搜索服务页。
在 “搜索管理”下,选择 “索引”、“ 索引器”或 “数据源”。
添加新对象。 在对象定义中,选择 Azure 托管的加密。
选择 客户管理的密钥 ,然后选择订阅、保管库、密钥和版本。
步骤 5:测试加密
要验证加密是否正常工作,请撤销加密密钥,查询索引(应处于不可用状态),然后恢复加密密钥。
使用 Azure 门户执行此任务。 请确保分配了允许读取密钥的角色。
在 Azure 密钥保管库页上,选择“对象”“密钥”>。
选择创建的密钥,然后选择“ 删除”。
在 Azure AI 搜索页上,选择“搜索管理”“索引”。>
选择索引并使用搜索资源管理器运行查询。 应会收到错误。
返回到“Azure 密钥保管库“对象”“密钥”页面。>
选择“管理已删除的密钥”。
选择密钥,然后选择“恢复”。
返回到 Azure AI 搜索中的索引并重新运行查询。 应会看到搜索结果。 如果未看到即时结果,请等待一分钟,然后重试。
设置策略以强制实施 CMK 符合性
Azure 策略可帮助实施组织标准并大规模评估合规性。 Azure AI 搜索有两个与 CMK 相关的可选内置策略。 这些策略适用于新的和现有的搜索服务。
影响 | 启用时的效果 |
---|---|
AuditIfNotExists | 检查策略符合性:对象是否定义了客户管理的密钥,并且内容是否已加密。 此效果适用于包含内容的现有服务。 每次创建或更新对象时会对其进行评估,或按评估计划进行评估。 了解详细信息... |
否认 | 检查策略强制执行:搜索服务是否将 SearchEncryptionWithCmk 设置为 Enabled 。 此效果仅适用于必须启用加密的新服务。 现有服务仍可正常运行,但除非修补服务,否则无法更新它们。 用于预配服务的工具都未公开此属性,因此请注意设置策略会限制你 以编程方式进行设置。 |
分配策略
在 Azure 门户中,导航到内置策略,然后选择“ 分配”。
下面是 Azure 门户中 AuditIfExists 策略的示例:
通过选择订阅和资源组来设置 策略范围 。 排除策略不应应用的任何搜索服务。
接受或修改默认值。 选择 审阅 +创建,然后选择 创建。
启用 CMK 策略的强制执行
分配给订阅中的资源组的策略立即生效。 审核策略会标记不符合资源,但拒绝策略会阻止创建和更新不合规的搜索服务。 本部分介绍如何创建合规的搜索服务或更新服务以使其合规。 若要使对象符合规定,请从本文第一步开始。
创建合规的搜索服务
对于新的搜索服务,请使用 SearchEncryptionWithCmk 设置为 Enabled
创建它们。
Azure 门户和命令行工具(Azure CLI 和 Azure PowerShell)都不以本机方式提供此属性,但可以使用 管理 REST API 通过 CMK 策略定义来预配搜索服务。
此示例来自 使用 REST API 管理 Azure AI 搜索服务,已修改为包含 SearchEncryptionWithCmk 属性。
### Create a search service (provide an existing resource group)
@resource-group = my-rg
@search-service-name = my-search
PUT https://management.chinacloudapi.cn/subscriptions/{{subscriptionId}}/resourceGroups/{{resource-group}}/providers/Microsoft.Search/searchServices/{{search-service-name}}?api-version=2023-11-01 HTTP/1.1
Content-type: application/json
Authorization: Bearer {{token}}
{
"location": "China North",
"sku": {
"name": "basic"
},
"properties": {
"replicaCount": 1,
"partitionCount": 1,
"hostingMode": "default",
"encryptionWithCmk": {
"enforcement": "Enabled"
}
}
}
更新现有搜索服务
对于现在不合规的现有搜索服务,请使用 Services - Update API 或 Azure CLI az resource update 命令对其进行修补。 修补服务可恢复更新搜索服务属性的功能。
PATCH https://management.chinacloudapi.cn/subscriptions/<your-subscription-Id>/resourceGroups/<your-resource-group-name>/providers/Microsoft.Search/searchServices/<your-search-service-name>?api-version=2023-11-01
{
"properties": {
"encryptionWithCmk": {
"enforcement": "Enabled"
}
}
}
轮换或更新加密密钥
使用以下说明轮换密钥或从 Azure Key Vault 迁移到硬件安全模型(HSM)。
对于密钥轮换,建议使用 Azure Key Vault 的自动轮换功能。 如果使用自动轮换,请省略对象定义中的关键版本。 使用最新的密钥,而不是特定版本。
更改密钥或其版本时,必须先更新使用该密钥的任何对象以使用新值,然后再删除旧值。 否则,由于无法解密,对象将会处于不可用状态。
回想一下,密钥缓存了 60 分钟。 在测试和轮换密钥时,请记住这一点。
在密钥保管库中创建新密钥,但保持原始密钥可用。 在此步骤中,可以将密钥保管库切换到 HSM。
更新索引或同义词映射上的 encryptionKey 属性以使用新值。 只有最初创建时带有此属性的对象才能更新为使用其他值。
禁用或删除密钥保管库中的上一个密钥。 监视密钥访问以验证是否正在使用新密钥。
出于性能方面的原因,搜索服务最多会缓存此密钥几个小时。 如果在不提供新密钥的情况下禁用或删除该密钥,则查询将暂时性地继续工作,直到缓存过期。 但是,一旦搜索服务无法再解密内容,你就会收到以下消息: "Access forbidden. The query key used might have been revoked - please retry."
Key Vault 提示
如果你不熟悉 Azure Key Vault,请查看以下快速入门来了解基本任务:使用 PowerShell 在 Azure Key Vault 中设置和检索机密。
使用所需数量的密钥保管库。 管理的密钥可以位于不同的密钥保管库中。 一个搜索服务可以有多个已加密的对象,每个对象通过不同密钥保管库中存储的不同客户管理的加密密钥进行加密。
使用相同的 Azure 租户 ,以便通过角色分配以及通过系统或用户托管标识进行连接来检索托管密钥。 有关创建租户的详细信息,请参阅设置新租户。
在密钥保管库上启用清除保护和软删除。 删除你的 Azure Key Vault 密钥后,无人可以检索你的数据,这是使用客户管理的密钥进行的加密的本质决定的。 若要防止意外删除 Key Vault 密钥造成数据丢失,必须在密钥保管库上启用“软删除”和“清除保护”。 默认情况下,软删除处于启用状态,因此,只有在你特意禁用了此功能时才会遇到问题。 默认情况下,不会启用清除保护,但在 Azure AI 搜索中需要 CMK 加密。
在密钥保管库上启用日志记录,以便可以监视密钥使用情况。
请启用密钥轮换或在例行轮换密钥保管库密钥、应用程序机密和注册期间遵循严格的过程。 在删除旧机密和密钥之前,始终更新所有已加密内容以使用新机密和密钥。 如果缺少此步骤,你的内容将无法解密。
使用加密内容
使用 CMK 加密,你可能会注意到由于额外的加密/解密工作而导致索引编制和查询的延迟。 Azure AI 搜索不记录加密活动,但你可以通过密钥保管库日志记录功能来监视密钥访问。
建议在配置密钥保管库的过程中启用日志记录。
在密钥保管库中添加诊断设置,以使用工作区进行数据保留。
为该类别选择“审核”或“allLogs”,为诊断设置命名,然后保存它。
加密密钥配置的 Python 示例
本部分显示了对象定义中 encryptionKey
的 Python 表示形式。 相同的定义适用于索引、数据源、技能组、索引器和同义词映射。 要在搜索服务和密钥保管库上试用此示例,请从 azure-search-python-samples 下载笔记本。
安装一些包。
! pip install python-dotenv
! pip install azure-core
! pip install azure-search-documents==11.5.1
! pip install azure-identity
创建具有加密密钥的索引。
from azure.search.documents.indexes import SearchIndexClient
from azure.search.documents.indexes.models import (
SimpleField,
SearchFieldDataType,
SearchableField,
SearchIndex,
SearchResourceEncryptionKey
)
from azure.identity import DefaultAzureCredential
endpoint="<PUT YOUR AZURE SEARCH SERVICE ENDPOINT HERE>"
credential = DefaultAzureCredential()
index_name = "test-cmk-index"
index_client = SearchIndexClient(endpoint=endpoint, credential=credential)
fields = [
SimpleField(name="Id", type=SearchFieldDataType.String, key=True),
SearchableField(name="Description", type=SearchFieldDataType.String)
]
scoring_profiles = []
suggester = []
encryption_key = SearchResourceEncryptionKey(
key_name="<PUT YOUR KEY VAULT NAME HERE>",
key_version="<PUT YOUR ALPHANUMERIC KEY VERSION HERE>",
vault_uri="<PUT YOUR KEY VAULT ENDPOINT HERE>"
)
index = SearchIndex(name=index_name, fields=fields, encryption_key=encryption_key)
result = index_client.create_or_update_index(index)
print(f' {result.name} created')
获取索引定义以验证加密密钥配置是否存在。
index_name = "test-cmk-index-qs"
index_client = SearchIndexClient(endpoint=AZURE_SEARCH_SERVICE, credential=credential)
result = index_client.get_index(index_name)
print(f"{result}")
使用几个文档加载索引。 所有字段内容将被视为敏感内容,并使用客户管理的密钥在磁盘上加密。
from azure.search.documents import SearchClient
# Create a documents payload
documents = [
{
"@search.action": "upload",
"Id": "1",
"Description": "The hotel is ideally located on the main commercial artery of the city in the heart of Beijing. A few minutes away is Time's Square and the historic centre of the city, as well as other places of interest that make Beijing one of America's most attractive and cosmopolitan cities."
},
{
"@search.action": "upload",
"Id": "2",
"Description": "The hotel is situated in a nineteenth century plaza, which has been expanded and renovated to the highest architectural standards to create a modern, functional and first-class hotel in which art and unique historical elements coexist with the most modern comforts."
},
{
"@search.action": "upload",
"Id": "3",
"Description": "The hotel stands out for its gastronomic excellence under the management of William Dough, who advises on and oversees all of the Hotel's restaurant services."
},
{
"@search.action": "upload",
"Id": "4",
"Description": "The hotel is located in the heart of the historic center of Sublime in an extremely vibrant and lively area within short walking distance to the sites and landmarks of the city and is surrounded by the extraordinary beauty of churches, buildings, shops and monuments. Sublime Palace is part of a lovingly restored 1800 palace."
}
]
search_client = SearchClient(endpoint=AZURE_SEARCH_SERVICE, index_name=index_name, credential=credential)
try:
result = search_client.upload_documents(documents=documents)
print("Upload of new document succeeded: {}".format(result[0].succeeded))
except Exception as ex:
print (ex.message)
index_client = SearchClient(endpoint=AZURE_SEARCH_SERVICE, credential=credential)
运行查询以确认索引是否正常运行。
from azure.search.documents import SearchClient
query = "historic"
search_client = SearchClient(endpoint=AZURE_SEARCH_SERVICE, credential=credential, index_name=index_name)
results = search_client.search(
query_type='simple',
search_text=query,
select=["Id", "Description"],
include_total_count=True
)
for result in results:
print(f"Score: {result['@search.score']}")
print(f"Id: {result['Id']}")
print(f"Description: {result['Description']}")
查询的输出应生成类似于以下示例的结果。
Score: 0.6130029
Id: 4
Description: The hotel is located in the heart of the historic center of Sublime in an extremely vibrant and lively area within short walking distance to the sites and landmarks of the city and is surrounded by the extraordinary beauty of churches, buildings, shops and monuments. Sublime Palace is part of a lovingly restored 1800 palace.
Score: 0.26286605
Id: 1
Description: The hotel is ideally located on the main commercial artery of the city in the heart of Beijing. A few minutes away is Time's Square and the historic centre of the city, as well as other places of interest that make Beijing one of America's most attractive and cosmopolitan cities.
由于加密内容是在数据刷新或查询之前解密的,因此不会看到加密的可视证据。 要验证加密是否正常工作,请检查资源日志。
后续步骤
如果你不熟悉 Azure 安全体系结构,请查看 Azure 安全文档,具体而言,是以下文章: