Azure Databricks PERMISSION_DENIED on ADLS container, seems to require account-level access

Scott Hietpas 11 Reputation points
2025-10-20T13:23:21.02+00:00

In Azure Databricks, I created an External Location and Credentials to access ADLS Gen2 storage container. I have the proper Unity Catalog permissions and the "Storage Blob Data Reader" role on the container. Unity catalog can browse the folders / files in the container, but I get "PERMISSION_DENIED" when attempting to access via compute, including Serverless SQL Warehouse or Serverless in a notebook.

I verified the appropriate Unity Catalog permissions are in place. If I add "Storage Blob Data Reader" role at the ADLS account-level, everything will work as expected. However, Databricks should only have access to specific containers, so I am not able to assign account-level permissions in this case.

I believe this may be a bug in how Databricks attempts to read the external location from compute? Since UC can browse the files without issue, and container-level permissions should be sufficient, this seems like an implementation issue where Databricks attempts some command that requires escalation.

Is this a limitation of Databricks external locations (that it cannot support container-level access)?

Here is example error from Notebook using serverless compute:

User's image

SQL Warehouse with serverless compute just returns "PERMISSION_DENIED: request not authorized"

Here I can browse the external location directly in Unity Catalog:

User's image

Azure Databricks
Azure Databricks
An Apache Spark-based analytics platform optimized for Azure.
{count} votes

2 answers

Sort by: Most helpful
  1. Sina Salam 25,926 Reputation points Volunteer Moderator
    2025-10-22T13:51:37.8333333+00:00

    Hello Scott Hietpas,

    Welcome to the Microsoft Q&A and thank you for posting your questions here.

    I understand that you are experiencing a PERMISSION_DENIED error in Azure Databricks when accessing files from an Azure Data Lake Storage Gen2 (ADLS) container, even though container-level Storage Blob Data Reader permissions have been granted.

    The reason is because ADLS Gen2 enforces both Azure RBAC and POSIX-style Access Control Lists (ACLs). To resolve this without using broad account-level permissions, it’s crucial to configure the correct identity, scope, and ACLs at the container and directory levels.

    First, identify the exact principal Databricks compute uses to access ADLS. Unity Catalog’s Explorer and compute workloads might use different identities typically, the Databricks Access Connector’s managed identity or a user-assigned managed identity linked to the storage credential. You can verify this by checking your Databricks External Location > Storage Credential settings or by reviewing storage access logs to confirm which principal ID performs read operations. - Databricks Access Connector Identity

    Next, confirm the RBAC assignment at the container level. Use the Azure CLI to ensure the correct principal has the Storage Blob Data Reader role assigned at container scope:

    az role assignment create \
      --assignee <principal-object-id> \
      --role "Storage Blob Data Reader" \
      --scope /subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Storage/storageAccounts/<storageAccount>/blobServices/default/containers/<containerName>
    

    Then, inspect and configure ADLS ACLs using:

    az storage fs access show \
      --account-name <storageAccount> \
      --file-system <containerName> \
      --path "<path/to/directory-or-file>" \
      --auth-mode login
    

    The compute identity must have execute (x) permission on every parent directory, read + execute (r-x) on the directory containing the data, and read (r--) on files. To apply these permissions, use:

    az storage fs access set \
      --account-name <storageAccount> \
      --file-system <containerName> \
      --path "path/to/directory" \
      --acl "user:<objId>:r-x" \
      --auth-mode login
    

    For many files or folders, apply ACLs recursively with:

    az storage fs access set-recursive \
      --account-name <storageAccount> \
      --file-system <containerName> \
      --path "path/to/directory" \
      --acl "user:<objId>:r-x" \
      --auth-mode login
    

    After updating permissions, verify access directly from your Databricks notebook:

    dbutils.fs.ls("abfss://<container>@<storageAccount>.dfs.core.windows.net/path/to/directory") spark.read.text("abfss://<container>@<storageAccount>.dfs.core.windows.net/path/to/file.csv").show(5)
    

    If the issue persists, check Azure Storage diagnostic logs in Log Analytics to identify the denied principalId and specific path. This confirms whether ACLs are applied to the correct identity. - Monitor and Troubleshoot Azure Storage Access

    Lastly, avoid granting account-level permissions as a long-term solution. Instead, maintain least-privilege by aligning RBAC with container scope, ensuring consistent ACL inheritance, and validating permissions on all parent directories. For complex directory structures, automate ACL propagation using scripts. - Azure Data Lake Storage Gen2 Best Practices

    I hope this is helpful! Do not hesitate to let me know if you have any other questions or clarifications.


    Please don't forget to close up the thread here by upvoting and accept it as an answer if it is helpful.

    0 comments No comments

  2. Scott Hietpas 11 Reputation points
    2025-10-24T15:35:34.4366667+00:00

    Although I don't fully understand the "why", I do have a workaround that will meet my needs.

    In short, we are unable to directly query the abfss location (using dbutils.fs, LIST, or other). Although this does seem to leverage the External Location definition (since I get a different error if no external location defined), the direct use of the external location seems to demand account-level permissions.

    The workaround is to define an External Volume based on the external location. When accessing using the volume (vs explicit abfss path), then Unity Catalog seems to support access directly to the container level.


Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.