Working with Access Rules in PowerShell

Yesterday I posted a function to create a summary report of ACL information using Windows PowerShell. I posted this in response to a question in the Ask Don and Jeff forum at I received an appreciative followup. The next step for this IT Pro it seems is to get a detailed list of the user based access control entries. Here is some of my response.

What you are experiencing is both the pleasure and pain of PowerShell. You can get to some amazing information, but sometimes it is buried deeply and takes a little work to unwind. Assuming you have my function loaded in your shell, try this on a small test folder.

dir c:\work -recurse | Where {$_.PSIsContainer} |
getaclinfo  | Where {$_.UserAcl -gt 0} |
ForEach {
 $_ | select -expand accessrules |
 where {$_.identityreference -notmatch "BUILTIN|NT AUTHORITY|EVERYONE|CREATOR OWNER"} |
 Select @{Name="Path";Expression={$Path}},IdentityReference,FileSystemRights

The first part command, DIR, gets goes through C:\Work recursively. These objects are piped to Where-Object which only keeps containers, i.e. folders. These folder objects are then piped to my Get-ACLInfo function. Its results are then piped to another Where-Object to filter out anything that doesn’t have a UserACL value greater than 0.

Now it gets a little trickier. I want to display both the file path and get at the underlying, nested access rules. So I’ll pipe each of my aclinfo objects to ForEach-Object. The first thing I do is save the path property from the incoming object. Then I pipe the object to Select-Object, expanding the Accessrules property. Remember, this is a collection of accessrule objects.

These in turn are filtered again to weed out the system accounts. You could also modify the filter to match say on a domain name or specific username. Finally, the filtered results are piped to Select-Object which shows the username, their rights, and a custom property that uses the saved Path variable.

Here’s what the end result looks like:

Path                     IdentityReference   FileSystemRights
—-                     —————–   —————-
C:\work\foo              SERENITY\fooby           FullControl
C:\work\foo\test         SERENITY\fooby           FullControl
C:\work\foo\test1        SERENITY\fooby           FullControl
C:\work\foo\test2        SERENITY\fooby           FullControl
C:\work\foo\test1\foo    SERENITY\fooby           FullControl
C:\work\foo\test1\foo2   SERENITY\fooby           FullControl
C:\work\foo\test1\foo3   SERENITY\fooby           FullControl
C:\work\foo\test2\bar    SERENITY\fooby           FullControl
C:\work\foo\test2\bar2   SERENITY\fooby           FullControl

In reality though, you could probably skip my function altogether since all you want are the underlying access rules. Here’s a variation that uses Get-ACL.

dir c:\work -recurse | Where {$_.PSIsContainer} | get-acl |
ForEach {
 $_ | select -expand access |
 where {$_.identityreference -notmatch "BUILTIN|NT AUTHORITY|EVERYONE|CREATOR OWNER"} |
 Select @{Name="Path";Expression={$Path}},IdentityReference,FileSystemRights

The logic is essentially the same except I threw in my regex code to make the folder path easier to read. Otherwise you get a path value like Microsoft.PowerShell.Core\FileSystem::C:\scripts\. I’ll admit this is a bit much to get your head around, especially for people still starting out in PowerShell. But I hope my logical explanation helps.

Post to Twitter Post to Plurk Post to Yahoo Buzz Post to Delicious Post to Digg Post to Facebook Post to FriendFeed Post to Google Buzz Post to Post to Reddit Post to Slashdot Post to StumbleUpon Post to Technorati