How to Handle NTFS Folder Permissions, Security Descriptors and ACLs in PowerShell
1. Overview
Some time ago, I was automating a few tasks with PowerShell and needed to set NTFS permissions on a folder. I was tempted to use the good old ICACLS.EXE command line, but I wanted to keep it all within PowerShell. While there are a number of different permissions you could want to set for a folder, my specific case called the following:
- Create a new folder
- Check the default permissions on the new folder
- Turn off inheritance on that folder, removing existing inherited permissions from the parent folder
- Grant “Full Control” permissions to Administrators, propagating via inheritance to files and subfolders
- Grant “Read” permissions to Users, propagating via inheritance to files and subfolders
- Review the permissions on the folder
2. The old ICACLS
In the old CMD.EXE world, you would use ICACLS.The commands would look like this:
- MD F:Folder
- ICACLS F:Folder
- ICACLS F:Folder /INHERITANCE:R
- ICACLS F:Folder /GRANT Administrators:(CI)(OI)F
- ICACLS F:Folder /GRANT Users: (CI)(OI)R
- ICACLS F:Folder
3. The PowerShell way
After some investigation, I found the PowerShell cmdlets to do the same things. You essentially rely on Get-Acl and Set-Acl to get, show and set permissions on a folder. Unfortunately, there are no cmdlets to help with the actual manipulation of the permissions. However, you can use a few .NET classes and methods to do the work. Here’s what I ended up with:
- New-Item F:Folder –Type Directory
- Get-Acl F:Folder | Format-List
- $acl = Get-Acl F:Folder
- $acl.SetAccessRuleProtection($True, $False)
- $rule = New-Object System.Security.AccessControl.FileSystemAccessRule("Administrators","FullControl", "ContainerInherit, ObjectInherit", "None", "Allow")
- $acl.AddAccessRule($rule)
- $rule = New-Object System.Security.AccessControl.FileSystemAccessRule("Users","Read", "ContainerInherit, ObjectInherit", "None", "Allow")
- $acl.AddAccessRule($rule)
- Set-Acl F:Folder $acl
- Get-Acl F:Folder | Format-List
4. Looking at the output
To show how this works, here’s the output you should get from those commands. Be sure to use the option to “Run as Administrator” if you’re creating a folder outside your user’s folders. Note that I made a few changes from the cmdlets shown previously. I also included couple of calls to the GetAccessRules method to get extra details about the permissions.
PS F:> New-Item F:Folder -Type Directory
Directory: F:
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 11/6/2010 8:10 PM Folder
PS F:> $acl = Get-Acl F:Folder
PS F:> $acl | Format-List
Path : Microsoft.PowerShell.CoreFileSystem::F:Folder
Owner : BUILTINAdministrators
Group : NORTHAMERICADomain Users
Access : BUILTINAdministrators Allow FullControl
BUILTINAdministrators Allow 268435456
NT AUTHORITYSYSTEM Allow FullControl
NT AUTHORITYSYSTEM Allow 268435456
NT AUTHORITYAuthenticated Users Allow Modify, Synchronize
NT AUTHORITYAuthenticated Users Allow -536805376
BUILTINUsers Allow ReadAndExecute, Synchronize
BUILTINUsers Allow -1610612736
Audit :
Sddl : O:BAG:S-1-5-21-124525095-708259637-1543119021-513D:(A;ID;FA;;;BA)(A;OICIIOID;GA;;;BA)(A;ID;FA;;;SY)(A;OICIIOID
;GA;;;SY)(A;ID;0x1301bf;;;AU)(A;OICIIOID;SDGXGWGR;;;AU)(A;ID;0x1200a9;;;BU)(A;OICIIOID;GXGR;;;BU)
PS F:> $acl.GetAccessRules($true, $true, [System.Security.Principal.NTAccount])
FileSystemRights : FullControl
AccessControlType : Allow
IdentityReference : BUILTINAdministrators
IsInherited : True
InheritanceFlags : None
PropagationFlags : None
FileSystemRights : 268435456
AccessControlType : Allow
IdentityReference : BUILTINAdministrators
IsInherited : True
InheritanceFlags : ContainerInherit, ObjectInherit
PropagationFlags : InheritOnly
FileSystemRights : FullControl
AccessControlType : Allow
IdentityReference : NT AUTHORITYSYSTEM
IsInherited : True
InheritanceFlags : None
PropagationFlags : None
FileSystemRights : 268435456
AccessControlType : Allow
IdentityReference : NT AUTHORITYSYSTEM
IsInherited : True
InheritanceFlags : ContainerInherit, ObjectInherit
PropagationFlags : InheritOnly
FileSystemRights : Modify, Synchronize
AccessControlType : Allow
IdentityReference : NT AUTHORITYAuthenticated Users
IsInherited : True
InheritanceFlags : None
PropagationFlags : None
FileSystemRights : -536805376
AccessControlType : Allow
IdentityReference : NT AUTHORITYAuthenticated Users
IsInherited : True
InheritanceFlags : ContainerInherit, ObjectInherit
PropagationFlags : InheritOnly
FileSystemRights : ReadAndExecute, Synchronize
AccessControlType : Allow
IdentityReference : BUILTINUsers
IsInherited : True
InheritanceFlags : None
PropagationFlags : None
FileSystemRights : -1610612736
AccessControlType : Allow
IdentityReference : BUILTINUsers
IsInherited : True
InheritanceFlags : ContainerInherit, ObjectInherit
PropagationFlags : InheritOnly
PS F:> $acl.SetAccessRuleProtection($True, $False)
PS F:> $rule = New-Object System.Security.AccessControl.FileSystemAccessRule("Administrators","FullControl", "ContainerInherit, ObjectInherit", "None", "Allow")
PS F:> $acl.AddAccessRule($rule)
Comments
- Anonymous
March 22, 2014
As a Microsoft Exchange Server focused Premier Field Engineer I spend a considerable amount of my time - Anonymous
April 07, 2016
Close, helpful, clear, but no cigar.The $acl.SetAccessRuleProtection($True, $False) seems to have no effect on ACEs inherited from the parent. As far as I can tell.To make this really work I need to delete inherited and existing ACEs.- Anonymous
September 12, 2017
To remove all of the existing ACEs, try this:$acl = get-acl c:\path\to\folderforeach ($a in $acl) {$acl.RemoveAccessRule($a)}Now you can create and add rules to $acl and then apply it to a folder.
- Anonymous