PowerShell Setting advanced NTFS permissions

76,513

Solution 1

Object access permissions in Windows are controlled via Access Control Lists (ACL), which basically consist of a list of Access Control Entries (ACE). Each ACE is a set of attributes that controls whether access is granted or denied, who the ACE applies to, if the ACE was inherited from a parent object, and whether it should be inherited by child objects.

If you take a look at the documentation of the FileSystemAccessRule class, you'll see that the "full" constructor takes 5 parameters:

  • IdentityReference/String: An object or string that identifies the trustee (user, group, computer, ...) to whom the ACE applies.
  • FileSystemRights: The actual permissions to be granted or denied.
  • InheritanceFlags: Flags to control which object types inherit permissions from this object (containers, leaf objects, or none).
  • PropagationFlags: Flags to control propagation of permissions. The flag InheritOnly exempts the current object from receiving the ACE. The flag NoPropagateInherit restricts inheritance to immediate child objects.
  • AccessControlType: The type of the ACE (allow or deny).

Now, if you want to assign multiple access rights to a given trustee, you can either do that with individual ACEs:

$acl  = Get-Acl $path
$ace1 = New-Object Security.AccessControl.FileSystemAccessRule 'DOMAIN\user',
        'ListDirectory', 'ContainerInherit, ObjectInherit', 'InheritOnly',
        'Allow'
$acl.AddAccessRule($ace1)
$ace2 = New-Object Security.AccessControl.FileSystemAccessRule 'DOMAIN\user',
        'ReadAttributes', 'ContainerInherit, ObjectInherit', 'InheritOnly',
        'Allow'
$acl.AddAccessRule($ace2)
...

Or by providing the permissions as a comma-separated string:

$acl = Get-Acl $path
$ace = New-Object Security.AccessControl.FileSystemAccessRule 'DOMAIN\user',
       'ListDirectory, ReadAttributes, ...', 'ContainerInherit,  ObjectInherit',
       'InheritOnly', 'Allow'
$acl.AddAccessRule($ace)

Note, however, that you cannot grant and deny permissions with the same ACE. If you want to deny specific access rights you need to do it with a separate ACE:

$acl  = Get-Acl $path
$ace1 = New-Object Security.AccessControl.FileSystemAccessRule 'DOMAIN\user',
        'Modify', 'ContainerInherit, ObjectInherit', 'InheritOnly',
        'Allow'
$acl.AddAccessRule($ace1)
$ace2 = New-Object Security.AccessControl.FileSystemAccessRule 'DOMAIN\user',
        'CreateDirectories', 'ContainerInherit, ObjectInherit', 'InheritOnly',
        'Deny'
$acl.AddAccessRule($ace2)
...

Note also, that explicit permissions take precedence over inherited permissions, and Deny takes precedence over Allow.

Solution 2

You know how it goes when you're fighting world problems. The moment you post the question, you find the answer 5 minutes later...

Thanks to the answer of Frode F. on another question, I found the solution to my own problem. I had to copy the output of the line FileSystemRights in $Correct.Access and paste it in an Array as you can see below:

 $rule = New-Object System.Security.AccessControl.FileSystemAccessRule("$ADobject", @("CreateFiles", "AppendData", "DeleteSubdirectoriesAndFiles"," ReadAndExecute", "Synchronize"), "None", "InheritOnly", "Allow") # This folder only   
 $acl.AddAccessRule($rule)
 $rule = New-Object System.Security.AccessControl.FileSystemAccessRule("$ADobject", @("DeleteSubdirectoriesAndFiles", "Modify", "Synchronize"), "ContainerInherit, ObjectInherit", "InheritOnly", "Allow") # Subfolders and files only
Share:
76,513
DarkLite1
Author by

DarkLite1

Master Bruce... why do we fall? So we can learn to stand up again.

Updated on July 12, 2022

Comments

  • DarkLite1
    DarkLite1 almost 2 years

    I'm trying to apply NTFS permissions that are defined in the 'Advanced' tab of the Windows security settings. One ACL $Rule is for This folder only and another one is for the Subfolders and files only.

    The permissions are heavily modified as you can see below:

    (Get-Acl 'L:\Test\Beez\RAPJOUR\Appels List\Correct').Access
    
    FileSystemRights  : FullControl
    AccessControlType : Allow
    IdentityReference : BUILTIN\Administrators
    IsInherited       : False
    InheritanceFlags  : ContainerInherit, ObjectInherit
    PropagationFlags  : None
    
    FileSystemRights  : CreateFiles, AppendData, DeleteSubdirectoriesAndFiles, ReadAndExecute, Synchronize
    AccessControlType : Allow
    IdentityReference : Domain\Dirk
    IsInherited       : False
    InheritanceFlags  : None
    PropagationFlags  : None
    
    FileSystemRights  : DeleteSubdirectoriesAndFiles, Modify, Synchronize
    AccessControlType : Allow
    IdentityReference : Domain\Dirk
    IsInherited       : False
    InheritanceFlags  : ContainerInherit, ObjectInherit
    PropagationFlags  : InheritOnly
    

    This folder only

    • Everything is on except for : Full control, Write attributes, Write extended attributes, Delete, Change permissions and Take ownership.

    Subfolders and files only

    • Everything is on except for : Full control, Change permissions and Take ownership.

    This is a piece of the code I use to apply permissions. In this case it has to be defined in the part Change:

     $f = 'L:\Test\Beez\RAPJOUR\Appels List\Wrong'
     $ADobject = 'Domain\User'
     $acl = Get-Acl $f
    
     $Grant = 'Change'
        # Remove user/group first
        $rule = New-Object system.security.AccessControl.FileSystemAccessRule("$ADobject","Read",,,"Allow")
        $acl.RemoveAccessRuleAll($rule)
    
        # Add read permissions
        if ($Grant -eq 'ReadAndExecute') {
            $rule = New-Object System.Security.AccessControl.FileSystemAccessRule("$ADobject", "ReadAndExecute", "ContainerInherit, ObjectInherit", "None", "Allow")
        }
    
        if ($Grant -eq 'Change') {
            $rule = New-Object System.Security.AccessControl.FileSystemAccessRule("$ADobject", "Modify", "ContainerInherit, ObjectInherit", "Synchronize", "Allow  DeleteSubdirectoriesAndFiles")
            $acl.AddAccessRule($rule)
            $rule = New-Object System.Security.AccessControl.FileSystemAccessRule("$ADobject", "AppendData", "ContainerInherit, ObjectInherit", "ReadAndExecute","Synchronize", "Allow  CreateFiles","DeleteSubdirectoriesAndFiles")
        }
    
        if ($Grant -eq 'Modify') {
            $rule = New-Object System.Security.AccessControl.FileSystemAccessRule("$ADobject", "Modify", "ContainerInherit, ObjectInherit", "None", "Allow")
        }
    
        if ($Grant -eq 'FullControl') {
            $rule = New-Object System.Security.AccessControl.FileSystemAccessRule("$ADobject", "FullControl", "ContainerInherit, ObjectInherit", "None", "Allow")
        }
    
        if ($Grant -eq 'ListFolderContents') {
            $rule = New-Object System.Security.AccessControl.FileSystemAccessRule("$ADobject", "ReadAndExecute", "ContainerInherit", "None", "Allow")
        }
    
    $acl.AddAccessRule($rule)
    Set-Acl $f $acl
    

    I can't seem to get the syntax right.. Thank you for your help.

    Thanks to this post I've already found the part for:

    • 'Subfolders and files only': "ContainerInherit, ObjectInherit", "InheritOnly"
    • 'This folder only': "None", "InheritOnly"
  • DarkLite1
    DarkLite1 over 9 years
    Thank you for your help Ansgar. This means we don't need to put it in Array format, but it's also accepted as a string in the format 'Value1, Value2, Value3, ...'. That's good to know :)
  • Rohn Edwards
    Rohn Edwards over 9 years
    Slight correction: InheritanceFlags control which types of child objects will inherit the ACE (for the filesystem, these flags control the subfolders and/or files part of the 'Apply to:' drop down box in the screenshot). PropagationFlags control whether or not the ACE will apply to the object itself and/or whether or not the ACE will apply to grandchildren (for the filesystem, these flags control the 'This folder' part of the 'Apply to:' box, and/or the 'Apply these permissions to objects and/or containers within this container only' checkbox in the screenshot).
  • Ansgar Wiechers
    Ansgar Wiechers over 9 years
    @RohnEdwards Indeed. Thanks for the correction. Fixed.