Using Set-Acl and the FileSystemAccessRule.RemoveAccessRule method not working

Viewed 3659

Summary:

I'm trying to script removing the modify permission of a particular folder (or file) for the "NT AUTHORITY\Authenticated Users" group, across multiple machines (actually as part of a file deployment script). I have some code that attempts to do this, but it is not working as expected.

Context:

The script copies down a file structure locally, and a particular file (ideally the whole folder structure) needs to be made unmodifiable (by non-admins). Setting the read-only setting isn't sufficient, since it can be reverted by those with modify permissions to the file.

My attempt:

$folder = "C:\folder"
$file = "C:\folder\file.ext"

# Get the existing ACL
$acl = Get-Acl -Path $folder

# See what it looks like
$acl.Access | ft

# Target and remove the specific modify rule
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("NT AUTHORITY\Authenticated Users","Modify","Allow")
$acl.RemoveAccessRule($rule)

# Check that the modification to the PS object took
$acl.Access | ft

# Perform the modification
$acl | Set-Acl -Path $folder

# Check that the modification to the folder/file took
$acl = Get-Acl -Path $folder
$acl.Access | ft

My results:

The .RemoveAccessRule() call has no effect on the ACL (even though it returns True), as shown by the second $acl.Access | ft. As such, the Set-Acl call has no effect either. I suspect that perhaps I'm not targeting the rule I want correctly, and perhaps the .RemoveAccessRule() call is returning True just because there were technically no "failures". But that's just a shot in the dark.

Here is what the output of $acl.Access | ft looks like in all cases:

           FileSystemRights AccessControlType IdentityReference                IsInherited InheritanceFlags PropagationFlags
           ---------------- ----------------- -----------------                ----------- ---------------- ----------------
                FullControl             Allow BUILTIN\Administrators                  True             None             None
                FullControl             Allow NT AUTHORITY\SYSTEM                     True             None             None
        Modify, Synchronize             Allow NT AUTHORITY\Authenticated Users        True             None             None
ReadAndExecute, Synchronize             Allow BUILTIN\Users                           True             None             None

I just can't get rid of that Modify flag. I've also tried targeting the file directly (replacing references to $folder with $file in the above code), but the result is the same. I've also tried replacing NT AUTHORITY\Authenticated Users with just Authenticated Users, to no effect.

Question:

Presumably I'm just doing it wrong. I'm fluent in Powershell, but have no previous experience using it to configure NTFS permissions. Perhaps I need to target the desired rule differently, or perhaps I need to overwrite it with .SetAccessRule() instead somehow...

How can I achieve this with Powershell? Thanks for your time.

Update: also perhaps inheritance is an issue? I'm unsure how to deal with that.

Sources:

My environment:

  • Windows 10 x64 20H2
  • Powershell 5.1
  • In my testing, I'm running the code in an elevated Powershell console, as a user with local admin permissions. In practice the code will be run by MECM in the same script that copies the files down (presumably as SYSTEM or some such).
1 Answers

Turns out my problem was that the folder was inheriting the modify permission from C:\. Apparently modifying permissions when inheritance is enabled simply does nothing and throws no errors (>:/). The solution was to disable inheritance on the folder first (copying the existing permissions), and then the rest of the code works as expected.

In my case, simply removing all permissions for NT AUTHORITY\Authenticated Users entirely was sufficient (and easier than performing modifications on the existing permissions), since BUILTIN\Users still has read permissions.

# Get the existing ACL
$acl = Get-Acl -Path $item

# Disable inheritance (copying permissions), so the modifications will actually take
$acl.SetAccessRuleProtection($true,$true)

# Perform the modification
$acl | Set-Acl -Path $item

# Get the existing ACL again
$acl = Get-Acl -Path $item

# Target and remove all permission for "NT AUTHORITY\Authenticated Users"
$rules = $acl.Access | Where { $_.IdentityReference -eq $identity }
foreach($rule in $rules) {
    $acl.RemoveAccessRule($rule)
}

# Perform the modification
$acl | Set-Acl -Path $item
Related