重要
标记为“预览”的特性、功能或属性不受服务级别协议 (SLA) 保障,不建议用于生产工作负载,并且在正式发布之前可能会更改或受到限制。
Azure AI 搜索预览条款适用于所有预览功能,无论是独立功能还是正式版功能的一部分。
使用 Microsoft 管理的密钥时,启用客户管理的密钥(CMK)在默认加密的基础上增加了额外的安全性。 启用 CMK 时,可以控制用于保护数据的加密密钥,包括:
- 根据客户定义的计划轮换密钥
- 禁用或撤销密钥以阻止对加密内容的访问 (缓存密钥可能持续长达 60 分钟)
- 通过Azure 密钥保管库日志记录审核密钥使用情况
可以使用以下任一方法创建、存储和管理密钥:
本文介绍如何配置 CMK 以进一步保护Azure AI 搜索中的加密数据。
重要
- 添加客户管理的密钥(CMK)适用于静态数据的加密。 如果需要保护正在使用的数据,请考虑使用 机密计算。
先决条件
Azure AI 搜索 处于可计费层(任何区域的基本层或更高层)。
Azure 密钥保管库 和启用了 软删除 和 清除保护 的密钥保管库。 或者是 Azure 密钥保管库 托管 HSM。 此资源可以位于任何订阅和不同的租户中。 这些说明假定单个租户。 有关跨租户配置,请参阅 跨不同租户配置客户管理的密钥。
如果计划配置服务级别 CMK,请使用搜索管理 REST API 版本 2026-03-01-preview 或更高版本。 若要检查对象是否继承服务级别密钥,请使用数据平面 API 版本 2026-05-01-preview 或更高版本。
能够设置密钥访问权限并分配角色。 若要创建密钥,必须在 Azure 密钥保管库 中具有 密钥保管库 Crypto Officer 身份或在 Azure 密钥保管库 托管 HSM 中具有 Managed HSM Crypto Officer 身份。
要分配角色,必须是订阅所有者、用户访问管理员、基于角色的访问控制管理员,或被分配具有 Microsoft.Authorization/roleAssignments/write 权限的自定义角色。
具有可以使用客户管理的密钥(CMK)配置的加密数据的对象包括索引、同义词列表、索引器、数据源、向量器和技能集。 加密的计算成本很高,因此仅加密敏感内容。
加密是通过:
在新创建对象时,必须将客户管理的密钥添加到对象。 请务必记住:
无法追溯性地将 CMK 添加到现有对象。 如果要将客户管理的密钥添加到现有对象,则必须删除并重新创建启用加密的对象。
配置 CMK 后,每次服务写入数据时都会进行加密,包括静态数据(长期存储)或临时缓存数据(短期存储)。 对于数据源、索引器和技能集等对象,对象定义是加密的。 对于索引,索引文档本身(而不仅仅是索引架构)将加密。
尽管无法向现有对象添加加密,但只要资源位于同一租户中,就可以更改对象的加密定义的所有部分,包括切换到其他密钥保管库或 HSM 存储。
使用 CMK 进行加密是不可逆的。 可以轮换密钥并更改 CMK 配置,但索引加密在索引的生存期内持续。 使用 CMK 加密后,仅当搜索服务有权访问密钥时,才能访问索引。 如果通过删除或更改角色分配来撤销对密钥的访问权限,则索引不可用,且在删除索引或还原对密钥的访问权限之前,服务将无法缩放。 如果删除或轮换密钥,则最新密钥最多缓存 60 分钟。
如果您在搜索服务中需要使用 CMK,请设置强制策略。
通过使用 Azure Policy 和服务级 CMK 配置(仍处于预览)来强制执行 CMK 是相互独立的设置。 可以根据需求使用任一或两者。 服务级别 CMK 配置将默认密钥应用于新对象,而Azure Policy强制实施可确保所有对象都符合加密要求。 如果在不使用服务级别密钥的情况下启用 CMK 强制策略,则所有启用 CMK 的对象必须在创建时指定自己的加密密钥。 忽略 CMK 配置的对象创建请求失败。
默认对新对象启用服务级别 CMK (预览版)
从 2026-03-01-preview 版本开始,可以在 Azure AI 搜索 服务本身的服务级别配置客户管理的密钥。 此功能允许你配置密钥一次,并默认将其应用到所有新建的对象。 该保护使搜索服务中的敏感数据与你控制的密钥保持安全,而无需每次创建对象时都指定密钥信息。 在数据平面 API 版本及更高版本中2026-05-01-preview,属性isServiceLevelKeyencryptionKey可帮助你确定对象是继承服务级别密钥还是使用显式对象级密钥。
在服务级启用 CMK 意味着:
可以通过为所创建的对象指定一个新键来替代此默认键。 指定的对象级密钥将替代该对象的默认服务级别密钥。
在服务级别和对象级 CMK 之间进行选择
默认情况下,使用服务级别 CMK 在所有对象中应用单个密钥。 配置密钥一次,新对象会自动继承该保护。
对需要独立密钥生命周期的工作负载使用对象级 CMK。 现有对象级 CMK 配置将继续正常运行,无需更改。 服务级别 CMK 简化了密钥管理,但不会替换对象级 CMK。
常见的企业模式是为大多数对象(索引、索引器、数据源、技能集、向量器和同义词映射)配置服务级别密钥。 符合性要求更严格的工作负荷可以配置对象级密钥,以独立管理访问、轮换和吊销。
步骤 1:创建加密密钥
使用Azure 密钥保管库或Azure 密钥保管库托管 HSM 创建密钥。 Azure AI 搜索加密支持大小为 2048、3072 和 4096 的 RSA 密钥。 有关支持的密钥类型的详细信息,请参阅 “关于密钥”。
建议在开始之前查看 这些提示 。
必需的操作是 Wrap、 Unwrap、 Encrypt 和 Decrypt。
可以使用 Azure 门户、Azure CLI或 Azure PowerShell 创建密钥保管库。
在 Azure 门户中转到密钥保管库。
选择左侧 的对象>键 ,然后选择“ 生成/导入”。
在“ 创建密钥 ”窗格中,从 “选项”列表中选择“ 生成 ”以创建新密钥。
输入密钥 的名称 ,并接受其他键属性的默认值。
(可选)设置密钥轮换策略以 启用自动轮换。
选择 “创建 ”以启动部署。
创建密钥后,获取其密钥标识符。 选择密钥,选择当前版本,然后复制密钥标识符。 它由键值 URI、密钥名称和密钥版本组成。 您需要标识符才能在 Azure AI 搜索 中定义加密索引。 回想一下,所需的操作是 Wrap、 Unwrap、 Encrypt 和 Decrypt。
步骤 2:创建安全主体
创建一个搜索服务用于访问加密密钥的安全主体。 可以使用托管标识和角色分配,也可以注册应用程序并让搜索服务针对请求提供应用程序 ID。
使用托管标识和角色。 可以使用系统托管标识或用户托管标识。 托管标识使搜索服务能够通过Microsoft Entra ID进行身份验证,而无需在代码中存储凭据(ApplicationID 或 ApplicationSecret)。 这种类型的托管标识的生命周期与搜索服务的生命周期相关联,该生命周期只能有一个系统分配的托管标识。 有关托管标识工作原理的详细信息,请参阅 什么是Azure资源的托管标识。
为搜索服务启用系统分配的托管标识。 这是一项两键式操作:启用和保存。
可以使用Azure门户或搜索管理 REST API 创建用户分配的托管标识并将标识分配给搜索服务。 有关详细信息,请参阅 创建用户分配的托管标识。
如果无法使用角色分配来搜索服务访问加密密钥,请按照以下说明操作。
在 Azure 门户中,找到您的订阅中的 Microsoft Entra 资源。
在左侧的 Manage 下,选择 应用注册,然后选择 New registration。
输入注册的名称,例如类似于搜索应用程序名称的名称。 选择 “注册”。
创建应用注册后,复制应用程序 ID。 向应用程序提供此字符串。
如果要逐步执行 DotNetHowToEncryptionUsingCMK,请将以下值粘贴到 appsettings.json 文件中。
接下来,选择 “证书和机密”。
选择 “新建客户端密码”。 输入机密的显示名称,然后选择“ 添加”。
复制应用程序机密。 如果要逐步执行此示例,请将以下值粘贴到 appsettings.json 文件中。
步骤 3:授予权限
如果将搜索服务配置为使用托管标识,请分配授予其对加密密钥访问权限的角色。
建议使用基于角色的访问控制而不是访问策略权限模型。 有关详细信息或迁移步骤,请从 Azure 基于角色的访问控制(Azure RBAC)与访问策略(旧版)。
在 Azure 门户中转到密钥保管库。
选择 访问控制(IAM), 然后选择 “添加角色分配”。
选择角色:
- 在Azure 密钥保管库上,选择密钥保管库加密服务加密用户。
- 在托管 HSM 上,选择 “托管 HSM 加密服务加密用户”。
选择托管标识,选择成员,然后选择搜索服务的托管标识。 如果要在本地进行测试,请同时将此角色分配给自己。
选择 “审阅 + 分配”。
请等待几分钟,让角色分配生效。
用于 CMK 的 密钥保管库 防火墙和虚拟网络访问
Azure AI 搜索必须能够访问Azure 密钥保管库中的加密密钥。
如果密钥保管库使用防火墙或虚拟网络限制,请配置以下选项之一:
启用受信任的服务旁路后,即使公共网络访问受到限制,Azure AI 搜索也可以使用托管标识以受信任的服务的形式访问密钥。
如果防火墙阻止访问,且未启用受信任的服务绕过,Azure AI 搜索 将无法检索到密钥,并且依赖 CMK 的操作将会失败。
创建加密对象时,输入密钥保管库 URI、密钥名称和密钥版本。 如果使用Microsoft Entra ID应用程序进行身份验证,则还要输入应用程序 ID 和机密。
若要将客户管理的密钥添加到搜索对象,可以是索引、索引器、数据源、技能集、向量器或同义词映射,可以在 服务级别 或 对象级别配置密钥。
服务级别:通过在服务级别设置客户管理的密钥,该密钥默认应用于所有新建的搜索对象。 它不适用于预先存在的搜索对象。
对象级别:还可以在创建新搜索对象时在对象级别定义一个新的唯一键。 此对象级密钥定义替代默认服务级别密钥。
注意
在服务级密钥定义与对象级密钥定义之间更新客户管理密钥配置时,在更新传播到整个服务之前,请保持先前配置中的资源可用。 删除标识、删除密钥保管库或撤消密钥太快可能会阻止某些服务组件解密仍依赖于以前的配置的数据。
若要在对象上配置 CMK,请使用 Azure 门户、Search Service REST API 或Azure SDK。
在 Azure 门户中创建新对象时,可以在密钥保管库中指定预定义的客户管理的密钥。 通过 Azure 门户,可以使用 CMK 为以下项启用加密:
若要使用 Azure 门户,密钥保管库和密钥必须存在,并且必须完成前面的步骤才能获得对密钥的授权访问。
在Azure门户中,技能集在 JSON 视图中定义。 使用 REST API 示例中所示的 JSON 为技能集配置客户管理密钥。
在 Azure 门户 中转到你的搜索服务。
在 “搜索管理”下,选择 “索引”、“ 索引器”或 “数据源”。
添加新对象。 在对象定义中,选择Microsoft托管加密。
选择 客户管理的密钥 ,然后选择订阅、保管库、密钥和版本。
调用创建 API 以指定 encryptionKey 属性:
将 encryptionKey 构造插入到对象定义中。 此属性是一个与名称和说明相同的级别的第一级属性。 如果使用相同的保管库、密钥和版本,则可以将相同的 encryptionKey 构造粘贴到每个对象定义中。
如果密钥标识符为 https://contoso-keyvault.vault.azure.net/keys/contoso-cmk/aaaaaaaa-0b0b-1c1c-2d2d-333333333333,则 URI 为 https://contoso-keyvault.vault.azure.net,密钥名称为 contoso-cmk,版本为 aaaaaaaa-0b0b-1c1c-2d2d-333333333333。
{
"encryptionKey": {
"keyVaultUri": "<YOUR-KEY-VAULT-URI>",
"keyVaultKeyName": "<YOUR-ENCRYPTION-KEY-NAME>",
"keyVaultKeyVersion": "<YOUR-ENCRYPTION-KEY-VERSION>",
"identity" : {
"@odata.type": "#Microsoft.Azure.Search.DataUserAssignedIdentity",
"userAssignedIdentity" : "/subscriptions/<your-subscription-ID>/resourceGroups/<your-resource-group-name>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<your-managed-identity-name>"
}
}
}
第一个示例显示了一个用于连接到搜索服务的加密密钥,该服务使用托管标识:
{
"encryptionKey": {
"keyVaultUri": "<YOUR-KEY-VAULT-URI>",
"keyVaultKeyName": "<YOUR-ENCRYPTION-KEY-NAME>",
"keyVaultKeyVersion": "<YOUR-ENCRYPTION-KEY-VERSION>"
}
}
第二个示例包括 accessCredentials,在Microsoft Entra ID中注册应用程序时是必需的:
{
"encryptionKey": {
"keyVaultUri": "<YOUR-KEY-VAULT-URI>",
"keyVaultKeyName": "<YOUR-ENCRYPTION-KEY-NAME>",
"keyVaultKeyVersion": "<YOUR-ENCRYPTION-KEY-VERSION>",
"accessCredentials": {
"applicationId": "<YOUR-APPLICATION-ID>",
"applicationSecret": "<YOUR-APPLICATION-SECRET>"
}
}
}
通过对对象发出 GET 来验证加密密钥是否存在。
通过执行任务(例如查询已加密的索引)来验证对象是否正常运行。
在搜索服务上创建加密对象后,可以像使用其类型的任何其他对象一样使用它。 加密对用户和开发人员是透明的。
这些密钥保管库详细信息都不被视为机密,可以通过浏览到Azure门户中的相关Azure 密钥保管库页轻松检索这些密钥保管库详细信息。
Azure SDK包支持对搜索对象进行CMK配置,包括< c0>Azure SDK for .NET< /c0>、< c1>Azure SDK for Java< /c1>、< c2>Azure SDK for JavaScript< /c2>和< c3>Azure SDK for Python< /c3>。
以下示例演示对象定义中 的 encryptionKey 表示形式。 相同的定义适用于索引、数据源、技能集、索引器和同义词映射。 若要在搜索服务和密钥保管库上试用此示例,请从 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=AZURE_SEARCH_SERVICE, credential=credential)
fields = [
SimpleField(name="Id", type=SearchFieldDataType.String, key=True),
SearchableField(name="Description", type=SearchFieldDataType.String),
]
encryption_key = SearchResourceEncryptionKey()
encryption_key.vault_uri = "<PUT YOUR KEY VAULT URI HERE>"
encryption_key.key_name = "<PUT YOUR KEY VAULT KEY NAME HERE>"
encryption_key.key_version = "<PUT YOUR ALPHANUMERIC KEY VERSION 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"
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 New York. A few minutes away is Time's Square and the historic centre of the city, as well as other places of interest that make New York 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)
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 New York. A few minutes away is Time's Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.
由于加密内容是在数据刷新或查询之前解密的,因此不会看到加密的可视证据。 若要验证加密是否正常工作,请检查资源日志。
重要
Azure AI 搜索中的加密内容配置为使用具有特定 version 的特定密钥。 如果更改密钥或版本,则必须更新该对象以在删除前一个对象 之前 使用它。 未能这样做会使对象不可用。 如果密钥丢失,则无法解密内容。
若要启用服务级别 CMK 配置,请使用搜索管理 REST API 或更新的 Azure SDK 包,以支持搜索管理 REST API 版本 2026-03-01-preview 或更高版本。 Azure门户尚不支持此功能。 在服务级别启用 CMK 时,不会向现有对象添加加密,但默认情况下将同一密钥应用于服务中的所有新创建的对象,除非指定不同的对象级密钥来替代服务级别默认值。
目前,Azure门户不支持服务级别加密。 直接使用 REST API。
若要在搜索服务上使用 CMK 配置加密,请使用服务 - 创建或更新并结合 PATCH 更新现有的搜索服务,或结合 PUT 创建新的搜索服务。 API 版本必须是 2026-03-01-preview 或更高版本才能支持服务级别配置。
在此示例中,请务必将{{subscription-id}}、{{resource-group}}、{{search-service}}和{{token}}分别替换为您的订阅 ID、资源组名称、搜索服务名称和访问令牌。 密钥定义使用与对象级 CMK 相同的架构,并且支持所有三个标识选项(系统分配的托管标识、用户分配的托管标识或已注册的应用程序)。
PATCH https://management.azure.com/subscriptions/{{subscription-id}}/resourceGroups/{{resource-group}}/providers/Microsoft.Search/searchServices/{{search-service}}?api-version=2026-03-01-preview
Authorization: Bearer {{token}}
Content-Type: application/json
请参阅以下示例,了解如何在不同的标识类型的服务级别插入 serviceLevelEncryptionKey 构造。
使用系统分配的托管标识的示例:
{
"encryptionWithCmk": {
"serviceLevelEncryptionKey": {
"keyVaultUri": "<YOUR-KEY-VAULT-URI>",
"keyVaultKeyName": "<YOUR-ENCRYPTION-KEY-NAME>",
"keyVaultKeyVersion": "<YOUR-ENCRYPTION-KEY-VERSION>"
}
}
}
使用用户托管身份的示例:
{
"encryptionWithCmk": {
"serviceLevelEncryptionKey": {
"keyVaultUri": "<YOUR-KEY-VAULT-URI>",
"keyVaultKeyName": "<YOUR-ENCRYPTION-KEY-NAME>",
"keyVaultKeyVersion": "<YOUR-ENCRYPTION-KEY-VERSION>",
"identity": {
"@odata.type": "#Microsoft.Azure.Search.DataUserAssignedIdentity",
"userAssignedIdentity": "/subscriptions/<your-subscription-ID>/resourceGroups/<your-resource-group-name>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<your-managed-identity-name>"
}
}
}
}
使用应用程序 ID 的示例:
{
"encryptionWithCmk": {
"serviceLevelEncryptionKey": {
"keyVaultUri": "<YOUR-KEY-VAULT-URI>",
"keyVaultKeyName": "<YOUR-ENCRYPTION-KEY-NAME>",
"keyVaultKeyVersion": "<YOUR-ENCRYPTION-KEY-VERSION>",
"accessCredentials": {
"applicationId": "<YOUR-APPLICATION-ID>",
"applicationSecret": "<YOUR-APPLICATION-SECRET>"
}
}
}
}
在面向 Search Management REST API 版本 2026-03-01-preview 或更高版本的 Azure SDK 包中支持服务级 CMK 配置。 若要确认支持,请检查包的更改日志:
检查搜索对象是否继承服务级别 CMK
若要检查搜索对象是使用在服务级别配置的客户管理的密钥作为默认密钥还是在对象级别配置的唯一客户管理的密钥,请使用 isServiceLevelKey 该属性检查继承的加密状态。
目前,Azure门户不支持服务级别加密。 直接使用 REST API。
在数据平面 API 版本 2026-05-01-preview 及更高版本中,使用对象 GET 调用来检查 encryptionKey.isServiceLevelKey。
下面的代码片段是一个示例。 您需要使用特定于您的使用场景的值来更新它。
GET https://{{search-service}}.search.windows.net/indexes/{{index-name}}?api-version=2026-08-01-preview
api-key: {{admin-api-key}}
{
"name": "hotels-cmk",
"fields": [
{
"name": "id",
"type": "Edm.String",
"key": true,
"searchable": false,
"retrievable": true
}
],
"encryptionKey": {
"keyVaultUri": "<YOUR-KEY-VAULT-URI>",
"keyVaultKeyName": "<YOUR-ENCRYPTION-KEY-NAME>",
"keyVaultKeyVersion": "<YOUR-ENCRYPTION-KEY-VERSION>",
"isServiceLevelKey": true
}
}
当 isServiceLevelKey 为 true 时,该对象将继承服务级密钥,并且没有显式的对象级覆盖设置。
若要将特定对象的生命周期解耦,请设置显式的对象级键,并在更新该对象的isServiceLevelKey请求中将false设置为PUT。
PUT https://{{search-service}}.search.windows.net/indexes/{{index-name}}?api-version=2026-08-01-preview
api-key: {{admin-api-key}}
Content-Type: application/json
{
"name": "regulated-index",
"fields": [
{
"name": "id",
"type": "Edm.String",
"key": true,
"searchable": false,
"retrievable": true
}
],
"encryptionKey": {
"keyVaultUri": "<YOUR-KEY-VAULT-URI>",
"keyVaultKeyName": "<YOUR-ENCRYPTION-KEY-NAME>",
"keyVaultKeyVersion": "<YOUR-ENCRYPTION-KEY-VERSION>",
"isServiceLevelKey": false
}
}
通过此替代,对象级密钥生命周期与服务级别默认值分离。 可以在不更改其他对象使用的服务级别密钥的情况下独立轮换对象级密钥。
启用服务级别 CMK 时,创建请求可以省略 encryptionKey ,对象默认继承服务级别密钥。 若要将现有对象从显式对象级密钥切换到服务级别 CMK 继承,请在更新请求中设置为isServiceLevelKeytrue。
在数据平面 API 版本及更高版本中 2026-05-01-preview ,请求验证适用于 encryptionKey 对象。 如果提供 encryptionKey, keyVaultUri 并且 keyVaultKeyName 是必需字符串字段,无论 isServiceLevelKey 是否存在还是具有什么值。 此验证检查字段是否存在,而不是键是否存在。 占位符字符串值满足此架构验证,缺少必填字段会导致 HTTP 400。
当 isServiceLevelKey 是 true时,该服务将配置的服务级别密钥应用于对象。 如果提供keyVaultUri或keyVaultKeyNamekeyVaultKeyVersion在同一请求中,服务将忽略该操作中键选择的这些值。
为了清楚和可维护性,请在请求中提供当前的服务级别密钥值,并通过对对象执行 GET 操作来验证有效密钥。
PUT https://{{search-service}}.search.windows.net/indexes/{{index-name}}?api-version=2026-08-01-preview
api-key: {{admin-api-key}}
Content-Type: application/json
{
"name": "regulated-index",
"fields": [
{
"name": "id",
"type": "Edm.String",
"key": true,
"searchable": false,
"retrievable": true
}
],
"encryptionKey": {
"isServiceLevelKey": true,
"keyVaultUri": "<SERVICE-LEVEL-KEY-VAULT-URI>",
"keyVaultKeyName": "<SERVICE-LEVEL-KEY-NAME>",
"keyVaultKeyVersion": "<SERVICE-LEVEL-KEY-VERSION>"
}
}
此更新后,搜索对象将继承服务级别密钥。 通过发出 GET 请求并确认 isServiceLevelKey 为 true,来验证生效的密钥。
若要设置对象级键,请提供encryptionKey对象级键值,并将其设置为isServiceLevelKeyfalse或省略isServiceLevelKey。
isServiceLevelKey如果是true,则请求不会将对象切换到对象级键。 省略 encryptionKey 更新请求会保留当前的加密密钥配置。
在面向 Search Management REST API 版本 2026-03-01-preview 或更高版本的 Azure SDK 包中支持服务级 CMK 配置。 若要确认支持,请检查包的更改日志:
步骤 5:测试加密
若要验证加密是否正常工作,请撤销加密密钥,查询索引(应不可用),然后恢复加密密钥。
为此任务使用Azure门户。 请确保分配了允许读取密钥的角色。
在Azure 密钥保管库页上,选择Objects>Keys。
选择创建的密钥,然后选择“ 删除”。
在“Azure AI 搜索”页上,选择Search management>Indexes。
选择索引并使用搜索资源管理器运行查询。 应会收到错误。
返回到 Azure 密钥保管库 Objects>Keys 页。
选择“ 管理已删除的密钥”。
选择密钥,然后选择“ 恢复”。
返回到Azure AI 搜索中的索引并重新运行查询。 您应该会看到搜索结果。 如果未看到即时结果,请等待一分钟,然后重试。
设置策略以强制实施 CMK 符合性
Azure策略有助于强制实施组织标准并大规模评估合规性。 Azure AI 搜索有两个与 CMK 相关的可选内置策略。 这些策略适用于新的和现有的搜索服务。
分配策略
在 Azure 门户中,导航到内置策略,然后选择 Assign。
下面是 Azure 门户中 AuditIfExists 策略的示例:
通过选择订阅和资源组来设置 策略范围 。 排除策略不应应用的任何搜索服务。
接受或修改默认值。 选择 “审阅 + 创建”,然后选择“ 创建”。
启用 CMK 策略的强制执行
将策略分配给订阅中的资源组时,它会立即生效。 审核策略会标记不符合资源,但拒绝策略会阻止创建和更新不合规的搜索服务。 本部分介绍如何创建合规的搜索服务或更新服务以使其合规。 若要使对象符合要求,请从本文的第一步开始。
创建合规的搜索服务
对于新的搜索服务,请使用 SearchEncryptionWithCmk 设置为 Enabled 创建它们。
Azure门户和命令行工具(Azure CLI和Azure PowerShell)均未原生提供此属性,但可以使用 Management 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.azure.com/subscriptions/{{subscriptionId}}/resourceGroups/{{resource-group}}/providers/Microsoft.Search/searchServices/{{search-service-name}}?api-version=2025-05-01 HTTP/1.1
Content-type: application/json
Authorization: Bearer {{token}}
{
"location": "North Central US",
"sku": {
"name": "basic"
},
"properties": {
"replicaCount": 1,
"partitionCount": 1,
"hostingMode": "default",
"encryptionWithCmk": {
"enforcement": "Enabled"
}
}
}
更新现有搜索服务
对于现在不合规的现有搜索服务,请使用 Services - Update API 或 Azure CLI az 资源更新命令对其进行修补。 修补服务可恢复更新搜索服务属性的功能。
PATCH https://management.azure.com/subscriptions/<your-subscription-Id>/resourceGroups/<your-resource-group-name>/providers/Microsoft.Search/searchServices/<your-search-service-name>?api-version=2025-05-01
{
"properties": {
"encryptionWithCmk": {
"enforcement": "Enabled"
}
}
}
运行以下命令,替换搜索服务和资源组的有效值。
az resource update --name SEARCH-SERVICE-PLACEHOLDER --resource-group RESOURCE-GROUP-PLACEHOLDER --resource-type searchServices --namespace Microsoft.Search --set properties.encryptionWithCmk.enforcement=Enabled
响应应包含以下语句:
"encryptionWithCmk": {
"encryptionComplianceStatus": "NonCompliant",
"enforcement": "Enabled"
}
...
“不符合”意味着搜索服务具有未加密 CMK 的现有对象。 若要实现合规性,请重新创建每个对象,并指定加密密钥。
轮换或更新加密密钥
使用以下说明轮换密钥或从Azure 密钥保管库迁移到硬件安全模块(HSM)。
对于密钥轮换,请使用 Azure 密钥保管库 的自动轮换功能。 如果使用自动旋转,请省略对象定义中的密钥版本。 使用最新的密钥,而不是特定版本。
更改密钥或其版本时,在删除旧值 之前 ,更新使用该密钥使用新值的任何对象。 否则,对象变得不可用,因为它无法解密。
如果在服务级别配置了 CMK,则轮换服务级别密钥适用于今后新建的对象。 已继承上一个服务级别密钥的对象会自动选取新密钥,因此无需更新它们。 但是,如果有任何对象配置了想要轮换的对象级别键,则需要更新这些对象以使用新密钥。
密钥缓存 60 分钟。 在测试和轮换密钥时,请记住这一点。
确定索引或同义词映射所使用的键。
在密钥保管库中创建新密钥,但保留原始密钥可用。 在此步骤中,可以将密钥保管库切换到 HSM。
更新索引或同义词映射上的 encryptionKey 属性以使用新值。 只有最初使用此属性创建的对象才能更新为使用不同的值。
禁用或删除密钥保管库中的上一个密钥。 监视密钥访问以验证正在使用的新密钥。
出于性能原因,搜索服务将密钥缓存长达数小时。 如果在未提供新密钥的情况下禁用或删除密钥,查询将继续临时工作,直到缓存过期。 但是,一旦搜索服务无法再解密内容,你就会收到以下消息: "Access forbidden. The query key used might have been revoked - please retry."
密钥保管库提示
如果你不熟悉Azure 密钥保管库,请查看本快速入门,了解基本任务:使用 PowerShell 从 Azure 密钥保管库 中检索机密。
根据需要使用任意数量的密钥保管库。 托管密钥可以位于不同的密钥保管库中。 搜索服务可以有多个加密对象,每个对象都使用不同的客户管理的加密密钥进行加密,存储在不同的密钥保管库中。
使用相同的 Azure 租户,以便可以通过角色分配以及通过系统或用户托管标识进行连接来检索托管密钥。 有关创建租户的详细信息,请参阅 “设置新租户”。
如果你的 Azure 密钥保管库 受防火墙保护,请确保启用 允许受信任的 Microsoft 服务绕过此防火墙,以便 Azure AI 搜索 能够访问该密钥。
在密钥保管库上启用清除保护和软删除。 由于使用客户管理的密钥进行加密的性质,如果删除了Azure 密钥保管库密钥,则任何人都无法检索数据。 若要防止意外密钥保管库密钥删除导致的数据丢失,必须在key vault上启用软删除和清除保护。 默认启用软删除,因此,仅当你故意禁用它时,才会遇到问题。 默认情况下不会启用清除保护,但需要使用 Azure AI 搜索 中的 CMK 进行加密。
在密钥保管库上启用日志记录,以便监视密钥使用情况。
启用密钥自动轮换,或在密钥保管库密钥和应用程序机密和注册的例行轮换过程中,遵循严格的过程。 在删除旧机密之前,请始终更新所有 加密内容 以使用新的机密和密钥。 如果错过此步骤,则无法解密内容。
处理加密内容
使用 CMK 时,由于额外的加密/解密工作,你可能会注意到索引编制和查询的延迟。 Azure AI 搜索不会记录加密活动,但可以通过密钥保管库日志记录监视密钥访问。
建议在 Key Vault 配置过程中 启用日志记录 。
创建 Log Analytics 工作区。
在密钥保管库中添加诊断设置 ,该设置使用工作区进行数据保留。
选择类别的 审核 或 allLogs ,为诊断设置指定一个名称,然后保存它。
FAQs
是否可以在服务级别定义的客户管理的密钥和在对象级别定义的客户管理的密钥之间更改搜索对象?
- Yes. 配置服务级别 CMK 时,每个新的搜索对象默认使用该密钥。 如果在对象级别定义中配置其他键,则对象级密钥优先于服务级别密钥。 如果删除对象级密钥定义,搜索对象默认返回到在服务级别定义的客户管理的密钥。
后续步骤
如果不熟悉Azure安全体系结构,请查看 Azure 安全文档,特别是本文: