viernes, 26 de junio de 2026

WINDOWS. AD Health Dashboard

 



Propósito:

Verificar el estado de mi AD. 

Pasos:

Código


#############################################################################

# Script: AD_Health_Fusion_Final.ps1

# Descripcion:

# Script avanzado para monitorizacion de Active Directory:

# - Ping DC

# - Servicios criticos (Netlogon, NTDS, DNS)

# - Replicacion REAL (repadmin)

# - Tests DCDIAG clave (Replications, Netlogons, Advertising, FSMOCheck)

# - Dashboard HTML

# - Envio email SOLO si hay errores

#

# Disenado para entornos grandes minimizando impacto

#############################################################################

 

# ==========================

# VARIABLES DEL USUARIO

# ==========================

$SMTPServer = "smtp01.midominio.com"

$SMTPPort   = 25

$From       = "miserver@midominio.com"

$To         = "test@test.com"

 

$Fecha = Get-Date -Format "yyyy-MM-dd - HH:mm"

$Errores = @()

 

$Subject = "$Fecha - AD Health Monitor"

 

$ReportPath = "C:\Temp\AD_Health.html"

 

# ==========================

# HTML INICIO

# ==========================

$HTML = @"

<html>

<head>

<style>

body { font-family: Arial; }

table { border-collapse: collapse; width: 100%; }

th { background-color: #2F5496; color: white; }

td { border: 1px solid #ccc; padding: 5px; text-align: center; }

.ok { background-color: #C6EFCE; }

.error { background-color: #FFC7CE; }

</style>

</head>

<body>

<h2>AD Health Dashboard v2</h2>

<table>

<tr>

<th>DC</th>

<th>Ping</th>

<th>Netlogon</th>

<th>NTDS</th>

<th>DNS</th>

<th>Repadmin</th>

<th>DCDIAG</th>

</tr>

"@

 

# ==========================

# OBTENER DCs

# ==========================

$DCs = Get-ADDomainController -Filter * | Select-Object -ExpandProperty HostName

 

# ==========================

# FUNCION SERVICIOS

# ==========================

function Get-ServiceState {

    param($dc,$name)

 

    try {

        $svc = Get-Service -ComputerName $dc -Name $name -ErrorAction Stop

        if ($svc.Status -eq "Running") {

            return @("OK","ok")

        } else {

            $Errores += "$dc servicio $name STOP"

            return @("STOP","error")

        }

    } catch {

        $Errores += "$dc servicio $name ERROR"

        return @("ERROR","error")

    }

}

 

# ==========================

# ANALISIS POR DC

# ==========================

foreach ($dc in $DCs) {

 

    # PING

    if (Test-Connection $dc -Count 1 -Quiet) {

        $PingStatus = "OK"; $PingClass = "ok"

    } else {

        $PingStatus = "FAIL"; $PingClass = "error"

        $Errores += "$dc Ping FAIL"

    }

 

    # SERVICIOS

    $Netlogon = Get-ServiceState $dc "Netlogon"

    $NTDS     = Get-ServiceState $dc "NTDS"

    $DNS      = Get-ServiceState $dc "DNS"

 

    # ==========================

    # REPLICACION (REPADMIN REAL)

    # ==========================

    $rep = repadmin /showrepl $dc | Out-String

 

    if ($rep -match "error|fail") {

        $RepStatus = "ERROR"

        $RepClass = "error"

        $Errores += "$dc Repadmin error"

    } else {

        $RepStatus = "OK"

        $RepClass = "ok"

    }

 

    # ==========================

    # DCDIAG CLAVE

    # ==========================

    $dcdiag = dcdiag /s:$dc /test:Replications /test:Netlogons /test:Advertising /test:FSMOCheck | Out-String

 

    if ($dcdiag -match "failed|error") {

        $DCDIAGStatus = "ERROR"

        $DCDIAGClass = "error"

        $Errores += "$dc DCDIAG error"

    } else {

        $DCDIAGStatus = "OK"

        $DCDIAGClass = "ok"

    }

 

    # ==========================

    # HTML

    # ==========================

    $HTML += "<tr>"

    $HTML += "<td>$dc</td>"

    $HTML += "<td class='$PingClass'>$PingStatus</td>"

    $HTML += "<td class='$($Netlogon[1])'>$($Netlogon[0])</td>"

    $HTML += "<td class='$($NTDS[1])'>$($NTDS[0])</td>"

    $HTML += "<td class='$($DNS[1])'>$($DNS[0])</td>"

    $HTML += "<td class='$RepClass'>$RepStatus</td>"

    $HTML += "<td class='$DCDIAGClass'>$DCDIAGStatus</td>"

    $HTML += "</tr>"

}

 

$HTML += "</table>"

 

# ==========================

# RESUMEN ERRORES

# ==========================

#lo envia solo si sale errores

if ($Errores.Count -gt 0) {

 

    $HTML += "<h3>Errores detectados ($($Errores.Count))</h3><ul>"

 

    foreach ($e in $Errores) {

        $HTML += "<li>$e</li>"

    }

 

    $HTML += "</ul>"

}

 

$HTML += "</body></html>"

 

$HTML | Out-File $ReportPath -Encoding UTF8

 

# ==========================

# EMAIL SOLO SI ERRORES

# ==========================

if ($Errores.Count -gt 0) {

 

    $Subject = "$Fecha - AD Health Alert - $($Errores.Count) elementos"

 

    Send-MailMessage -SmtpServer $SMTPServer `

        -Port $SMTPPort `

        -From $From `

        -To $To `

        -Subject $Subject `

        -Body $HTML `

        -BodyAsHtml

}



[] Tarea programada

Interfaz de usuario gráfica, Texto, Aplicación, Correo electrónico

Descripción generada automáticamente

No funciona con el usuario system, hay que poner con uno con privilegios en el AD

Lo ideal sería ejecutarlo cada hora y que solo envía si hay errores. Yo lo hago una vez al día porque en principio no tengo problemas de sincronización y durante el día si lo tuviese seguro que tendría algún otro indicador que me alertaría.

 

Interfaz de usuario gráfica, Texto, Aplicación

Descripción generada automáticamente

 

Interfaz de usuario gráfica, Texto, Aplicación

Descripción generada automáticamente

 

Resultado

 Interfaz de usuario gráfica

Descripción generada automáticamente

 

by GoN | Published: Jun 2026 | Last Updated: