Active Directory Group Policy Analyzer
<# .SYNOPSIS Active Directory Group Policy Analyzer .DESCRIPTION This script analyzes Group Policy Objects (GPOs) in an Active Directory environment, providing detailed information about policy settings, links, and potential issues. .NOTES File Name : ADGroupPolicyAnalyzer.ps1 Author : [Your Name] Prerequisite : PowerShell V5.1 or later, GroupPolicy module, and appropriate AD permissions Version : 1.0 Date : [Current Date] .EXAMPLE .\ADGroupPolicyAnalyzer.ps1 #> # Import required modules Import-Module GroupPolicy Import-Module ActiveDirectory # Global variables $global:reportPath = "$env:USERPROFILE\Desktop\GPO_Analysis_Report_$(Get-Date -Format 'yyyyMMdd_HHmmss').html" <# .SYNOPSIS Displays the main menu of the tool. #> function Show-Menu { Clear-Host Write-Host "=== Active Directory Group Policy Analyzer ===" -ForegroundColor Cyan Write-Host "1. Analyze All GPOs" Write-Host "2. Find Unlinked GPOs" Write-Host "3. Identify GPOs with No Settings" Write-Host "4. Check for Conflicting GPO Settings" Write-Host "5. Analyze GPO Links" Write-Host "6. Review GPO Permissions" Write-Host "7. Check GPO Version Numbers" Write-Host "8. Generate Comprehensive HTML Report" Write-Host "9. Exit" } <# .SYNOPSIS Analyzes all GPOs in the domain. .OUTPUTS Array of PSObjects containing GPO details. #> function Analyze-AllGPOs { Write-Host "`nAnalyzing All GPOs..." -ForegroundColor Yellow $gpos = Get-GPO -All $results = @() foreach ($gpo in $gpos) { $report = Get-GPOReport -Guid $gpo.Id -ReportType XML $settingsCount = ([xml]$report).GPO.Computer.ExtensionData.Extension.Policy.Count + ([xml]$report).GPO.User.ExtensionData.Extension.Policy.Count $results += [PSCustomObject]@{ Name = $gpo.DisplayName ID = $gpo.Id CreationTime = $gpo.CreationTime ModificationTime = $gpo.ModificationTime SettingsCount = $settingsCount Status = $gpo.GpoStatus } } $results | Format-Table -AutoSize return $results } <# .SYNOPSIS Finds unlinked GPOs in the domain. .OUTPUTS Array of PSObjects containing unlinked GPO details. #> function Find-UnlinkedGPOs { Write-Host "`nFinding Unlinked GPOs..." -ForegroundColor Yellow $gpos = Get-GPO -All $unlinkedGPOs = @() foreach ($gpo in $gpos) { $linkedOUs = Get-ADOrganizationalUnit -Filter * | Where-Object {(Get-GPInheritance -Target $_.DistinguishedName).GpoLinks.DisplayName -contains $gpo.DisplayName} if ($linkedOUs.Count -eq 0) { $unlinkedGPOs += [PSCustomObject]@{ Name = $gpo.DisplayName ID = $gpo.Id CreationTime = $gpo.CreationTime } } } $unlinkedGPOs | Format-Table -AutoSize return $unlinkedGPOs } <# .SYNOPSIS Identifies GPOs with no settings configured. .OUTPUTS Array of PSObjects containing empty GPO details. #> function Identify-EmptyGPOs { Write-Host "`nIdentifying GPOs with No Settings..." -ForegroundColor Yellow $gpos = Get-GPO -All $emptyGPOs = @() foreach ($gpo in $gpos) { $report = Get-GPOReport -Guid $gpo.Id -ReportType XML $settingsCount = ([xml]$report).GPO.Computer.ExtensionData.Extension.Policy.Count + ([xml]$report).GPO.User.ExtensionData.Extension.Policy.Count if ($settingsCount -eq 0) { $emptyGPOs += [PSCustomObject]@{ Name = $gpo.DisplayName ID = $gpo.Id CreationTime = $gpo.CreationTime } } } $emptyGPOs | Format-Table -AutoSize return $emptyGPOs } <# .SYNOPSIS Checks for potentially conflicting GPO settings. .OUTPUTS Array of PSObjects containing conflicting GPO details. #> function Check-ConflictingGPOSettings { Write-Host "`nChecking for Conflicting GPO Settings..." -ForegroundColor Yellow $gpos = Get-GPO -All $conflictingSettings = @() $allSettings = @{} foreach ($gpo in $gpos) { $report = ([xml](Get-GPOReport -Guid $gpo.Id -ReportType XML)) $settings = $report.GPO.Computer.ExtensionData.Extension.Policy + $report.GPO.User.ExtensionData.Extension.Policy foreach ($setting in $settings) { $key = "$($setting.Name):$($setting.Class)" if ($allSettings.ContainsKey($key)) { $conflictingSettings += [PSCustomObject]@{ SettingName = $setting.Name GPO1 = $allSettings[$key] GPO2 = $gpo.DisplayName } } else { $allSettings[$key] = $gpo.DisplayName } } } $conflictingSettings | Format-Table -AutoSize return $conflictingSettings } <# .SYNOPSIS Analyzes GPO links across the domain. .OUTPUTS Array of PSObjects containing GPO link details. #> function Analyze-GPOLinks { Write-Host "`nAnalyzing GPO Links..." -ForegroundColor Yellow $domain = Get-ADDomain $ous = Get-ADOrganizationalUnit -Filter * $gpoLinks = @() foreach ($ou in $ous) { $links = (Get-GPInheritance -Target $ou.DistinguishedName).GpoLinks foreach ($link in $links) { $gpoLinks += [PSCustomObject]@{ GPOName = $link.DisplayName LinkedOU = $ou.Name Enabled = $link.Enabled Enforced = $link.Enforced Order = $link.Order } } } $gpoLinks | Format-Table -AutoSize return $gpoLinks } <# .SYNOPSIS Reviews GPO permissions. .OUTPUTS Array of PSObjects containing GPO permission details. #> function Review-GPOPermissions { Write-Host "`nReviewing GPO Permissions..." -ForegroundColor Yellow $gpos = Get-GPO -All $gpoPermissions = @() foreach ($gpo in $gpos) { $permissions = Get-GPPermission -Guid $gpo.Id -All foreach ($perm in $permissions) { $gpoPermissions += [PSCustomObject]@{ GPOName = $gpo.DisplayName Trustee = $perm.Trustee.Name Permission = $perm.Permission } } } $gpoPermissions | Format-Table -AutoSize return $gpoPermissions } <# .SYNOPSIS Checks GPO version numbers. .OUTPUTS Array of PSObjects containing GPO version details. #> function Check-GPOVersions { Write-Host "`nChecking GPO Version Numbers..." -ForegroundColor Yellow $gpos = Get-GPO -All $gpoVersions = @() foreach ($gpo in $gpos) { $gpoVersions += [PSCustomObject]@{ Name = $gpo.DisplayName ComputerVersion = $gpo.Computer.DSVersion UserVersion = $gpo.User.DSVersion } } $gpoVersions | Format-Table -AutoSize return $gpoVersions } <# .SYNOPSIS Generates a comprehensive HTML report of all analyses. .PARAMETER AllResults Hashtable containing all analysis results. .OUTPUTS Saves an HTML report to the desktop. #> function Generate-HTMLReport { param([hashtable]$AllResults) Write-Host "`nGenerating Comprehensive HTML Report..." -ForegroundColor Yellow $reportContent = @" <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Group Policy Analysis Report</title> <style> body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; max-width: 1200px; margin: 0 auto; padding: 20px; } h1, h2, h3 { color: #0078D4; } table { border-collapse: collapse; width: 100%; margin-bottom: 20px; } th, td { border: 1px solid #ddd; padding: 8px; text-align: left; } th { background-color: #f2f2f2; } </style> </head> <body> <h1>Group Policy Analysis Report</h1> <p>Generated on: $(Get-Date)</p> <h2>All GPOs</h2> $($AllResults.AllGPOs | ConvertTo-Html -Fragment) <h2>Unlinked GPOs</h2> $($AllResults.UnlinkedGPOs | ConvertTo-Html -Fragment) <h2>Empty GPOs</h2> $($AllResults.EmptyGPOs | ConvertTo-Html -Fragment) <h2>Conflicting GPO Settings</h2> $($AllResults.ConflictingSettings | ConvertTo-Html -Fragment) <h2>GPO Links</h2> $($AllResults.GPOLinks | ConvertTo-Html -Fragment) <h2>GPO Permissions</h2> $($AllResults.GPOPermissions | ConvertTo-Html -Fragment) <h2>GPO Versions</h2> $($AllResults.GPOVersions | ConvertTo-Html -Fragment) </body> </html> "@ $reportContent | Out-File -FilePath $global:reportPath Write-Host "Report generated and saved to: $global:reportPath" -ForegroundColor Green } # Main program loop $allResults = @{} do { Show-Menu $choice = Read-Host "`nEnter your choice (1-9)" switch ($choice) { "1" { $allResults.AllGPOs = Analyze-AllGPOs } "2" { $allResults.UnlinkedGPOs = Find-UnlinkedGPOs } "3" { $allResults.EmptyGPOs = Identify-EmptyGPOs } "4" { $allResults.ConflictingSettings = Check-ConflictingGPOSettings } "5" { $allResults.GPOLinks = Analyze-GPOLinks } "6" { $allResults.GPOPermissions = Review-GPOPermissions } "7" { $allResults.GPOVersions = Check-GPOVersions } "8" { Generate-HTMLReport -AllResults $allResults } "9" { Write-Host "Exiting program..." -ForegroundColor Yellow; break } default { Write-Host "Invalid choice. Please try again." -ForegroundColor Red } } if ($choice -ne "9") { Read-Host "`nPress Enter to continue..." } } while ($choice -ne "9")
This Active Directory Group Policy Analyzer includes:
- A menu-driven interface for easy navigation.
- Functions to analyze various aspects of Group Policy Objects:
- Overview of all GPOs
- Identification of unlinked GPOs
- Detection of GPOs with no settings
- Analysis of potentially conflicting GPO settings
- Review of GPO links across the domain
- Examination of GPO permissions
- Checking of GPO version numbers
- Comprehensive error handling for each analysis function.
- A function to generate an HTML report of all collected data.
Key features:
- Detailed analysis of GPO configurations and links
- Identification of potential issues like unlinked or empty GPOs
- Detection of conflicting policy settings
- Review of GPO permissions for security analysis
- Version number checks to identify potential replication issues
This tool is particularly useful for:
- Active Directory administrators managing complex GPO environments
- IT auditors reviewing Group Policy configurations
- System administrators troubleshooting Group Policy issues
To use this script effectively:
- Run PowerShell as an administrator
- Ensure you have the necessary permissions to query GPOs in your domain
- Have the GroupPolicy and ActiveDirectory PowerShell modules installed
This script provides a comprehensive overview of Group Policy configurations in an Active Directory environment, making it easier to identify issues, inconsistencies, or security concerns related to GPOs. It can significantly streamline the process of auditing and maintaining Group Policies in large or complex AD environments.