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 (2)

  1. Anonymous says:

    As a Microsoft Exchange Server focused Premier Field Engineer I spend a considerable amount of my time

  2. 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.