Dr. Scripto’s Firewall Fiasco

Dr. Scripto, the renowned PowerShell wizard, received an urgent call from Contoso Corp. Their network was under siege, and the firewall was acting up!

“Fear not!” exclaimed Dr. Scripto, grabbing his trusty laptop. “I’ll sort this out faster than you can say ‘Get-NetFirewallRule’!”

Arriving at Contoso, he found chaos. Employees couldn’t access critical services, and the IT team was in panic mode.

Dr. Scripto cracked his knuckles and summoned his PowerShell console. “Let’s see what’s going on here,” he muttered.

He began with a simple command:

Get-NetFirewallRule | Where-Object Enabled -eq 'True'

Suddenly, his screen filled with a flood of rules. “Great Scott!” he exclaimed. “This firewall has more rules than a lawyer’s handbook!”

Undeterred, Dr. Scripto dug deeper. He discovered a rogue rule blocking all incoming traffic:

Get-NetFirewallRule -DisplayName "BlockEverything" | Get-NetFirewallPortFilter

“Aha!” he shouted triumphantly. “Here’s our culprit!”

With a flourish of his keyboard, he disabled the troublesome rule:

Set-NetFirewallRule -DisplayName "BlockEverything" -Enabled False

The office erupted in cheers as services came back online. But Dr. Scripto wasn’t finished. He turned to the IT team with a twinkle in his eye.

“Now, let’s set up some proper rules and monitoring. Repeat after me: ‘New-NetFirewallRule’…”

For the next hour, Dr. Scripto regaled them with the wonders of PowerShell firewall management. By the time he left, Contoso had a lean, mean, properly configured firewall machine.

As he drove away, Dr. Scripto chuckled to himself. “Another day, another firewall tamed by the power of PowerShell!”

And so, Dr. Scripto’s legend grew, one cmdlet at a time.

Firewall Analyzer Tool

<#
.SYNOPSIS
Firewall Analyzer Tool

.DESCRIPTION
This script analyzes Windows Firewall configurations, rules, and potential issues across servers in your network.

.NOTES
File Name      : FirewallAnalyzer.ps1
Author         : [Your Name]
Prerequisite   : PowerShell V5.1 or later, appropriate admin permissions
Version        : 1.0
Date           : [Current Date]

.EXAMPLE
.\FirewallAnalyzer.ps1
#>

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

<#
.SYNOPSIS
Displays the main menu of the tool.
#>
function Show-Menu {
    Clear-Host
    Write-Host "=== Firewall Analyzer Tool ===" -ForegroundColor Cyan
    Write-Host "1. Analyze Firewall Profiles"
    Write-Host "2. Check Firewall Rules"
    Write-Host "3. Analyze Inbound Rules"
    Write-Host "4. Analyze Outbound Rules"
    Write-Host "5. Check for Potentially Risky Rules"
    Write-Host "6. Analyze Firewall Logging Settings"
    Write-Host "7. Check Firewall Service Status"
    Write-Host "8. Generate Comprehensive HTML Report"
    Write-Host "9. Exit"
}

<#
.SYNOPSIS
Gets a list of servers to analyze.

.OUTPUTS
Array of server names.
#>
function Get-TargetServers {
    $option = Read-Host "Analyze (A)ll domain servers, (S)pecific servers, or (F)ile input? (A/S/F)"
    switch ($option.ToUpper()) {
        "A" {
            return (Get-ADComputer -Filter {OperatingSystem -like "*Server*"} | Select-Object -ExpandProperty Name)
        }
        "S" {
            $servers = @()
            do {
                $server = Read-Host "Enter server name (or press Enter to finish)"
                if ($server -ne "") { $servers += $server }
            } while ($server -ne "")
            return $servers
        }
        "F" {
            $filePath = Read-Host "Enter the path to the file containing server names"
            return (Get-Content $filePath)
        }
        default {
            Write-Host "Invalid option. Defaulting to all domain servers." -ForegroundColor Yellow
            return (Get-ADComputer -Filter {OperatingSystem -like "*Server*"} | Select-Object -ExpandProperty Name)
        }
    }
}

<#
.SYNOPSIS
Analyzes firewall profiles on target servers.

.PARAMETER Servers
Array of server names to analyze.

.OUTPUTS
Array of PSObjects containing firewall profile details.
#>
function Analyze-FirewallProfiles {
    param([string[]]$Servers)

    Write-Host "`nAnalyzing Firewall Profiles..." -ForegroundColor Yellow
    $profileResults = @()
    foreach ($server in $Servers) {
        try {
            $profiles = Get-NetFirewallProfile -CimSession $server -ErrorAction Stop
            foreach ($profile in $profiles) {
                $profileResults += [PSCustomObject]@{
                    Server = $server
                    ProfileName = $profile.Name
                    Enabled = $profile.Enabled
                    DefaultInboundAction = $profile.DefaultInboundAction
                    DefaultOutboundAction = $profile.DefaultOutboundAction
                    AllowInboundRules = $profile.AllowInboundRules
                    AllowLocalFirewallRules = $profile.AllowLocalFirewallRules
                }
            }
        }
        catch {
            Write-Host "Error analyzing firewall profiles on $server : $_" -ForegroundColor Red
        }
    }
    $profileResults | Format-Table -AutoSize
    return $profileResults
}

<#
.SYNOPSIS
Checks firewall rules on target servers.

.PARAMETER Servers
Array of server names to analyze.

.OUTPUTS
Array of PSObjects containing firewall rule details.
#>
function Check-FirewallRules {
    param([string[]]$Servers)

    Write-Host "`nChecking Firewall Rules..." -ForegroundColor Yellow
    $ruleResults = @()
    foreach ($server in $Servers) {
        try {
            $rules = Get-NetFirewallRule -CimSession $server -ErrorAction Stop
            $ruleResults += [PSCustomObject]@{
                Server = $server
                TotalRules = $rules.Count
                EnabledRules = ($rules | Where-Object { $_.Enabled -eq $true }).Count
                DisabledRules = ($rules | Where-Object { $_.Enabled -eq $false }).Count
                InboundRules = ($rules | Where-Object { $_.Direction -eq "Inbound" }).Count
                OutboundRules = ($rules | Where-Object { $_.Direction -eq "Outbound" }).Count
            }
        }
        catch {
            Write-Host "Error checking firewall rules on $server : $_" -ForegroundColor Red
        }
    }
    $ruleResults | Format-Table -AutoSize
    return $ruleResults
}

<#
.SYNOPSIS
Analyzes inbound firewall rules on target servers.

.PARAMETER Servers
Array of server names to analyze.

.OUTPUTS
Array of PSObjects containing inbound rule details.
#>
function Analyze-InboundRules {
    param([string[]]$Servers)

    Write-Host "`nAnalyzing Inbound Rules..." -ForegroundColor Yellow
    $inboundResults = @()
    foreach ($server in $Servers) {
        try {
            $inboundRules = Get-NetFirewallRule -CimSession $server -Direction Inbound -Enabled True -ErrorAction Stop
            foreach ($rule in $inboundRules) {
                $ports = (Get-NetFirewallPortFilter -AssociatedNetFirewallRule $rule).LocalPort -join ", "
                $inboundResults += [PSCustomObject]@{
                    Server = $server
                    RuleName = $rule.DisplayName
                    Action = $rule.Action
                    Protocol = (Get-NetFirewallPortFilter -AssociatedNetFirewallRule $rule).Protocol
                    LocalPort = if ($ports) { $ports } else { "Any" }
                    RemoteAddress = (Get-NetFirewallAddressFilter -AssociatedNetFirewallRule $rule).RemoteAddress -join ", "
                }
            }
        }
        catch {
            Write-Host "Error analyzing inbound rules on $server : $_" -ForegroundColor Red
        }
    }
    $inboundResults | Format-Table -AutoSize
    return $inboundResults
}

<#
.SYNOPSIS
Analyzes outbound firewall rules on target servers.

.PARAMETER Servers
Array of server names to analyze.

.OUTPUTS
Array of PSObjects containing outbound rule details.
#>
function Analyze-OutboundRules {
    param([string[]]$Servers)

    Write-Host "`nAnalyzing Outbound Rules..." -ForegroundColor Yellow
    $outboundResults = @()
    foreach ($server in $Servers) {
        try {
            $outboundRules = Get-NetFirewallRule -CimSession $server -Direction Outbound -Enabled True -ErrorAction Stop
            foreach ($rule in $outboundRules) {
                $ports = (Get-NetFirewallPortFilter -AssociatedNetFirewallRule $rule).RemotePort -join ", "
                $outboundResults += [PSCustomObject]@{
                    Server = $server
                    RuleName = $rule.DisplayName
                    Action = $rule.Action
                    Protocol = (Get-NetFirewallPortFilter -AssociatedNetFirewallRule $rule).Protocol
                    RemotePort = if ($ports) { $ports } else { "Any" }
                    RemoteAddress = (Get-NetFirewallAddressFilter -AssociatedNetFirewallRule $rule).RemoteAddress -join ", "
                }
            }
        }
        catch {
            Write-Host "Error analyzing outbound rules on $server : $_" -ForegroundColor Red
        }
    }
    $outboundResults | Format-Table -AutoSize
    return $outboundResults
}

<#
.SYNOPSIS
Checks for potentially risky firewall rules on target servers.

.PARAMETER Servers
Array of server names to analyze.

.OUTPUTS
Array of PSObjects containing potentially risky rule details.
#>
function Check-PotentiallyRiskyRules {
    param([string[]]$Servers)

    Write-Host "`nChecking for Potentially Risky Rules..." -ForegroundColor Yellow
    $riskyResults = @()
    foreach ($server in $Servers) {
        try {
            $rules = Get-NetFirewallRule -CimSession $server -Enabled True -ErrorAction Stop
            foreach ($rule in $rules) {
                $isRisky = $false
                $riskReason = @()

                if ($rule.Action -eq "Allow" -and $rule.Direction -eq "Inbound") {
                    $remoteAddress = (Get-NetFirewallAddressFilter -AssociatedNetFirewallRule $rule).RemoteAddress
                    if ($remoteAddress -contains "Any") {
                        $isRisky = $true
                        $riskReason += "Allows inbound from any address"
                    }

                    $localPort = (Get-NetFirewallPortFilter -AssociatedNetFirewallRule $rule).LocalPort
                    if ($localPort -contains "Any") {
                        $isRisky = $true
                        $riskReason += "Allows inbound on any port"
                    }
                }

                if ($isRisky) {
                    $riskyResults += [PSCustomObject]@{
                        Server = $server
                        RuleName = $rule.DisplayName
                        Direction = $rule.Direction
                        Action = $rule.Action
                        RiskReason = $riskReason -join ", "
                    }
                }
            }
        }
        catch {
            Write-Host "Error checking for risky rules on $server : $_" -ForegroundColor Red
        }
    }
    $riskyResults | Format-Table -AutoSize
    return $riskyResults
}

<#
.SYNOPSIS
Analyzes firewall logging settings on target servers.

.PARAMETER Servers
Array of server names to analyze.

.OUTPUTS
Array of PSObjects containing firewall logging setting details.
#>
function Analyze-FirewallLoggingSettings {
    param([string[]]$Servers)

    Write-Host "`nAnalyzing Firewall Logging Settings..." -ForegroundColor Yellow
    $loggingResults = @()
    foreach ($server in $Servers) {
        try {
            $profiles = Get-NetFirewallProfile -CimSession $server -ErrorAction Stop
            foreach ($profile in $profiles) {
                $loggingResults += [PSCustomObject]@{
                    Server = $server
                    ProfileName = $profile.Name
                    LogAllowed = $profile.LogAllowed
                    LogBlocked = $profile.LogBlocked
                    LogIgnored = $profile.LogIgnored
                    LogFileName = $profile.LogFileName
                    LogMaxSizeKilobytes = $profile.LogMaxSizeKilobytes
                }
            }
        }
        catch {
            Write-Host "Error analyzing firewall logging settings on $server : $_" -ForegroundColor Red
        }
    }
    $loggingResults | Format-Table -AutoSize
    return $loggingResults
}

<#
.SYNOPSIS
Checks firewall service status on target servers.

.PARAMETER Servers
Array of server names to analyze.

.OUTPUTS
Array of PSObjects containing firewall service status details.
#>
function Check-FirewallServiceStatus {
    param([string[]]$Servers)

    Write-Host "`nChecking Firewall Service Status..." -ForegroundColor Yellow
    $serviceResults = @()
    foreach ($server in $Servers) {
        try {
            $service = Get-Service -ComputerName $server -Name MpsSvc -ErrorAction Stop
            $serviceResults += [PSCustomObject]@{
                Server = $server
                Status = $service.Status
                StartType = $service.StartType
            }
        }
        catch {
            Write-Host "Error checking firewall service status on $server : $_" -ForegroundColor Red
        }
    }
    $serviceResults | Format-Table -AutoSize
    return $serviceResults
}

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

    <h2>Firewall Profiles</h2>
    $($AllResults.FirewallProfiles | ConvertTo-Html -Fragment)

    <h2>Firewall Rules Summary</h2>
    $($AllResults.FirewallRules | ConvertTo-Html -Fragment)

    <h2>Inbound Rules</h2>
    $($AllResults.InboundRules | ConvertTo-Html -Fragment)

    <h2>Outbound Rules</h2>
    $($AllResults.OutboundRules | ConvertTo-Html -Fragment)

    <h2>Potentially Risky Rules</h2>
    $($AllResults.RiskyRules | ConvertTo-Html -Fragment)

    <h2>Firewall Logging Settings</h2>
    $($AllResults.LoggingSettings | ConvertTo-Html -Fragment)

    <h2>Firewall Service Status</h2>
    $($AllResults.ServiceStatus | 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
$targetServers = Get-TargetServers
$allResults = @{}

do {
    Show-Menu
    $choice = Read-Host "`nEnter your choice (1-9)"

    switch ($choice) {
        "1" { $allResults.FirewallProfiles = Analyze-FirewallProfiles -Servers $targetServers }
        "2" { $allResults.FirewallRules = Check-FirewallRules -Servers $targetServers }
        "3" { $allResults.InboundRules = Analyze-InboundRules -Servers $targetServers }
        "4" { $allResults.OutboundRules = Analyze-OutboundRules -Servers $targetServers }
        "5" { $allResults.RiskyRules = Check-PotentiallyRiskyRules -Servers $targetServers }
        "6" { $allResults.LoggingSettings = Analyze-FirewallLoggingSettings -Servers $targetServers }
        "7" { $allResults.ServiceStatus = Check-FirewallServiceStatus -Servers $targetServers }
        "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 Firewall Analyzer Tool includes:

  1. A menu-driven interface for easy navigation.
  2. Functions to analyze various aspects of Windows Firewall:
    • Firewall Profile analysis
    • Firewall Rules summary
    • Inbound Rules analysis
    • Outbound Rules analysis
    • Potentially Risky Rules check
    • Firewall Logging Settings analysis
    • Firewall Service Status check
  3. Flexible server selection (all domain servers, specific servers, or from a file).
  4. Comprehensive error handling for each analysis function.
  5. A function to generate an HTML report of all collected data.

Key features:

  • Detailed analysis of firewall profiles across multiple servers
  • Comprehensive overview of firewall rules, including inbound and outbound rules
  • Identification of potentially risky firewall rules
  • Analysis of firewall logging settings
  • Verification of firewall service status
  • HTML report generation for easy sharing and viewing of results

This tool is particularly useful for:

  • Network administrators managing Windows servers
  • Security professionals auditing firewall configurations
  • IT professionals performing security assessments
  • System administrators troubleshooting network connectivity issues

To use this script effectively:

  1. Run PowerShell as an administrator
  2. Ensure you have the necessary permissions to query the target servers
  3. Have the required PowerShell modules available (like ActiveDirectory if querying domain servers)

This script provides a comprehensive overview of Windows Firewall configurations and potential security issues across multiple servers in your network. It can significantly streamline the process of auditing and maintaining firewall configurations, enhancing the overall security posture of your Windows server environment.

SMB Analyzer Tool

<#
.SYNOPSIS
SMB Analyzer Tool

.DESCRIPTION
This script analyzes SMB configurations, shares, and potential issues across servers in your network.

.NOTES
File Name      : SMBAnalyzer.ps1
Author         : [Your Name]
Prerequisite   : PowerShell V5.1 or later, appropriate admin permissions
Version        : 1.0
Date           : [Current Date]

.EXAMPLE
.\SMBAnalyzer.ps1
#>

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

<#
.SYNOPSIS
Displays the main menu of the tool.
#>
function Show-Menu {
    Clear-Host
    Write-Host "=== SMB Analyzer Tool ===" -ForegroundColor Cyan
    Write-Host "1. Analyze SMB Shares"
    Write-Host "2. Check SMB Protocol Versions"
    Write-Host "3. Analyze SMB Security Settings"
    Write-Host "4. Check SMB Performance Counters"
    Write-Host "5. Analyze SMB Encryption Status"
    Write-Host "6. Check SMB Signing Configuration"
    Write-Host "7. Analyze SMB Client Connections"
    Write-Host "8. Generate Comprehensive HTML Report"
    Write-Host "9. Exit"
}

<#
.SYNOPSIS
Gets a list of servers to analyze.

.OUTPUTS
Array of server names.
#>
function Get-TargetServers {
    $option = Read-Host "Analyze (A)ll domain servers, (S)pecific servers, or (F)ile input? (A/S/F)"
    switch ($option.ToUpper()) {
        "A" {
            return (Get-ADComputer -Filter {OperatingSystem -like "*Server*"} | Select-Object -ExpandProperty Name)
        }
        "S" {
            $servers = @()
            do {
                $server = Read-Host "Enter server name (or press Enter to finish)"
                if ($server -ne "") { $servers += $server }
            } while ($server -ne "")
            return $servers
        }
        "F" {
            $filePath = Read-Host "Enter the path to the file containing server names"
            return (Get-Content $filePath)
        }
        default {
            Write-Host "Invalid option. Defaulting to all domain servers." -ForegroundColor Yellow
            return (Get-ADComputer -Filter {OperatingSystem -like "*Server*"} | Select-Object -ExpandProperty Name)
        }
    }
}

<#
.SYNOPSIS
Analyzes SMB shares on target servers.

.PARAMETER Servers
Array of server names to analyze.

.OUTPUTS
Array of PSObjects containing SMB share details.
#>
function Analyze-SMBShares {
    param([string[]]$Servers)

    Write-Host "`nAnalyzing SMB Shares..." -ForegroundColor Yellow
    $shareResults = @()
    foreach ($server in $Servers) {
        try {
            $shares = Get-SmbShare -CimSession $server -ErrorAction Stop
            foreach ($share in $shares) {
                $shareResults += [PSCustomObject]@{
                    Server = $server
                    ShareName = $share.Name
                    Path = $share.Path
                    Description = $share.Description
                    AccessBasedEnumerationEnabled = $share.FolderEnumerationMode
                }
            }
        }
        catch {
            Write-Host "Error analyzing shares on $server : $_" -ForegroundColor Red
        }
    }
    $shareResults | Format-Table -AutoSize
    return $shareResults
}

<#
.SYNOPSIS
Checks SMB protocol versions on target servers.

.PARAMETER Servers
Array of server names to analyze.

.OUTPUTS
Array of PSObjects containing SMB protocol version details.
#>
function Check-SMBProtocolVersions {
    param([string[]]$Servers)

    Write-Host "`nChecking SMB Protocol Versions..." -ForegroundColor Yellow
    $protocolResults = @()
    foreach ($server in $Servers) {
        try {
            $smbServer = Get-SmbServerConfiguration -CimSession $server -ErrorAction Stop
            $protocolResults += [PSCustomObject]@{
                Server = $server
                EnableSMB1Protocol = $smbServer.EnableSMB1Protocol
                EnableSMB2Protocol = $smbServer.EnableSMB2Protocol
            }
        }
        catch {
            Write-Host "Error checking SMB protocol versions on $server : $_" -ForegroundColor Red
        }
    }
    $protocolResults | Format-Table -AutoSize
    return $protocolResults
}

<#
.SYNOPSIS
Analyzes SMB security settings on target servers.

.PARAMETER Servers
Array of server names to analyze.

.OUTPUTS
Array of PSObjects containing SMB security setting details.
#>
function Analyze-SMBSecuritySettings {
    param([string[]]$Servers)

    Write-Host "`nAnalyzing SMB Security Settings..." -ForegroundColor Yellow
    $securityResults = @()
    foreach ($server in $Servers) {
        try {
            $smbServer = Get-SmbServerConfiguration -CimSession $server -ErrorAction Stop
            $securityResults += [PSCustomObject]@{
                Server = $server
                RequireSecuritySignature = $smbServer.RequireSecuritySignature
                EncryptData = $smbServer.EncryptData
                EnableAuthenticateUserSharing = $smbServer.EnableAuthenticateUserSharing
                EnableSecuritySignature = $smbServer.EnableSecuritySignature
            }
        }
        catch {
            Write-Host "Error analyzing SMB security settings on $server : $_" -ForegroundColor Red
        }
    }
    $securityResults | Format-Table -AutoSize
    return $securityResults
}

<#
.SYNOPSIS
Checks SMB performance counters on target servers.

.PARAMETER Servers
Array of server names to analyze.

.OUTPUTS
Array of PSObjects containing SMB performance counter details.
#>
function Check-SMBPerformanceCounters {
    param([string[]]$Servers)

    Write-Host "`nChecking SMB Performance Counters..." -ForegroundColor Yellow
    $performanceResults = @()
    foreach ($server in $Servers) {
        try {
            $counters = Get-Counter -ComputerName $server -Counter @(
                "\SMB Server\Data Bytes/sec",
                "\SMB Server\Read Bytes/sec",
                "\SMB Server\Write Bytes/sec"
            ) -ErrorAction Stop
            $performanceResults += [PSCustomObject]@{
                Server = $server
                DataBytesPerSec = $counters.CounterSamples[0].CookedValue
                ReadBytesPerSec = $counters.CounterSamples[1].CookedValue
                WriteBytesPerSec = $counters.CounterSamples[2].CookedValue
            }
        }
        catch {
            Write-Host "Error checking SMB performance counters on $server : $_" -ForegroundColor Red
        }
    }
    $performanceResults | Format-Table -AutoSize
    return $performanceResults
}

<#
.SYNOPSIS
Analyzes SMB encryption status on target servers.

.PARAMETER Servers
Array of server names to analyze.

.OUTPUTS
Array of PSObjects containing SMB encryption status details.
#>
function Analyze-SMBEncryptionStatus {
    param([string[]]$Servers)

    Write-Host "`nAnalyzing SMB Encryption Status..." -ForegroundColor Yellow
    $encryptionResults = @()
    foreach ($server in $Servers) {
        try {
            $smbServer = Get-SmbServerConfiguration -CimSession $server -ErrorAction Stop
            $encryptionResults += [PSCustomObject]@{
                Server = $server
                EncryptData = $smbServer.EncryptData
                RejectUnencryptedAccess = $smbServer.RejectUnencryptedAccess
            }
        }
        catch {
            Write-Host "Error analyzing SMB encryption status on $server : $_" -ForegroundColor Red
        }
    }
    $encryptionResults | Format-Table -AutoSize
    return $encryptionResults
}

<#
.SYNOPSIS
Checks SMB signing configuration on target servers.

.PARAMETER Servers
Array of server names to analyze.

.OUTPUTS
Array of PSObjects containing SMB signing configuration details.
#>
function Check-SMBSigningConfiguration {
    param([string[]]$Servers)

    Write-Host "`nChecking SMB Signing Configuration..." -ForegroundColor Yellow
    $signingResults = @()
    foreach ($server in $Servers) {
        try {
            $smbServer = Get-SmbServerConfiguration -CimSession $server -ErrorAction Stop
            $signingResults += [PSCustomObject]@{
                Server = $server
                RequireSecuritySignature = $smbServer.RequireSecuritySignature
                EnableSecuritySignature = $smbServer.EnableSecuritySignature
            }
        }
        catch {
            Write-Host "Error checking SMB signing configuration on $server : $_" -ForegroundColor Red
        }
    }
    $signingResults | Format-Table -AutoSize
    return $signingResults
}

<#
.SYNOPSIS
Analyzes SMB client connections on target servers.

.PARAMETER Servers
Array of server names to analyze.

.OUTPUTS
Array of PSObjects containing SMB client connection details.
#>
function Analyze-SMBClientConnections {
    param([string[]]$Servers)

    Write-Host "`nAnalyzing SMB Client Connections..." -ForegroundColor Yellow
    $connectionResults = @()
    foreach ($server in $Servers) {
        try {
            $connections = Get-SmbConnection -CimSession $server -ErrorAction Stop
            foreach ($connection in $connections) {
                $connectionResults += [PSCustomObject]@{
                    Server = $server
                    ClientComputerName = $connection.ClientComputerName
                    ShareName = $connection.ShareName
                    Dialect = $connection.Dialect
                    NumOpens = $connection.NumOpens
                }
            }
        }
        catch {
            Write-Host "Error analyzing SMB client connections on $server : $_" -ForegroundColor Red
        }
    }
    $connectionResults | Format-Table -AutoSize
    return $connectionResults
}

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

    <h2>SMB Shares</h2>
    $($AllResults.SMBShares | ConvertTo-Html -Fragment)

    <h2>SMB Protocol Versions</h2>
    $($AllResults.ProtocolVersions | ConvertTo-Html -Fragment)

    <h2>SMB Security Settings</h2>
    $($AllResults.SecuritySettings | ConvertTo-Html -Fragment)

    <h2>SMB Performance Counters</h2>
    $($AllResults.PerformanceCounters | ConvertTo-Html -Fragment)

    <h2>SMB Encryption Status</h2>
    $($AllResults.EncryptionStatus | ConvertTo-Html -Fragment)

    <h2>SMB Signing Configuration</h2>
    $($AllResults.SigningConfiguration | ConvertTo-Html -Fragment)

    <h2>SMB Client Connections</h2>
    $($AllResults.ClientConnections | 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
$targetServers = Get-TargetServers
$allResults = @{}

do {
    Show-Menu
    $choice = Read-Host "`nEnter your choice (1-9)"

    switch ($choice) {
        "1" { $allResults.SMBShares = Analyze-SMBShares -Servers $targetServers }
        "2" { $allResults.ProtocolVersions = Check-SMBProtocolVersions -Servers $targetServers }
        "3" { $allResults.SecuritySettings = Analyze-SMBSecuritySettings -Servers $targetServers }
        "4" { $allResults.PerformanceCounters = Check-SMBPerformanceCounters -Servers $targetServers }
        "5" { $allResults.EncryptionStatus = Analyze-SMBEncryptionStatus -Servers $targetServers }
        "6" { $allResults.SigningConfiguration = Check-SMBSigningConfiguration -Servers $targetServers }
        "7" { $allResults.ClientConnections = Analyze-SMBClientConnections -Servers $targetServers }
        "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 SMB Analyzer Tool includes:

  1. A menu-driven interface for easy navigation.
  2. Functions to analyze various aspects of SMB:
    • SMB Shares analysis
    • SMB Protocol Versions check
    • SMB Security Settings analysis
    • SMB Performance Counters check
    • SMB Encryption Status analysis
    • SMB Signing Configuration check
    • SMB Client Connections analysis
  3. Flexible server selection (all domain servers, specific servers, or from a file).
  4. Comprehensive error handling for each analysis function.
  5. A function to generate an HTML report of all collected data.

Key features:

  • Detailed analysis of SMB shares across multiple servers
  • Checking of SMB protocol versions in use
  • Review of SMB security settings and configurations
  • Performance analysis using SMB-related counters
  • Encryption and signing configuration checks
  • Analysis of current SMB client connections
  • HTML report generation for easy sharing and viewing of results

This tool is particularly useful for:

  • System administrators managing file servers
  • Network administrators troubleshooting SMB-related issues
  • Security professionals auditing SMB configurations
  • IT professionals performing server health checks

To use this script effectively:

  1. Run PowerShell as an administrator
  2. Ensure you have the necessary permissions to query the target servers
  3. Have the required PowerShell modules available (like ActiveDirectory if querying domain servers)

This script provides a comprehensive overview of SMB configurations and potential issues across multiple servers in your network. It can significantly streamline the process of auditing and maintaining SMB services, enhancing both performance and security aspects of file sharing in your environment.

NETLOGON Analyzer Tool

<#
.SYNOPSIS
NETLOGON Analyzer Tool

.DESCRIPTION
This script analyzes NETLOGON-related issues, log files, and configurations across Domain Controllers
in an Active Directory environment.

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

.EXAMPLE
.\NETLOGONAnalyzer.ps1
#>

# Import required modules
Import-Module ActiveDirectory

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

<#
.SYNOPSIS
Displays the main menu of the tool.
#>
function Show-Menu {
    Clear-Host
    Write-Host "=== NETLOGON Analyzer Tool ===" -ForegroundColor Cyan
    Write-Host "1. Check NETLOGON Service Status"
    Write-Host "2. Analyze NETLOGON Log Files"
    Write-Host "3. Verify NETLOGON Share Accessibility"
    Write-Host "4. Check NETLOGON Registry Settings"
    Write-Host "5. Analyze NETLOGON-related Group Policies"
    Write-Host "6. Check Secure Channel Status"
    Write-Host "7. Analyze NETLOGON Performance Counters"
    Write-Host "8. Generate Comprehensive HTML Report"
    Write-Host "9. Exit"
}

<#
.SYNOPSIS
Checks NETLOGON service status on all Domain Controllers.

.OUTPUTS
Array of PSObjects containing NETLOGON service status for each DC.
#>
function Check-NETLOGONServiceStatus {
    Write-Host "`nChecking NETLOGON Service Status..." -ForegroundColor Yellow
    $dcs = Get-ADDomainController -Filter *
    $serviceStatus = @()
    foreach ($dc in $dcs) {
        $status = Get-Service -ComputerName $dc.HostName -Name "Netlogon" -ErrorAction SilentlyContinue
        $serviceStatus += [PSCustomObject]@{
            DomainController = $dc.HostName
            Status = if ($status) { $status.Status } else { "Unable to retrieve" }
            StartType = if ($status) { $status.StartType } else { "Unknown" }
        }
    }
    $serviceStatus | Format-Table -AutoSize
    return $serviceStatus
}

<#
.SYNOPSIS
Analyzes NETLOGON log files on all Domain Controllers.

.OUTPUTS
Array of PSObjects containing NETLOGON log analysis for each DC.
#>
function Analyze-NETLOGONLogFiles {
    Write-Host "`nAnalyzing NETLOGON Log Files..." -ForegroundColor Yellow
    $dcs = Get-ADDomainController -Filter *
    $logAnalysis = @()
    foreach ($dc in $dcs) {
        $logPath = "\\$($dc.HostName)\c$\Windows\debug\netlogon.log"
        if (Test-Path $logPath) {
            $logContent = Get-Content $logPath -Tail 100
            $errorCount = ($logContent | Select-String -Pattern "ERROR" -CaseSensitive).Count
            $warningCount = ($logContent | Select-String -Pattern "WARNING" -CaseSensitive).Count
            $recentErrors = $logContent | Select-String -Pattern "ERROR" -CaseSensitive | Select-Object -Last 5

            $logAnalysis += [PSCustomObject]@{
                DomainController = $dc.HostName
                ErrorCount = $errorCount
                WarningCount = $warningCount
                RecentErrors = $recentErrors -join "`n"
            }
        } else {
            $logAnalysis += [PSCustomObject]@{
                DomainController = $dc.HostName
                ErrorCount = "N/A"
                WarningCount = "N/A"
                RecentErrors = "Unable to access log file"
            }
        }
    }
    $logAnalysis | Format-Table -AutoSize
    return $logAnalysis
}

<#
.SYNOPSIS
Verifies NETLOGON share accessibility on all Domain Controllers.

.OUTPUTS
Array of PSObjects containing NETLOGON share accessibility status for each DC.
#>
function Verify-NETLOGONShareAccessibility {
    Write-Host "`nVerifying NETLOGON Share Accessibility..." -ForegroundColor Yellow
    $dcs = Get-ADDomainController -Filter *
    $shareStatus = @()
    foreach ($dc in $dcs) {
        $sharePath = "\\$($dc.HostName)\NETLOGON"
        $accessible = Test-Path $sharePath -ErrorAction SilentlyContinue
        $shareStatus += [PSCustomObject]@{
            DomainController = $dc.HostName
            ShareAccessible = $accessible
            SharePath = $sharePath
        }
    }
    $shareStatus | Format-Table -AutoSize
    return $shareStatus
}

<#
.SYNOPSIS
Checks NETLOGON-related registry settings on all Domain Controllers.

.OUTPUTS
Array of PSObjects containing NETLOGON registry settings for each DC.
#>
function Check-NETLOGONRegistrySettings {
    Write-Host "`nChecking NETLOGON Registry Settings..." -ForegroundColor Yellow
    $dcs = Get-ADDomainController -Filter *
    $registrySettings = @()
    foreach ($dc in $dcs) {
        $settings = Invoke-Command -ComputerName $dc.HostName -ScriptBlock {
            $netlogonParams = Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters" -ErrorAction SilentlyContinue
            return @{
                MaximumLogFileSize = $netlogonParams.MaximumLogFileSize
                DebugFlag = $netlogonParams.DbFlag
                ScavengeInterval = $netlogonParams.ScavengeInterval
            }
        } -ErrorAction SilentlyContinue

        $registrySettings += [PSCustomObject]@{
            DomainController = $dc.HostName
            MaxLogFileSize = if ($settings) { $settings.MaximumLogFileSize } else { "Unable to retrieve" }
            DebugFlag = if ($settings) { $settings.DebugFlag } else { "Unable to retrieve" }
            ScavengeInterval = if ($settings) { $settings.ScavengeInterval } else { "Unable to retrieve" }
        }
    }
    $registrySettings | Format-Table -AutoSize
    return $registrySettings
}

<#
.SYNOPSIS
Analyzes NETLOGON-related Group Policies.

.OUTPUTS
Array of PSObjects containing NETLOGON-related Group Policy settings.
#>
function Analyze-NETLOGONGroupPolicies {
    Write-Host "`nAnalyzing NETLOGON-related Group Policies..." -ForegroundColor Yellow
    $gpos = Get-GPO -All | Where-Object { $_.DisplayName -like "*NETLOGON*" -or $_.DisplayName -like "*Secure Channel*" }
    $gpAnalysis = @()
    foreach ($gpo in $gpos) {
        $report = Get-GPOReport -Guid $gpo.Id -ReportType XML
        $netlogonSettings = ([xml]$report).GPO.Computer.ExtensionData.Extension.Policy | 
            Where-Object { $_.Name -like "*NETLOGON*" -or $_.Name -like "*Secure Channel*" }
        
        foreach ($setting in $netlogonSettings) {
            $gpAnalysis += [PSCustomObject]@{
                GPOName = $gpo.DisplayName
                PolicyName = $setting.Name
                PolicyState = $setting.State
            }
        }
    }
    $gpAnalysis | Format-Table -AutoSize
    return $gpAnalysis
}

<#
.SYNOPSIS
Checks Secure Channel status for all Domain Controllers.

.OUTPUTS
Array of PSObjects containing Secure Channel status for each DC.
#>
function Check-SecureChannelStatus {
    Write-Host "`nChecking Secure Channel Status..." -ForegroundColor Yellow
    $dcs = Get-ADDomainController -Filter *
    $secureChannelStatus = @()
    foreach ($dc in $dcs) {
        $status = Test-ComputerSecureChannel -Server $dc.HostName -ErrorAction SilentlyContinue
        $secureChannelStatus += [PSCustomObject]@{
            DomainController = $dc.HostName
            SecureChannelStatus = if ($status) { "Healthy" } else { "Unhealthy" }
        }
    }
    $secureChannelStatus | Format-Table -AutoSize
    return $secureChannelStatus
}

<#
.SYNOPSIS
Analyzes NETLOGON-related performance counters on all Domain Controllers.

.OUTPUTS
Array of PSObjects containing NETLOGON performance counter data for each DC.
#>
function Analyze-NETLOGONPerformanceCounters {
    Write-Host "`nAnalyzing NETLOGON Performance Counters..." -ForegroundColor Yellow
    $dcs = Get-ADDomainController -Filter *
    $perfCounters = @()
    foreach ($dc in $dcs) {
        $counters = Invoke-Command -ComputerName $dc.HostName -ScriptBlock {
            $netlogonCounters = Get-Counter -Counter @(
                "\Netlogon(*)\*"
            ) -ErrorAction SilentlyContinue
            return $netlogonCounters.CounterSamples | Select-Object Path, CookedValue
        } -ErrorAction SilentlyContinue

        if ($counters) {
            $perfCounters += [PSCustomObject]@{
                DomainController = $dc.HostName
                Semaphore_Acquires = ($counters | Where-Object { $_.Path -like "*Semaphore Acquires*" }).CookedValue
                Semaphore_Timeouts = ($counters | Where-Object { $_.Path -like "*Semaphore Timeouts*" }).CookedValue
                Semaphore_Holders = ($counters | Where-Object { $_.Path -like "*Semaphore Holders*" }).CookedValue
                Semaphore_Waiters = ($counters | Where-Object { $_.Path -like "*Semaphore Waiters*" }).CookedValue
            }
        } else {
            $perfCounters += [PSCustomObject]@{
                DomainController = $dc.HostName
                Semaphore_Acquires = "Unable to retrieve"
                Semaphore_Timeouts = "Unable to retrieve"
                Semaphore_Holders = "Unable to retrieve"
                Semaphore_Waiters = "Unable to retrieve"
            }
        }
    }
    $perfCounters | Format-Table -AutoSize
    return $perfCounters
}

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

    <h2>NETLOGON Service Status</h2>
    $($AllResults.ServiceStatus | ConvertTo-Html -Fragment)

    <h2>NETLOGON Log File Analysis</h2>
    $($AllResults.LogAnalysis | ConvertTo-Html -Fragment)

    <h2>NETLOGON Share Accessibility</h2>
    $($AllResults.ShareStatus | ConvertTo-Html -Fragment)

    <h2>NETLOGON Registry Settings</h2>
    $($AllResults.RegistrySettings | ConvertTo-Html -Fragment)

    <h2>NETLOGON-related Group Policies</h2>
    $($AllResults.GPAnalysis | ConvertTo-Html -Fragment)

    <h2>Secure Channel Status</h2>
    $($AllResults.SecureChannelStatus | ConvertTo-Html -Fragment)

    <h2>NETLOGON Performance Counters</h2>
    $($AllResults.PerfCounters | 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.ServiceStatus = Check-NETLOGONServiceStatus }
        "2" { $allResults.LogAnalysis = Analyze-NETLOGONLogFiles }
        "3" { $allResults.ShareStatus = Verify-NETLOGONShareAccessibility }
        "4" { $allResults.RegistrySettings = Check-NETLOGONRegistrySettings }
        "5" { $allResults.GPAnalysis = Analyze-NETLOGONGroupPolicies }
        "6" { $allResults.SecureChannelStatus = Check-SecureChannelStatus }
        "7" { $allResults.PerfCounters = Analyze-NETLOGONPerformanceCounters }
        "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 NETLOGON Analyzer Tool includes:

  1. A menu-driven interface for easy navigation.
  2. Functions to analyze various aspects of NETLOGON:
    • NETLOGON Service Status check
    • NETLOGON Log File analysis
    • NETLOGON Share accessibility verification
    • NETLOGON Registry Settings check
    • NETLOGON-related Group Policy analysis
    • Secure Channel status check
    • NETLOGON Performance Counter analysis
  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 NETLOGON service status across all Domain Controllers
  • Examination of NETLOGON log files for errors and warnings
  • Verification of NETLOGON share accessibility
  • Analysis of NETLOGON-related registry settings
  • Review of Group Policies affecting NETLOGON
  • Checking Secure Channel status for each DC
  • Analysis of NETLOGON performance counters
  • HTML report generation for easy sharing and viewing of results

This tool is particularly useful for:

  • Active Directory administrators
  • System administrators troubleshooting NETLOGON issues
  • IT professionals performing AD health checks
  • Security teams auditing AD configurations

To use this script effectively:

  1. Run PowerShell as an administrator
  2. Ensure you have the necessary permissions to query Domain Controllers and access NETLOGON-related information
  3. Have the Active Directory PowerShell module installed

This script provides a comprehensive overview of NETLOGON-related configurations and potential issues across an Active Directory environment. It can significantly streamline the process of troubleshooting NETLOGON problems and maintaining a healthy AD infrastructure.

FSMO (Flexible Single Master Operation)

Roles: Ensuring Efficient Domain Management

In the world of Microsoft Active Directory, the Flexible Single Master Operation (FSMO) roles play a crucial part in maintaining the integrity and functionality of the domain. These specialized roles are responsible for managing specific domain-wide operations, ensuring that the directory services operate seamlessly and efficiently.

Understanding FSMO Roles: FSMO roles are assigned to specific domain controllers within an Active Directory environment. These roles are designed to handle specific tasks that require a single, authoritative source to maintain consistency and prevent conflicts. There are five FSMO roles in total, each with its own unique responsibilities:

  1. Schema Master: This role is responsible for managing and updating the Active Directory schema, which defines the structure and attributes of objects within the directory.
  2. Domain Naming Master: This role is responsible for managing the addition and removal of domains within the forest.
  3. RID (Relative Identifier) Master: This role is responsible for allocating unique security identifiers (RIDs) to new objects, ensuring that each object has a unique identifier within the domain.
  4. PDC (Primary Domain Controller) Emulator: This role is responsible for handling password changes, password replication, and other time-sensitive operations within the domain.
  5. Infrastructure Master: This role is responsible for maintaining the integrity of cross-domain object references, ensuring that objects in one domain can be properly referenced from other domains.

Importance of FSMO Roles: The FSMO roles are crucial for the proper functioning of an Active Directory environment. If a FSMO role is not properly managed or if a domain controller holding a FSMO role becomes unavailable, it can lead to various issues, such as:

  • Schema changes not being replicated correctly
  • Inability to add or remove domains within the forest
  • Inconsistent security identifiers for new objects
  • Incorrect password changes and replication
  • Broken cross-domain object references

Maintaining FSMO Roles: To ensure the efficient management of FSMO roles, it is essential to follow best practices, such as:

  1. Identifying the FSMO role holders: Regularly monitor the FSMO role holders and ensure that they are distributed across multiple domain controllers for redundancy.
  2. Transferring FSMO roles: When necessary, transfer FSMO roles to other domain controllers to maintain availability and balance the load.
  3. Monitoring FSMO role health: Regularly check the health and status of FSMO roles, and address any issues or failures promptly.
  4. Implementing backup and recovery strategies: Ensure that you have a comprehensive backup and recovery plan in place to quickly restore FSMO roles in the event of a disaster or system failure.

By understanding and properly managing FSMO roles, IT administrators can ensure the stability, reliability, and efficient operation of their Active Directory environments, ultimately providing a seamless user experience and maintaining the overall integrity of the directory services.

# Function to get the current FSMO role holders
function Get-FSMORoleHolders {
    $schemaMaster = (Get-ADDomain).SchemaMaster
    $domainNamingMaster = (Get-ADDomain).DomainNamingMaster
    $ridMaster = (Get-ADDomain).RIDMaster
    $pdc = (Get-ADDomain).PDCEmulator
    $infrastructureMaster = (Get-ADDomain).InfrastructureMaster

    return [PSCustomObject]@{
        "Schema Master" = $schemaMaster
        "Domain Naming Master" = $domainNamingMaster
        "RID Master" = $ridMaster
        "PDC Emulator" = $pdc
        "Infrastructure Master" = $infrastructureMaster
    }
}

# Function to transfer FSMO roles
function Transfer-FSMORoles {
    param (
        [Parameter(Mandatory=$true)]
        [string]$TargetDomainController
    )

    # Transfer Schema Master role
    Set-ADDomainControllerPassword -Credential (Get-Credential) -Server $TargetDomainController
    Move-ADDirectoryServerOperationMasterRole -Identity $TargetDomainController -OperationMasterRole SchemaMaster

    # Transfer Domain Naming Master role
    Move-ADDirectoryServerOperationMasterRole -Identity $TargetDomainController -OperationMasterRole DomainNamingMaster

    # Transfer RID Master role
    Move-ADDirectoryServerOperationMasterRole -Identity $TargetDomainController -OperationMasterRole RIDMaster

    # Transfer PDC Emulator role
    Move-ADDirectoryServerOperationMasterRole -Identity $TargetDomainController -OperationMasterRole PDCEmulator

    # Transfer Infrastructure Master role
    Move-ADDirectoryServerOperationMasterRole -Identity $TargetDomainController -OperationMasterRole InfrastructureMaster
}

# Example usage
$currentFSMORoleHolders = Get-FSMORoleHolders
$currentFSMORoleHolders

# Transfer FSMO roles to a new domain controller
Transfer-FSMORoles -TargetDomainController "NewDomainController.contoso.com"

Here’s how the script works:

  1. The Get-FSMORoleHolders function retrieves the current FSMO role holders by querying the Active Directory domain.
  2. The Transfer-FSMORoles function takes a target domain controller as a parameter and transfers all FSMO roles to that domain controller.
    • It first sets the domain controller password using Set-ADDomainControllerPassword.
    • Then, it transfers each FSMO role using the Move-ADDirectoryServerOperationMasterRole cmdlet.

To use the script, follow these steps:

  1. Save the script to a file (e.g., FSMOManagement.ps1).
  2. Open PowerShell and navigate to the directory where you saved the script.
  3. Run the script to get the current FSMO role holders: .\FSMOManagement.ps1
  4. To transfer the FSMO roles to a new domain controller, run the Transfer-FSMORoles function and provide the target domain controller name: Transfer-FSMORoles -TargetDomainController "NewDomainController.contoso.com"
  5. Make sure to replace "NewDomainController.contoso.com" with the actual name of the target domain controller.

This script provides a simple way to manage FSMO roles in your Active Directory environment. You can customize it further to fit your specific needs, such as adding error handling, logging, or scheduling the role transfer process.

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.

Domain Controller Analyzer Tool

<#
.SYNOPSIS
Domain Controller Analyzer Tool

.DESCRIPTION
This script analyzes Domain Controllers in an Active Directory environment, providing detailed information
about DC health, replication status, performance metrics, and potential issues.

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

.EXAMPLE
.\DCAnalyzer.ps1
#>

# Import required modules
Import-Module ActiveDirectory

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

<#
.SYNOPSIS
Displays the main menu of the tool.
#>
function Show-Menu {
    Clear-Host
    Write-Host "=== Domain Controller Analyzer Tool ===" -ForegroundColor Cyan
    Write-Host "1. Perform DC Health Check"
    Write-Host "2. Analyze Replication Status"
    Write-Host "3. Check FSMO Roles"
    Write-Host "4. Analyze DC Performance Metrics"
    Write-Host "5. Check AD Services Status"
    Write-Host "6. Verify DNS Configuration"
    Write-Host "7. Analyze SYSVOL and NETLOGON Shares"
    Write-Host "8. Generate Comprehensive HTML Report"
    Write-Host "9. Exit"
}

<#
.SYNOPSIS
Performs a health check on all Domain Controllers.

.OUTPUTS
Array of PSObjects containing DC health check results.
#>
function Perform-DCHealthCheck {
    Write-Host "`nPerforming DC Health Check..." -ForegroundColor Yellow
    $dcs = Get-ADDomainController -Filter *
    $healthResults = @()
    foreach ($dc in $dcs) {
        $dcdiag = Invoke-Command -ComputerName $dc.HostName -ScriptBlock {
            dcdiag /test:services /test:advertising /test:fsmocheck /test:ridmanager /test:machineaccount /test:replications /test:netlogons /test:systemlog
        } -ErrorAction SilentlyContinue

        $healthResults += [PSCustomObject]@{
            DomainController = $dc.HostName
            Services = if ($dcdiag -match "passed test Services") { "Passed" } else { "Failed" }
            Advertising = if ($dcdiag -match "passed test Advertising") { "Passed" } else { "Failed" }
            FSMORoles = if ($dcdiag -match "passed test FsmoCheck") { "Passed" } else { "Failed" }
            RidManager = if ($dcdiag -match "passed test RidManager") { "Passed" } else { "Failed" }
            MachineAccount = if ($dcdiag -match "passed test MachineAccount") { "Passed" } else { "Failed" }
            Replications = if ($dcdiag -match "passed test Replications") { "Passed" } else { "Failed" }
            Netlogons = if ($dcdiag -match "passed test NetLogons") { "Passed" } else { "Failed" }
            SystemLog = if ($dcdiag -match "passed test SystemLog") { "Passed" } else { "Failed" }
        }
    }
    $healthResults | Format-Table -AutoSize
    return $healthResults
}

<#
.SYNOPSIS
Analyzes replication status between Domain Controllers.

.OUTPUTS
Array of PSObjects containing replication status details.
#>
function Analyze-ReplicationStatus {
    Write-Host "`nAnalyzing Replication Status..." -ForegroundColor Yellow
    $replicationStatus = @()
    $dcs = Get-ADDomainController -Filter *
    foreach ($dc in $dcs) {
        $replStatus = repadmin /showrepl $dc.HostName | Select-String "Last attempt" -Context 2,0
        foreach ($status in $replStatus) {
            $replicationStatus += [PSCustomObject]@{
                SourceDC = $dc.HostName
                DestinationDC = ($status.Context.PreContext[0] -split ":")[1].Trim()
                LastAttempt = ($status.Line -split "@")[1].Trim()
                Result = $status.Context.PostContext[0].Trim()
            }
        }
    }
    $replicationStatus | Format-Table -AutoSize
    return $replicationStatus
}

<#
.SYNOPSIS
Checks FSMO roles distribution.

.OUTPUTS
PSObject containing FSMO roles information.
#>
function Check-FSMORoles {
    Write-Host "`nChecking FSMO Roles..." -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
Analyzes performance metrics of Domain Controllers.

.OUTPUTS
Array of PSObjects containing DC performance metrics.
#>
function Analyze-DCPerformanceMetrics {
    Write-Host "`nAnalyzing DC Performance Metrics..." -ForegroundColor Yellow
    $dcs = Get-ADDomainController -Filter *
    $performanceMetrics = @()
    foreach ($dc in $dcs) {
        $cpu = Get-WmiObject Win32_Processor -ComputerName $dc.HostName | Measure-Object -Property LoadPercentage -Average | Select-Object -ExpandProperty Average
        $memory = Get-WmiObject Win32_OperatingSystem -ComputerName $dc.HostName | Select-Object @{Name="MemoryUsage";Expression={"{0:N2}" -f ((($_.TotalVisibleMemorySize - $_.FreePhysicalMemory)*100)/ $_.TotalVisibleMemorySize)}}
        $disk = Get-WmiObject Win32_LogicalDisk -ComputerName $dc.HostName -Filter "DeviceID='C:'" | Select-Object @{Name="FreeSpace";Expression={"{0:N2}" -f ($_.FreeSpace/1GB)}}

        $performanceMetrics += [PSCustomObject]@{
            DomainController = $dc.HostName
            CPUUsage = "$cpu%"
            MemoryUsage = "$($memory.MemoryUsage)%"
            FreeDiskSpace = "$($disk.FreeSpace) GB"
        }
    }
    $performanceMetrics | Format-Table -AutoSize
    return $performanceMetrics
}

<#
.SYNOPSIS
Checks the status of critical AD services on Domain Controllers.

.OUTPUTS
Array of PSObjects containing AD services status.
#>
function Check-ADServicesStatus {
    Write-Host "`nChecking AD Services Status..." -ForegroundColor Yellow
    $dcs = Get-ADDomainController -Filter *
    $servicesStatus = @()
    $criticalServices = @("NTDS", "Netlogon", "DNS", "DFSR", "KDC")

    foreach ($dc in $dcs) {
        $services = Get-Service -ComputerName $dc.HostName -Name $criticalServices -ErrorAction SilentlyContinue
        $servicesStatus += [PSCustomObject]@{
            DomainController = $dc.HostName
            NTDS = ($services | Where-Object {$_.Name -eq "NTDS"}).Status
            Netlogon = ($services | Where-Object {$_.Name -eq "Netlogon"}).Status
            DNS = ($services | Where-Object {$_.Name -eq "DNS"}).Status
            DFSR = ($services | Where-Object {$_.Name -eq "DFSR"}).Status
            KDC = ($services | Where-Object {$_.Name -eq "KDC"}).Status
        }
    }
    $servicesStatus | Format-Table -AutoSize
    return $servicesStatus
}

<#
.SYNOPSIS
Verifies DNS configuration on Domain Controllers.

.OUTPUTS
Array of PSObjects containing DNS configuration details.
#>
function Verify-DNSConfiguration {
    Write-Host "`nVerifying DNS Configuration..." -ForegroundColor Yellow
    $dcs = Get-ADDomainController -Filter *
    $dnsConfig = @()
    foreach ($dc in $dcs) {
        $dnsServers = Get-DnsClientServerAddress -CimSession $dc.HostName -AddressFamily IPv4 | Where-Object {$_.InterfaceAlias -notlike "*Loopback*"}
        $dnsConfig += [PSCustomObject]@{
            DomainController = $dc.HostName
            DNSServers = ($dnsServers.ServerAddresses -join ", ")
            HasDNSRole = [bool](Get-WindowsFeature -ComputerName $dc.HostName -Name DNS).Installed
        }
    }
    $dnsConfig | Format-Table -AutoSize
    return $dnsConfig
}

<#
.SYNOPSIS
Analyzes SYSVOL and NETLOGON shares on Domain Controllers.

.OUTPUTS
Array of PSObjects containing SYSVOL and NETLOGON share details.
#>
function Analyze-SYSVOLandNETLOGON {
    Write-Host "`nAnalyzing SYSVOL and NETLOGON Shares..." -ForegroundColor Yellow
    $dcs = Get-ADDomainController -Filter *
    $shareAnalysis = @()
    foreach ($dc in $dcs) {
        $sysvol = Get-WmiObject -Class Win32_Share -ComputerName $dc.HostName -Filter "Name='SYSVOL'"
        $netlogon = Get-WmiObject -Class Win32_Share -ComputerName $dc.HostName -Filter "Name='NETLOGON'"
        $shareAnalysis += [PSCustomObject]@{
            DomainController = $dc.HostName
            SYSVOLPath = $sysvol.Path
            NETLOGONPath = $netlogon.Path
            SYSVOLAccessible = Test-Path "\\$($dc.HostName)\SYSVOL" -ErrorAction SilentlyContinue
            NETLOGONAccessible = Test-Path "\\$($dc.HostName)\NETLOGON" -ErrorAction SilentlyContinue
        }
    }
    $shareAnalysis | Format-Table -AutoSize
    return $shareAnalysis
}

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

    <h2>DC Health Check</h2>
    $($AllResults.HealthCheck | ConvertTo-Html -Fragment)

    <h2>Replication Status</h2>
    $($AllResults.ReplicationStatus | ConvertTo-Html -Fragment)

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

    <h2>DC Performance Metrics</h2>
    $($AllResults.PerformanceMetrics | ConvertTo-Html -Fragment)

    <h2>AD Services Status</h2>
    $($AllResults.ServicesStatus | ConvertTo-Html -Fragment)

    <h2>DNS Configuration</h2>
    $($AllResults.DNSConfig | ConvertTo-Html -Fragment)

    <h2>SYSVOL and NETLOGON Analysis</h2>
    $($AllResults.ShareAnalysis | 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.HealthCheck = Perform-DCHealthCheck }
        "2" { $allResults.ReplicationStatus = Analyze-ReplicationStatus }
        "3" { $allResults.FSMORoles = Check-FSMORoles }
        "4" { $allResults.PerformanceMetrics = Analyze-DCPerformanceMetrics }
        "5" { $allResults.ServicesStatus = Check-ADServicesStatus }
        "6" { $allResults.DNSConfig = Verify-DNSConfiguration }
        "7" { $allResults.ShareAnalysis = Analyze-SYSVOLandNETLOGON }
        "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 Domain Controller Analyzer Tool includes:

  1. A menu-driven interface for easy navigation.
  2. Functions to analyze various aspects of Domain Controllers:
    • DC Health Check using dcdiag
    • Replication Status analysis
    • FSMO Roles check
    • Performance Metrics analysis
    • AD Services Status check
    • DNS Configuration verification
    • SYSVOL and NETLOGON share analysis
  3. Comprehensive error handling for each analysis function.
  4. A function to generate an HTML report of all collected data.

Key features:

  • Detailed health check of all Domain Controllers
  • Analysis of replication status between DCs
  • Verification of FSMO roles distribution
  • Performance metrics collection (CPU, Memory, Disk)
  • Status check of critical AD services
  • DNS configuration verification
  • SYSVOL and NETLOGON share accessibility check
  • 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
  • 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
  3. Have the Active Directory PowerShell module installed

This script provides a comprehensive overview of Domain Controllers in an Active Directory environment, making it easier to identify issues, performance bottlenecks, or misconfigurations. It can significantly streamline the process of maintaining and troubleshooting Domain Controllers in organizations of any size.

Microsoft 365 Analyzer Tool

<#
.SYNOPSIS
Microsoft 365 Analyzer Tool

.DESCRIPTION
This script analyzes various aspects of a Microsoft 365 environment, including user accounts,
licenses, Exchange Online, SharePoint Online, and Teams.

.NOTES
File Name      : Microsoft365Analyzer.ps1
Author         : [Your Name]
Prerequisite   : PowerShell V5.1 or later, Microsoft 365 PowerShell modules, and appropriate admin permissions
Version        : 1.0
Date           : [Current Date]

.EXAMPLE
.\Microsoft365Analyzer.ps1
#>

# Check and install required modules
$requiredModules = @("MSOnline", "ExchangeOnlineManagement", "Microsoft.Online.SharePoint.PowerShell", "MicrosoftTeams")
foreach ($module in $requiredModules) {
    if (!(Get-Module -ListAvailable -Name $module)) {
        Write-Host "Installing $module module..." -ForegroundColor Yellow
        Install-Module -Name $module -Force -AllowClobber
    }
}

# Import required modules
Import-Module MSOnline
Import-Module ExchangeOnlineManagement
Import-Module Microsoft.Online.SharePoint.PowerShell
Import-Module MicrosoftTeams

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

<#
.SYNOPSIS
Displays the main menu of the tool.
#>
function Show-Menu {
    Clear-Host
    Write-Host "=== Microsoft 365 Analyzer Tool ===" -ForegroundColor Cyan
    Write-Host "1. Analyze User Accounts and Licenses"
    Write-Host "2. Check Exchange Online Configuration"
    Write-Host "3. Analyze SharePoint Online Usage"
    Write-Host "4. Review Teams Configuration"
    Write-Host "5. Check Security and Compliance Settings"
    Write-Host "6. Analyze Azure AD Configuration"
    Write-Host "7. Generate Comprehensive HTML Report"
    Write-Host "8. Exit"
}

<#
.SYNOPSIS
Connects to Microsoft 365 services.
#>
function Connect-Microsoft365Services {
    Write-Host "Connecting to Microsoft 365 services..." -ForegroundColor Yellow
    Connect-MsolService
    Connect-ExchangeOnline
    $orgName = (Get-MsolCompanyInformation).DisplayName
    $adminSiteUrl = "https://$($orgName.Replace(' ', ''))-admin.sharepoint.com"
    Connect-SPOService -Url $adminSiteUrl
    Connect-MicrosoftTeams
}

<#
.SYNOPSIS
Analyzes user accounts and licenses.

.OUTPUTS
PSObject containing user account and license analysis.
#>
function Analyze-UserAccountsAndLicenses {
    Write-Host "`nAnalyzing User Accounts and Licenses..." -ForegroundColor Yellow
    $users = Get-MsolUser -All
    $licenses = Get-MsolAccountSku

    $analysis = [PSCustomObject]@{
        TotalUsers = $users.Count
        LicensedUsers = ($users | Where-Object {$_.IsLicensed -eq $true}).Count
        UnlicensedUsers = ($users | Where-Object {$_.IsLicensed -eq $false}).Count
        BlockedUsers = ($users | Where-Object {$_.BlockCredential -eq $true}).Count
        LicenseTypes = $licenses | Select-Object AccountSkuId, ActiveUnits, ConsumedUnits
    }

    $analysis | Format-List
    return $analysis
}

<#
.SYNOPSIS
Checks Exchange Online configuration.

.OUTPUTS
PSObject containing Exchange Online configuration details.
#>
function Check-ExchangeOnlineConfiguration {
    Write-Host "`nChecking Exchange Online Configuration..." -ForegroundColor Yellow
    $mailboxes = Get-Mailbox -ResultSize Unlimited
    $transportRules = Get-TransportRule

    $exchangeConfig = [PSCustomObject]@{
        TotalMailboxes = $mailboxes.Count
        SharedMailboxes = ($mailboxes | Where-Object {$_.RecipientTypeDetails -eq "SharedMailbox"}).Count
        ResourceMailboxes = ($mailboxes | Where-Object {$_.RecipientTypeDetails -eq "RoomMailbox" -or $_.RecipientTypeDetails -eq "EquipmentMailbox"}).Count
        TransportRules = $transportRules.Count
    }

    $exchangeConfig | Format-List
    return $exchangeConfig
}

<#
.SYNOPSIS
Analyzes SharePoint Online usage.

.OUTPUTS
PSObject containing SharePoint Online usage details.
#>
function Analyze-SharePointOnlineUsage {
    Write-Host "`nAnalyzing SharePoint Online Usage..." -ForegroundColor Yellow
    $sites = Get-SPOSite -Limit All
    $oneDriveUsage = Get-SPOTenantOneDriveUsageReport

    $spUsage = [PSCustomObject]@{
        TotalSites = $sites.Count
        TotalStorage = [math]::Round(($sites | Measure-Object StorageUsageCurrent -Sum).Sum / 1024, 2)
        AverageStoragePerSite = [math]::Round(($sites | Measure-Object StorageUsageCurrent -Average).Average / 1024, 2)
        OneDriveUsage = $oneDriveUsage
    }

    $spUsage | Format-List
    return $spUsage
}

<#
.SYNOPSIS
Reviews Teams configuration.

.OUTPUTS
PSObject containing Teams configuration details.
#>
function Review-TeamsConfiguration {
    Write-Host "`nReviewing Teams Configuration..." -ForegroundColor Yellow
    $teams = Get-Team
    $policies = Get-CsTeamsClientConfiguration

    $teamsConfig = [PSCustomObject]@{
        TotalTeams = $teams.Count
        PublicTeams = ($teams | Where-Object {$_.Visibility -eq "Public"}).Count
        PrivateTeams = ($teams | Where-Object {$_.Visibility -eq "Private"}).Count
        AllowEmailIntoChannel = $policies.AllowEmailIntoChannel
        AllowGiphy = $policies.AllowGiphy
        AllowStickers = $policies.AllowStickers
        AllowUserEditMessages = $policies.AllowUserEditMessages
    }

    $teamsConfig | Format-List
    return $teamsConfig
}

<#
.SYNOPSIS
Checks security and compliance settings.

.OUTPUTS
PSObject containing security and compliance settings.
#>
function Check-SecurityAndComplianceSettings {
    Write-Host "`nChecking Security and Compliance Settings..." -ForegroundColor Yellow
    $mfaStatus = Get-MsolUser -All | Where-Object {$_.StrongAuthenticationRequirements.State}
    $alertPolicies = Get-ProtectionAlert

    $securitySettings = [PSCustomObject]@{
        MFAEnabledUsers = $mfaStatus.Count
        AlertPolicies = $alertPolicies.Count
    }

    $securitySettings | Format-List
    return $securitySettings
}

<#
.SYNOPSIS
Analyzes Azure AD configuration.

.OUTPUTS
PSObject containing Azure AD configuration details.
#>
function Analyze-AzureADConfiguration {
    Write-Host "`nAnalyzing Azure AD Configuration..." -ForegroundColor Yellow
    $domains = Get-MsolDomain
    $devices = Get-MsolDevice -All

    $azureADConfig = [PSCustomObject]@{
        TotalDomains = $domains.Count
        VerifiedDomains = ($domains | Where-Object {$_.Status -eq "Verified"}).Count
        TotalDevices = $devices.Count
        AzureADJoinedDevices = ($devices | Where-Object {$_.DeviceTrustType -eq "Azure AD Joined"}).Count
    }

    $azureADConfig | Format-List
    return $azureADConfig
}

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

    <h2>User Accounts and Licenses</h2>
    $($AllResults.UserAccountsAndLicenses | ConvertTo-Html -Fragment)

    <h2>Exchange Online Configuration</h2>
    $($AllResults.ExchangeOnlineConfig | ConvertTo-Html -Fragment)

    <h2>SharePoint Online Usage</h2>
    $($AllResults.SharePointOnlineUsage | ConvertTo-Html -Fragment)

    <h2>Teams Configuration</h2>
    $($AllResults.TeamsConfig | ConvertTo-Html -Fragment)

    <h2>Security and Compliance Settings</h2>
    $($AllResults.SecuritySettings | ConvertTo-Html -Fragment)

    <h2>Azure AD Configuration</h2>
    $($AllResults.AzureADConfig | 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
Connect-Microsoft365Services
$allResults = @{}

do {
    Show-Menu
    $choice = Read-Host "`nEnter your choice (1-8)"

    switch ($choice) {
        "1" { $allResults.UserAccountsAndLicenses = Analyze-UserAccountsAndLicenses }
        "2" { $allResults.ExchangeOnlineConfig = Check-ExchangeOnlineConfiguration }
        "3" { $allResults.SharePointOnlineUsage = Analyze-SharePointOnlineUsage }
        "4" { $allResults.TeamsConfig = Review-TeamsConfiguration }
        "5" { $allResults.SecuritySettings = Check-SecurityAndComplianceSettings }
        "6" { $allResults.AzureADConfig = Analyze-AzureADConfiguration }
        "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")

# Disconnect from services
Disconnect-ExchangeOnline -Confirm:$false
Disconnect-SPOService
Disconnect-MicrosoftTeams

This Microsoft 365 Analyzer Tool includes:

  1. A menu-driven interface for easy navigation.
  2. Functions to analyze various aspects of Microsoft 365:
    • User accounts and licenses
    • Exchange Online configuration
    • SharePoint Online usage
    • Teams configuration
    • Security and compliance settings
    • Azure AD configuration
  3. Automatic installation of required PowerShell modules.
  4. Connection to necessary Microsoft 365 services.
  5. A function to generate an HTML report of all collected data.

Key features:

  • Comprehensive analysis of Microsoft 365 environment
  • Detailed insights into user accounts, licenses, and service configurations
  • Security and compliance overview
  • Azure AD configuration analysis
  • HTML report generation for easy sharing and viewing of results

This tool is particularly useful for:

  • Microsoft 365 administrators
  • IT professionals managing Microsoft 365 environments
  • Security teams auditing Microsoft 365 configurations
  • Consultants performing Microsoft 365 health checks

To use this script effectively:

  1. Run PowerShell as an administrator
  2. Ensure you have the necessary permissions to access Microsoft 365 services (Global Administrator or appropriate admin roles)
  3. Have an active internet connection

This script provides a comprehensive overview of a Microsoft 365 environment, making it easier to identify configuration issues, security concerns, or areas for optimization. It can significantly streamline the process of auditing and maintaining Microsoft 365 services in organizations of any size.

Active Directory Computer Analysis Tool

<#
.SYNOPSIS
Active Directory Computer Analysis Tool

.DESCRIPTION
This script analyzes computer accounts in Active Directory, providing detailed information
about computer properties, group memberships, operating systems, and potential issues.

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

.EXAMPLE
.\ADComputerAnalyzer.ps1
#>

# Import required modules
Import-Module ActiveDirectory

# Global variables
$global:reportPath = "$env:USERPROFILE\Desktop\AD_Computer_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 Computer Analysis Tool ===" -ForegroundColor Cyan
    Write-Host "1. Analyze Computer Account Statuses"
    Write-Host "2. Check Operating System Distribution"
    Write-Host "3. Analyze Group Memberships"
    Write-Host "4. Identify Inactive Computer Accounts"
    Write-Host "5. Check for Outdated Operating Systems"
    Write-Host "6. Analyze Computer Account Properties"
    Write-Host "7. Check DNS Registration Status"
    Write-Host "8. Generate Comprehensive HTML Report"
    Write-Host "9. Exit"
}

<#
.SYNOPSIS
Analyzes computer account statuses.

.OUTPUTS
Array of PSObjects containing computer account status details.
#>
function Analyze-ComputerAccountStatuses {
    Write-Host "`nAnalyzing Computer Account Statuses..." -ForegroundColor Yellow
    $computers = Get-ADComputer -Filter * -Properties Enabled, PasswordLastSet
    $statuses = @()
    foreach ($computer in $computers) {
        $statuses += [PSCustomObject]@{
            ComputerName = $computer.Name
            Enabled = $computer.Enabled
            PasswordLastSet = $computer.PasswordLastSet
            DaysSincePasswordSet = if ($computer.PasswordLastSet) { ((Get-Date) - $computer.PasswordLastSet).Days } else { "N/A" }
        }
    }
    $statuses | Format-Table -AutoSize
    return $statuses
}

<#
.SYNOPSIS
Checks operating system distribution.

.OUTPUTS
Array of PSObjects containing OS distribution details.
#>
function Check-OSDistribution {
    Write-Host "`nChecking Operating System Distribution..." -ForegroundColor Yellow
    $computers = Get-ADComputer -Filter * -Properties OperatingSystem
    $osDistribution = $computers | Group-Object -Property OperatingSystem | Select-Object Name, Count
    $osDistribution | Format-Table -AutoSize
    return $osDistribution
}

<#
.SYNOPSIS
Analyzes group memberships.

.OUTPUTS
Array of PSObjects containing group membership details.
#>
function Analyze-GroupMemberships {
    Write-Host "`nAnalyzing Group Memberships..." -ForegroundColor Yellow
    $computers = Get-ADComputer -Filter * -Properties MemberOf
    $memberships = @()
    foreach ($computer in $computers) {
        $groups = $computer.MemberOf | ForEach-Object { (Get-ADGroup $_).Name }
        $memberships += [PSCustomObject]@{
            ComputerName = $computer.Name
            GroupCount = $groups.Count
            Groups = $groups -join ", "
        }
    }
    $memberships | Format-Table -AutoSize
    return $memberships
}

<#
.SYNOPSIS
Identifies inactive computer accounts.

.OUTPUTS
Array of PSObjects containing inactive computer account details.
#>
function Identify-InactiveComputerAccounts {
    Write-Host "`nIdentifying Inactive Computer Accounts..." -ForegroundColor Yellow
    $inactiveThreshold = (Get-Date).AddDays(-90)
    $computers = Get-ADComputer -Filter {Enabled -eq $true} -Properties LastLogonDate
    $inactiveComputers = @()
    foreach ($computer in $computers) {
        if ($computer.LastLogonDate -lt $inactiveThreshold) {
            $inactiveComputers += [PSCustomObject]@{
                ComputerName = $computer.Name
                LastLogonDate = $computer.LastLogonDate
                DaysSinceLastLogon = ((Get-Date) - $computer.LastLogonDate).Days
            }
        }
    }
    $inactiveComputers | Format-Table -AutoSize
    return $inactiveComputers
}

<#
.SYNOPSIS
Checks for outdated operating systems.

.OUTPUTS
Array of PSObjects containing outdated OS details.
#>
function Check-OutdatedOS {
    Write-Host "`nChecking for Outdated Operating Systems..." -ForegroundColor Yellow
    $computers = Get-ADComputer -Filter * -Properties OperatingSystem, OperatingSystemVersion
    $outdatedOS = @()
    foreach ($computer in $computers) {
        if ($computer.OperatingSystem -like "*Windows 7*" -or 
            $computer.OperatingSystem -like "*Windows 8*" -or 
            $computer.OperatingSystem -like "*Windows Server 2008*" -or 
            $computer.OperatingSystem -like "*Windows Server 2012*") {
            $outdatedOS += [PSCustomObject]@{
                ComputerName = $computer.Name
                OperatingSystem = $computer.OperatingSystem
                OSVersion = $computer.OperatingSystemVersion
            }
        }
    }
    $outdatedOS | Format-Table -AutoSize
    return $outdatedOS
}

<#
.SYNOPSIS
Analyzes computer account properties.

.OUTPUTS
Array of PSObjects containing computer account property details.
#>
function Analyze-ComputerAccountProperties {
    Write-Host "`nAnalyzing Computer Account Properties..." -ForegroundColor Yellow
    $computers = Get-ADComputer -Filter * -Properties *
    $properties = @()
    foreach ($computer in $computers) {
        $properties += [PSCustomObject]@{
            ComputerName = $computer.Name
            OperatingSystem = $computer.OperatingSystem
            IPAddress = $computer.IPv4Address
            Created = $computer.Created
            LastModified = $computer.Modified
            Description = $computer.Description
        }
    }
    $properties | Format-Table -AutoSize
    return $properties
}

<#
.SYNOPSIS
Checks DNS registration status.

.OUTPUTS
Array of PSObjects containing DNS registration status details.
#>
function Check-DNSRegistrationStatus {
    Write-Host "`nChecking DNS Registration Status..." -ForegroundColor Yellow
    $computers = Get-ADComputer -Filter * -Properties DNSHostName
    $dnsStatus = @()
    foreach ($computer in $computers) {
        $pingResult = Test-Connection -ComputerName $computer.DNSHostName -Count 1 -ErrorAction SilentlyContinue
        $dnsStatus += [PSCustomObject]@{
            ComputerName = $computer.Name
            DNSHostName = $computer.DNSHostName
            Pingable = if ($pingResult) { $true } else { $false }
        }
    }
    $dnsStatus | Format-Table -AutoSize
    return $dnsStatus
}

<#
.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>AD Computer 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>Active Directory Computer Analysis Report</h1>
    <p>Generated on: $(Get-Date)</p>

    <h2>Computer Account Statuses</h2>
    $($AllResults.AccountStatuses | ConvertTo-Html -Fragment)

    <h2>Operating System Distribution</h2>
    $($AllResults.OSDistribution | ConvertTo-Html -Fragment)

    <h2>Group Memberships</h2>
    $($AllResults.GroupMemberships | ConvertTo-Html -Fragment)

    <h2>Inactive Computer Accounts</h2>
    $($AllResults.InactiveAccounts | ConvertTo-Html -Fragment)

    <h2>Outdated Operating Systems</h2>
    $($AllResults.OutdatedOS | ConvertTo-Html -Fragment)

    <h2>Computer Account Properties</h2>
    $($AllResults.AccountProperties | ConvertTo-Html -Fragment)

    <h2>DNS Registration Status</h2>
    $($AllResults.DNSStatus | 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.AccountStatuses = Analyze-ComputerAccountStatuses }
        "2" { $allResults.OSDistribution = Check-OSDistribution }
        "3" { $allResults.GroupMemberships = Analyze-GroupMemberships }
        "4" { $allResults.InactiveAccounts = Identify-InactiveComputerAccounts }
        "5" { $allResults.OutdatedOS = Check-OutdatedOS }
        "6" { $allResults.AccountProperties = Analyze-ComputerAccountProperties }
        "7" { $allResults.DNSStatus = Check-DNSRegistrationStatus }
        "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 Computer Analysis Tool includes:

  1. A menu-driven interface for easy navigation.
  2. Functions to analyze various aspects of computer accounts:
    • Computer account statuses (enabled, password last set)
    • Operating system distribution
    • Group memberships
    • Inactive computer accounts
    • Outdated operating systems
    • Computer account properties
    • DNS registration status
  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 computer account statuses and properties
  • Overview of operating system distribution across the domain
  • Identification of inactive computer accounts
  • Detection of outdated operating systems
  • Analysis of group memberships for computer accounts
  • Checking DNS registration status and connectivity
  • HTML report generation for easy sharing and viewing of results

This tool is particularly useful for:

  • Active Directory administrators managing computer accounts
  • IT security professionals auditing computer account security
  • System administrators planning OS upgrades or migrations
  • Network administrators troubleshooting DNS and connectivity issues

To use this script effectively:

  1. Run PowerShell as an administrator
  2. Ensure you have the necessary permissions to query AD computer information
  3. Have the Active Directory PowerShell module installed

This script provides a comprehensive overview of computer accounts in an Active Directory environment, making it easier to identify security issues, outdated systems, or potential network problems. It can significantly streamline the process of auditing and maintaining computer accounts in large or complex AD environments.

Active Directory User Analysis Tool

<#
.SYNOPSIS
Active Directory User Analysis Tool

.DESCRIPTION
This script analyzes user accounts in Active Directory, providing detailed information
about user properties, group memberships, account statuses, and potential security issues.

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

.EXAMPLE
.\ADUserAnalyzer.ps1
#>

# Import required modules
Import-Module ActiveDirectory

# Global variables
$global:reportPath = "$env:USERPROFILE\Desktop\AD_User_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 User Analysis Tool ===" -ForegroundColor Cyan
    Write-Host "1. Analyze User Account Statuses"
    Write-Host "2. Check Password Policies Compliance"
    Write-Host "3. Analyze Group Memberships"
    Write-Host "4. Identify Inactive User Accounts"
    Write-Host "5. Check for Privileged Accounts"
    Write-Host "6. Analyze User Account Properties"
    Write-Host "7. Check for Expired Accounts"
    Write-Host "8. Generate Comprehensive HTML Report"
    Write-Host "9. Exit"
}

<#
.SYNOPSIS
Analyzes user account statuses.

.OUTPUTS
Array of PSObjects containing user account status details.
#>
function Analyze-UserAccountStatuses {
    Write-Host "`nAnalyzing User Account Statuses..." -ForegroundColor Yellow
    $users = Get-ADUser -Filter * -Properties Enabled, LockedOut, PasswordExpired, PasswordNeverExpires
    $statuses = @()
    foreach ($user in $users) {
        $statuses += [PSCustomObject]@{
            Username = $user.SamAccountName
            Enabled = $user.Enabled
            LockedOut = $user.LockedOut
            PasswordExpired = $user.PasswordExpired
            PasswordNeverExpires = $user.PasswordNeverExpires
        }
    }
    $statuses | Format-Table -AutoSize
    return $statuses
}

<#
.SYNOPSIS
Checks password policies compliance.

.OUTPUTS
Array of PSObjects containing password policy compliance details.
#>
function Check-PasswordPoliciesCompliance {
    Write-Host "`nChecking Password Policies Compliance..." -ForegroundColor Yellow
    $defaultPolicy = Get-ADDefaultDomainPasswordPolicy
    $users = Get-ADUser -Filter * -Properties PasswordLastSet, PasswordNeverExpires
    $compliance = @()
    foreach ($user in $users) {
        $passwordAge = (Get-Date) - $user.PasswordLastSet
        $compliance += [PSCustomObject]@{
            Username = $user.SamAccountName
            PasswordLastSet = $user.PasswordLastSet
            PasswordAge = "$($passwordAge.Days) days"
            CompliantMaxAge = if ($user.PasswordNeverExpires) { "N/A" } elseif ($passwordAge.Days -le $defaultPolicy.MaxPasswordAge.Days) { $true } else { $false }
            PasswordNeverExpires = $user.PasswordNeverExpires
        }
    }
    $compliance | Format-Table -AutoSize
    return $compliance
}

<#
.SYNOPSIS
Analyzes group memberships.

.OUTPUTS
Array of PSObjects containing group membership details.
#>
function Analyze-GroupMemberships {
    Write-Host "`nAnalyzing Group Memberships..." -ForegroundColor Yellow
    $users = Get-ADUser -Filter * -Properties MemberOf
    $memberships = @()
    foreach ($user in $users) {
        $groups = $user.MemberOf | ForEach-Object { (Get-ADGroup $_).Name }
        $memberships += [PSCustomObject]@{
            Username = $user.SamAccountName
            GroupCount = $groups.Count
            Groups = $groups -join ", "
        }
    }
    $memberships | Format-Table -AutoSize
    return $memberships
}

<#
.SYNOPSIS
Identifies inactive user accounts.

.OUTPUTS
Array of PSObjects containing inactive user account details.
#>
function Identify-InactiveUserAccounts {
    Write-Host "`nIdentifying Inactive User Accounts..." -ForegroundColor Yellow
    $inactiveThreshold = (Get-Date).AddDays(-90)
    $users = Get-ADUser -Filter {Enabled -eq $true} -Properties LastLogonDate
    $inactiveUsers = @()
    foreach ($user in $users) {
        if ($user.LastLogonDate -lt $inactiveThreshold) {
            $inactiveUsers += [PSCustomObject]@{
                Username = $user.SamAccountName
                LastLogonDate = $user.LastLogonDate
                DaysSinceLastLogon = ((Get-Date) - $user.LastLogonDate).Days
            }
        }
    }
    $inactiveUsers | Format-Table -AutoSize
    return $inactiveUsers
}

<#
.SYNOPSIS
Checks for privileged accounts.

.OUTPUTS
Array of PSObjects containing privileged account details.
#>
function Check-PrivilegedAccounts {
    Write-Host "`nChecking for Privileged Accounts..." -ForegroundColor Yellow
    $privilegedGroups = @("Domain Admins", "Enterprise Admins", "Schema Admins", "Administrators")
    $privilegedAccounts = @()
    foreach ($group in $privilegedGroups) {
        $members = Get-ADGroupMember -Identity $group -Recursive | Where-Object {$_.objectClass -eq "user"}
        foreach ($member in $members) {
            $privilegedAccounts += [PSCustomObject]@{
                Username = $member.SamAccountName
                PrivilegedGroup = $group
            }
        }
    }
    $privilegedAccounts | Format-Table -AutoSize
    return $privilegedAccounts
}

<#
.SYNOPSIS
Analyzes user account properties.

.OUTPUTS
Array of PSObjects containing user account property details.
#>
function Analyze-UserAccountProperties {
    Write-Host "`nAnalyzing User Account Properties..." -ForegroundColor Yellow
    $users = Get-ADUser -Filter * -Properties *
    $properties = @()
    foreach ($user in $users) {
        $properties += [PSCustomObject]@{
            Username = $user.SamAccountName
            FullName = $user.Name
            Email = $user.EmailAddress
            Department = $user.Department
            Title = $user.Title
            Manager = if ($user.Manager) { (Get-ADUser $user.Manager).Name } else { "N/A" }
            Created = $user.Created
            LastModified = $user.Modified
        }
    }
    $properties | Format-Table -AutoSize
    return $properties
}

<#
.SYNOPSIS
Checks for expired accounts.

.OUTPUTS
Array of PSObjects containing expired account details.
#>
function Check-ExpiredAccounts {
    Write-Host "`nChecking for Expired Accounts..." -ForegroundColor Yellow
    $users = Get-ADUser -Filter {Enabled -eq $true -and AccountExpirationDate -lt (Get-Date)} -Properties AccountExpirationDate
    $expiredAccounts = @()
    foreach ($user in $users) {
        $expiredAccounts += [PSCustomObject]@{
            Username = $user.SamAccountName
            ExpirationDate = $user.AccountExpirationDate
            DaysExpired = ((Get-Date) - $user.AccountExpirationDate).Days
        }
    }
    $expiredAccounts | Format-Table -AutoSize
    return $expiredAccounts
}

<#
.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>AD User 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>Active Directory User Analysis Report</h1>
    <p>Generated on: $(Get-Date)</p>

    <h2>User Account Statuses</h2>
    $($AllResults.AccountStatuses | ConvertTo-Html -Fragment)

    <h2>Password Policies Compliance</h2>
    $($AllResults.PasswordCompliance | ConvertTo-Html -Fragment)

    <h2>Group Memberships</h2>
    $($AllResults.GroupMemberships | ConvertTo-Html -Fragment)

    <h2>Inactive User Accounts</h2>
    $($AllResults.InactiveAccounts | ConvertTo-Html -Fragment)

    <h2>Privileged Accounts</h2>
    $($AllResults.PrivilegedAccounts | ConvertTo-Html -Fragment)

    <h2>User Account Properties</h2>
    $($AllResults.AccountProperties | ConvertTo-Html -Fragment)

    <h2>Expired Accounts</h2>
    $($AllResults.ExpiredAccounts | 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.AccountStatuses = Analyze-UserAccountStatuses }
        "2" { $allResults.PasswordCompliance = Check-PasswordPoliciesCompliance }
        "3" { $allResults.GroupMemberships = Analyze-GroupMemberships }
        "4" { $allResults.InactiveAccounts = Identify-InactiveUserAccounts }
        "5" { $allResults.PrivilegedAccounts = Check-PrivilegedAccounts }
        "6" { $allResults.AccountProperties = Analyze-UserAccountProperties }
        "7" { $allResults.ExpiredAccounts = Check-ExpiredAccounts }
        "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 User Analysis Tool includes:

  1. A menu-driven interface for easy navigation.
  2. Functions to analyze various aspects of user accounts:
    • User account statuses (enabled, locked out, password expired)
    • Password policies compliance
    • Group memberships
    • Inactive user accounts
    • Privileged accounts
    • User account properties
    • Expired accounts
  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 user account statuses and properties
  • Checking password policy compliance across all users
  • Identification of inactive and expired accounts
  • Analysis of group memberships, including privileged groups
  • Comprehensive overview of user account properties
  • HTML report generation for easy sharing and viewing of results

This tool is particularly useful for:

  • Active Directory administrators managing user accounts
  • IT security professionals auditing user account security
  • HR departments needing reports on user account statuses and properties
  • Compliance officers ensuring adherence to password policies

To use this script effectively:

  1. Run PowerShell as an administrator
  2. Ensure you have the necessary permissions to query AD user information
  3. Have the Active Directory PowerShell module installed

This script provides a comprehensive overview of user accounts in an Active Directory environment, making it easier to identify security issues, compliance problems, or outdated account information. It can significantly streamline the process of auditing and maintaining user accounts in large or complex AD environments.