Partager via


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.