PowerShell Users and Membership – Part 2

Scenario:

PowerShell Users and Membership – Part 2

In part 1, I have shown you a simple script on how you are able to list all users or under a specific location along with their membership. The problem with that script is that you can only get the groups that the user is a direct member. If a user is a member of a group and that group is a member of another group, then due to inheritance the user is a member of that group also.

Changes:

Group Membership

I have made some changes in the script in order to get also the groups that the user is not directly member of. After the script will get the direct groups of the user, it will check each group if it is a member of another group. Those groups are added in the initial list of the groups. They are saved also in another array and the script will check each of the new groups if they are member of other groups. This process continues until no group is member of another group.

Code:

Foreach ($User in $Users){ $DirectGroups = Get-adprincipalgroupmembership $User.SamAccountName $UserName = $User.Name $AllGroups = @() $AllGroupsName = @() $UpperGroups = @() $GroupsTemp = @() $AllGroups += $DirectGroups.DistinguishedName $Groups = $DirectGroups.DistinguishedName do{ foreach ($Group in $Groups){ $UpperGroups = @() $UpperGroups = (Get-ADGroup $Group -Properties MemberOf).MemberOf if ($UpperGroups -ne ""){ $AllGroups += $UpperGroups $GroupsTemp += $UpperGroups } } $Groups = $GroupsTemp $GroupsTemp = @() }while ($Groups -ne "")

[adinserter name=”In Article”]

Groups value in email

In the previous script, it was not easy to distinguish one group from another as the whole list was part of the same cell in the email report. Now the groups will be separated by a comma ( , ) in email. It provides a better presentation than before.

Code:

foreach ($UserGroup in $AllGroups){ $GroupName = (Get-ADGroup -Identity $UserGroup).SamAccountName $AllGroupsName += $GroupName } $AllGroupsNameJoined = $AllGroupsName -join ' , ' $EmailTemp = @" <tr> <td class="colorm">$UserName</td> <td>$AllGroupsNameJoined</td> </tr> "@ $EmailResult = $EmailResult + "`r`n" + $EmailTemp

Email code

In the previous script, I was using back-tick to split the code for the email. As back-tick is difficult sometime to see it in a script and might be omitted, I have changed the code to use splatting in order to send the email reports with the results.

Code:

$EmailParams = @{ To = $To Subject = "Users and their Groups Report $(Get-Date -format dd/MM/yyyy)" Body = $Email BodyAsHtml = $True Priority = "High" UseSsl = $True Port = "587" SmtpServer = "smtp.office365.com" Credential = $EmailCredentials From = $From} send-mailmessage @EmailParams

Please note that the script takes a lot of time to run. This is related to the number of user and groups that you have in Active Directory. Making the script faster is one of the next improvements on the code.

You can download the script here or copy it from below. (Note that html code within the script might be wrong due to syntax highlighting.)

Hope you like it. If you have any questions or anything else please let me know in the comments below.

[adinserter name=”In Article”]

Related Links:

[adinserter name=”In Article”]

Solution / Script:

<# .SYNOPSIS Name: Get-UsersMembership.ps1 The purpose of this script is to retrieve all users and their current membership. .DESCRIPTION This is a script that will let you retrieve all users from Active Directory and then for each user it will get the membership including nested groups. At the end, it will provide the intended receipient/s with en email report with the results. If there is any error during run, a separate email will be send to the intended recipients including all the errors. .RELATED LINKS Home .NOTES Version: 1.1 Updated: 13-06-2018 - Now it retrieves nested groups also - Code improvements Release Date: 09-01-2018 Author: Stephanos Constantinou .EXAMPLE Run the Get-UserMembership script to retrieve the information. Get-UserMembership.ps1 #> import-module ActiveDirectory cd ad: $File = "C:\Scripts\Password.txt" $Key = (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) $EmailUser = "[email protected]" $Password = Get-Content $File | ConvertTo-SecureString -Key $Key $EmailCredentials = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $EmailUser,$Password $To = '[email protected]','[email protected]' $From = '[email protected]' $Users = Get-ADUser -Filter * -SearchBase "DC=domain,DC=com" $EmailResult = "" $ErrorEmailTemp = "" Foreach ($User in $Users){ $DirectGroups = Get-adprincipalgroupmembership $User.SamAccountName $UserName = $User.Name $AllGroups = @() $AllGroupsName = @() $UpperGroups = @() $GroupsTemp = @() $AllGroups += $DirectGroups.DistinguishedName $Groups = $DirectGroups.DistinguishedName do{ foreach ($Group in $Groups){ $UpperGroups = @() $UpperGroups = (Get-ADGroup $Group -Properties MemberOf).MemberOf if ($UpperGroups -ne ""){ $AllGroups += $UpperGroups $GroupsTemp += $UpperGroups } } $Groups = $GroupsTemp $GroupsTemp = @() }while ($Groups -ne "") $AllGroups = $AllGroups | select -Unique foreach ($UserGroup in $AllGroups){ $GroupName = (Get-ADGroup -Identity $UserGroup).SamAccountName $AllGroupsName += $GroupName } $AllGroupsNameJoined = $AllGroupsName -join ' , ' $EmailTemp = @" <tr> <td class="colorm">$UserName</td> <td>$AllGroupsNameJoined</td> </tr> "@ $EmailResult = $EmailResult + "`r`n" + $EmailTemp } $EmailUp = @" <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cstyle%3E%0Abody%20%7Bfont-family%3ASegoe%2C%20%22Segoe%20UI%22%2C%20%22DejaVu%20Sans%22%2C%20%22Trebuchet%20MS%22%2C%20Verdana%2C%20sans-serif%20!important%3B%20color%3A%23434242%3B%7D%0ATABLE%20%7Bfont-family%3ASegoe%2C%20%22Segoe%20UI%22%2C%20%22DejaVu%20Sans%22%2C%20%22Trebuchet%20MS%22%2C%20Verdana%2C%20sans-serif%20!important%3B%20border-width%3A%201px%3Bborder-style%3A%20solid%3Bborder-color%3A%20black%3Bborder-collapse%3A%20collapse%3B%7D%0ATR%20%7Bborder-width%3A%201px%3Bpadding%3A%2010px%3Bborder-style%3A%20solid%3Bborder-color%3A%20white%3B%20%7D%0ATD%20%7Bfont-family%3ASegoe%2C%20%22Segoe%20UI%22%2C%20%22DejaVu%20Sans%22%2C%20%22Trebuchet%20MS%22%2C%20Verdana%2C%20sans-serif%20!important%3B%20border-width%3A%201px%3Bpadding%3A%2010px%3Bborder-style%3A%20solid%3Bborder-color%3A%20white%3B%20background-color%3A%23C3DDDB%3B%7D%0A.colorm%20%7Bbackground-color%3A%2358A09E%3B%20color%3Awhite%3B%7D%0Ah3%20%7Bcolor%3A%23BD3337%20!important%3B%7D%0A%3C%2Fstyle%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="<style>" title="<style>" /> <body> <h3>Script has been completed successfully</h3> <h4>Users and their MemberOf Attribute have been exported.</h4> <table> <tr> <td class="colort">User</td> <td class="colort">Groups</td> </tr> "@ $EmailDown = @" </table> </body> "@ $Email = $EmailUp + $EmailResult + $EmailDown if ($EmailResult -ne ""){ $EmailParams = @{ To = $To Subject = "Users and their Groups Report $(Get-Date -format dd/MM/yyyy)" Body = $Email BodyAsHtml = $True Priority = "High" UseSsl = $True Port = "587" SmtpServer = "smtp.office365.com" Credential = $EmailCredentials From = $From} send-mailmessage @EmailParams } if ($error -ne $null){ foreach ($value in $error){ $ErrorEmailTemp = @" <tr> <td class="colorm">$value</td> </tr> "@ $ErrorEmailResult = $ErrorEmailResult + "`r`n" + $ErrorEmailTemp } $ErrorEmailUp = @" <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cstyle%3E%0D%0Abody%20%7Bfont-family%3ASegoe%2C%20%22Segoe%20UI%22%2C%20%22DejaVu%20Sans%22%2C%20%22Trebuchet%20MS%22%2C%20Verdana%2C%20sans-serif%20!important%3B%20color%3A%23434242%3B%7D%0D%0ATABLE%20%7Bfont-family%3ASegoe%2C%20%22Segoe%20UI%22%2C%20%22DejaVu%20Sans%22%2C%20%22Trebuchet%20MS%22%2C%20Verdana%2C%20sans-serif%20!important%3B%20border-width%3A%201px%3Bborder-style%3A%20solid%3Bborder-color%3A%20black%3Bborder-collapse%3A%20collapse%3B%7D%0D%0ATR%20%7Bborder-width%3A%201px%3Bpadding%3A%2010px%3Bborder-style%3A%20solid%3Bborder-color%3A%20white%3B%20%7D%0D%0ATD%20%7Bfont-family%3ASegoe%2C%20%22Segoe%20UI%22%2C%20%22DejaVu%20Sans%22%2C%20%22Trebuchet%20MS%22%2C%20Verdana%2C%20sans-serif%20!important%3B%20border-width%3A%201px%3Bpadding%3A%2010px%3Bborder-style%3A%20solid%3Bborder-color%3A%20white%3B%20background-color%3A%23C3DDDB%3B%7D%0D%0A.colorm%20%7Bbackground-color%3A%2358A09E%3B%20color%3Awhite%3B%7D%0D%0Ah3%20%7Bcolor%3A%23BD3337%20!important%3B%7D%0D%0A%3C%2Fstyle%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="<style>" title="<style>" /> <body> <h3 style="color:#BD3337 !important;> WARNING!!!</h3> <p>There were errors during users check</p> <p>Please check the errors and act accordingly</p> <table> "@ $ErrorEmailDown = @" </table> </body> "@ $ErrorEmail = $ErrorEmailUp + $ErrorEmailResult + $ErrorEmailDown $ErrorEmailParams = @{ To = $To Subject = "Users and their Groups Report $(Get-Date -format dd/MM/yyyy) - WARNING" Body = $ErrorEmail BodyAsHtml = $True Priority = "High" UseSsl = $True Port = "587" SmtpServer = "smtp.office365.com" Credential = $EmailCredentials From = $From} send-mailmessage @ErrorEmailParams }

[adinserter name=”Matched-Content”]