Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Note
This feature is currently in public preview. This preview is provided without a service-level agreement and isn't recommended for production workloads. Certain features might not be supported or might have constrained capabilities. For more information, see Supplemental Terms of Use for Microsoft Azure Previews.
Azure Data Lake Storage (ADLS) Gen2 supports per-user access to directories and files through access control lists (ACLs) and role-based access control (Azure RBAC). Attribute-based access control (Azure ABAC) isn't supported.
Preview APIs in Azure AI Search can ingest this permission metadata alongside document content. Users who lack access to a directory or file in storage don't see the corresponding documents in search results. This is one of several strategies for document-level access control in Azure AI Search.
This article explains how to configure an ADLS Gen2 indexer or ADLS Gen2 blob knowledge source to automatically pull permission metadata into a search index. It supplements Index data from ADLS Gen2 and Create a blob knowledge source for ADLS Gen2 with information specific to permission ingestion. To manually push permission metadata, see Index document ACLs using the push API.
Prerequisites
Microsoft Entra ID authentication and authorization. Services and apps must be in the same tenant. Users can be in different tenants as long as all tenants use Microsoft Entra ID. Role assignments are used for each authenticated connection.
Azure AI Search on a billable tier (Basic or higher) in any region. The search service must have role-based access enabled and a system-assigned or user-assigned managed identity.
ADLS Gen2 blobs in a hierarchical namespace, with user permissions granted through ACLs or roles.
REST API version 2025-05-01-preview or later for indexer permission ingestion. REST API version 2025-11-01-preview for knowledge source support. Use the latest preview REST API or a preview SDK package that supports permission filters.
Limitations
The Azure portal doesn't support this feature.
The
owning users,owning groups, andOther(all) ACL identity categories aren't supported during public preview. Usenamed usersandnamed groupsassignments instead.The following indexer features don't support permission inheritance in indexed documents originating from ADLS Gen2. If you use any of these features in a skillset or indexer, document-level permissions aren't included in the indexed content.
Support for the permission model
This section compares document-level access control features between ADLS Gen2 and Azure AI Search. It explains which Azure Data Lake Storage (ADLS) Gen2 access control mechanisms AI Search supports or maps. This helps you understand how permissions are enforced at the document level.
| ADLS Gen2 Feature | Description | Supported | Notes |
|---|---|---|---|
| RBAC | Coarse-grained access at container level | Yes | AI Search honors RBAC for access to all documents in the entire container. |
| ABAC | Attribute-based conditions on top of RBAC | No | AI Search doesn't evaluate ABAC conditions for document-level access. |
| ACL | Fine-grained permissions at directory/file (document) level | Yes | AI Search uses document-level ACLs for permission filters. |
| Security groups | Group-based permission assignments | Yes | Supported if security groups are mapped inside the document-level ACL. |
At query time, Azure AI Search evaluates container-level RBAC first and then checks document-level ACL entries. Access is granted if any mechanism permits it.
About ACL hierarchical permissions
Indexers and knowledge sources can retrieve ACL assignments from the specified container and all directories leading to each file by following the ADLS Gen2 hierarchical access evaluation flow. The final effective access lists for each file are computed and the different access categories are indexed into the corresponding index fields.
For example, in ADLS Gen2 common scenarios related to permissions as the file path /Oregon/Portland/Data.txt.
| Operation | / | Oregon/ | Portland/ | Data.txt |
|---|---|---|---|---|
| Read Data.txt | --X | --X | --X | R-- |
The indexer or knowledge source collects ACLs from each container and directory. It then determines effective access at lower levels and continues until it resolves permissions for every file.
/ assigned access vs Oregon/ assigned access
=> Oregon/ effective access vs Portland/ assigned access
=> Portland/ effective access vs Data.txt assigned access
=> Data.txt effective access
Configure ADLS Gen2
An indexer or knowledge source can retrieve ACLs on a storage account if the following criteria are met. For more information about ACL assignments, see ADLS Gen2 ACL assignments.
Authorization
For indexing, your search service identity must have Storage Blob Data Reader permission.
If you're testing locally, you should also have a Storage Blob Data Reader role assignment. For more information, see Connect to Azure Storage using a managed identity.
Root container permissions:
Assign all
GroupandUsersets (security principals) at the root container/withReadandExecutepermissions.Ensure both
ReadandExecuteare added as "Default permissions" so they propagate to newly created files and directories automatically.
Propagate permissions down the file hierarchy
Although new directories and files inherit permissions, existing directories and files don't automatically inherit these assignments.
Use the ADLS Gen2 tool to apply ACLs recursively for assignments propagation on existing content. This tool propagates the root container's ACL assignments to all underlying directories and files.
Remove excess permissions
After applying ACLs recursively, review permissions for each directory and file.
Remove any Group or User sets that shouldn't have access to specific directories or files. For example, remove User2 on folder Portland/, and for folder Idaho remove Group2 and User2 from its assignments, and so on.
Sample ACL assignments structure
Here's a diagram of the ACL assignment structure for the fictitious directory hierarchy in the ADLS Gen2 documentation.

Updating ACL assignments over time
Over time, as any new ACL assignments are added or modified, repeat the preceding steps to ensure proper propagation and permissions alignment. Updated permissions in ADLS Gen2 are updated in the search index when you re-ingest the content using the indexer or knowledge source.
Configure Azure AI Search
Recall that the search service must have:
Authorization
For indexing, the client issuing the API call must have Search Service Contributor permission to create objects, Search Index Data Contributor permission to perform data import, and Search Index Data Reader to query an index.
If you're testing locally, you should have the same role assignments. For more information, see Connect to Azure AI Search using roles.
Configure a knowledge source
If you're using a knowledge source, definitions in the knowledge source are used to generate a full indexing pipeline (indexer, data source, and index). ACL assignments are detected and automatically included in the generated index. There's no need to modify any of the generated objects if you want permission inheritance in your indexed content.
Key points about the configuration that make it work for this scenario:
isADLSGen2is set to true, meeting the data source requirement for this scenario.ingestionPermissionOptionsspecifies user and group IDs.disableImageVerbalizationis set to true because the GenAI Prompt skill that backs this experience isn't currently supported in ADLS Gen2 permission inheritance.
# Create / Update Azure Blob Knowledge Source
###
PUT {{url}}/knowledgesources/azure-blob-ks?api-version=2025-11-01-preview
api-key: {{key}}
Content-Type: application/json
{
"name": "azure-blob-ks",
"kind": "azureBlob",
"description": "A sample azure blob knowledge source",
"azureBlobParameters": {
"connectionString": "{{blob-connection-string}}",
"containerName": "blobcontainer",
"folderPath": null,
"isADLSGen2": true,
"ingestionParameters": {
"identity": null,
"embeddingModel": {
"kind": "azureOpenAI",
"azureOpenAIParameters": {
"deploymentId": "text-embedding-3-large",
"modelName": "text-embedding-3-large",
"resourceUri": "{{aoai-endpoint}}",
"apiKey": "{{aoai-key}}"
}
},
"chatCompletionModel": null,
"disableImageVerbalization": true,
"ingestionSchedule": null,
"ingestionPermissionOptions": [
"userIds","groupIds"
],
"contentExtractionMode": "minimal",
"aiServices": {
"uri": "{{ai-endpoint}}",
"apiKey": "{{ai-key}}"
}
}
}
}
###
Configure indexer-based indexing
If you're using an indexer, configure it, the data source, and the index to pull permission metadata from ADLS Gen2 blobs.
Create the data source
This section supplements Index data from ADLS Gen2 with information that's specific to ingesting permissions alongside document content into an Azure AI Search index.
Data Source type must be
adlsgen2.Data source must have
indexerPermissionOptionswithuserIds,groupIds, and/orrbacScope.For
rbacScope, configure the connection string with managed identity format.For connection strings using a user-assigned managed identity, you must also specify the
identityproperty.
JSON example with system managed identity:
{
"name" : "my-adlsgen2-acl-datasource",
"type": "adlsgen2",
"indexerPermissionOptions": ["userIds", "groupIds", "rbacScope"],
"credentials": {
"connectionString": "ResourceId=/subscriptions/<your subscription ID>/resourceGroups/<your resource group name>/providers/Microsoft.Storage/storageAccounts/<your storage account name>/;"
},
"container": {
"name": "<your container name>",
"query": "<optional-virtual-directory-name>"
}
}
JSON schema example with a user-managed identity in the connection string:
{
"name" : "my-adlsgen2-acl-datasource",
"type": "adlsgen2",
"indexerPermissionOptions": ["userIds", "groupIds", "rbacScope"],
"credentials": {
"connectionString": "ResourceId=/subscriptions/<your subscription ID>/resourceGroups/<your resource group name>/providers/Microsoft.Storage/storageAccounts/<your storage account name>/;"
},
"container": {
"name": "<your container name>",
"query": "<optional-virtual-directory-name>"
},
"identity": {
"@odata.type": "#Microsoft.Azure.Search.DataUserAssignedIdentity",
"userAssignedIdentity": "/subscriptions/{subscription-ID}/resourceGroups/{resource-group-name}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/{user-assigned-managed-identity-name}"
}
}
Create permission fields in the index
In Azure AI Search, make sure your index contains field definitions for the permission metadata. Permission metadata can be indexed when indexerPermissionOptions is specified in the data source definition.
Recommended schema attributes for ACL (UserIds, GroupIds) and RBAC Scope:
- User identifier (ID) field with
userIdspermissionFilter value. - Group IDs field with
groupIdspermissionFilter value. - RBAC scope field with
rbacScopepermissionFilter value. - Property
permissionFilterOptionto enable filtering at querying time. - Use string fields for permission metadata
- Set
filterableto true on all fields.
Notice that retrievable is false. You can set it true during development to verify permissions are present, but remember to set to back to false before deploying to a production environment.
JSON schema example:
{
...
"fields": [
...
{ "name": "UserIds", "type": "Collection(Edm.String)", "permissionFilter": "userIds", "filterable": true, "retrievable": false },
{ "name": "GroupIds", "type": "Collection(Edm.String)", "permissionFilter": "groupIds", "filterable": true, "retrievable": false },
{ "name": "RbacScope", "type": "Edm.String", "permissionFilter": "rbacScope", "filterable": true, "retrievable": false }
],
"permissionFilterOption": "enabled"
}
Configure the indexer
Field mappings within an indexer set the data path to fields in an index. Target and destination fields that vary by name or data type require an explicit field mapping. The following metadata fields in ADLS Gen2 might need field mappings if you vary the field name:
- metadata_user_ids (
Collection(Edm.String)) - the ACL user IDs list. - metadata_group_ids (
Collection(Edm.String)) - the ACL group IDs list. - metadata_rbac_scope (
Edm.String) - the container RBAC scope.
Specify fieldMappings in the indexer to route the permission metadata to target fields during indexing.
JSON schema example:
{
...
"fieldMappings": [
{ "sourceFieldName": "metadata_user_ids", "targetFieldName": "UserIds" },
{ "sourceFieldName": "metadata_group_ids", "targetFieldName": "GroupIds" },
{ "sourceFieldName": "metadata_rbac_scope", "targetFieldName": "RbacScope" }
]
}
Recommendations and best practices
Plan the ADLS Gen2 folder structure carefully before creating any folders.
Organize identities into groups and use groups whenever possible, rather than granting access directly to individual users. Continuously adding individual users instead of applying groups increases the number of access control entries that must be tracked and evaluated. Not following this best practice can lead to more frequent security metadata updates required to the index as this metadata changes, causing increased delays and inefficiencies in the refresh process.
Synchronize permissions between indexed and source content
Enabling ACL or RBAC enrichment on an indexer works automatically only in two situations:
The very first full indexer run / data crawl: all permission metadata that exists at that moment for each document is captured.
Brand-new documents added after ACL/RBAC support is enabled: their ACL/RBAC information is ingested along with their content.
If you change document permissions, such as adding a user to an ACL or updating a role assignment, the change doesn’t appear in the search index unless you tell the indexer to crawl the document's permission metadata again.
Choose one of the following mechanisms, depending on how many items changed:
| Scope of your change | Best trigger | What gets refreshed on the next run |
|---|---|---|
| A single blob or just a handful | Update the blob’s Last-Modified timestamp in storage (touch the file) |
Document content and ACL/RBAC metadata |
| Dozens to thousands of blobs | Call /resetdocs (preview) and list the affected document keys. | Document content and ACL/RBAC metadata |
| Entire data source | Call /resync (preview) with the permissions option. | Only ACL/RBAC metadata (content is left untouched) |
Resetdocs (preview) API example:
POST https://{service}.search.windows.net/indexers/{indexer}/resetdocs?api-version=2025-11-01-preview
{
"documentKeys": [
"1001",
"4452"
]
}
Resync (preview) API example:
POST https://{service}.search.windows.net/indexers/{indexer}/resync?api-version=2025-11-01-preview
{
"options": [
"permissions"
]
}
Important
If you change permissions on indexed documents and don't trigger one of the mechanisms above, the search index continues serving outdated ACL or RBAC data. New documents continue to be indexed automatically; no manual trigger is needed for them.
Deletion tracking
To manage blob deletion effectively, make sure deletion tracking is enabled before your indexer runs for the first time. This feature lets the system detect deleted blobs in your source and remove them from the index.