使用标识将应用连接到Azure AI 搜索

在您的应用程序代码中,可以设置无密钥的连接到 Azure AI 搜索,该连接使用 Microsoft Entra ID 和角色进行身份验证和授权。 对大多数Azure服务的应用程序请求必须使用密钥或无密钥连接进行身份验证。 开发人员必须尽量避免在不安全的位置公开密钥。 能够访问密钥的任何人都可以对服务进行身份验证。 无密钥身份验证提供了比帐户密钥更好的管理和安全优势,因为不需要存储任何密钥或连接字符串。

本文介绍如何在应用程序代码中使用 DefaultAzureCredential

若要在代码中实现无键连接,请执行以下步骤:

  • 在搜索服务上启用基于角色的访问
  • 根据需要设置环境变量。
  • 使用Azure标识库凭据类型创建Azure AI 搜索客户端对象。

先决条件

  • Azure AI 搜索,任何地区,但必须是计费层(基本层或更高层)。

  • 在搜索服务上启用基于角色的访问

  • Azure AI 搜索上的角色分配。 将这些角色分配给身份:

    • 用于本地开发的搜索服务参与者搜索索引数据参与者(完全访问权限)
    • 用于生产只读查询的搜索索引数据读取器

    有关分步说明,请参阅 “分配角色进行开发”。

安装Azure标识客户端库

若要使用无键方法,请使用Azure标识客户端库更新已启用 AI 搜索的代码。

安装 Azure Identity 客户端库 for .NETAzure Search Documents 客户端库

dotnet add package Azure.Identity
dotnet add package Azure.Search.Documents

更新源代码以使用 DefaultAzureCredential

Azure标识库的 DefaultAzureCredential 允许在本地开发环境和 Azure 云中运行相同的代码。 创建一个单一凭据,并在需要时重复使用该凭据实例,以利用令牌缓存。

有关 DefaultAzureCredential 的详细信息,请参阅 Azure Identity 客户端库 for .NET

using Azure;
using Azure.Search.Documents;
using Azure.Search.Documents.Indexes;
using Azure.Search.Documents.Indexes.Models;
using Azure.Search.Documents.Models;
using Azure.Identity;
using System;
using static System.Environment;

string endpoint = GetEnvironmentVariable("AZURE_SEARCH_ENDPOINT");
string indexName = "my-search-index";

DefaultAzureCredential credential = new();
SearchClient searchClient = new(new Uri(endpoint), indexName, credential);
SearchIndexClient searchIndexClient = new(endpoint, credential);

Reference:SearchClient、SearchIndexClientDefaultAzureCredential

验证连接

设置客户端后,通过运行一个简单的操作来验证连接。 以下示例列出搜索服务上的索引:

// List indexes to verify connection
var indexes = searchIndexClient.GetIndexNames();
foreach (var name in indexes)
{
    Console.WriteLine(name);
}

成功的连接将输出索引的名称(如果没有索引,则为空列表)。 如果收到身份验证错误,请验证是否已启用基于角色的访问,并且您的身份具有所需的角色分配。

默认权限是 Azure 公有云。 主权云或专用云的自定义 audience 值包括:

  • Azure 由世纪互联运营 https://search.azure.cn

本地开发

使用角色的本地开发过程包括以下步骤:

  • 为特定资源的 RBAC 角色分配个人标识。
  • 使用Azure CLI或Azure PowerShell等工具通过Azure进行身份验证。
  • 为资源建立环境变量。

用于本地开发的角色

作为本地开发人员,您的Azure身份需要能够完全控制数据平面操作。 以下是建议的角色:

  • 搜索服务参与者,创建和管理对象
  • 搜索索引数据参与者,加载和查询索引

使用以下工具之一查找个人标识。 使用该标识作为 <identity-id> 值。

在以下命令中,将<role-name><identity-id><subscription-id><resource-group-name>这些占位符替换为您的实际值。

  1. 登录到Azure CLI。

    az login
    

    此时会打开浏览器窗口进行身份验证。 成功登录后,终端会显示订阅信息。

  2. 获取个人标识。

    az ad signed-in-user show \
        --query id -o tsv
    

    该命令返回用户对象 ID(GUID)。 请保存其值供下一步骤使用。

  3. 将基于角色的访问控制 (RBAC) 角色分配给资源组的标识对象。

    az role assignment create \
        --role "<role-name>" \
        --assignee "<identity-id>" \
        --scope "/subscriptions/<subscription-id>/resourceGroups/<resource-group-name>"
    

    成功的分配返回具有角色分配详细信息的 JSON 对象。

用于本地开发的身份验证

使用工具在本地开发环境中对 Azure 身份进行身份验证。 进行身份验证后,您的源代码中的DefaultAzureCredential 实例会查找并使用您的身份进行身份验证。

选择一个工具,在本地开发过程中用于身份验证

为本地开发配置环境变量

若要连接到Azure AI 搜索,代码需要知道资源终结点。

为Azure AI 搜索终结点创建名为 AZURE_SEARCH_ENDPOINT 的环境变量。 此 URL 通常采用 https://<YOUR-RESOURCE-NAME>.search.azure.cn/ 格式。

生产工作负载

部署生产工作负载包括以下步骤:

  • 选择遵循最低特权原则的 RBAC 角色。
  • 将对特定资源的 RBAC 角色分配给生产标识。
  • 为资源设置环境变量。

用于生产工作负载的角色

若要创建生产资源,需要创建用户分配的托管标识,然后使用正确的角色将该标识分配给资源。

建议对生产应用程序使用以下角色:

角色名称 Id
搜索索引数据读取者 1407120a-92aa-4202-b7e9-c0e197c71c8f

生产工作负载的身份验证

使用以下 Azure AI 搜索 Bicep 模板创建资源,并为 identityId 设置身份验证。 Bicep 需要角色 ID。 此 Bicep 代码片段中显示的 name 不是 Azure 角色,而是特定于 Bicep 部署。

// main.bicep
param environment string = 'production'
param roleGuid string = ''

module aiSearchRoleUser 'core/security/role.bicep' = {
    scope: aiSearchResourceGroup
    name: 'aiSearch-role-user'
    params: {
        principalId: (environment == 'development') ? principalId : userAssignedManagedIdentity.properties.principalId 
        principalType: (environment == 'development') ? 'User' : 'ServicePrincipal'
        roleDefinitionId: roleGuid
    }
}

main.bicep 文件调用以下通用的 Bicep 代码来创建所需的角色。 可以选择创建多个 RBAC 角色,例如为用户创建一个角色,再为生产创建另一个角色。 这样,就可以在同一Bicep部署中同时启用开发和生产环境。

// core/security/role.bicep
metadata description = 'Creates a role assignment for an identity.'
param principalId string // passed in from main.bicep

@allowed([
    'Device'
    'ForeignGroup'
    'Group'
    'ServicePrincipal'
    'User'
])
param principalType string = 'ServicePrincipal'
param roleDefinitionId string // Role ID

resource role 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
    name: guid(subscription().id, resourceGroup().id, principalId, roleDefinitionId)
    properties: {
        principalId: principalId
        principalType: principalType
        roleDefinitionId: resourceId('Microsoft.Authorization/roleDefinitions', roleDefinitionId)
    }
}

为生产工作负载配置环境变量

若要连接到Azure AI 搜索,代码需要知道资源终结点以及托管标识的 ID。

为您已部署的 Azure AI 搜索资源和无需密钥的资源创建环境变量:

  • AZURE_SEARCH_ENDPOINT:此 URL 是Azure AI 搜索资源的接入点。 此 URL 通常采用 https://<YOUR-RESOURCE-NAME>.search.azure.cn/ 格式。
  • AZURE_CLIENT_ID:这是要进行身份验证的标识。

解决常见问题

错误 原因 解决方案
AuthenticationFailedException 凭据缺失或无效 确保已使用 az login (CLI) 或 Connect-AzAccount (PowerShell) 登录。 验证Azure帐户是否有权访问订阅。
403 Forbidden 标识缺少所需角色 分配适当的角色(用于查询的搜索索引数据读取者、用于索引编制的搜索索引数据参与者)。 角色分配最多可能需要 10 分钟才能传播。
401 Unauthorized 搜索服务上未启用 RBAC 在 Azure 门户中的 Settings>Keys>基于Role 的访问控制下启用基于角色的访问。
ResourceNotFoundException 终结点或索引名称无效 AZURE_SEARCH_ENDPOINT验证环境变量是否与搜索服务 URL 匹配(格式: https://<service-name>.search.azure.cn) 。
CredentialUnavailableException 找不到有效的凭据 DefaultAzureCredential 尝试多种身份验证方法。 确保至少配置了一个(Azure CLI、Visual Studio、环境变量)。