PowerShell Tips: Who has Access To This Directory?

Here's a question many IT Administrators get from time to time:

"Can you tell me who has access to this directory?"

This question is being asked more often as many more devices are trying to gain access to the data you secure. While it is easy to see all the groups that have access just by right-clicking a directory and going to the Security tab, it is a challenge to view all the users who belong to those groups – especially those users listed inside nested groups.  I created this scripts, to be run alongside the ActiveDirectory PowerShell module, to read the Access Control List (ACL) on the directory.  An admin account is required to run the script in order to view the ACL.

Most of the tricky bits of this script contain comments in-line. Your input is welcome should a better method be available.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 #requires -Version 1 -Modules ActiveDirectory   #function to return the SamAccountNames of all the users in a group #if the group is empty, return the name of the group Function Get-NestedGroupMember {     param     (         [Parameter(Mandatory=$True,                 Position=1,         ValueFromPipeline=$True)]         [string]$Group     )     $Users = @(Get-ADGroupMember $group -recursive).SamAccountName     if ($Users) { return $Users }     else { return $Group } }   #function to enumerate types of access held by individuals to a directory Function Get-Access {     param     (         [Parameter(Mandatory=$True,                 Position=1,         ValueFromPipeline=$True)]         [string]$Dir     )          #record the current erroractionpreference so we can set it back later     $OldEAP = $ErrorActionPreference          #set erroracctionpreference to silently continue so we ignore errors from empty groups and weird broken ACLs     $ErrorActionPreference = 'silentlycontinue'          #get the full ACL of the directory from the parameter     $ACL = Get-Acl $Dir          #retrieve the Access attribute     $arrAccess = @($ACL.Access)          #separate the IdentityReference and FileSystemRights attributes from within the Access attribute     $arrIdentRef = $arrAccess | select-object IdentityReference, FileSystemRights          #for each item in the access attribute of the ACL,      #write the type of filesystemrights associated with the entry and get the recursive group membership     $arrIdentRef | % { Write-Output "ACCESS $($_.FileSystemRights) HELD BY: `r`n$(Get-NestedGroupMember $_.IdentityReference.Value.ToString().Split('\')[-1])"; Write-Output "`r`n`r`n" }          #set the erroractionpreference back to whatever it was before we started     $ErrorActionPreference = $OldEAP }   Get-Access '\\host\share\some folder'