Restructuring file server permissions without breaking access
The companion piece to this one, on file server migration without breaking permissions, gives one piece of advice firmly: when the pre-migration audit turns up a decade of accumulated permission exceptions, document them and move them as they are. Do not fix them during the migration, because two changes in one window leave you unable to tell which one broke access on Monday.
This is the other half. The migration is done, the audit output is sitting in a spreadsheet, and someone has to deal with what it says. Here is how to restructure permissions on a live file server without a weekend of lockouts.
The actual root cause is user accounts on ACLs
Nearly every unmanageable file server has the same underlying fault, and it is not broken inheritance or stray deny entries — those are symptoms. It is that individual user accounts appear directly on folder ACLs.
It always starts reasonably. Someone needs access to one folder today, adding them directly takes ten seconds, and creating a group takes a conversation about naming. Repeat for six years across four administrators and two of them leaving.
The cost is that two questions become unanswerable. "What does this person have access to?" now requires walking the entire tree, because their SID could be on any folder. "Who can read this folder?" requires expanding every group on the ACL, recursively, and then checking for direct entries as well. Neither question can be answered from the directory, which means neither can be answered when a leaver's access needs revoking or an auditor asks who could see the payroll folder.
This is why permission problems get worse rather than plateauing. Every direct ACE is a fact recorded in only one place, on the file system, where nothing reports on it.
The model, and an honest word about it
The standard answer is AGDLP: accounts go into global groups, global groups go into domain local groups, and the domain local group is what gets the permission on the folder. In practice this means a global group that describes people ("Finance") nested inside a domain local group that describes an access level ("FS-Finance-Modify"), and only the second one ever appears on an ACL.
The criticism of AGDLP is fair and worth stating: it is verbose, and a naive application produces two groups for every folder and an unmanageable directory instead of an unmanageable file system. You have moved the mess, not removed it.
The rule that keeps it honest is not about the model, it is about depth. Grant permissions at a small number of defined levels — typically the share root and one level beneath it — and nowhere else. If a folder five levels down needs its own permissions, that is a signal the structure is wrong, not that you need another pair of groups. Most estates need far fewer groups than they fear, once they stop granting at arbitrary depth.
| Symptom in the audit | What it usually means | Fix |
|---|---|---|
| User SIDs directly on ACLs | Ad-hoc grants over years | Replace with a domain local group holding the same people |
| Inheritance disabled deep in the tree | An urgent exception nobody reverted | Restructure so the exception is a sibling folder, not a nested one |
| Explicit deny entries | A blunt fix for an over-broad allow | Remove the over-broad allow instead; deny is almost never the right tool |
| Unresolvable S-1-5-21 entries | Deleted accounts, or old local accounts | Remove once confirmed against the audit CSV |
| Everyone or Authenticated Users with Modify | A share created quickly and never revisited | Replace with a group, after checking what breaks |
| Same people in many overlapping groups | Groups created per folder rather than per role | Consolidate, and watch the Kerberos token size |
Group sprawl has a hard failure mode
Consolidating badly has a specific consequence rather than a vague one. Every group a user belongs to goes into their Kerberos ticket, and MaxTokenSize defaults to 48,000 bytes on Windows Server 2012 and later. Microsoft's guidance puts the practical ceiling at roughly 120 universal groups per user.
Past that, authentication fails in ways that do not name the cause: HTTP 400 "Request Header too long" from web applications, Group Policy silently not applying. NTLM continues to work, so the problem looks like a bug in one application. If a permissions project doubles the number of groups every user is in, this is the wall it eventually hits.
Changing permissions without a big bang
The safe method is additive, and it is safe precisely because every step is reversible on its own. Do one share at a time.
- •Create the new group and populate it from the existing ACL, so membership starts as an exact copy of who has access today.
- •Add the group to the ACL alongside the existing entries. Nobody loses anything, because you have only granted. Effective access is unchanged.
- •Wait a full business cycle. A week catches the weekly report; a month catches the monthly close. This is where the service account and the scheduled job you did not know about surface.
- •Remove the old direct entries. This is the only destructive step, and by now the new grant has been proven in production.
- •Re-run the audit and diff it against the pre-change output.
# step 1: who is on this ACL directly today, as accounts rather than groups
(Get-Acl 'D:\Data\Finance').Access |
Where-Object { $_.AccessControlType -eq 'Allow' } |
ForEach-Object {
$id = $_.IdentityReference.Value
$obj = try { Get-ADObject -LDAPFilter "(sAMAccountName=$($id -replace '.*\\',''))" } catch { $null }
[PSCustomObject]@{ Identity = $id; Class = $obj.ObjectClass; Rights = $_.FileSystemRights }
} | Sort-Object Class, Identity
# step 2: add the new group WITHOUT removing anything
$acl = Get-Acl 'D:\Data\Finance'
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule(
'CONTOSO\FS-Finance-Modify', 'Modify',
'ContainerInherit,ObjectInherit', 'None', 'Allow')
$acl.AddAccessRule($rule)
Set-Acl 'D:\Data\Finance' $aclTake a backup of the ACLs before touching anything: icacls D:\Data /save acl-backup.txt /t /c writes the whole tree, and /restore puts it back. It is the only rollback that works at the speed an incident requires.
Two settings worth fixing while you are there
Access-based enumeration hides folders a user cannot open, rather than showing them a list of things that will deny them. It reduces support calls and stops the folder structure itself from leaking information — a directory named "Redundancies-2026" is a disclosure even if nobody can open it.
Get-SmbShare | Where-Object { $_.Name -notlike '*$' } |
Select-Object Name, FolderEnumerationMode
Set-SmbShare -Name 'Finance' -FolderEnumerationMode AccessBased -ForceAnd check the share-level ACL. On most servers it is Everyone / Full Control, with NTFS doing all the real work. That is a defensible design as long as it is deliberate, because effective access is the more restrictive of the two. It stops being defensible when somebody assumes the share ACL is protecting something.
Verifying, and what to verify against
- •Effective access for one real member of each group, not for a test account that belongs to nothing. Configured permissions and effective access are different questions.
- •The applications, not just Explorer. A service account reaching a share is the classic thing nobody tests.
- •The audit diff. Anything that changed between the before and after export should be a change you can name.
- •Access-denied events in the security log for the first week after each removal step.
- •Group counts per user, if you consolidated. Confirm nobody crossed into token-size territory.
How long this actually takes
The honest answer for a file server that has been accumulating exceptions for a decade is weeks, not a weekend, and most of that is waiting rather than working. Each share needs a business cycle between the additive step and the destructive one, and the cycles can run in parallel across shares but cannot be compressed.
Anyone offering to fix a permission structure over a weekend is planning to skip the waiting, which is the part that catches the monthly job and the appliance nobody remembers. That is where the outage comes from.
The audit queries referenced above are collected in the printable file server migration checklist, along with a free review of whatever output they produce.
Permissions nobody can explain any more?
We run file server permission audits, restructuring and migrations, plus ongoing Windows and Linux server administration. €65/hour, fixed-scope quotes for projects, from €60/month per server for ongoing support.