Überwachung der Gültigkeit von Zertifikaten unter Windows mit NetXMS

Kürzlich standen wir vor der Herausforderung, das Ablaufdatum von Zertifikaten auf unseren Windows-Servern zu überwachen. Es war notwendig, nachdem die Zertifikate mehrmals in ein Pumpkin-Problem verwandelt wurden, besonders während der Abwesenheit unseres zuständigen Kollegen, der gerade im Urlaub war. Danach hatten wir einen Verdacht und beschlossen, das näher zu betrachten. Da bei uns gerade das Monitoring-System NetXMS schrittweise implementiert wird, wurde es zum Hauptkandidaten für diese Aufgabe.

Das Endergebnis sah wie folgt aus:

Überwachung der Gültigkeit von Zertifikaten unter Windows mit NetXMS

Und der Prozess ging weiter.

Legen wir los. In NetXMS gibt es keinen eingebauten Zähler für ablaufende Zertifikate, daher müssen wir unseren eigenen erstellen und Skripte verwenden, um ihn mit Daten zu versorgen. Natürlich in PowerShell, schließlich handelt es sich um Windows. Das Skript soll alle Zertifikate im Betriebssystem auslesen, das Ablaufdatum in Tagen erfassen und diese Zahl an NetXMS über seinen Agenten übertragen. Damit fangen wir an.

Option eins, die einfachste. Einfach die Anzahl der Tage bis zum Ablauf des Zertifikats mit dem nächstgelegenen Datum abrufen.

Damit der NetXMS-Server von unserem benutzerdefinierten Parameter erfährt, muss er ihn vom Agenten beziehen. Andernfalls kann dieser Parameter nicht hinzugefügt werden, da er nicht vorhanden ist. Daher fügen wir in die Konfigurationsdatei des Agenten ein. nxagentd.conf Wir fügen eine Zeile für den externen Parameter mit dem Namen HTTPS.CertificateExpireDateSimple, in der wir den Skriptaufruf festlegen:

ExternalParameter = HTTPS.CertificateExpireDateSimple: powershell.exe -File "servershareNetXMS_CertExpireDateSimple.ps1"

Da das Skript über das Netzwerk ausgeführt wird, sollten wir nicht die Execution Policyvergessen, ebenso wie die anderen „-NoLogo -NoProfile -NonInteractive“-Optionen, die ich zur besseren Lesbarkeit des Codes weggelassen habe.

Dadurch sieht die Agentenkonfiguration etwa so aus:

#
# NetXMS agent configuration file
# Created by agent installer at Thu Jun 13 11:24:43 2019
#
 
MasterServers = netxms.corp.testcompany.ru
ConfigIncludeDir = C:NetXMSetcnxagentd.conf.d
LogFile = {syslog}
FileStore = C:NetXMSvar
SubAgent = ecs.nsm
SubAgent = filemgr.nsm
SubAgent = ping.nsm
SubAgent = logwatch.nsm
SubAgent = portcheck.nsm
SubAgent = winperf.nsm
SubAgent = wmi.nsm
 
ExternalParameter = HTTPS.CertificateExpireDateSimple: powershell.exe -File "servershareNetXMS_CertExpireDateSimple.ps1"

Danach muss die Konfiguration gespeichert und der Agent neu gestartet werden. Dies kann über die NetXMS-Konsole erfolgen: Konfiguration öffnen (Edit agent’s configuration file), bearbeiten, Save&Apply ausführen, was im Wesentlichen dasselbe bewirkt. Dann die Konfiguration erneut laden (Poll > Configuration), falls man nicht auf die Rückmeldung warten möchte. Nach diesen Schritten sollte es möglich sein, unseren benutzerdefinierten Parameter hinzuzufügen.

In der NetXMS-Konsole gehen wir zu Datenkonfigurationssammlung Ein Testserver, auf dem wir die Zertifikate überwachen und dort einen neuen Parameter erstellen. Nach der Konfiguration macht es Sinn, ihn in die Vorlagen zu übertragen. Wählen Sie HTTPS.CertificateExpireDateSimple aus der Liste, geben Sie eine verständliche Beschreibung ein, stellen Sie den Typ auf Integer und konfigurieren Sie das Abfrageintervall. Für die Debugging-Zeit ist es sinnvoll, es kürzer zu machen, zum Beispiel 30 Sekunden. Fertig, das ist vorerst genug.

Man kann es überprüfen... nein, das ist noch zu früh. Jetzt werden wir natürlich nichts erhalten. Einfach weil das Skript noch nicht geschrieben wurde. Lassen Sie uns dieses Versäumnis beheben. Das Skript wird einfach eine Zahl ausgeben, die Anzahl der Tage, die bis zum Ablauf des Zertifikats verbleiben. Das Minimum von allen verfügbaren.

try {
    # Alle Zertifikate aus dem Zertifikatspeicher abrufen
    $lmCertificates = @( Get-ChildItem -Recurse -path 'Cert:LocalMachineMy' -ErrorAction Stop )
     
    # Wenn keine Zertifikate vorhanden sind, "10 Jahre" zurückgeben
    if ($lmCertificates.Count -eq 0) { return 3650 }
 
    # Fälligkeitsdatum aller Zertifikate abrufen
    $expirationDates = @( $lmCertificates | ForEach-Object { return $_.NotAfter } )
 
    # Das nächste Fälligkeitsdatum aus allen abrufen
    $minExpirationDate = ($expirationDates | Measure-Object -Minimum -ErrorAction Stop ).Minimum
 
    # Das nächste Fälligkeitsdatum in die verbleibenden Tage umwandeln, abrunden
    $daysLeft = [Math]::Floor( ($minExpirationDate - [DateTime]::Now).TotalDays )
 
    # Wert zurückgeben
    return $daysLeft
}
catch {
    return -1
}

So ergibt sich:

Überwachung der Gültigkeit von Zertifikaten unter Windows mit NetXMS

723 Tage, bis das Zertifikat abläuft, sind noch fast zwei Jahre. Das ist naheliegend, weil ich die Zertifikate für die Testumgebung von Exchange erst vor kurzem erneuert habe.

Das war die einfache Variante. Vielleicht ist das für manche ausreichend, aber wir wollten mehr. Unsere Aufgabe war es, eine Liste aller Zertifikate auf dem Server einzuholen, namentlich, und bei jedem die Anzahl der verbleibenden Tage bis zum Ablauf des Zertifikats zu sehen.

Die zweite Option, etwas komplizierter.

Wir bearbeiten erneut die Agenten-Konfiguration und ersetzen die Zeile mit ExternalParameter durch zwei andere:

ExternalList = HTTPS.CertificateNames: powershell.exe -File "serversharenetxms_CertExternalNames.ps1"
ExternalParameter = HTTPS.CertificateExpireDate(*): powershell.exe -File "serversharenetxms_CertExternalParameter.ps1" -CertificateId "$1"

In ExternalList Wir erhalten einfach eine Liste von Zeilen. In unserem Fall ist es eine Liste von Zeilen mit den Namen der Zertifikate. Diese Liste werden wir durch ein Skript erhalten. Der Name der Liste ist: HTTPS.CertificateNames.

Skript NetXMS_CertNames.ps1:

#Список возможных имен сертификатов
$nameTypeList = @(
        [System.Security.Cryptography.X509Certificates.X509NameType]::SimpleName,
        [System.Security.Cryptography.X509Certificates.X509NameType]::DnsName,
        [System.Security.Cryptography.X509Certificates.X509NameType]::DnsFromAlternativeName,
        [System.Security.Cryptography.X509Certificates.X509NameType]::UrlName,
        [System.Security.Cryptography.X509Certificates.X509NameType]::EmailName,
        [System.Security.Cryptography.X509Certificates.X509NameType]::UpnName
)
 
#Ищем все сертификаты, имеющие закрытый ключ
$certList = @( Get-ChildItem -Path 'Cert:LocalMachineMy' | Where-Object { $_.HasPrivateKey -eq $true } )
 
#Проходим по списку сертификатов, формируем строку "Имя сертификата - Дата - Thumbprint" и возвращаем её
foreach ($cert in $certList) {
    $name = '(unknown name)'
    try {
        $thumbprint = $cert.Thumbprint
        $dateExpire = $cert.NotAfter
        foreach ($nameType in $nameTypeList) {
            $name_temp = $cert.GetNameInfo( $nameType, $false)
            if ($name_temp -ne $null -and $name_temp -ne '') {
                $name = $name_temp;
                break;
            }
        }
        Write-Output "$($name) - $($dateExpire.ToString('dd.MM.yyyy')) - [T:$($thumbprint)]"
    }
    catch {
        Write-Error -Message "Error processing certificate list: $($_.Exception.Message)"
    }
}

Und dann bei ExternalParameter geben wir die Zeilen aus der Liste ExternalList ein, und als Ausgang erhalten wir die Anzahl der Tage für jedes Zertifikat. Der Identifikator ist der Thumbprint des Zertifikats. Beachten Sie, dass HTTPS.CertificateExpireDate in dieser Variante ein Sternchen (*) enthält. Dies ist notwendig, damit es externe Variablen, speziell unsere CertificateId, akzeptiert.

Skript NetXMS_CertExpireDate.ps1:

#Определяем входящий параметр $CertificateId
param (
    [Parameter(Mandatory=$false)]
    [String]$CertificateId
)
 
#Проверка на существование
if ($CertificateId -eq $null) {
    Write-Error -Message "CertificateID parameter is required!"
    return
}
 
#По Thumbprint из строки в $CertificateId ищем сертификат и определяем его Expiration Date 
$certId = $CertificateId;
try {
    if ($certId -match '^.*[T:(?<Thumbprint>[A-Z0-9]+)]$') {
        $thumbprint = $Matches['Thumbprint']
        $certificatePath = "Cert:LocalMachineMy$($thumbprint)"
         
        if (Test-Path -PathType Leaf -Path $certificatePath ) {
            $certificate = Get-Item -Path $certificatePath;
            $certificateExpirationDate = $certificate.NotAfter
            $certificateDayToLive = [Math]::Floor( ($certificateExpirationDate - [DateTime]::Now).TotalDays )
            Write-Output "$($certificateDayToLive)";
        }
        else {
            Write-Error -Message "No certificate matching this thumbprint found on this server $($certId)"
        }
    }
    else {
        Write-Error -Message "CertificateID provided in wrong format. Must be FriendlyName [T:<thumbprint>]"
    }
}
catch {
    Write-Error -Message "Error while executing script: $($_.Exception.Message)"
}

In der Datenkonfigurationssammlung des Servers erstellen wir einen neuen Parameter. In Parameter wählen wir unseren HTTPS.CertificateExpireDate(*) aus der Liste aus und (Achtung!) ersetzen das Sternchen durch {instance}. Dieser wichtige Punkt ermöglicht es, einen separaten Zähler für jede Instanz (Zertifikat) zu erstellen. Der Rest wird wie im vorherigen Fall ausgefüllt:

Überwachung der Gültigkeit von Zertifikaten unter Windows mit NetXMS

Um die Zähler zu erstellen, müssen Sie im Tab Instanzentdeckung die Agentenliste aus der Liste auswählen und im Feld Listenname den Namen unserer ExternalList aus dem Skript — HTTPS.CertificateNames eintragen.

Fast fertig, bitte etwas warten oder manuell Poll > Konfiguration und Poll > Instanzentdeckung durchführen, falls es völlig unmöglich ist zu warten. In der Folge erhalten wir alle unsere Zertifikate mit den Ablaufdaten:

Überwachung der Gültigkeit von Zertifikaten unter Windows mit NetXMS

Ist das, was Sie brauchen? Ja, nur der Perfektionismus sorgt dafür, dass ich auf diesen unnötigen Thumbprint im Namen des Zählers mit traurigen Augen blicke und mir nicht erlaubt, den Artikel zu beenden. Um ihn zu beruhigen, öffnen wir erneut die Eigenschaften des Zählers und fügen im Tab Instanzentdeckung im Feld "Instance discovery filter script" das geschriebene Skript hinzu: NXSL (interne Sprache von NetXMS):

instance = $1;
 if (instance ~= "^(.*)s-s[T:[a-zA-Z0-9]+]$")
 {
 return %(true, instance, $1);
 }
 return true;

das den Thumbprint filtern wird:

Überwachung der Gültigkeit von Zertifikaten unter Windows mit NetXMS

Um ihn gefiltert anzuzeigen, ändern wir im Tab Allgemein das Feld Beschreibung von CertificateExpireDate: {instance} zu CertificateExpireDate: {instance-name}:

Überwachung der Gültigkeit von Zertifikaten unter Windows mit NetXMS

So, endlich das Ziel erreicht:

Überwachung der Gültigkeit von Zertifikaten unter Windows mit NetXMS

Ist das nicht schön?

Jetzt müssen wir nur noch die Benachrichtigungen einrichten, damit sie per E-Mail kommen, wenn das Zertifikat seinem logischen Ende näher kommt.

1. Zuerst müssen Sie eine Ereignisvorlage (Event Template) erstellen, um diese zu aktivieren, wenn der Zählerstand einen bestimmten von uns festgelegten Schwellenwert erreicht. In Ereigniskonfiguration erstellen wir zwei neue Vorlagen mit Namen wie CertificateExpireDate_Threshold_Activate mit dem Status Warnung:

Überwachung der Gültigkeit von Zertifikaten unter Windows mit NetXMS

und eine ähnliche CertificateExpireDate_Threshold_Deactivate mit dem Status Normal.

2. Danach gehen wir zu den Eigenschaften des Zählers und konfigurieren auf dem Tab Tresholds den Schwellenwert:

Überwachung der Gültigkeit von Zertifikaten unter Windows mit NetXMS

wobei wir unsere erstellten Ereignisse CertificateExpireDate_Threshold_Activate und CertificateExpireDate_Threshold_Deactivate auswählen, die Anzahl der Messungen (Samples) auf 1 setzen (für diesen Zähler macht es keinen Sinn, mehr zu wählen), den Wert auf 30 (Tage) festlegen, zum Beispiel, und wichtig, die Wiederholzeit des Ereignisses einstellen. Für Zertifikate in der Produktion setze ich einmal täglich (86400 Sekunden), sonst könnte man in Benachrichtigungen ertrinken (was übrigens einmal passiert ist, so dass das Postfach an einem Wochenende überfüllt wurde). Für Debugging-Zwecke macht es Sinn, einen kleineren Wert, z.B. 60 Sekunden, zu setzen.

3. In Aktionskonfiguration erstellen wir eine Vorlage für die Benachrichtigungs-E-Mail, etwa so:

Überwachung der Gültigkeit von Zertifikaten unter Windows mit NetXMS

All diese %m, %S usw. sind Makros, in die Werte aus unserem Parameter eingesetzt werden. Mehr dazu finden Sie im Handbuch NetXMS.

4. Und schließlich, indem wir die vorherigen Punkte zusammenfassen, in Richtlinie zur Ereignisverarbeitung erstellen wir eine Regel, nach der ein Alarm erzeugt und eine E-Mail versendet wird:

Überwachung der Gültigkeit von Zertifikaten unter Windows mit NetXMS

Wir speichern die Richtlinie, alles klar, es kann getestet werden. Ich werde die Schwelle etwas höher setzen, um zu prüfen. Mein nächstes Zertifikat läuft in 723 Tagen ab, also habe ich 724 Tage gesetzt. Das Ergebnis wird folgender Alarm sein:

Überwachung der Gültigkeit von Zertifikaten unter Windows mit NetXMS

und diese Benachrichtigung per E-Mail:

Überwachung der Gültigkeit von Zertifikaten unter Windows mit NetXMS

Jetzt ist wirklich alles erledigt. Natürlich könnte man ein Dashboard einrichten, Grafiken erstellen, aber für Zertifikate sind das einige sinnlose und langweilige Gerade Linien, im Gegensatz zu CPU- oder Speicherauslastungsgrafiken beispielsweise. Aber das können wir ein anderes Mal besprechen.

Quelle: habr.com

Kaufen Sie zuverlässiges Hosting für Websites mit DDoS-Schutz, VPS VDS-Server 🔥 Kaufen Sie zuverlässiges Hosting für Websites mit DDoS-Schutz, VPS VDS-Server | ProHoster