Compare group memberships against network share ACL's

Hi Everyone,

I am fairly new to PowerShell but so far I am loving it!

I am currently trying to put together a PowerShell script that will look at all ACL’s within all sub folders of a certain share or folder, then compare those ACL’s against a users group membership. So let’s say Tom says "I want Jerry to have the same access as I do, but ONLY for the CONSTRUCTION share and all of it’s sub folders, no other areas outside of the CONSTRUCTION folder. I would like to then see all the groups that Tom is a member of that reside within the CONSTRUCTION folder’s subs so then I can add Jerry to only those groups.

So far I have a few pieces that I think I need, but am not quite sure how to piece them together to give me what I need:

This will give me a list of the ACL’s, but only for this folder

This will give me a list of all sub folders within CONSTRUCTION

This will give me a list of all the groups Tom is a member of

Now for the hard part, which is to string it all together so I can say "Ok, THESE are the groups that I need to add Jerry to in order to have his access be the same as Tom’s within the CONSTRUCTION folder and its subs only (as some sub folders may have different acl’s than the parent and I want him added to those as well).

As I say, I am new to PowerShell so please let me know if I am way off base with these cmndlets. Any help that can be offered would be greatly appreciated. Thanks in advance!

So, given that you know who is on the ACL, and you know what the user belongs to, you need a list of groups that have access to which the user does not belong?

Wow the legendary Don Jones responded to me! Going to put this on my resume! :slight_smile:

That’s right, Don. I want to see which ACLS’s Tom is a member of that grant him access to \share\construction so I can then add Jerry to only those same ACL’s as I do not want to mirror his whole account, but essentially just the “construction” portion of the folder structure.

I just realized the cmdlets I posted did not show up. I figure the below cmndlets can help me, but I can’t figure out how to string them together for the output I need. I would appreciate any help or nudge in a certain direction as I am only on chapter 3 of “Learn Windows PowerShell in a month of lunches”!

Get-Acl -Path “\share\construction” | Format-List
This will give me a list of the ACL’s, but only for this folder

get-childitem -Path \share\construction -dir -Recurse | format-list -Property name
This will give me a list of all sub folders within CONSTRUCTION

Get-ADPrincipalGroupMembership Tom
This will give me a list of all the groups Tom is a member of

and possibly Get-ChildItem $path -recurse | Get-Acl ??

So, you want to compare two sets of things and see what’s present in one set, but not the other. Diff can do that easily, but you need to feed it two sets of simple strings. Set 1 are the groups on the ACL, set 2 are the groups the guy belongs to. Diff will show you what’s present in one list but not the other.

I will give that a shot. Thanks Don!

Well I am a bit further now.

But I don’t understand a few things. Why does “Get-ChildItem c:\test -dir -recurse | get-acl | Format-List” show me nice ACCESS groupings like:

PS C:\Users\Administrator> Get-ChildItem c:\test -dir -recurse | get-acl | Format-List
Path : Microsoft.PowerShell.Core\FileSystem::C:\test\test2
Owner : BUILTIN\Administrators
Group : CONTOSO\Domain Users
Access : CONTOSO\acl-test (CHANGE) Allow FullControl
NT AUTHORITY\SYSTEM Allow FullControl
BUILTIN\Administrators Allow FullControl
BUILTIN\Users Allow ReadAndExecute, Synchronize
BUILTIN\Users Allow AppendData
BUILTIN\Users Allow CreateFiles
CREATOR OWNER Allow 268435456

But when I try to format the list by the ACCESS property, it looks like the below with different groupings?

Get-ChildItem c:\test -dir -recurse | get-acl | Format-List -Property access

PS C:\Users\Administrator> Get-ChildItem c:\test -dir -recurse | get-acl | Format-List -Property access
Access : {System.Security.AccessControl.FileSystemAccessRule, System.Security.AccessControl.FileSystemAccessRule, System.Security.AccessControl.FileSystemAccessRule,
System.Security.AccessControl.FileSystemAccessRule…}

Access : {System.Security.AccessControl.FileSystemAccessRule, System.Security.AccessControl.FileSystemAccessRule, System.Security.AccessControl.FileSystemAccessRule,
System.Security.AccessControl.FileSystemAccessRule…}

My final piece of code is:

$A = Get-ChildItem c:\test -dir -recurse | get-acl | Format-List -Property access
$B = get-aduser chucktest -property memberof | Format-List -Property memberof
Compare-Object $A $B

Which gives me the below. Any ideas what I am doing wrong? I was hoping to have a readout that listed at least the “acl-test (CHANGE)” group but instead I have the below.

PS C:\Users\Administrator> $A = Get-ChildItem c:\test -dir -recurse | get-acl | Format-List -Property access
$B = get-aduser chucktest -property memberof | Format-List -Property memberof
Compare-Object $A $B

InputObject SideIndicator


Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData <=

Get rid of the Format-List command as this is only for making pretty on the screen. This converts your objects to format data and destroys any further use of them. Try Select-object instead to select the data you want eg

Get-ChildItem c:\test -dir -recurse | get-acl | Select-Object -Property access

I’ve actually managed to get pretty far. I run the below code:

$A = (get-childitem c:\test -dir -Recurse | get-acl).Access | Select-Object -ExpandProperty IdentityReference
$B = Get-ADPrincipalGroupMembership chucktest | Select-Object -ExpandProperty Name
Compare-Object $A $B

and get the below results:

InputObject SideIndicator


Domain Users =>
Users =>
acl-test (CHANGE) =>
acl-random (CHANGE) =>
CONTOSO\acl-random (CHANGE) <=
NT AUTHORITY\SYSTEM <=
BUILTIN\Administrators <=
BUILTIN\Users <=
BUILTIN\Users <=
BUILTIN\Users <=
CREATOR OWNER <=
CONTOSO\acl-test (CHANGE) <=
CONTOSO\acl-random (CHANGE) <=
NT AUTHORITY\SYSTEM <=
BUILTIN\Administrators <=
BUILTIN\Users <=
BUILTIN\Users <=
BUILTIN\Users <=
CREATOR OWNER

The issue is that the NAME property looks like "acl-test (CHANGE)" and the IdentityReference property adds the domain prefix to it so it looks like "CONTOSO\acl-test (CHANGE)" which causes PowerShell to see them as 2 different InputObjects. Any ideas on how to mitigate this so they use the same format?

Dang, the formatting on my last post got butchered somehow :frowning:

I’m going to try adding this:

function append-text {
process{
foreach-object {"Contoso" + $_ }
}
}

I ended up creating the below code and it works great. Thanks for the input!

$A = (get-childitem c:\test -dir -Recurse | get-acl).Access | Select-Object -ExpandProperty IdentityReference
$B = Get-ADPrincipalGroupMembership chucktest | Select-Object -ExpandProperty Name
$A = $A -creplace ‘(?s)^.*\’, ‘’
$A = $A | select -uniq

Compare-Object -ReferenceObject $A -DifferenceObject $B -IncludeEqual