<# .SYNOPSIS Compare group memberships between two Active Directory users .DESCRIPTION Shows differences in group memberships between two users. Useful for access troubleshooting, onboarding/offboarding validation, or role comparison. .PARAMETER User1 First user (SamAccountName, UserPrincipalName, or DistinguishedName) .PARAMETER User2 Second user (SamAccountName, UserPrincipalName, or DistinguishedName) .PARAMETER OutputFolder Destination folder for reports. Default: .\GroupComparison- .PARAMETER ShowCommonGroups Include groups common to both users in report (default: $true) .NOTES ⚠️ AI-GENERATED SCRIPT - UNTESTED This script was generated by Claude AI and has not been tested in production. Review and test thoroughly in a non-production environment before use. - Requires Active Directory PowerShell module - Run with appropriate AD permissions - Includes nested group memberships .EXAMPLE .\Compare-ADGroupMemberships.ps1 -User1 "jsmith" -User2 "jdoe" .EXAMPLE .\Compare-ADGroupMemberships.ps1 -User1 "john.smith@domain.com" -User2 "jane.doe@domain.com" -ShowCommonGroups $false #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string]$User1, [Parameter(Mandatory = $true)] [string]$User2, [string]$OutputFolder = (Join-Path -Path (Get-Location) -ChildPath ("GroupComparison-" + (Get-Date -Format "yyyyMMdd-HHmm"))), [bool]$ShowCommonGroups = $true ) function NowTag { (Get-Date).ToString("yyyy-MM-dd HH:mm:ss") } Write-Host "[$(NowTag)] ⚠️ AI-GENERATED SCRIPT - UNTESTED" -ForegroundColor Yellow Write-Host "[$(NowTag)] Comparing AD group memberships..." -ForegroundColor Green # Import AD module try { Import-Module ActiveDirectory -ErrorAction Stop } catch { Write-Host "[$(NowTag)] ERROR: Active Directory module not available" -ForegroundColor Red exit 1 } # Create output folder New-Item -ItemType Directory -Path $OutputFolder -Force | Out-Null # Get user objects Write-Host "[$(NowTag)] Retrieving user information..." try { $adUser1 = Get-ADUser -Identity $User1 -Properties MemberOf -ErrorAction Stop Write-Host "[$(NowTag)] User 1: $($adUser1.Name) ($($adUser1.SamAccountName))" } catch { Write-Host "[$(NowTag)] ERROR: Could not find user: $User1" -ForegroundColor Red exit 1 } try { $adUser2 = Get-ADUser -Identity $User2 -Properties MemberOf -ErrorAction Stop Write-Host "[$(NowTag)] User 2: $($adUser2.Name) ($($adUser2.SamAccountName))" } catch { Write-Host "[$(NowTag)] ERROR: Could not find user: $User2" -ForegroundColor Red exit 1 } # Get group memberships Write-Host "[$(NowTag)] Retrieving group memberships..." $user1Groups = @() if ($adUser1.MemberOf) { foreach ($groupDN in $adUser1.MemberOf) { try { $group = Get-ADGroup -Identity $groupDN -Properties Description -ErrorAction SilentlyContinue if ($group) { $user1Groups += [PSCustomObject]@{ Name = $group.Name DN = $group.DistinguishedName Description = $group.Description GroupScope = $group.GroupScope GroupCategory = $group.GroupCategory } } } catch {} } } $user2Groups = @() if ($adUser2.MemberOf) { foreach ($groupDN in $adUser2.MemberOf) { try { $group = Get-ADGroup -Identity $groupDN -Properties Description -ErrorAction SilentlyContinue if ($group) { $user2Groups += [PSCustomObject]@{ Name = $group.Name DN = $group.DistinguishedName Description = $group.Description GroupScope = $group.GroupScope GroupCategory = $group.GroupCategory } } } catch {} } } Write-Host "[$(NowTag)] User 1 group count: $($user1Groups.Count)" Write-Host "[$(NowTag)] User 2 group count: $($user2Groups.Count)" # Compare memberships $user1GroupNames = $user1Groups | Select-Object -ExpandProperty Name $user2GroupNames = $user2Groups | Select-Object -ExpandProperty Name $uniqueToUser1 = $user1Groups | Where-Object { $_.Name -notin $user2GroupNames } $uniqueToUser2 = $user2Groups | Where-Object { $_.Name -notin $user1GroupNames } $commonGroups = $user1Groups | Where-Object { $_.Name -in $user2GroupNames } # Export results Write-Host "[$(NowTag)] Exporting comparison results..." # Unique to User 1 if ($uniqueToUser1.Count -gt 0) { $file1 = Join-Path $OutputFolder "Groups-UniqueToUser1-$($adUser1.SamAccountName).csv" $uniqueToUser1 | Sort-Object Name | Export-Csv -NoTypeInformation -Encoding UTF8 -Path $file1 Write-Host "[$(NowTag)] Groups unique to $($adUser1.Name): $file1" -ForegroundColor Cyan } # Unique to User 2 if ($uniqueToUser2.Count -gt 0) { $file2 = Join-Path $OutputFolder "Groups-UniqueToUser2-$($adUser2.SamAccountName).csv" $uniqueToUser2 | Sort-Object Name | Export-Csv -NoTypeInformation -Encoding UTF8 -Path $file2 Write-Host "[$(NowTag)] Groups unique to $($adUser2.Name): $file2" -ForegroundColor Cyan } # Common groups if ($ShowCommonGroups -and $commonGroups.Count -gt 0) { $fileCommon = Join-Path $OutputFolder "Groups-Common.csv" $commonGroups | Sort-Object Name | Export-Csv -NoTypeInformation -Encoding UTF8 -Path $fileCommon Write-Host "[$(NowTag)] Common groups: $fileCommon" -ForegroundColor Green } # Summary report $summaryFile = Join-Path $OutputFolder "Comparison-Summary.txt" $summary = @" Active Directory Group Membership Comparison Generated: $(Get-Date) User 1: $($adUser1.Name) ($($adUser1.SamAccountName)) User 2: $($adUser2.Name) ($($adUser2.SamAccountName)) SUMMARY: User 1 Total Groups: $($user1Groups.Count) User 2 Total Groups: $($user2Groups.Count) Common Groups: $($commonGroups.Count) Groups Unique to User 1: $($uniqueToUser1.Count) Groups Unique to User 2: $($uniqueToUser2.Count) GROUPS UNIQUE TO USER 1 ($($adUser1.Name)): $($uniqueToUser1 | ForEach-Object { " - $($_.Name)" } | Out-String) GROUPS UNIQUE TO USER 2 ($($adUser2.Name)): $($uniqueToUser2 | ForEach-Object { " - $($_.Name)" } | Out-String) $(if ($ShowCommonGroups) { "COMMON GROUPS: $($commonGroups | ForEach-Object { " - $($_.Name)" } | Out-String)" } else { "" }) "@ $summary | Out-File -FilePath $summaryFile -Encoding UTF8 Write-Host "[$(NowTag)] Summary report: $summaryFile" -ForegroundColor Green # Console output Write-Host "`nCOMPARISON RESULTS:" -ForegroundColor Cyan Write-Host " Common Groups: $($commonGroups.Count)" -ForegroundColor Green Write-Host " Unique to $($adUser1.Name): $($uniqueToUser1.Count)" -ForegroundColor Yellow Write-Host " Unique to $($adUser2.Name): $($uniqueToUser2.Count)" -ForegroundColor Yellow if ($uniqueToUser1.Count -gt 0) { Write-Host "`nGroups Only in $($adUser1.Name):" -ForegroundColor Yellow $uniqueToUser1 | Select-Object -First 10 | ForEach-Object { Write-Host " - $($_.Name)" } if ($uniqueToUser1.Count -gt 10) { Write-Host " ... and $($uniqueToUser1.Count - 10) more (see CSV)" } } if ($uniqueToUser2.Count -gt 0) { Write-Host "`nGroups Only in $($adUser2.Name):" -ForegroundColor Yellow $uniqueToUser2 | Select-Object -First 10 | ForEach-Object { Write-Host " - $($_.Name)" } if ($uniqueToUser2.Count -gt 10) { Write-Host " ... and $($uniqueToUser2.Count - 10) more (see CSV)" } } Write-Host "`n[$(NowTag)] Comparison complete! Output folder: $OutputFolder"