Configuring NTFS permissions using PowerShell

Configuring NTFS permissions is something that you can do using your Windows Explorer, Server Manager, or by using command-line tools like subinacl.exe or icacls.exe. In this blog post, I will show you how to set NTFS permissions in two different ways using PowerShell 🙂

Built-in cmdlets

PowerShell has two ACL cmdlets for retrieving and setting NTFS permissions, Get-Acl and Set-Acl.

Get-Acl

When using Get-Acl with the -Path parameter to specify the folder or file you want to check the permissions of, it will look like this:

C:\Users\HarmVeenstra> Get-Acl -Path C:\Windows\ | Format-List

Path   : Microsoft.PowerShell.Core\FileSystem::C:\Windows\
Owner  : NT SERVICE\TrustedInstaller
Group  : NT SERVICE\TrustedInstaller
Access : CREATOR OWNER Allow  268435456
         NT AUTHORITY\SYSTEM Allow  268435456
         NT AUTHORITY\SYSTEM Allow  Modify, Synchronize
         BUILTIN\Administrators Allow  268435456
         BUILTIN\Administrators Allow  Modify, Synchronize
         BUILTIN\Users Allow  -1610612736
         BUILTIN\Users Allow  ReadAndExecute, Synchronize
         NT SERVICE\TrustedInstaller Allow  268435456
         NT SERVICE\TrustedInstaller Allow  FullControl
         APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES Allow  ReadAndExecute, Synchronize
         APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES Allow  -1610612736
         APPLICATION PACKAGE AUTHORITY\ALL RESTRICTED APPLICATION PACKAGES Allow  ReadAndExecute, Synchronize
         APPLICATION PACKAGE AUTHORITY\ALL RESTRICTED APPLICATION PACKAGES Allow  -1610612736
Audit  :
Sddl   : O:S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464G:S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464D:PAI(A;OICIIO;GA;;;CO)(A;OICIIO;GA;;;SY)(A;;0x1301bf
         ;;;SY)(A;OICIIO;GA;;;BA)(A;;0x1301bf;;;BA)(A;OICIIO;GXGR;;;BU)(A;;0x1200a9;;;BU)(A;CIIO;GA;;;S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464)(A;;FA;;;S-1-5-80-9560088
         85-3418522649-1831038044-1853292631-2271478464)(A;;0x1200a9;;;AC)(A;OICIIO;GXGR;;;AC)(A;;0x1200a9;;;S-1-15-2-2)(A;OICIIO;GXGR;;;S-1-15-2-2)

It will show the Owner, Group, and individual permissions of the file or folder. The numbers 268435456, -536805376, and -1610612736 indicate this:

NumberAccess
268435456 FullControl
-536805376Modify, Synchronize
-1610612736ReadAndExecute, Synchronize

The Sddl (Security Descriptor Definition Language) details can be found here.

You can also show the Access Permissions in more detail using (Get-Acl -Path c:\windows\).Access

C:\Users\HarmVeenstra> (Get-Acl -Path C:\Windows\).Access

FileSystemRights  : 268435456
AccessControlType : Allow
IdentityReference : CREATOR OWNER
IsInherited       : False
InheritanceFlags  : ContainerInherit, ObjectInherit
PropagationFlags  : InheritOnly

FileSystemRights  : 268435456
AccessControlType : Allow
IdentityReference : NT AUTHORITY\SYSTEM
IsInherited       : False
InheritanceFlags  : ContainerInherit, ObjectInherit
PropagationFlags  : InheritOnly

FileSystemRights  : Modify, Synchronize
AccessControlType : Allow
IdentityReference : NT AUTHORITY\SYSTEM
IsInherited       : False
InheritanceFlags  : None
PropagationFlags  : None

FileSystemRights  : 268435456
AccessControlType : Allow
IdentityReference : BUILTIN\Administrators
IsInherited       : False
InheritanceFlags  : ContainerInherit, ObjectInherit
PropagationFlags  : InheritOnly

FileSystemRights  : Modify, Synchronize
AccessControlType : Allow
IdentityReference : BUILTIN\Administrators
IsInherited       : False
InheritanceFlags  : None
PropagationFlags  : None

More (advanced) examples can be found here.

Set-Acl

The Set-Acl cmdlet can be used to set permissions on files or folders. The nice thing about it is that you can copy/paste permission. In the example below, I copy the permissions from the d:\Test1 folder and set them on the d:\Test2 folder. First, I retrieve the permissions using Get-Acl, store them in the $permissions object, and set them using Set-Acl on the newly created D:\Test2 folder.

C:\Users\HarmVeenstra> (Get-Acl -Path D:\Test1).Access

FileSystemRights  : ReadAndExecute, Synchronize
AccessControlType : Allow
IdentityReference : Everyone
IsInherited       : False
InheritanceFlags  : ContainerInherit, ObjectInherit
PropagationFlags  : None

FileSystemRights  : FullControl
AccessControlType : Allow
IdentityReference : NT AUTHORITY\SYSTEM
IsInherited       : False
InheritanceFlags  : ContainerInherit, ObjectInherit
PropagationFlags  : None

FileSystemRights  : FullControl
AccessControlType : Allow
IdentityReference : BUILTIN\Administrators
IsInherited       : False
InheritanceFlags  : ContainerInherit, ObjectInherit
PropagationFlags  : None


C:\Users\HarmVeenstra> (Get-Acl -Path D:\Test2).Access

FileSystemRights  : FullControl
AccessControlType : Allow
IdentityReference : Everyone
IsInherited       : True
InheritanceFlags  : ContainerInherit, ObjectInherit
PropagationFlags  : None


C:\Users\HarmVeenstra> $permissions=Get-Acl d:\Test1
C:\Users\HarmVeenstra> Set-Acl -Path D:\Test2\ -AclObject $permissions


C:\Users\HarmVeenstra> (Get-Acl -Path D:\Test2).Access

FileSystemRights  : ReadAndExecute, Synchronize
AccessControlType : Allow
IdentityReference : Everyone
IsInherited       : False
InheritanceFlags  : ContainerInherit, ObjectInherit
PropagationFlags  : None

FileSystemRights  : FullControl
AccessControlType : Allow
IdentityReference : NT AUTHORITY\SYSTEM
IsInherited       : False
InheritanceFlags  : ContainerInherit, ObjectInherit
PropagationFlags  : None

FileSystemRights  : FullControl
AccessControlType : Allow
IdentityReference : BUILTIN\Administrators
IsInherited       : False
InheritanceFlags  : ContainerInherit, ObjectInherit
PropagationFlags  : None

More (advanced) examples can be found here.

NTFSSecurity PowerShell module

You can also use the NTFSSecurity module (Install it using Install-Module -Name NTFSSecurity). This module is made and maintained by Raimund Andrée  (https://github.com/raandree). This module contains the following cmdlets that you can use to view and set NTFS permissions.

Note: The module has not been updated in years, it still works but no bugfixes/improvements

Add-NTFSAccess
Add-NTFSAudit
Clear-NTFSAccess
Clear-NTFSAudit
Copy-Item2
Disable-NTFSAccessInheritance
Disable-NTFSAuditInheritance
Disable-Privileges
Enable-NTFSAccessInheritance
Enable-NTFSAuditInheritance
Enable-Privileges
Get-ChildItem2
Get-DiskSpace
Get-FileHash2
Get-Item2
Get-NTFSAccess
Get-NTFSAudit
Get-NTFSEffectiveAccess
Get-NTFSHardLink
Get-NTFSInheritance
Get-NTFSOrphanedAccess
Get-NTFSOrphanedAudit
Get-NTFSOwner
Get-NTFSSecurityDescriptor
Get-NTFSSimpleAccess
Get-Privileges
Move-Item2
New-NTFSHardLink
New-NTFSSymbolicLink
Remove-Item2
Remove-NTFSAccess
Remove-NTFSAudit
Set-NTFSInheritance
Set-NTFSOwner
Set-NTFSSecurityDescriptor
Test-Path2

To show the permissions of a file or folder, you can use it like the example below:

C:\Users\HarmVeenstra> Get-NTFSAccess -Path c:\windows | Format-Table -AutoSize

    Path: c:\windows (Inheritance disabled)


Account                                                           Access Rights               Applies to             Type  IsInherited InheritedFrom
-------                                                           -------------               ----------             ----  ----------- -------------
CREATOR OWNER                                                     GenericAll                  SubfoldersAndFilesOnly Allow False
NT AUTHORITY\SYSTEM                                               GenericAll                  SubfoldersAndFilesOnly Allow False
NT AUTHORITY\SYSTEM                                               Modify, Synchronize         ThisFolderOnly         Allow False
BUILTIN\Administrators                                            GenericAll                  SubfoldersAndFilesOnly Allow False
BUILTIN\Administrators                                            Modify, Synchronize         ThisFolderOnly         Allow False
BUILTIN\Users                                                     GenericExecute, GenericRead SubfoldersAndFilesOnly Allow False
BUILTIN\Users                                                     ReadAndExecute, Synchronize ThisFolderOnly         Allow False
NT SERVICE\TrustedInstaller                                       GenericAll                  SubfoldersOnly         Allow False
NT SERVICE\TrustedInstaller                                       FullControl                 ThisFolderOnly         Allow False
APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES            ReadAndExecute, Synchronize ThisFolderOnly         Allow False
APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES            GenericExecute, GenericRead SubfoldersAndFilesOnly Allow False
APPLICATION PACKAGE AUTHORITY\ALL RESTRICTED APPLICATION PACKAGES ReadAndExecute, Synchronize ThisFolderOnly         Allow False
APPLICATION PACKAGE AUTHORITY\ALL RESTRICTED APPLICATION PACKAGES GenericExecute, GenericRead SubfoldersAndFilesOnly Allow False

To set the permissions on a file or folder, you can use it like the example below: (Same as my Set-Acl example, copy NTFS permissions in an object and set it on the desired file or folder.

Note: Set-ACL copies the Inheritance flag by default. With the NTFSSecurity cmdlet, you will need to remove the Inheritance Flag first if needed (As I also did in the example below)

C:\Users\HarmVeenstra> Get-NTFSAccess -Path D:\Test1

    Path: D:\Test1 (Inheritance disabled)


Account                             Access Rights                                          Applies to                Type                                                   IsInherited                                           InheritedFrom
-------                             -------------                                          ----------                ----                                                   -----------                                           -------------
Everyone                            ReadAndExecute, Synchronize                            ThisFolderSubfoldersAndF… Allow                                                  False
NT AUTHORITY\SYSTEM                 FullControl                                            ThisFolderSubfoldersAndF… Allow                                                  False
BUILTIN\Administrators              FullControl                                            ThisFolderSubfoldersAndF… Allow                                                  False

C:\Users\HarmVeenstra> Get-NTFSAccess -Path D:\Test2

    Path: D:\Test2 (Inheritance enabled)


Account                             Access Rights                                          Applies to                Type                                                   IsInherited                                           InheritedFrom
-------                             -------------                                          ----------                ----                                                   -----------                                           -------------
Everyone                            FullControl                                            ThisFolderSubfoldersAndF… Allow                                                  True                                                  D:

C:\Users\HarmVeenstra> Disable-NTFSAccessInheritance d:\Test2
C:\Users\HarmVeenstra> Get-NTFSAccess -Path d:\test1 | Add-NTFSAccess D:\Test2


C:\Users\HarmVeenstra> Get-NTFSAccess -Path d:\Test2

    Path: d:\Test2 (Inheritance disabled)


Account                             Access Rights                                          Applies to                Type                                                   IsInherited                                           InheritedFrom
-------                             -------------                                          ----------                ----                                                   -----------                                           -------------
Everyone                            FullControl                                            ThisFolderSubfoldersAndF… Allow                                                  False
NT AUTHORITY\SYSTEM                 FullControl                                            ThisFolderSubfoldersAndF… Allow                                                  False
BUILTIN\Administrators              FullControl                                            ThisFolderSubfoldersAndF… Allow                                                  False

There is a site with good documentation about all the cmdlets of the NTFSecurity module, with excellent examples and detailed instructions. Go and check that out. I think the NTFSSecurity module is the thing you should use when setting (automated) permissions. More flexible than Get-Acl/Set-Acl IMHO 🙂

7 thoughts on “Configuring NTFS permissions using PowerShell

  1. Thanks for this. I did a terabytes of filesystem permissions work last year as part of an enterprise divesture migration and found icacls is orders of magnitude faster than get-acl and set-acl. The pattern we used was to export the source permissions to a file with icacl, munge the file, and then import it on the target. It was crazy fast.

  2. Any idea, how i can uncheck the „delete“ and check the box „delete only lower folders and Files“ in the advanced permissions?

    • “Allow on Subfolders and files only with Read&Execute/List Folder Contents/Read/Only apply these permissions on objects and/or containers within this container” rights?

  3. Very very underrated PS Module. I use this almost daily has a system admin, but I did not know about “Note: Set-ACL copies the Inheritance flag by default. With the NTFSSecurity cmdlet, you will need to remove the Inheritance Flag first if needed (As I also did in the example below)”.
    That’s some good info, most of the time I’m using the module to GET info on FileShares.

    There are some really good PS scripts that I use made by others as well.

    Great script, I use this when I’m wanting to audit a fileshare and see if permissions need to be set differently or AD groups cleaned up on the ACL’s.
    https://github.com/seyo-IV/PowerShell/blob/master/Get-Effective-Permissions-EXCEL.ps1

    Good article for the ntfs module.
    https://zamarax.com/2020/07/01/how-to-manage-ntfs-permissions-with-powershell/

    This is a work in progress, but I get sick of making AD groups for FileShares, so wanting to make a script that would make it easier for me.
    Any feedback would be appreciated!!

    “`ps
    Function Create-NewFolderWithGroups {
    [CmdletBinding()]
    Param (
    [Parameter(Mandatory = $true)]
    [String]$FolderPath,

    [Parameter(Mandatory = $true)]
    [String]$FolderName
    )

    # Import the Active Directory module
    Import-Module ActiveDirectory

    # Import the NTFSSecurity module
    Import-Module NTFSSecurity

    # Combine the folder path and name to create the full folder path
    $newFolderFull = Join-Path $FolderPath $FolderName

    # Display the new folder path
    Write-Output “New Folder will be: $newFolderFull”

    # Prompt for confirmation
    $confirm = Read-Host “Confirm? Y/N”
    if ($confirm -ne “y”) {
    # End the function if confirmation is not “y”
    return
    }

    # Create AD Groups
    $groupNameRW = “fs_$FolderName_RW”
    $groupNameR = “fs_$FolderName_RO”

    # Create the Read-Write group
    New-ADGroup -Name $groupNameRW -SamAccountName $groupNameRW -GroupScope Universal -GroupCategory Security -Path “OU=NTFS Groups,DC=TR12R,DC=local”

    $confirmReadOnly = Read-Host “Is a Read-Only Group Needed? Y/N”

    if ($confirmReadOnly -eq “y”) {
    # Create the Read-Only group if needed
    New-ADGroup -Name $groupNameR -SamAccountName $groupNameR -GroupScope Universal -GroupCategory Security -Path “OU=NTFS Groups,DC=TR12R,DC=local”
    }

    # Add a delay to allow time for group replication
    Start-Sleep -Seconds 15

    # Create the folder
    Write-Output “Add Folder..”
    New-Item $newFolderFull -ItemType Directory

    # Set rights and access control settings using NTFSSecurity module
    $readOnly = “ReadAndExecute”
    $readWrite = “Modify”
    $userRW = “DOMAIN\$groupNameRW”
    $userR = “DOMAIN\$groupNameR”

    # Grant Read-Write access to the Read-Write group
    Add-NTFSAccess -Path $newFolderFull -Account $userRW -AccessRights $readWrite -AppliesTo ThisFolderSubfoldersAndFiles

    # Grant Read-Only access to the Read-Only group
    Add-NTFSAccess -Path $newFolderFull -Account $userR -AccessRights $readOnly -AppliesTo ThisFolderSubfoldersAndFiles
    }

    # Usage example
    Create-NewFolderWithGroups -FolderPath “C:\Path\To\Folder” -FolderName “NewFolder”
    “`

    • Justin,

      I updated your script a little 😉 Renamed it to New-FolderWithGroups so that the naming is an approved verb and addedsome error handling and status output:

      Function New-FolderWithGroups {
      [CmdletBinding()]
      Param (
      [Parameter(Mandatory = $true)]
      [String]$FolderPath,

          [Parameter(Mandatory = $true)]
          [String]$FolderName
      )
      
      # Set variables
      $Domain = 'Test'
      $OU = 'OU=Groups,OU=Corp,DC=test,DC=local'
      
      # Import the Active Directory module
      try {
          Import-Module ActiveDirectory -ErrorAction Stop
          Write-Output ("Imported the ActiveDirectory Module")
      }
      catch {
          Write-Warning ("ActiveDirectory module not found, installing now...")
          try {
              Install-WindowsFeature RSAT-AD-PowerShell -ErrorAction Stop
              Import-Module ActiveDirectory -ErrorAction Stop
              Write-Output ("Imported the ActiveDirectory Module")
          }
          catch {
              Write-Warning ("Could not install Active Directory Module, exiting...")
              return
          }
      }
      
      # Import the NTFSSecurity module
      try {
          Import-Module NTFSSecurity -ErrorAction Stop
          Write-Output ("Imported the NTFSSecurity Module")
      }
      catch {
          Write-Warning ("NTFSSecurity module not found, installing now...")
          try {
              Install-Module NTFSSecurity -Force:$true -ErrorAction Stop
              Import-Module NTFSSecurity -ErrorAction Stop
              Write-Output ("Imported the NTFSSecurity Module")
          }
          catch {
              Write-Warning ("Could not install NTFSSecurityModule, exiting...")
              return
          }
      }
      
      # Combine the folder path and name to create the full folder path
      $newFolderFull = Join-Path $FolderPath $FolderName
      
      # Display the new folder path
      Write-Output "New Folder will be: $($newFolderFull)"
      
      # Prompt for confirmation
      $confirm = Read-Host 'Confirm? Y/N'
      if ($confirm.ToLower() -ne 'y') {
          # End the function if confirmation is not “y”
          Write-Warning ("Incorrect input, exiting...")
          return
      }
      
      # Create AD Groups
      $groupNameRW = "fs_$($FolderName)_RW"
      $groupNameR = "fs_$($FolderName)_RO"
      
      # Create the Read-Write group
      try { 
          New-ADGroup -Name $groupNameRW -SamAccountName $groupNameRW -GroupScope Universal -GroupCategory Security -Path $OU -ErrorAction Stop
          Write-Output ("Created {0}" -f $groupNameRW)
      }
      catch {
          Write-Warning ("Error creating {0}, exiting..." -f $groupNameRW)
      }
      
      $confirmReadOnly = Read-Host "Is a Read-Only Group Needed? Y/N"
      
      if ($confirmReadOnly.ToLower() -eq 'y') {
          # Create the Read-Only group if needed
          try {
              New-ADGroup -Name $groupNameR -SamAccountName $groupNameR -GroupScope Universal -GroupCategory Security -Path $OU -ErrorAction Stop
              Write-Output ("Created {0}" -f $groupNameR)
          }
          catch {
              Write-Warning ("Error creating {0}, exiting..." -f $groupNameR)
          }
      }
      
      # Add a delay to allow time for group replication
      Write-Output ("Waiting for 15 seconds to allow group replication")
      Start-Sleep -Seconds 15
      
      # Create the folder
      try {
          New-Item $newFolderFull -ItemType Directory -ErrorAction Stop | Out-Null
          Write-Output ("Created {0}" -f $newFolderFull)
      }
      catch {
          Write-Warning ("Could not create {0} or already exists, exiting..." -f $newFolderFull)
          return
      }
      
      # Set rights and access control settings using NTFSSecurity module
      $readOnly = "ReadAndExecute"
      $readWrite = "Modify"
      $userRW = "$($Domain)\$($groupNameRW)"
      $userR = "$($Domain)\$($groupNameR)"
      
      # Grant Read-Write access to the Read-Write group
      try {
          Add-NTFSAccess -Path $newFolderFull -Account $userRW -AccessRights $readWrite -AppliesTo ThisFolderSubfoldersAndFiles -ErrorAction Stop
          Write-Output ("Added ReadWrite rights to {0}" -f $newFolderFull)
      }
      catch {
          Write-Warning ("Error setting rights on {0} for {1}, exiting..." -f $newFolderFull, $userRW)
          return
      }
      
      # Grant Read-Only access to the Read-Only group
      try {
          Add-NTFSAccess -Path $newFolderFull -Account $userR -AccessRights $readOnly -AppliesTo ThisFolderSubfoldersAndFiles -ErrorAction Stop
          Write-Output ("Added Read rights to {0}" -f $newFolderFull)
      }
      catch {
          Write-Warning ("Error setting rights on {0} for {1}, exiting..." -f $newFolderFull, $userR)
          return
      }
      

      }

      Usage example

      #New-FolderWithGroups -FolderPath ‘C:\Path\To\Folder’ -FolderName ‘NewFolder’

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.