2021 Dec 21

Check Sensitive Groups Membership

In the world of audit and escalated accounts, you will need to have an overview of the privileged groups and members there, this could be a regulator requirement, too. This small script will show how to do this, and have just one file per check with all the groups you need. Of course, it could be applied to any set of groups, no need to limit yourself.

We will use the text file with the list of groups in it, as in our example we have the groups in several OUs and for different purposes, so we can have either a list of the groups in the script itself (which could be harder to maintain and to overview), or we can have a file with that list. The groups are put one per line, and it is more visible overall. In this example, our text file is located in the same directory as the script (LIne 5), so it is possible to use the .\ notation, but the absolute path might be more reasonable in general. Just to note, if you want to replace the file with the groups in the script itself, you can put the in a form of $Group=("Group 1", "Group 2", "Group 3", ..., "Group N"). $Day = Get-Date -uformat "%Y-%m-%d"
$File = "Admin_" +$Day + ".csv"
$Path="\\Path\to\the\$File"

$Groups = (Get-Content .\ADGroups.txt)$Table=@()
$Record = [ordered]@{"Group" = ""; "SamAccountName" = ""; "Name" = ""; "Enabled" = ""} Foreach ($Group in $Groups) {$Members = Get-ADGroupMember -identity $Group -recursive | ? {$_.objectclass -eq 'user'} | Get-ADUser
foreach ($Member in$Members) {
$Record."Group" =$Group
$Record."Name" =$Member.Name
$Record."SamAccountName" =$Member.samaccountname
$Record."Enabled" =$Member.enabled
$objRecord = New-Object PSObject -property$Record
$Table +=$objrecord
}
}

$Table | export-csv$Path -NoTypeInformation

On the first lines, we create a file name to be saved in the desired location. I am using the file server, but it's up to you where to have it - later on you can make the scheduled task and just check for the files afterwards.

Then, we create a few objects: an empty array $Table and an empty hashtable with the ordered keys$Record, It will ensure we will have the result we really want to see. In my particular case, I wanted to see the group name on the first place, then the sAMAccountName of the user, display name, and finally, if the user is enabled or not.

Then, we go through each line of the file (or through each object in the array/OU), and verify that we are checking for the users for sure, and do that recursively, so the nested groups (when the user is a member of Group A, and not Group B directly, but is still a member of a Group B, as Group A is a member of it) are also included in the output (Line 10). We also create a separate array of the user in each group, and call it $Members, so we can check each member of it individually now. We ensure to get all the required information we need by adding Get-ADUser in the end, as we apply it to the output of the Get-ADGroupMember. Then, we create another loop to check for each member of each group. We assign the attributes of the users we are interested in to the values of our hashtable, and in the end, we create a temporary object$objRecord, so we can add its content based on the input above to the array $Table. In the end, when all loops are stopped and proceeded, we export the whole "table" to the .CSV file, where$Path is specified on lines 1-3, and -NoTypeInformation will remove some irrelevant "rubbish" data.

You will get something like this (I've hidden some rows for the demonstration purpose: