Use Azure AI Search without keys
In your application code, you can set up a keyless connection to Azure AI Search that uses Microsoft Entra ID and roles for authentication and authorization. Application requests to most Azure services must be authenticated with keys or keyless connections. Developers must be diligent to never expose the keys in an unsecure location. Anyone who gains access to the key is able to authenticate to the service. Keyless authentication offers improved management and security benefits over the account key because there's no key (or connection string) to store.
Keyless connections are enabled with the following steps:
- Configure your authentication.
- Set environment variables, as needed.
- Use an Azure Identity library credential type to create an Azure AI Search client object.
Prerequisites
The following steps need to be completed for both local development and production workloads:
- Create an AI Search resource
- Enable role-based access on your search service
- Install Azure Identity client library
Create an AI Search resource
Before continuing with this article, you need an Azure AI Search resource to work with. If you don't have a resource, create your resource now. Enable role-based access control (RBAC) for the resource.
Install Azure Identity client library
Before working locally without keyless, update your AI Search enabled code with the Azure Identity client library.
Install the Azure Identity client library for .NET:
dotnet add package Azure.Identity
Update source code to use DefaultAzureCredential
The Azure Identity library's DefaultAzureCredential
allows you to run the same code in the local development environment and in the Azure cloud. Create a single credential and reuse the credential instance as needed to take advantage of token caching.
For more information on DefaultAzureCredential
for .NET, see Azure Identity client library 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);
Local development
Local development without keyless includes these steps:
- Assign your personal identity with RBAC roles on the specific resource.
- Use a tool to authenticate with Azure.
- Establish environment variables for your resource.
Roles for local development
As a local developer, your Azure identity needs full control of your service. This control is provided with RBAC roles. To manage your resource during development, these are the suggested roles:
- Search Service Contributor
- Search Index Data Contributor
- Search Index Data Reader
Find your personal identity with one of the following tools. Use that identity as the <identity-id>
value.
Sign in to Azure CLI.
az login
Get your personal identity.
az ad signed-in-user show \ --query id -o tsv
Assign the role-based access control (RBAC) role to the identity for the resource group.
az role assignment create \ --role "<role-name>" \ --assignee "<identity-id>" \ --scope "/subscriptions/<subscription-id>/resourceGroups/<resource-group-name>"
Where applicable, replace <identity-id>
, <subscription-id>
, and <resource-group-name>
with your actual values.
Authentication for local development
Use a tool in your local development environment to authentication to Azure identity. Once you're authenticated, the DefaultAzureCredential
instance in your source code finds and uses the authentication.
Select a tool for authentication during local development.
Configure environment variables for local development
To connect to Azure AI Search, your code needs to know your resource endpoint.
Create an environment variable named AZURE_SEARCH_ENDPOINT
for your Azure AI Search endpoint. This URL generally has the format https://<YOUR-RESOURCE-NAME>.search.windows.net/
.
Production workloads
Deploy production workloads includes these steps:
- Choose RBAC roles that adhere to the principle of least privilege.
- Assign RBAC roles to your production identity on the specific resource.
- Set up environment variables for your resource.
Roles for production workloads
To create your production resources, you need to create a user-assigned managed identity then assign that identity to your resources with the correct roles.
The following role is suggested for a production application:
Role name | Id |
---|---|
Search Index Data Reader | 1407120a-92aa-4202-b7e9-c0e197c71c8f |
Authentication for production workloads
Use the following Azure AI Search Bicep template to create the resource and set the authentication for the identityId
. Bicep requires the role ID. The name
shown in this Bicep snippet isn't the Azure role; it's specific to the Bicep deployment.
// 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
}
}
The main.bicep
file calls the following generic Bicep code to create any role. You have the option to create multiple RBAC roles, such as one for the user and another for production. This allows you to enable both development and production environments within the same Bicep deployment.
// 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)
}
}
Configure environment variables for production workloads
To connect to Azure AI Search, your code needs to know your resource endpoint, and the ID of the managed identity.
Create environment variables for your deployed and keyless Azure AI Search resource:
AZURE_SEARCH_ENDPOINT
: This URL is the access point for your Azure AI Search resource. This URL generally has the formathttps://<YOUR-RESOURCE-NAME>.search.windows.net/
.AZURE_CLIENT_ID
: This is the identity to authenticate as.