Add 12 AI-generated PowerShell scripts with documentation
⚠️ IMPORTANT: These scripts are AI-GENERATED and UNTESTED Exchange Scripts (5): - Get-MailboxPermissions.ps1: Audit delegate access permissions - Get-InactiveMailboxes.ps1: Identify stale mailboxes - Compare-MailboxDatabases.ps1: Database health comparison - Export-DistributionGroups.ps1: Distribution group inventory - Get-MailflowStats.ps1: Transport log analysis Active Directory Scripts (3): - Get-ADUserLastLogon.ps1: True LastLogon across all DCs - Export-OUStructure.ps1: OU hierarchy with GPO links - Compare-ADGroupMemberships.ps1: Compare user group memberships System Maintenance Scripts (4): - Get-ServerInventory.ps1: Hardware/software inventory report - Monitor-DiskSpace.ps1: Disk space monitoring with alerts - Backup-ExchangeCertificates.ps1: Certificate backup to PFX - Test-ExchangeHealth.ps1: Aggregated Exchange health checks Documentation: - Updated CLAUDE.md with AI-generated scripts section - Added AI-GENERATED-SCRIPTS.md with warnings and testing guide All scripts include prominent warnings and follow established patterns from existing scripts. Require thorough testing before production use. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
215
ActiveDirectory/Compare-ADGroupMemberships.ps1
Normal file
215
ActiveDirectory/Compare-ADGroupMemberships.ps1
Normal file
@ -0,0 +1,215 @@
|
||||
<#
|
||||
.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-<date>
|
||||
|
||||
.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"
|
||||
Reference in New Issue
Block a user