Group Policy Analyzer Tool

<#
.SYNOPSIS
Group Policy Analyzer Tool

.DESCRIPTION
This script analyzes and audits Group Policy Objects (GPOs) in an Active Directory environment,
providing detailed information about policy settings, links, and potential issues.

.NOTES
File Name      : GroupPolicyAnalyzer.ps1
Author         : [Your Name]
Prerequisite   : PowerShell V5.1 or later, GroupPolicy module, and appropriate AD permissions
Version        : 1.0
Date           : [Current Date]

.EXAMPLE
.\GroupPolicyAnalyzer.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 "=== Group Policy Analyzer Tool ===" -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. Analyze GPO WMI Filters"
    Write-Host "9. Generate Comprehensive HTML Report"
    Write-Host "10. 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
Analyzes GPO WMI Filters.

.OUTPUTS
Array of PSObjects containing GPO WMI Filter details.
#>
function Analyze-GPOWMIFilters {
    Write-Host "`nAnalyzing GPO WMI Filters..." -ForegroundColor Yellow
    $gpos = Get-GPO -All
    $wmiFilters = @()

    foreach ($gpo in $gpos) {
        $filter = $gpo.WmiFilter
        if ($filter) {
            $wmiFilters += [PSCustomObject]@{
                GPOName = $gpo.DisplayName
                WMIFilterName = $filter.Name
                WMIFilterDescription = $filter.Description
            }
        }
    }
    $wmiFilters | Format-Table -AutoSize
    return $wmiFilters
}

<#
.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)

    <h2>GPO WMI Filters</h2>
    $($AllResults.WMIFilters | 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-10)"

    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" { $allResults.WMIFilters = Analyze-GPOWMIFilters }
        "9" { Generate-HTMLReport -AllResults $allResults }
        "10" { Write-Host "Exiting program..." -ForegroundColor Yellow; break }
        default { Write-Host "Invalid choice. Please try again." -ForegroundColor Red }
    }

    if ($choice -ne "10") {
        Read-Host "`nPress Enter to continue..."
    }
} while ($choice -ne "10")

This Group Policy Analyzer Tool includes:

  1. A menu-driven interface for easy navigation.
  2. Functions to analyze various aspects of Group Policy:
    • Analysis of all GPOs
    • Identification of unlinked GPOs
    • Detection of GPOs with no settings
    • Checking for conflicting GPO settings
    • Analysis of GPO links
    • Review of GPO permissions
    • Checking GPO version numbers
    • Analysis of GPO WMI filters
  3. Comprehensive error handling for each analysis function.
  4. A function to generate an HTML report of all collected data.

Key features:

  • Detailed analysis of all GPOs in the domain
  • Identification of potential issues like unlinked or empty GPOs
  • Detection of conflicting policy settings
  • Review of GPO links and their order
  • Analysis of GPO permissions for security auditing
  • Version number checks to identify potential replication issues
  • WMI filter analysis
  • Comprehensive HTML report generation

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
  • Security professionals assessing GPO-based security settings

To use this script effectively:

  1. Run PowerShell as an administrator
  2. Ensure you have the necessary permissions to query GPOs in your domain
  3. 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.

0 replies

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *