使用 Azure 基于角色的访问控制 (Azure RBAC) 连接到 Azure 认知搜索
本文内容
Azure 为平台上运行的所有服务提供一种全局基于角色的访问控制授权系统 。 在认知搜索中,可以将 Azure 角色用于:
不支持按用户访问搜索结果(有时称为行级安全性或文档级安全性)。 一种解决方法是创建安全筛选器 ,以根据用户标识来精选结果,并删除请求者不应访问的文档。
搜索中使用的内置角色
以下角色是内置角色。 如果这些角色不足以满足要求,请创建自定义角色 。
角色
平面
说明
所有者
控制平面和数据平面
对搜索资源的控制平面拥有完全访问权限,包括能够分配 Azure 角色。 只有所有者角色可以启用或禁用身份验证选项或管理其他用户的角色。 默认情况下,订阅管理员是成员。 在数据平面上,此角色具有与搜索服务参与者角色相同的访问权限。 它包括对除了查询文档或编制文档索引之外的所有数据平面操作的访问权限。
参与者
控制平面和数据平面
与所有者相同的控制平面访问权限级别,但无法分配角色或更改身份验证选项。 在数据平面上,此角色具有与搜索服务参与者角色相同的访问权限。 它包括对除了查询文档或编制文档索引之外的所有数据平面操作的访问权限。
读者
控制平面和数据平面
跨整个服务的读取访问权限,包括搜索指标、内容指标(消耗的存储、对象数量)和数据平面资源的对象定义(索引、索引器等)。 但是,它无法读取 API 密钥或读取索引中的内容。
搜索服务参与者
控制平面和数据平面
对对象定义(索引、同义词映射、索引器、数据源和技能组)的读写访问权限。 有关权限列表,请参阅 Microsoft.Search/searchServices/*
。 此角色无法访问索引中的内容,因此不会进行查询或索引编制,但它可以创建、删除和列出索引,返回索引定义和统计信息,以及测试分析器。 此角色适用于需要管理搜索服务及其对象但没有内容访问权限的搜索服务管理员。
搜索索引数据参与者
数据
对搜索服务上所有索引中的内容的读写访问权限。 此角色适用于需要导入、刷新或查询索引文档集合的开发人员或索引所有者。
搜索索引数据读取者
数据
对搜索服务上所有搜索索引的只读访问权限。 此角色适用于运行查询的应用和用户。
注意
如果禁用 Azure 基于角色的访问权限,则控制平面的内置角色(所有者、参与者、读取者)将继续可用。 禁用 Azure RBAC 只会删除与这些角色关联的数据相关权限。 在已禁用 RBAC 的场景下,搜索服务参与者等效于控制平面参与者。
限制
采用基于角色的访问控制可能会增大某些请求的延迟。 请求中使用的服务资源(索引、索引器等)和服务主体的每个唯一组合都会触发授权检查。 这些授权检查可能会给请求最多增加 200 毫秒的延迟。
在罕见的情况下,请求源自大量不同的服务主体,而这些服务主体针对不同的服务资源(索引、索引器等),对于这种情况,授权检查可能会导致发生限制。 仅当在一秒钟内使用了搜索服务资源和服务主体的数百个独特组合时,才会发生限制。
适用于:搜索索引数据参与者、搜索索引数据读取者、搜索服务参与者
在此步骤中配置搜索服务,以识别提供 OAuth2 访问令牌的数据请求上的授权头。
登录到 Azure 门户 ,然后打开搜索服务页面。
在左侧导航窗格中,选择“密钥”。
选择一个 API 访问控制选项。 如果你希望拥有灵活性或需要迁移应用,建议使用“两者”。
选项
说明
API 密钥
(默认值)。 需要请求标头中的管理员或查询 API 密钥 才能授权。 不使用任何角色。
基于角色的访问控制
需要角色分配中的成员身份才能完成任务,如下一步所述。 它还需要授权标头。
两者
使用基于 API 密钥或基于角色的访问控制时,请求都是有效的。
更改会立即生效,但请等待几秒钟,然后再进行测试。
对搜索服务操作和内容的所有网络调用都将遵循你选择的选项:API 密钥、持有者令牌或两者(如果你选择“两者”)。
在门户中启用基于角色的访问控制时,如果授权失败,失败模式将为“http401WithBearerChallenge”。
使用管理 REST API 版本 2022-09-01 创建或更新服务 来配置服务。
对管理 REST API 的所有调用都通过 Azure Active Directory 进行身份验证,具有参与者或所有者权限。 如果在 Postman 中设置经过身份验证的请求时需要帮助,请参阅使用 REST 管理 Azure 认知搜索 。
获取服务设置,以便可以查看当前配置。
GET https://management.chinacloudapi.cn/subscriptions/{{subscriptionId}}/providers/Microsoft.Search/searchServices?api-version=2022-09-01
使用 PATCH 更新服务配置。 以下修改启用基于密钥的访问和基于角色的访问。 如果你需要仅限角色的配置,请参阅禁用 API 密钥 。
在“属性”下,将“authOptions” 设置为“aadOrApiKey”。 “disableLocalAuth”属性必须为 false 才能设置“authOptions”。
(可选)设置“aadAuthFailureMode” ,以指定是否在身份验证失败时返回 401 而非 403。 有效值为“http401WithBearerChallenge”或“http403”。
PATCH https://management.chinacloudapi.cn/subscriptions/{{subscriptionId}}/resourcegroups/{{resource-group}}/providers/Microsoft.Search/searchServices/{{search-service-name}}?api-version=2022-09-01
{
"properties": {
"disableLocalAuth": false,
"authOptions": {
"aadOrApiKey": {
"aadAuthFailureMode": "http401WithBearerChallenge"
}
}
}
}
按照下一步中的说明为数据平面操作分配角色。
分配角色
角色分配会在所有工具和客户端库中很普遍的操作,并且会不断累计。 你可以使用 Azure 基于角色的访问控制文档中所述的任何受支持方法 分配角色。
必须是所有者或拥有 Microsoft.Authorization/roleAssignments/write 权限才能管理角色分配。
门户中的角色分配是在服务范围内进行的。 如果要向单个索引授予权限 ,请改为使用 PowerShell 或 Azure CLI。
登录 Azure 门户 。
导航到你的搜索服务。
在左侧导航窗格中,选择“访问控制(IAM)”。
选择“+ 添加” > “添加角色分配”。
选择适用的角色:
所有者
参与者
读取器
搜索服务参与者
搜索索引数据参与者
搜索索引数据读取者
在“成员”选项卡上,选择 Azure AD 用户或组标识。
在“查看 + 分配”选项卡上,选择“查看 + 分配”,以分配角色 。
使用 PowerShell 分配角色 时,请调用 New-AzRoleAssignment (提供 Azure 用户或组名称以及分配的范围)。
在开始之前,请确保加载 Az 和 AzureAD 模块并连接到 Azure:
Import-Module -Name Az
Import-Module -Name AzureAD
Connect-AzAccount -Environment AzureChinaCloud
此示例创建一个范围限定为搜索服务的角色分配:
New-AzRoleAssignment -SignInName <email> `
-RoleDefinitionName "Search Index Data Contributor" `
-Scope "/subscriptions/<subscription>/resourceGroups/<resource-group>/providers/Microsoft.Search/searchServices/<search-service>"
此示例创建一个范围限定为特定索引的角色分配:
New-AzRoleAssignment -SignInName <email> `
-RoleDefinitionName "Search Index Data Contributor" `
-Scope "/subscriptions/<subscription>/resourceGroups/<resource-group>/providers/Microsoft.Search/searchServices/<search-service>/indexes/<index-name>"
回想一下,只能将访问权限范围限定为顶级资源(如索引、同义词映射、索引器、数据源和技能组)。 无法使用 Azure 角色控制对搜索文档(索引内容)的访问。
测试角色分配
使用客户端测试角色分配。 请记住,角色是累积性的,并且在资源(搜索服务)级别无法删除或拒绝范围限定为订阅或资源组的继承角色。
在测试访问权限之前,请确保将客户端应用程序注册到 Azure Active Directory 并且角色分配已到位。
登录 Azure 门户 。
导航到你的搜索服务。
在“概述”页上,选择“索引”选项卡:
参与者可以查看和创建任何对象,但无法使用搜索资源管理器查询索引。
搜索索引数据读取者可以使用搜索资源管理器查询索引。 可以使用任何 API 版本来检查访问权限。 你应该可以发送查询并查看结果,但无法查看索引定义。
搜索索引数据参与者可以选择“新建索引”创建新索引。 保存新索引时会验证对服务的写入访问权限。
此方法假设将 Postman 用作 REST 客户端,并使用 Postman 集合和变量来提供持有者令牌。 使用 Azure CLI 或其他工具可为 REST 客户端创建安全主体。
打开 Azure CLI 的命令 shell 并登录到你的 Azure 订阅。
az login
获取你的订阅 ID。 该 ID 会在稍后的步骤中用作变量。
az account show --query id -o tsv
为安全主体创建资源组。 此示例使用“中国北部”区域。 在稍后的步骤中你要将此值作为变量提供。 你创建的角色的范围将限定为该资源组。
az group create -l chinanorth -n MyResourceGroup
创建服务主体,将占位符值替换为安全主体名称、订阅 ID 和资源组名称的有效值。 此示例使用“搜索索引数据读取者”(括在引号中)角色。
az ad sp create-for-rbac --name mySecurityPrincipalName --role "Search Index Data Reader" --scopes /subscriptions/mySubscriptionID/resourceGroups/myResourceGroupName
成功的响应包括“appId”、“password”和“tenant”。 你需为变量“clientId”、“clientSecret”和“tenant”使用这些值。
启动新的 Postman 集合并编辑其属性。 在“变量”选项卡中,创建以下变量:
变量
说明
clientId
提供在 Azure AD 中创建的先前生成的“appID”。
clientSecret
提供为客户创建的“密码”。
tenantId
提供在上一步中返回的“租户”。
subscriptionId
提供订阅的订阅 ID。
resource
输入 https://search.azure.com
。
bearerToken
(留空;令牌以编程方式生成)
在“授权”选项卡中,选择“持有者令牌”作为类型。
在“令牌”字段中,指定变量占位符 {{bearerToken}}
。
在“预请求脚本”选项卡中,粘贴以下脚本:
pm.test("Check for collectionVariables", function () {
let vars = ['clientId', 'clientSecret', 'tenantId', 'subscriptionId'];
vars.forEach(function (item, index, array) {
console.log(item, index);
pm.expect(pm.collectionVariables.get(item), item + " variable not set").to.not.be.undefined;
pm.expect(pm.collectionVariables.get(item), item + " variable not set").to.not.be.empty;
});
if (!pm.collectionVariables.get("bearerToken") || Date.now() > new Date(pm.collectionVariables.get("bearerTokenExpiresOn") * 1000)) {
pm.sendRequest({
url: 'https://login.chinacloudapi.cn/' + pm.collectionVariables.get("tenantId") + '/oauth2/token',
method: 'POST',
header: 'Content-Type: application/x-www-form-urlencoded',
body: {
mode: 'urlencoded',
urlencoded: [
{ key: "grant_type", value: "client_credentials", disabled: false },
{ key: "client_id", value: pm.collectionVariables.get("clientId"), disabled: false },
{ key: "client_secret", value: pm.collectionVariables.get("clientSecret"), disabled: false },
{ key: "resource", value: pm.collectionVariables.get("resource") || "https://search.azure.com", disabled: false }
]
}
}, function (err, res) {
if (err) {
console.log(err);
} else {
let resJson = res.json();
pm.collectionVariables.set("bearerTokenExpiresOn", resJson.expires_on);
pm.collectionVariables.set("bearerToken", resJson.access_token);
}
});
}
});
保存集合。
发送使用指定的变量的请求。 对于“搜索索引数据读取者”角色,可以查询索引(记得在 URI 中提供一个有效的搜索服务名称)。 可以使用任何受支持的 API 版本 。
POST https://<service-name>.search.azure.cn/indexes/hotels-quickstart/docs/search?api-version=2020-06-30
{
"queryType": "simple",
"search": "motel",
"filter": "",
"select": "HotelName,Description,Category,Tags",
"count": true
}
有关如何获取特定环境的令牌的详细信息,请参阅 Microsoft 标识平台身份验证库 。
使用 Azure.Search.Documents 11.4.0 包。
使用 Azure.Identity for .NET 进行令牌身份验证。 对于大多数情况,Azure 建议使用 DefaultAzureCredential()
。
获取 OAuth 令牌时,范围为 "https://search.azure.com/.default"。 SDK 要求受众为 "https://search.azure.com"。 “.default”是一种 Azure AD 约定。
SDK 将验证用户是否具有“user_impersonation”范围,该范围必须由应用授予,但 SDK 本身只要求提供 "https://search.azure.com/.default"。
下面是使用 DefaultAzureCredential()
的客户端连接的示例。
// Create a SearchIndexClient to send create/delete index commands
SearchIndexClient adminClient = new SearchIndexClient(serviceEndpoint, new DefaultAzureCredential());
// Create a SearchClient to load and query documents
SearchClient srchclient = new SearchClient(serviceEndpoint, indexName, new DefaultAzureCredential());
下面是另一个使用客户端机密凭据 的示例:
var tokenCredential = new ClientSecretCredential(aadTenantId, aadClientId, aadSecret);
SearchClient srchclient = new SearchClient(serviceEndpoint, indexName, tokenCredential);
作为当前用户进行测试
如果你已经是搜索服务的参与者或所有者,则可为用户标识提供持有者令牌,以便向 Azure 认知搜索进行身份验证。 以下说明介绍了如何设置 Postman 集合,以便以当前用户身份发送请求。
获取当前用户的持有者令牌:
az account get-access-token https://search.azure.com/.default
启动新的 Postman 集合并编辑其属性。 在“变量”选项卡中,创建以下变量:
变量
说明
bearerToken
(从命令行上的 get-access-token 输出进行复制粘贴)
在“授权”选项卡中,选择“持有者令牌”作为类型。
在“令牌”字段中,指定变量占位符 {{bearerToken}}
。
保存集合。
发送请求以确认访问权限。 下面的这个用于查询 hotels-quickstart 索引:
POST https://<service-name>.search.azure.cn/indexes/hotels-quickstart/docs/search?api-version=2020-06-30
{
"queryType": "simple",
"search": "motel",
"filter": "",
"select": "HotelName,Description,Category,Tags",
"count": true
}
授予对单个索引的访问权限
在某些情况下,你可能希望限制应用程序对单个资源(如索引)的访问权限。
门户目前不支持此粒度级别的角色分配,但可以使用 PowerShell 或 Azure CLI 实现此操作。
在 PowerShell 中,使用 New-AzRoleAssignment ,并提供 Azure 用户或组名称以及分配范围。
加载 Azure 和 AzureAD 模块并连接到 Azure 帐户:
Import-Module -Name Az
Import-Module -Name AzureAD
Connect-AzAccount -Environment AzureChinaCloud
添加范围限定为单个索引的角色分配:
New-AzRoleAssignment -ObjectId <objectId> `
-RoleDefinitionName "Search Index Data Contributor" `
-Scope "/subscriptions/<subscription>/resourceGroups/<resource-group>/providers/Microsoft.Search/searchServices/<search-service>/indexes/<index-name>"
创建自定义角色
如果内置角色 未提供适当的权限组合,你可以创建一个自定义角色 来支持所需的操作
此示例克隆“搜索索引数据读取者”,然后添加按名称列出索引的功能。 通常,在搜索服务中列出索引被视为一种管理权限。
这些步骤源自使用 Azure 门户创建或更新 Azure 自定义角色 。 支持在搜索服务页从现有角色克隆。
这些步骤将创建一个自定义角色来补充搜索查询权限,以包括按名称列出索引的权限。 通常,列出索引被视为一项管理功能。
在 Azure 门户中,导航到你的搜索服务。
在左侧导航窗格中,选择“访问控制(IAM)”。
在操作栏中,选择“角色”。
右键单击“搜索索引数据读取者”(或其他角色),然后选择“克隆”打开“创建自定义角色”向导。
在“基本信息”选项卡上,为自定义角色提供名称(例如“搜索索引数据浏览者”),然后选择“下一步”。
在“权限”选项卡上,选择“添加权限”。
在“添加权限”选项卡上,搜索并选择“Microsoft 搜索”磁贴。
为自定义角色设置权限。 在页面顶部,使用默认的“操作”选项:
在“Microsoft.Search/operations”下,选择“读取: 列出所有可用操作”。
在“Microsoft.Search/searchServices/indexes”下,选择“读取: 读取索引”。
在同一页上,切换到“数据操作”,然后在“Microsoft.Search/searchServices/indexes/documents”下选择“读取: 读取文档”。
JSON 定义如以下示例所示:
{
"properties": {
"roleName": "search index data explorer",
"description": "",
"assignableScopes": [
"/subscriptions/a5b1ca8b-bab3-4c26-aebe-4cf7ec4791a0/resourceGroups/heidist-free-search-svc/providers/Microsoft.Search/searchServices/demo-search-svc"
],
"permissions": [
{
"actions": [
"Microsoft.Search/operations/read",
"Microsoft.Search/searchServices/indexes/read"
],
"notActions": [],
"dataActions": [
"Microsoft.Search/searchServices/indexes/documents/read"
],
"notDataActions": []
}
]
}
}
选择“查看 + 创建”以创建角色。 现在可将用户和组分配到该角色。
该 PowerShell 示例显示了用于创建自定义角色的 JSON 语法,该角色是“搜索索引数据读取者”的克隆,但可以按名称列出所有索引。
查看原子权限列表 以确定所需的权限。 对于此示例,需要执行以下操作:
"Microsoft.Search/operations/read",
"Microsoft.Search/searchServices/read",
"Microsoft.Search/searchServices/indexes/read"
设置 PowerShell 会话以创建自定义角色。 有关详细说明,请参阅 Azure PowerShell
以 JSON 文档的形式提供角色定义。 以下示例演示了使用 PowerShell 创建自定义角色的语法。
{
"Name": "Search Index Data Explorer",
"Id": "88888888-8888-8888-8888-888888888888",
"IsCustom": true,
"Description": "List all indexes on the service and query them.",
"Actions": [
"Microsoft.Search/operations/read",
"Microsoft.Search/searchServices/read"
],
"NotActions": [],
"DataActions": [
"Microsoft.Search/searchServices/indexes/read"
],
"NotDataActions": [],
"AssignableScopes": [
"/subscriptions/{subscriptionId1}"
]
}
注意
如果可分配的范围处于索引级别,则数据操作应是 "Microsoft.Search/searchServices/indexes/documents/read"
。
禁用 API 密钥身份验证
无法删除 API 密钥,但如果使用“搜索服务参与者”、“搜索索引数据参与者”和“搜索索引数据读取者”角色以及 Azure AD 身份验证,则可以对服务禁用这些密钥。 禁用 API 密钥会导致搜索服务拒绝在标头中传递 API 密钥的所有与数据相关的请求。
需要拥有所有者或参与者权限才能禁用功能。
若要禁用基于密钥的身份验证 ,请使用 Azure 门户或管理 REST API。
在 Azure 门户中,导航到你的搜索服务。
在左侧导航窗格中,选择“密钥”。
选择“基于角色的访问控制”。
更改会立即生效,但请等待几秒钟,然后再进行测试。 假设你有权将角色分配为所有者、服务管理员或共同管理员的成员,则可以使用门户功能来测试基于角色的访问。
若要禁用基于密钥的身份验证,请将“disableLocalAuth”设置为 true。
获取服务设置,以便可以查看当前配置。
GET https://management.chinacloudapi.cn/subscriptions/{{subscriptionId}}/providers/Microsoft.Search/searchServices?api-version=2022-09-01
使用 PATCH 更新服务配置。 以下修改会将“authOptions”设置为 null。
PATCH https://management.chinacloudapi.cn/subscriptions/{{subscriptionId}}/resourcegroups/{{resource-group}}/providers/Microsoft.Search/searchServices/{{search-service-name}}?api-version=2022-09-01
{
"properties": {
"disableLocalAuth": true
}
}
仅包含 API 密钥但不包含持有者令牌的请求会失败,并显示 HTTP 401。
若要重新启用密钥身份验证,请重新运行最后一个请求,并将“disableLocalAuth”设置为 false。 搜索服务将自动继续接受请求上的 API 密钥(假设已指定)。
条件性访问
条件访问 是 Azure Active Directory 中用于强制实施组织策略的工具。 使用条件访问策略,可以在必要时应用适当的访问控制来确保组织的安全。 使用基于角色的访问控制访问 Azure 认知搜索服务时,条件访问可以强制实施组织策略。
若要为 Azure 认知搜索启用条件访问策略,请执行以下步骤:
登录 Azure 门户。
搜索“Azure AD 条件访问”。
选择“策略”。
选择“+ 新建策略”。
在策略的“云应用或操作”部分,根据你设置策略的方式,添加“Azure 认知搜索”作为云应用 。
更新策略的其余参数。 例如,指定要将此策略应用于哪些用户和组。
保存策略。
重要
如果为搜索服务分配了托管标识,则特定的搜索服务将显示为可在条件访问策略中包含或排除的云应用。 无法对特定的搜索服务强制实施条件访问策略。 应确保选择常规的“Azure 认知搜索”云应用。