By the end of this build sheet your pilot share has production-shaped identity: named Entra groups at the RBAC gate, a working NTFS ACL tree that a cloud-only user actually hits, group SIDs flowing in tickets, the Conditional Access exclusion in place and documented, and a validation pass proving a standard user sees exactly what the ACLs say. No domain controller, no hybrid sync, no storage key in daily use.
Prerequisites: the [AF 1.1] share (or any share with Entra Kerberos enabled and admin consent granted); Entra roles to create groups and edit Conditional Access; Owner or User Access Administrator on the storage account for role assignments; a Windows 11 24H2+ Entra-joined test device and two test users, one intended for read-write and one for read-only. This sheet assumes cloud-only identities; every step also works for hybrid identities under Entra Kerberos.
Step 1: Create the access groups
Model permissions in groups from the first minute, even in a pilot, because retrofitting groups under per-user ACLs is the single most tedious cleanup this platform offers. My naming convention for file access groups carries the share and the level: AZF-<share>-RW and AZF-<share>-RO, plus one AZF-<share>-Admins per share for the people allowed to edit ACLs.
Connect-MgGraph -Scopes "Group.ReadWrite.All"
foreach ($g in "AZF-Pilot-RW","AZF-Pilot-RO","AZF-Pilot-Admins") {
New-MgGroup -DisplayName $g -MailEnabled:$false -MailNickname $g `
-SecurityEnabled:$true
}
Add your read-write test user to AZF-Pilot-RW, the read-only user to AZF-Pilot-RO, and your own admin account to AZF-Pilot-Admins. Expected result: three security groups, memberships confirmed in the Entra admin center.
Step 2: Tag the storage app for cloud group SIDs
This step is mandatory for cloud-only identities, not an optimization. Without the tag, tickets issued for cloud-only users do not carry cloud group SIDs, and Microsoft is explicit that authentication for those identities fails as a result. Treat any outcome milder than that, group ACLs evaluating as though the user belonged to nothing, as the lucky version. The fix is a tag on the storage account’s auto-created application manifest. In the Entra admin center, open app registrations, find [Storage Account] stvciofiles01.file.core.windows.net, open its manifest, and add kdc_enable_cloud_group_sids to the tags array. Via Graph:
$app = @(Get-MgApplication -Filter "displayName eq '[Storage Account] stvciofiles01.file.core.windows.net'")
if ($app.Count -ne 1) { throw "Expected exactly one application, found $($app.Count)" }
Update-MgApplication -ApplicationId $app[0].Id `
-Tags ($app[0].Tags + "kdc_enable_cloud_group_sids")
The count check is not defensive padding. A tenant with several storage accounts using Entra Kerberos holds several near-identically named applications, and a filter that returns two of them will happily write the tag onto the wrong one, leaving you debugging the account you did not touch. Failure mode: on a cloud-only tenant, skipping this breaks authentication outright; in the milder variants people report, share-level access passes and every group-based deny or grant in the ACL tree silently misbehaves. If group permissions “don’t apply,” check this tag before touching a single ACL. Also note the ceiling: a ticket carries at most 1,010 group SIDs; users in sprawling nested-group estates can fail ticket issuance entirely (error 140011), and the fix is group hygiene, not a setting.
Step 3: Replace the default share permission with RBAC on groups
The starter build used a tenant-wide default share permission. Production uses named groups against the three SMB data roles, and the default goes back to None.
| Setting | Value | Why |
|---|---|---|
| Role for AZF-Pilot-RW | Storage File Data SMB Share Contributor | Read, write, delete through the gate; ACLs still refine beneath it. |
| Role for AZF-Pilot-RO | Storage File Data SMB Share Reader | Read-only through the gate regardless of any generous ACL beneath. |
| Role for AZF-Pilot-Admins | Storage File Data SMB Share Elevated Contributor | The only role that may modify NTFS ACLs over SMB. |
| Default share-level permission | None | The gate should name its groups; “all authenticated users” was pilot scaffolding. |
$scope = "/subscriptions/<sub-id>/resourceGroups/rg-files-pilot/providers/Microsoft.Storage/storageAccounts/stvciofiles01/fileServices/default/fileshares/pilot"
New-AzRoleAssignment -ObjectId (Get-MgGroup -Filter "displayName eq 'AZF-Pilot-RW'").Id `
-RoleDefinitionName "Storage File Data SMB Share Contributor" -Scope $scope
New-AzRoleAssignment -ObjectId (Get-MgGroup -Filter "displayName eq 'AZF-Pilot-RO'").Id `
-RoleDefinitionName "Storage File Data SMB Share Reader" -Scope $scope
New-AzRoleAssignment -ObjectId (Get-MgGroup -Filter "displayName eq 'AZF-Pilot-Admins'").Id `
-RoleDefinitionName "Storage File Data SMB Share Elevated Contributor" -Scope $scope
Set-AzStorageAccount -ResourceGroupName "rg-files-pilot" `
-StorageAccountName "stvciofiles01" -DefaultSharePermission None
One regional honesty note: assigning roles to specific cloud-only users and groups is still limited to a published subset of Azure regions (roughly fifty as I write this, and growing). If your region is not on the list yet, the supported pattern is the default share-level permission as the gate with ACLs doing all refinement; check the current list at publish-time of your own deployment rather than trusting any article, including this one. Expected result either way: within 30 minutes, the RW user mounts and writes, the RO user mounts and cannot write.
Step 4: The Conditional Access exclusion, done deliberately
If any Conditional Access policy requiring MFA applies to all cloud apps, mounts will fail with system error 1327 until the storage account’s application is excluded. Do the exclusion as governance, not as a quiet fix: in each MFA policy’s target apps, exclude [Storage Account] stvciofiles01.file.core.windows.net, and record in the policy’s description why the exclusion exists (SMB Kerberos cannot satisfy MFA; enforcement for file access lives on the network path). If your CA estate follows a framework with a standing exclusion group pattern, add the storage app there instead, one place, documented. The compensating control is the subject of the next two articles; an exclusion without a compensating control is a finding, and you should treat it as one.
Step 5: Build the ACL tree
Now the real permission model. Worked example, the one I use because it is the shape of almost every departmental share: the share holds \Common (everyone reads and writes), \Finance (RW group writes, RO group has nothing), and \Readonly-Published (everyone reads, only admins write).
With cloud-only identities you do not use File Explorer’s security tab or icacls; they cannot resolve cloud principals. The portal path is the share’s file browser: select a directory, choose Manage access, and add allow entries per group. For anything beyond a handful of entries, use the RestSetAcls PowerShell module, which speaks REST and needs no line of sight to anything:
Install-Module RestSetAcls -Scope CurrentUser
$ctx = New-AzStorageContext -StorageAccountName "stvciofiles01" -UseConnectedAccount
# \Common : RW group modify, RO group read
Add-AzFileAce -Context $ctx -FileShareName pilot -FilePath "Common" `
-Principal "AZF-Pilot-RW" -AccessRights Modify
Add-AzFileAce -Context $ctx -FileShareName pilot -FilePath "Common" `
-Principal "AZF-Pilot-RO" -AccessRights Read
# \Finance : RW only
Add-AzFileAce -Context $ctx -FileShareName pilot -FilePath "Finance" `
-Principal "AZF-Pilot-RW" -AccessRights Modify
# \Readonly-Published : everyone read, admins write
Add-AzFileAce -Context $ctx -FileShareName pilot -FilePath "Readonly-Published" `
-Principal "AZF-Pilot-RO" -AccessRights Read
Add-AzFileAce -Context $ctx -FileShareName pilot -FilePath "Readonly-Published" `
-Principal "AZF-Pilot-RW" -AccessRights Read
Add-AzFileAce -Context $ctx -FileShareName pilot -FilePath "Readonly-Published" `
-Principal "AZF-Pilot-Admins" -AccessRights Modify
Two rules carried over from every file server you have ever run, both still true here: set the root and top-level ACLs before data lands in bulk, because propagation across a large tree is slow and disruptive; and never ACL to individual users, because the group is the unit your future self can audit. One rule that is new: an ACL entry for a principal that Entra Kerberos cannot resolve (an old on-prem SID, an unsynced account) is accepted and stored but never enforced, silently. If you migrated data in with old ACLs, assume dead ACEs exist and rebuild deliberately; the migration articles handle this at scale.
Step 6: Validate like an auditor
The end-to-end test, run as each test user on the Entra-joined device, no cached sessions (sign out and in between users, or use separate devices):
net use Z: \\stvciofiles01.file.core.windows.net\pilot
klist get cifs/stvciofiles01.file.core.windows.net
# RW user, expected: succeeds, succeeds, FAILS (access denied)
echo test > Z:\Common\rw-test.txt
echo test > Z:\Finance\rw-test.txt
echo test > Z:\Readonly-Published\rw-test.txt
# RO user, expected: read succeeds, both writes FAIL, Finance not even readable
type Z:\Common\rw-test.txt
echo test > Z:\Common\ro-test.txt
dir Z:\Finance
Every expected failure is as much a pass condition as every expected success. If the RO user can write to Common, the likely culprits in order: the manifest tag (Step 2), RBAC still propagating, or a leftover default share permission granting Contributor above your ACLs. If Finance is invisible to the RO user in a listing but its name still shows, that is not a bug: access-based enumeration does not exist on direct mounts, users see names they cannot open, and managing that expectation belongs to you, not the platform.
Close the loop on the key: with identity working, nobody mounts with the storage account key anymore. Rotate both keys now (storage account, Security + networking, Access keys, rotate each) so any copy that escaped during testing dies, and record the Admins group, not the key, as the operational path for permission changes. The key stays in the break-glass drawer with the same ceremony as a domain recovery credential. From here, the networking articles decide what carries this traffic in production.
Azure Files
‹ Previous: [AF 2] Identity: Who Your File Server Trusts Now
Next: [AF 3] Port 445 and the Internet: The Honest Risk Model ›




