PowerShell Setting advanced NTFS permissions
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 flagInheritOnly
exempts the current object from receiving the ACE. The flagNoPropagateInherit
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
![DarkLite1](https://i.stack.imgur.com/cFWku.jpg?s=256&g=1)
DarkLite1
Master Bruce... why do we fall? So we can learn to stand up again.
Updated on July 12, 2022Comments
-
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 forThis folder only
and another one is for theSubfolders 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
- Everything is on except for : Full control, Write attributes, Write extended attributes, Delete, Change permissions and Take ownership.
- 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 over 9 yearsThank 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 over 9 yearsSlight 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 over 9 years@RohnEdwards Indeed. Thanks for the correction. Fixed.