9

I have a directory which I want to go through recursively and set permissions on all the folders. So the order of operations should be:

  1. Remove all ACL from folder
  2. Add ACL to folder
  3. Set ACL

I tried the below code, but I am getting the error

Cannot set the ACL because the method that it needs to invoke, SetSecurityDescriptor, does not exist.

foreach ($folder in Get-ChildItem -Path c:\perms -Recurse -Directory) {
    $AccessRule = New-Object System.Security.Accesscontrol.FileSystemAccessRule ("user", "FullControl", "ContainerInherit,ObjectInherit", "InheritOnly", "Allow")
    $acl = Get-Acl $folder
    $acl.SetAcccessRule($AccessRule)
    Set-Acl -Path $folder.FullName -AclObject $acl
}

I got rid of the error message, and it added the ACL, but I want to basically remove all ACLs from the folder and add new ones.

I updated my script to look like this:

$acl = Get-Acl -Path "c:\perms"
$acl.SetAccessRuleProtection($true,$false)
$acl.Access | ForEach-Object { $acl.RemoveAccessRule($_) | Out-Null }
$ace = New-Object System.Security.Accesscontrol.FileSystemAccessRule ("user", "FullControl", "ContainerInherit,ObjectInherit", "InheritOnly", "Allow")
$acl.AddAccessRule($ace)
Set-Acl -Path "c:\perms" -AclObject $acl

If I want to add multiple $ace, is it just a matter of declaring $ace2, $ace3 and then calling $acl.AddAccessRule($ace2), $acl.AddAccessRule($ace3).

Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
xaisoft
  • 3,343
  • 8
  • 44
  • 72
  • *If I want to add multiple `$ace`, is it just a matter of ...* Please *test* simple stuff like that yourself before posting. Adding this update to your question probably took you longer than it would have taken to verify it by running a quick test. I'm not going to spoon-feed you a solution. – Ansgar Wiechers Jan 23 '18 at 23:45

1 Answers1

8

Use SetAccessRuleProtection() to disable inheritance and remove inherited ACEs:

$acl.SetAccessRuleProtection($true, $false)

Use RemoveAccessRule() to remove existing (non-inherited) ACEs:

$acl.Access | ForEach-Object { $acl.RemoveAccessRule($_) | Out-Null }

Use AddAccessRule() to add new ACEs:

$ace = New-Object Security.AccessControl.FileSystemAccessRule "user", ...
$acl.AddAccessRule($ace)
...

Do this only for the topmost folder. Leave inheritance enabled everywhere below, so your changes are propagated automatically.

Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
  • Hi, I am a bit confused on where I should put $acl.SetAccessRuleProtection. I get the $acl in the loop, but you said to only apply it to the topmost folder. – xaisoft Jan 23 '18 at 21:05
  • 1
    Do not recurse at all. Let inheritance take care of permission propagation. – Ansgar Wiechers Jan 23 '18 at 21:08
  • So by setting permissions on the root folder, it will automatically set permissions on all sub folders (even sub/sub... folders)? – xaisoft Jan 23 '18 at 21:12
  • It should unless someone already tampered with the inheritance settings there. Should that be the case use `icacls` for resetting the permissions in the folder subtree (`icacls "C:\perms" /reset /t /c`), then re-apply your permission changes to `c:\perms`. – Ansgar Wiechers Jan 23 '18 at 21:18
  • Ok I got the permissions to be removed, I updated my post about adding multiple ace's – xaisoft Jan 23 '18 at 21:37
  • I also noticed that when I add the user, it checks `Special Permissions` and not the other ones (Full Control, Modify....) – xaisoft Jan 23 '18 at 21:43
  • Ok changing the InheritanceFlags property to "None" fixed that issue with Special Permissions – xaisoft Jan 23 '18 at 21:49
  • @xaisoft For information about the effect of inheritance and propagation flags [see here](https://stackoverflow.com/a/32382956/1630171). – Ansgar Wiechers Jan 23 '18 at 23:41
  • Good answer but it only works when you are allowed to read the acls. If you have special folders where even administrators have no permission (e.g. Roaming User Profil Folders) then this solution does not work. – M46 Feb 25 '21 at 15:20