In PowerShell, I can define a .NET Directory Security object and give it different rules:

$acl = New-Object System.Security.AccessControl.DirectorySecurity
$acl.AddAccessRule($rule_a)
$acl.AddAccessRule($rule_b)
...

Now depending of the Access Rule Protection settings, those settings in the .Net Directory Security object $acl could be inherited to the child items of the folder or not. The inheritance rules can be changed like this:

$acl.SetAccessRuleProtection($true, $true) # could also be ($false, $false) or a different setting...

After $acl has been defined as needed, it gets applied to a folder:

Set-Acl $folder $acl

Now I want to test if the settings in $acl have been applied correctly to $folder. My expected settings are simply what I defined before in $acl:

$expectedAclSettings = $acl

I can get the Access Control Lists of a folder and all its child items recursively like this to get the actual acl settings:

$folderAndChildren = @(Get-Item -Path $folder) + @(Get-ChildItem -Path $folder -Recurse)
$actualAclSettings = ($folderAndChildren | Get-Acl)

Now my question is:

Is there an easy way (like a one-liner) to compare $expectedAclSettings and $actualAclSettings and test if the settings have been applied correctly for all files in $actualAclSettings?

Or do I have to check in $expectedAclSettings if the inheritance rules are preserved/protected or not, and depending on that, write a more complex test function that f.e. iterates over each path in $actualAclSettings, and checks based on the depth of the current file/folder and the inheritance settings that acl values should have been applied or not? Are there other approaches to test the acl values?

1

There are 1 best solutions below

0
On

I did not find a solution to compare the access control lists in a one-liner. The solution I used to compare the permissions and have the differences in a readable output, is to "hash" the permissions to a string, and recursively compare if the permissions. I will post the code I used below, maybe it helps somebody. If anyone has a better answer, feel free to post it, and I might update my code.


I used the following function Compare-AccessRules to compare access rules. It expects two objects of type "Access", these are returned from Get-ACL, f.e.:

$actualAclSettings = Get-Acl -Path $Path
$diff = Compare-AccessRules $actualAclSettings.Access $aexpectedAclSettings.Access

Here is the function:

function Compare-AccessRules {
  param (
    $ActualAccessRules,
    $ExpectedAccessRules
  )

  $actualAccessRuleStrings = foreach ($rule in $ActualAccessRules) {
    Convert-AccessRuleToString -AccessRule $rule
  }

  $expectedAccessRuleStrings = foreach ($rule in $ExpectedAccessRules) {
    Convert-AccessRuleToString -AccessRule $rule
  }

  return Compare-Object $expectedAccessRuleStrings $actualAccessRuleStrings
}

Inside this function, access rules are "hashed" with the Convert-AccessRuleToString function:

function Convert-AccessRuleToString {
  param(
    $AccessRule
  )

  return "IdentityReference : $($AccessRule.IdentityReference)`n" +
  "FileSystemRights  : $($AccessRule.FileSystemRights)`n" +
  "AccessControlType : $($AccessRule.AccessControlType)`n" +
  "IsInherited       : $($AccessRule.IsInherited)`n" + 
  "InheritanceFlags  : $($AccessRule.InheritanceFlags)`n" + 
  "PropagationFlags  : $($AccessRule.PropagationFlags)"
}