The Get-Acl cmdlet can help us to obtain the access control list of a resource, for example a directory. With this information we can determine the permissions that a domain user or a security group has over a resource. Let’s check the help for this command:
Get-Acl
[[-Path] <String[]>]
[-Audit]
[-Filter <String>]
[-Include <String[]>]
[-Exclude <String[]>]
[<CommonParameters>]
The Get-Help shows three different sets of parameters for Get-Acl: by path, by object and by literal path. For the purpose of this article, we’re going to stick with the first one. Regarding this cmdlet, we’re going to use several properties of the resultant object: Access, IdentityReference and FileSystemRights. Access property is actually a collection of ACE objects that include IdentityReference and FileSystemRights.
Get-Acl is going to help us determine the permissions over a resource but what happens if we have a lot of subfolders in the parent-item? Chances are this will be the most common scenario in a corporate setting. Luckily for us, we can use Get-ChildItem to iterate through a folder and obtain the paths of its subfolders. The following is the sintaxis of Get-ChildItem:
Get-ChildItem
[[-Path] <string[]>]
[[-Filter] <string>]
[-Include <string[]>]
[-Exclude <string[]>]
[-Recurse]
[-Depth <uint32>]
[-Force]
[-Name]
[-Attributes <FlagsExpression[FileAttributes]>]
[-FollowSymlink]
[-Directory]
[-File]
[-Hidden]
[-ReadOnly]
[-System]
[<CommonParameters>]
This cmdlet has two sets of parameters. We’ll be using the first one. When calling it we’ll provide a value for the following parameters:
- -Path: here goes the shared folder path (\\winser2016\Apps)
- -Recurse: so we can obtain the information about the folder and its sub-folders.
- -Depth: specifies the depth of the recursion. In this case we are going to use 1 to include the first level of sub-folders.
- -Directory: to get a list of directories in the resulting object.
Having say all this, let’s dive in the script. For this case we’re going to work based on the following assumptions:
- We have an array with the names of the security groups or users we want to check against the resource in order to determine group or user permissions. Keep in mind this could also be a .csv file or similar.
- We have the path of a shared folder available in our domain network
- The shared folder has one or more subfolders.
Let’s declare our variables:
$groups = @(
"Administrators"
"Contractors"
"Students"
)
$folders = Get-ChildItem -Path "\\winser2016\Apps" -Recurse -Depth 1 -Directory
Next comes the fun part. We have an array with several groups and a folder with one or more subfolders. This means we have to check each group or user and then we have to check that against the folder to determine whether that domain user or security group has permissions. A FOR could be useful for this purpose, but since we have to iterate first by the groups or users and then by the folders, we need a nested for. In each iteration we need a variable for the domain user or security group and other for the shared folder.
Finally, an IF will allow us to check permissions and show a message in the terminal with the respective information. The final result will show us if a domain user or a security group has permissions over a resource with a result like “FullControl” or “Doesn’t have permissions” for a specific folder and user:
for($i=0; $i -lt $groups.Count; $i++)
{
for($j=0; $j -lt $folders.Count; $j++)
{
$groupsIN = $groups[$i]
$folderIN = $folders[$j].FullName
$permission = (Get-Acl $folderIN).Access | Where-Object{$_.IdentityReference -match $groupsIN} | Select IdentityReference,FileSystemRights
If ($permission)
{
$permission | ForEach-Object {Write-Host "$groupsIN $($_.IdentityReference) has '$($_.FileSystemRights)' permissions on directory $folderIN"}
}
Else
{
Write-Host "$groupsIN doesn't have any permission on $folderIN"
}
}
}