Private/_New-SecurityAuditHtml.ps1

function _New-SecurityAuditHtml {
    <#
    .SYNOPSIS
        Generates the consolidated HTML security audit dashboard.
    #>

    param(
        [hashtable]$AuditResults,
        [string]$Domain,
        [int]$DaysInactive
    )

    $css = @"
    <style>
        body { font-family: Segoe UI, Arial, sans-serif; margin: 20px; background: #f5f5f5; }
        h1 { color: #2c3e50; border-bottom: 3px solid #e74c3c; padding-bottom: 10px; }
        h2 { color: #34495e; margin-top: 30px; border-bottom: 1px solid #bdc3c7; padding-bottom: 5px; }
        .meta { color: #7f8c8d; margin-bottom: 20px; }
        .dashboard { display: flex; gap: 15px; flex-wrap: wrap; margin-bottom: 20px; }
        .card { background: #fff; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); min-width: 180px; text-align: center; }
        .card .number { font-size: 36px; font-weight: bold; }
        .card .label { color: #7f8c8d; font-size: 12px; margin-top: 5px; }
        .card.warning .number { color: #e67e22; }
        .card.danger .number { color: #e74c3c; }
        .card.ok .number { color: #27ae60; }
        table { border-collapse: collapse; width: 100%; background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,0.1); margin-bottom: 20px; }
        th { background: #2c3e50; color: #fff; padding: 10px 8px; text-align: left; font-size: 11px; }
        td { padding: 8px; border-bottom: 1px solid #ecf0f1; font-size: 11px; }
        tr:nth-child(even) { background: #f9f9f9; }
        tr:hover { background: #eaf2f8; }
        .flag { color: #e74c3c; font-weight: bold; }
    </style>
"@


    $staleUserCount = $AuditResults['StaleUsers'].Count
    $staleCompCount = $AuditResults['StaleComputers'].Count
    $privCount = ($AuditResults['PrivilegedGroups'] | Measure-Object -Property MemberCount -Sum).Sum
    $localAdminCount = if ($AuditResults['LocalAdmins']) { @($AuditResults['LocalAdmins'] | Where-Object { $_.Expected -eq $false -and $_.Status -eq 'OK' }).Count } else { 'N/A' }

    $staleUserClass = if ($staleUserCount -gt 20) { 'danger' } elseif ($staleUserCount -gt 5) { 'warning' } else { 'ok' }
    $staleCompClass = if ($staleCompCount -gt 20) { 'danger' } elseif ($staleCompCount -gt 5) { 'warning' } else { 'ok' }

    # Build stale users table rows
    $staleUserRows = ($AuditResults['StaleUsers'] | ForEach-Object {
        "<tr><td>$($_.Name)</td><td>$($_.SAMAccountName)</td><td>$($_.LastLogon)</td><td>$($_.DaysStale)</td><td>$($_.Department)</td><td>$($_.DN)</td></tr>"
    }) -join "`n"

    # Build stale computers table rows
    $staleCompRows = ($AuditResults['StaleComputers'] | ForEach-Object {
        "<tr><td>$($_.Name)</td><td>$($_.LastLogon)</td><td>$($_.DaysStale)</td><td>$($_.Department)</td></tr>"
    }) -join "`n"

    # Build privileged groups rows
    $privRows = ($AuditResults['PrivilegedGroups'] | ForEach-Object {
        $memberList = ($_.Members | ForEach-Object { "$($_.SAMAccountName)$(if($_.Flags){" <span class='flag'>[$($_.Flags)]</span>"})" }) -join '<br>'
        "<tr><td>$($_.GroupName)</td><td>$($_.MemberCount)</td><td>$memberList</td></tr>"
    }) -join "`n"

    @"
<!DOCTYPE html>
<html>
<head><title>AD Security Audit - $Domain</title>$css</head>
<body>
    <h1>Active Directory Security Audit</h1>
    <div class="meta">Domain: $Domain | Generated: $(Get-Date -Format 'yyyy-MM-dd HH:mm') | Inactive threshold: $DaysInactive days</div>
 
    <div class="dashboard">
        <div class="card $staleUserClass"><div class="number">$staleUserCount</div><div class="label">Stale Users</div></div>
        <div class="card $staleCompClass"><div class="number">$staleCompCount</div><div class="label">Stale Computers</div></div>
        <div class="card warning"><div class="number">$privCount</div><div class="label">Privileged Accounts</div></div>
        <div class="card"><div class="number">$localAdminCount</div><div class="label">Unexpected Local Admins</div></div>
    </div>
 
    <h2>Stale User Accounts ($staleUserCount)</h2>
    <table>
        <tr><th>Name</th><th>SAMAccountName</th><th>Last Logon</th><th>Days Stale</th><th>Department</th><th>DN</th></tr>
        $staleUserRows
    </table>
 
    <h2>Stale Computer Accounts ($staleCompCount)</h2>
    <table>
        <tr><th>Name</th><th>Last Logon</th><th>Days Stale</th><th>Operating System</th></tr>
        $staleCompRows
    </table>
 
    <h2>Privileged Group Membership</h2>
    <table>
        <tr><th>Group</th><th>Members</th><th>Member Details</th></tr>
        $privRows
    </table>
</body>
</html>
"@

}