Monitorizarea valabilității certificatelor în Windows pe NetXMS

Recentl, we faced the task of monitoring the expiration dates of certificates on Windows servers. Well, it arose after the certificates turned into pumpkins a few times while our colleague, responsible for their renewal, was on vacation. After that, we suspected something and decided to think about it. Since we are gently implementing the NetXMS monitoring system, it became the main and, in fact, the only candidate for this task.

The result was ultimately obtained in the following form:

Monitorizarea valabilității certificatelor în Windows pe NetXMS

And the process further.

Let's go. There is no built-in counter for the expiration of certificates in NetXMS, so we need to create our own and use scripts to provide it with data. Of course, in PowerShell, it's Windows after all. The script should read all certificates in the operating system, take their expiration period in days, and pass this number to NetXMS through its agent. That's where we'll start.

Option one, the simplest. Just get the number of days until the nearest certificate expiration date.

For the NetXMS server to be aware of our custom parameter, it must receive it from the agent. Otherwise, this parameter cannot be added due to its absence. Therefore, in the agent configuration file nxagentd.conf , we add a line for the external parameter with the name HTTPS.CertificateExpireDateSimple, in which we specify the script launch:

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

Considering that the script runs over the network, don't forget about Execution Policy, as well as other options like «-NoLogo -NoProfile -NonInteractive», which I left out for better readability.

As a result, the agent configuration looks something like this:

#
# 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"

After that, you need to save the config and restart the agent. This can be done from the NetXMS console: open the config (Edit agent’s configuration file), edit it, execute Save&Apply, which will essentially do the same. Then read the configuration again (Poll > Configuration), if you can't wait to see the changes. After these actions, the ability to add our custom parameter should appear.

In the NetXMS console, go to Data Collection Configuration serverul de test pe care ne-am propus să monitorizăm certificatele și creăm un nou parametru acolo (ulterior, după configurare, va avea sens să-l mutăm în template-uri). Alegem HTTPS.CertificateExpireDateSimple din listă, completăm Description cu un nume clar, setăm tipul pe Integer și configurăm intervalul de interogare. În timpul debug-ului, are sens să-l facem mai scurt, 30 de secunde, de exemplu. Totul e gata, deocamdată e suficient.

Putem verifica... nu, e prea devreme. Deocamdată, evident, nu vom obține nimic. Pur și simplu pentru că scriptul nu a fost încă scris. Să corectăm această omisiune. Scriptul va returna pur și simplu un număr, numărul de zile rămase până la expirarea certificatului. Cea mai mică dintre toate cele existente. Exemplu de script:

try {
    # Obține toate certificatele din depozitul de certificate
    $lmCertificates = @( Get-ChildItem -Recurse -path 'Cert:LocalMachineMy' -ErrorAction Stop )
     
    # Dacă nu există certificate, returnează "10 ani"
    if ($lmCertificates.Count -eq 0) { return 3650 }
 
    # Obține data de expirare a tuturor certificatelor
    $expirationDates = @( $lmCertificates | ForEach-Object { return $_.NotAfter } )
 
    # Obține cea mai apropiată dată de expirare dintre toate
    $minExpirationDate = ($expirationDates | Measure-Object -Minimum -ErrorAction Stop ).Minimum
 
    # Convertește cea mai apropiată dată de expirare în numărul de zile rămase, rotunjind în jos
    $daysLeft = [Math]::Floor( ($minExpirationDate - [DateTime]::Now).TotalDays )
 
    # Returnează valoarea
    return $daysLeft
}
catch {
    return -1
}

Rezultatul este acesta:

Monitorizarea valabilității certificatelor în Windows pe NetXMS

723 de zile, până la expirarea certificatului mai sunt aproape doi ani. Logic, pentru că am reemis certificatele de pe testul Exchange foarte recent.

Aceasta a fost o variantă simplă. Probabil că unii ar fi mulțumiți de așa ceva, dar ne-am dorit mai mult. Sarcina pe care ne-am asumat-o a fost să obținem o listă cu toate certificatele de pe server, cu numele fiecăruia și să vedem câte zile au rămas până la expirarea certificatului.

A doua opțiune, ceva mai complex.

Din nou edităm configurația agentului și, în locul liniei cu ExternalParameter, scriem două altele:

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

În ExternalList obținem pur și simplu o listă de stringuri. În cazul nostru, o listă de stringuri cu numele certificatelor. Această listă va fi obținută prin script. Numele listei este HTTPS.CertificateNames.

Script 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)"
    }
}

Iar deja în ExternalParameter Introducem șiruri din lista ExternalList, iar la ieșire vom obține același număr de zile pentru fiecare certificat. Identificatorul este Thumbprint-ul certificatului. Rețineți că HTTPS.CertificateExpireDate în această variantă conține o stea (*). Acest lucru este necesar pentru a accepta variabile externe, exact CertificateId-ul nostru.

Scriptul 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)"
}

În Configurarea Colectării Datelor a serverului, creăm o nouă parametră. La Parametru alegem HTTPS.CertificateExpireDate(*) din listă și, (atenție!) schimbăm steaua cu {instance}. Acest aspect important va permite crearea unui contor separat pentru fiecare instanță (certificat). Restul se completează la fel ca în varianta anterioară:

Monitorizarea valabilității certificatelor în Windows pe NetXMS

Pentru a putea crea contoare, în tab-ul Descoperirii Instanței trebuie să selectați Lista Agentului din listă și în câmpul Numele Listei să scrieți numele ExternalList-ului nostru din script — HTTPS.CertificateNames.

Aproape terminat, mai așteptați puțin sau efectuați forțat Poll > Configurare și Poll > Descoperirea Instanței, dacă așteptarea devine insuportabilă. Ca rezultat, obținem toate certificatele noastre cu datele de expirare:

Monitorizarea valabilității certificatelor în Windows pe NetXMS

Este ceea ce trebuie? Da, doar că un vierme al perfecționismului se uită cu ochi tristi la acest Thumbprint inutil în numele contorului și nu-mi dă pace să termin articolul. Pentru a-l hrăni, deschidem din nou proprietățile contorului și în tab-ul Descoperirii Instanței, în câmpul „scriptul filtrului pentru descoperirea instanței” adăugăm scriptul scris în NXSL (limbajul intern al NetXMS):

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

care va filtra Thumbprint-ul:

Monitorizarea valabilității certificatelor în Windows pe NetXMS

Și pentru a-l afișa filtrat, în tab-ul General în câmpul Descriere schimbăm CertificateExpireDate: {instance} în CertificateExpireDate: {instance-name}:

Monitorizarea valabilității certificatelor în Windows pe NetXMS

Totul, în sfârșit am terminat de la KDPV:

Monitorizarea valabilității certificatelor în Windows pe NetXMS

Frumos, nu-i așa?

Mai trebuie să configurăm alertele, astfel încât să ajungă pe email când termenul certificatului se apropie de sfârșit.

1. Mai întâi trebuie să creăm un model de eveniment (Event Template) pentru a-l activa atunci când valoarea contorului scade sub un anumit prag stabilit de noi. În Configurarea Evenimentului creăm două noi șablonuri cu numele, să zicem, CertificateExpireDate_Threshold_Activate cu statusul Avertizare:

Monitorizarea valabilității certificatelor în Windows pe NetXMS

și un similar CertificateExpireDate_Threshold_Deactivate cu statusul Normal.

2. Apoi mergem la proprietățile contorului și în tab-ul Praguri configurăm pragul:

Monitorizarea valabilității certificatelor în Windows pe NetXMS

unde alegem evenimentele noastre create CertificateExpireDate_Threshold_Activate și CertificateExpireDate_Threshold_Deactivate, setăm numărul de probe (Samples) 1 (în mod special pentru acest contor, nu are sens să punem mai mult), valoarea de 30 (zile), de exemplu, și, ceea ce este important, configurăm timpul de repetare a evenimentului. Pentru certificatele din producție, pun o dată pe zi (86400 de secunde); altfel, putem fi copleșiți de notificări (ceea ce, de altfel, s-a întâmplat o dată, astfel încât căsuța poștală s-a umplut în weekend). Pentru timpul de depanare are sens să punem mai puțin, 60 de secunde, de exemplu.

3. În Configurarea Acțiunii creăm un șablon de email de alertă, de genul:

Monitorizarea valabilității certificatelor în Windows pe NetXMS

Toți acești %m, %S și așa mai departe — macrocomenzi, în care vor fi introduse valorile din parametrul nostru. Mai multe detalii sunt descrise în manual NetXMS.

4. Și, în sfârșit, combinând punctele anterioare, în Politica de Procesare a Evenimentelor creăm o regulă, conform căreia va fi generată o Alarmă și trimis un email:

Monitorizarea valabilității certificatelor în Windows pe NetXMS

Salvăm politica, totul, putem testa. Vom seta un prag mai ridicat pentru verificare. Cel mai apropiat certificat al meu expiră în 723 de zile, pentru verificare am setat 724. Ca rezultat, vom obține o astfel de alarmă:

Monitorizarea valabilității certificatelor în Windows pe NetXMS

și o astfel de notificare prin email:

Monitorizarea valabilității certificatelor în Windows pe NetXMS

Acum, cu siguranță, totul este finalizat. Ar fi fost posibil, desigur, să configurăm un tablou de bord, să construim grafice, dar pentru certificate vor fi niște linii directe destul de lipsită de sens și plictisitoare, spre deosebire de graficele încărcării procesorului sau memoriei, de exemplu. Dar, despre asta, altă dată.

Sursa: habr.com

Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS 🔥 Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS | ProHoster