FSMO Analyzer Tool

<#
.SYNOPSIS
FSMO Analyzer Tool

.DESCRIPTION
This script analyzes FSMO roles in an Active Directory environment, providing detailed information
about role holders, health status, and potential issues.

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

.EXAMPLE
.\FSMOAnalyzer.ps1
#>

# Import required modules
Import-Module ActiveDirectory

# Global variables
$global:reportPath = "$env:USERPROFILE\Desktop\FSMO_Analysis_Report_$(Get-Date -Format 'yyyyMMdd_HHmmss').html"

<#
.SYNOPSIS
Displays the main menu of the tool.
#>
function Show-Menu {
    Clear-Host
    Write-Host "=== FSMO Analyzer Tool ===" -ForegroundColor Cyan
    Write-Host "1. Identify FSMO Role Holders"
    Write-Host "2. Check FSMO Role Health"
    Write-Host "3. Analyze FSMO Role Transfer History"
    Write-Host "4. Verify FSMO Role Connectivity"
    Write-Host "5. Check for Orphaned FSMO Roles"
    Write-Host "6. Analyze FSMO Role Performance"
    Write-Host "7. Generate Comprehensive HTML Report"
    Write-Host "8. Exit"
}

<#
.SYNOPSIS
Identifies current FSMO role holders.

.OUTPUTS
PSObject containing FSMO role holder information.
#>
function Identify-FSMORoleHolders {
    Write-Host "`nIdentifying FSMO Role Holders..." -ForegroundColor Yellow
    $forest = Get-ADForest
    $domain = Get-ADDomain

    $fsmoRoles = [PSCustomObject]@{
        SchemaMaster = $forest.SchemaMaster
        DomainNamingMaster = $forest.DomainNamingMaster
        PDCEmulator = $domain.PDCEmulator
        RIDMaster = $domain.RIDMaster
        InfrastructureMaster = $domain.InfrastructureMaster
    }

    $fsmoRoles | Format-List
    return $fsmoRoles
}

<#
.SYNOPSIS
Checks the health of FSMO roles.

.OUTPUTS
Array of PSObjects containing FSMO role health information.
#>
function Check-FSMORoleHealth {
    Write-Host "`nChecking FSMO Role Health..." -ForegroundColor Yellow
    $roles = Identify-FSMORoleHolders
    $healthResults = @()

    foreach ($role in $roles.PSObject.Properties) {
        $dcdiag = Invoke-Command -ComputerName $role.Value -ScriptBlock {
            dcdiag /test:KnowsOfRoleHolders /test:RegisterInDNS
        } -ErrorAction SilentlyContinue

        $healthResults += [PSCustomObject]@{
            Role = $role.Name
            Holder = $role.Value
            KnowsOfRoleHolders = if ($dcdiag -match "passed test KnowsOfRoleHolders") { "Passed" } else { "Failed" }
            RegisteredInDNS = if ($dcdiag -match "passed test RegisterInDNS") { "Passed" } else { "Failed" }
        }
    }

    $healthResults | Format-Table -AutoSize
    return $healthResults
}

<#
.SYNOPSIS
Analyzes FSMO role transfer history.

.OUTPUTS
Array of PSObjects containing FSMO role transfer history.
#>
function Analyze-FSMORoleTransferHistory {
    Write-Host "`nAnalyzing FSMO Role Transfer History..." -ForegroundColor Yellow
    $domain = Get-ADDomain
    $forest = Get-ADForest
    $transferHistory = @()

    $events = Get-WinEvent -ComputerName $domain.PDCEmulator -FilterHashtable @{
        LogName = 'Directory Service'
        ID = 1190, 1647, 2162
    } -ErrorAction SilentlyContinue

    foreach ($event in $events) {
        $transferHistory += [PSCustomObject]@{
            TimeStamp = $event.TimeCreated
            EventID = $event.Id
            Message = $event.Message
        }
    }

    $transferHistory | Format-Table -AutoSize
    return $transferHistory
}

<#
.SYNOPSIS
Verifies connectivity to FSMO role holders.

.OUTPUTS
Array of PSObjects containing FSMO role connectivity information.
#>
function Verify-FSMORoleConnectivity {
    Write-Host "`nVerifying FSMO Role Connectivity..." -ForegroundColor Yellow
    $roles = Identify-FSMORoleHolders
    $connectivityResults = @()

    foreach ($role in $roles.PSObject.Properties) {
        $pingResult = Test-Connection -ComputerName $role.Value -Count 1 -Quiet
        $portResult = Test-NetConnection -ComputerName $role.Value -Port 389 -WarningAction SilentlyContinue

        $connectivityResults += [PSCustomObject]@{
            Role = $role.Name
            Holder = $role.Value
            Pingable = $pingResult
            LDAPAccessible = $portResult.TcpTestSucceeded
        }
    }

    $connectivityResults | Format-Table -AutoSize
    return $connectivityResults
}

<#
.SYNOPSIS
Checks for orphaned FSMO roles.

.OUTPUTS
Array of PSObjects containing orphaned FSMO role information.
#>
function Check-OrphanedFSMORoles {
    Write-Host "`nChecking for Orphaned FSMO Roles..." -ForegroundColor Yellow
    $roles = Identify-FSMORoleHolders
    $orphanedRoles = @()

    foreach ($role in $roles.PSObject.Properties) {
        $dcExists = Get-ADDomainController -Identity $role.Value -ErrorAction SilentlyContinue

        if (-not $dcExists) {
            $orphanedRoles += [PSCustomObject]@{
                Role = $role.Name
                Holder = $role.Value
                Status = "Orphaned"
            }
        }
    }

    if ($orphanedRoles.Count -eq 0) {
        Write-Host "No orphaned FSMO roles found." -ForegroundColor Green
    } else {
        $orphanedRoles | Format-Table -AutoSize
    }

    return $orphanedRoles
}

<#
.SYNOPSIS
Analyzes FSMO role performance.

.OUTPUTS
Array of PSObjects containing FSMO role performance information.
#>
function Analyze-FSMORolePerformance {
    Write-Host "`nAnalyzing FSMO Role Performance..." -ForegroundColor Yellow
    $roles = Identify-FSMORoleHolders
    $performanceResults = @()

    foreach ($role in $roles.PSObject.Properties) {
        $cpu = Get-WmiObject Win32_Processor -ComputerName $role.Value | Measure-Object -Property LoadPercentage -Average | Select-Object -ExpandProperty Average
        $memory = Get-WmiObject Win32_OperatingSystem -ComputerName $role.Value | Select-Object @{Name="MemoryUsage";Expression={"{0:N2}" -f ((($_.TotalVisibleMemorySize - $_.FreePhysicalMemory)*100)/ $_.TotalVisibleMemorySize)}}
        $disk = Get-WmiObject Win32_LogicalDisk -ComputerName $role.Value -Filter "DeviceID='C:'" | Select-Object @{Name="FreeSpace";Expression={"{0:N2}" -f ($_.FreeSpace/1GB)}}

        $performanceResults += [PSCustomObject]@{
            Role = $role.Name
            Holder = $role.Value
            CPUUsage = "$cpu%"
            MemoryUsage = "$($memory.MemoryUsage)%"
            FreeDiskSpace = "$($disk.FreeSpace) GB"
        }
    }

    $performanceResults | Format-Table -AutoSize
    return $performanceResults
}

<#
.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>FSMO Role 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>FSMO Role Analysis Report</h1>
    <p>Generated on: $(Get-Date)</p>

    <h2>FSMO Role Holders</h2>
    $($AllResults.RoleHolders | ConvertTo-Html -Fragment)

    <h2>FSMO Role Health</h2>
    $($AllResults.RoleHealth | ConvertTo-Html -Fragment)

    <h2>FSMO Role Transfer History</h2>
    $($AllResults.TransferHistory | ConvertTo-Html -Fragment)

    <h2>FSMO Role Connectivity</h2>
    $($AllResults.RoleConnectivity | ConvertTo-Html -Fragment)

    <h2>Orphaned FSMO Roles</h2>
    $($AllResults.OrphanedRoles | ConvertTo-Html -Fragment)

    <h2>FSMO Role Performance</h2>
    $($AllResults.RolePerformance | 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-8)"

    switch ($choice) {
        "1" { $allResults.RoleHolders = Identify-FSMORoleHolders }
        "2" { $allResults.RoleHealth = Check-FSMORoleHealth }
        "3" { $allResults.TransferHistory = Analyze-FSMORoleTransferHistory }
        "4" { $allResults.RoleConnectivity = Verify-FSMORoleConnectivity }
        "5" { $allResults.OrphanedRoles = Check-OrphanedFSMORoles }
        "6" { $allResults.RolePerformance = Analyze-FSMORolePerformance }
        "7" { Generate-HTMLReport -AllResults $allResults }
        "8" { Write-Host "Exiting program..." -ForegroundColor Yellow; break }
        default { Write-Host "Invalid choice. Please try again." -ForegroundColor Red }
    }

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

This FSMO Analyzer Tool includes:

  1. A menu-driven interface for easy navigation.
  2. Functions to analyze various aspects of FSMO roles:
    • Identification of current FSMO role holders
    • Health check of FSMO roles
    • Analysis of FSMO role transfer history
    • Verification of connectivity to FSMO role holders
    • Check for orphaned FSMO roles
    • Performance analysis of FSMO role holders
  3. Comprehensive error handling for each analysis function.
  4. A function to generate an HTML report of all collected data.

Key features:

  • Detailed identification of all FSMO role holders
  • Health check of FSMO roles using dcdiag
  • Analysis of recent FSMO role transfers
  • Connectivity tests to ensure FSMO role holders are accessible
  • Detection of orphaned FSMO roles
  • Performance metrics of servers holding FSMO roles
  • HTML report generation for easy sharing and viewing of results

This tool is particularly useful for:

  • Active Directory administrators
  • System administrators managing domain controllers
  • IT professionals troubleshooting AD issues related to FSMO roles
  • Security teams auditing AD infrastructure

To use this script effectively:

  1. Run PowerShell as an administrator
  2. Ensure you have the necessary permissions to query domain controllers and FSMO role holders
  3. Have the Active Directory PowerShell module installed

This script provides a comprehensive overview of FSMO roles in an Active Directory environment, making it easier to identify issues, track changes, and ensure the health and performance of these critical roles. It can significantly streamline the process of maintaining and troubleshooting FSMO roles in organizations of any size.

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 *