ADLS Gen2 — how RBAC, ABAC and ACLs combine, ACL rules, and Blob API differences

How Azure Data Lake Storage authorizes a request on a hierarchical-namespace account — role assignments first, then ABAC conditions, then POSIX ACLs, so an ACL can never take away what a role grants — with the ACL rules that cause most 403s (Execute on every parent, default ACLs only apply to new children, service principal object ID, 32-entry limit, mask, sticky bit, $superuser from Shared Key), what anonymous access and Shared Key skip, and where Blob APIs and Data Lake APIs disagree.

markdownreferencev1RAAZ-9BZRstage: buildtrust: officialservice: storageinterface: anyADLS Gen2 403Data Lake ACLPOSIX ACLaccess ACLdefault ACLExecute permission traverseACL inheritance existing childrenset ACL recursivelyaz storage fs access set-recursiveservice principal object ID ACL32 ACL entriesACL masksticky bit 403$superuserStorage Blob Data Owner ACLRBAC ACL evaluation orderABAC role assignment conditionACL cannot restrict RBACdfs endpointDataLakeServiceClienthierarchical namespace known issues

Created 21 Oct 2026 · Modified 23 Oct 2026 · 1 version

ADLS Gen2 — RBAC, ABAC and ACLs together

Order of evaluation for an Entra ID caller: (1) Azure role assignments; if one grants the action, (2) its ABAC conditions are checked; if they match, access is granted. (3) Only if nothing granted it are the ACLs evaluated. So an ACL can't restrict access that a role already grants. Give broad roles sparingly (Storage Blob Data Reader at the account means everyone with it reads everything) and use ACLs for fine-grained grants.

Shared Key, account SAS and service SAS skip all of this: no identity, so RBAC, ABAC and ACLs have no effect, and items they create are owned by $superuser. Anonymous read on a container also ignores its ACLs (writes still honour them). Both are reasons to turn them off (reference/storage/access-models.md).

ACL rules that cause 403s

RuleConsequence
Execute (X) on every parent directory, from the container root down, is needed to reach an item when access comes from ACLs onlyGranting r-- on a file alone still returns 403
Listing a directory needs Read + Execute on it; creating children needs Write + Execute—
Default ACLs are templates for new children only; changing a parent's default ACL doesn't change existing childrenUse recursive ACL updates (az storage fs access set-recursive / update-recursive); not available in the portal
Permissions aren't inherited after the fact: an item's ACL is stored on the itemMoving or creating items before setting defaults leaves them without the grant
For a service principal, use the service principal's object ID, not the app registration'saz ad sp show --id <appId> --query id -o tsv
ACLs apply only to principals in the same tenantPrincipals from another tenant get nothing from an ACL
32 entries per access ACL and per default ACL, effectively 28 usableGrant to groups, not individuals
The mask caps named users, named groups and the owning groupAn entry with rwx under mask r-x can't write
Sticky bit on a directory: only the child's owner, the directory's owner or the superuser can delete or rename children403 on delete or rename for everyone else
Changing permissions: the item's owning user (its creator) or a super-user; changing the owning user: a super-user only. Storage Blob Data Owner is the role Microsoft lists for setting ownership and managing ACLsSetting ACLs as a Contributor on items someone else created fails

Blob APIs on a hierarchical-namespace account

  • Blob APIs, Data Lake APIs and NFS 3.0 can read the same data, but can't write the same file: a file written with the Data Lake API can't take Put Block / Put Block List (409 BlobOperationNotSupported); overwrite with Put Blob instead.
  • List Blobs without a delimiter returns directories too; the only supported delimiter is /.
  • Blob Delete removes a directory only when it's empty; use the Data Lake API with recursive: true.
  • Not supported: page blobs (Put Page, Get Page Ranges), Incremental Copy Blob, Put Page from URL, Append Blob Seal, unmanaged VM disks.
  • Private endpoints: create both blob and dfs; ACL management and directory operations need dfs.

Client choice (TypeScript)

Use @azure/storage-file-datalake (DataLakeServiceClient, endpoint https://<acct>.dfs.core.windows.net) for directories, renames and ACLs: fileSystemClient.getDirectoryClient(path).setAccessControlRecursive(acl). Use @azure/storage-blob for plain object reads and writes. Both take the same TokenCredential. Setup: guides/storage/access-blobs-from-typescript.md.

Read this document as markdown — the same bytes an agent receives.