Sledování platnosti certifikátů ve Windows na NetXMS

Nedávno jsme se setkali s úkolem monitorovat dobu platnosti certifikátů na serverech s Windows. No, jak už to bývá, poté, co certifikáty několikrát přestaly fungovat ve chvíli, kdy odpovědný za jejich obnovu kolega byl na dovolené. Poté jsme si s ním něco začali podezřívat a rozhodli se tuto otázku prozkoumat. Takže, jelikož jsme pomalu zaváděli systém monitorování NetXMS, stal se právě on hlavním a vlastně jediným kandidátem na tento úkol.

Výsledkem nakonec byl tento výstup:

Sledování platnosti certifikátů ve Windows na NetXMS

A samotný proces následně.

Jdeme na to. V NetXMS není vestavěný počítač pro končící certifikáty, takže musíme vytvořit vlastní a použít skripty pro získání potřebných dat. Samozřejmě, v Powershellu, vždyť je to Windows. Skript by měl přečíst všechny certifikáty v operačním systému, vzít z nich dobu expirace v dnech a předat toto číslo do NetXMS. Přes jeho agenta. Takže odtud začneme.

Varianta první, ta nejsnazší. Jednoduše získat počet dní do konce platnosti certifikátu s nejbližším datem.

Aby server NetXMS věděl o existenci našeho vlastního parametru, musí ho dostat od agenta. Jinak nebude možné tento parametr přidat, kvůli jeho absenci. Proto do konfiguračního souboru agenta nxagentd.conf přidáme řádek externího parametru s názvem HTTPS.CertificateExpireDateSimple, kde specifikujeme spuštění skriptu:

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

Vzhledem k tomu, že skript se spouští přes síť, je také nutné nezapomenout na Execution Policy, a nezapomenout na další „-NoLogo -NoProfile -NonInteractive“, které jsem opustil pro lepší čitelnost kódu.

Výsledkem toho by měl konfigurace agenta vypadat přibližně takto:

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

Poté je třeba uložit konfiguraci a restartovat agenta. Můžete to udělat z konzole NetXMS: otevřít konfiguraci (Edit agent’s configuration file), upravit ji, provést Save&Apply, čímž se vlastně stane totéž. Pak přečíst konfiguraci (Poll > Configuration), pokud se vám opravdu nechce čekat. Po těchto krocích by se měla objevit možnost přidat náš vlastní parametr.

V konzole NetXMS přejdeme do Data Collection Configuration testovací server, na kterém budeme monitorovat certifikáty a vytváříme tam nový parametr (po konfiguraci má smysl to přenést do šablon). Vybereme HTTPS.CertificateExpireDateSimple ze seznamu, napíšeme popis s srozumitelným názvem, typ nastavíme na Integer a nastavíme interval dotazování. Na čas ladění má smysl udělat ho kratší, například 30 sekund. Všechno, je to готовé, zatím dost.

Můžeme zkontrolovat… ne, ještě je brzy. Teď samozřejmě nic nedostaneme. Prostě proto, že skript ještě nebyl napsán. Oprava této chyby. Skript bude vracet pouze číslo, počet dnů zbývajících do vypršení platnosti certifikátu. Nejmenší z dostupných. Příklad skriptu:

try {
    # Získání všech certifikátů ze skladu certifikátů
    $lmCertificates = @( Get-ChildItem -Recurse -path 'Cert:LocalMachineMy' -ErrorAction Stop )
     
    # Pokud certifikáty neexistují, vrátit "10 let"
    if ($lmCertificates.Count -eq 0) { return 3650 }
 
    # Získání data vypršení platnosti všech certifikátů
    $expirationDates = @( $lmCertificates | ForEach-Object { return $_.NotAfter } )
 
    # Získání nejbližšího data vypršení platnosti
    $minExpirationDate = ($expirationDates | Measure-Object -Minimum -ErrorAction Stop ).Minimum
 
    # Převod nejbližšího data vypršení platnosti na počet zbývajících dnů zaokrouhlením dolů
    $daysLeft = [Math]::Floor( ($minExpirationDate - [DateTime]::Now).TotalDays )
 
    # Vracení hodnoty
    return $daysLeft
}
catch {
    return -1
}

Vyšlo to takto:

Sledování platnosti certifikátů ve Windows na NetXMS

723 dny, do vypršení platnosti certifikátu zbývá ještě skoro dva roky. Logické, protože certifikáty na Exchange testovacího prostředí jsem obnovoval teprve nedávno.

To byla jednoduchá varianta. Možná je to pro někoho dostačující, ale my jsme chtěli více. Úkol jsme si určili získat seznam všech certifikátů na serveru, osobně, a u každého vidět počet dnů zbývajících do vypršení platnosti certifikátu.

Druhá varianta, o něco složitější.

Opět upravujeme konfiguraci agenta a namísto řádku s ExternalParameter napíšeme dvě jiné:

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

V ExternalList jen dostaneme seznam řetězců. V našem případě seznam řetězců s názvy certifikátů. Tento seznam řetězců získáme skriptem. Název seznamu — 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)"
    }
}

A už v ExternalParameter Dáváme vstupy ve formě řetězců ze seznamu ExternalList a na výstupu dostaneme stejné množství dní pro každou položku. Identifikátorem je Thumbprint certifikátu. Všimněte si, že HTTPS.CertificateExpireDate v tomto případě obsahuje hvězdičku (*). To je nutné, aby akceptoval externí proměnné, což je náš CertificateId.

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

V konfiguraci sběru dat serveru vytvoříme nový parametr. V Parametru vybereme náš HTTPS.CertificateExpireDate(*) ze seznamu, a (pozor!) změníme hvězdičku na {instance}. Tento důležitý moment umožní vytvořit samostatný čítač pro každou instanci (certifikát). Zbytek se vyplní jako v předchozím případě:

Sledování platnosti certifikátů ve Windows na NetXMS

Abychom měli z čeho vytvářet čítače, na kartě Discovery Instance je třeba vybrat Agent List ze seznamu a do pole List Name napsat název našeho ExternalList ze skriptu — HTTPS.CertificateNames.

Téměř hotovo, stačí chvíli počkat nebo ručně provést Poll > Configuration a Poll > Instance Discovery, pokud se opravdu nedá čekat. Výsledkem budou všechny naše certifikáty s datumy vypršení:

Sledování platnosti certifikátů ve Windows na NetXMS

To je ono? No ano, jenže červík perfekcionismu se dívá na tento zbytečný Thumbprint v názvu čítače smutnýma očima a nedává mi to spát. Abych ho nakrmil, znovu otevřeme vlastnosti čítače a na kartě Discovery Instance přidáme do pole „Instance discovery filter script“ napsaný skript v NXSL (interním jazyce NetXMS):

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

který bude filtrovat Thumbprint:

Sledování platnosti certifikátů ve Windows na NetXMS

Abychom jej zobrazili jako filtrovaný, na kartě General ve poli Description změníme CertificateExpireDate: {instance} na CertificateExpireDate: {instance-name}:

Sledování platnosti certifikátů ve Windows na NetXMS

Hotovo, konečně finále z KDPV:

Sledování platnosti certifikátů ve Windows na NetXMS

Krása, že?

Zbývá nastavit upozornění, aby byla doručována na e-mail, když se blíží konec platnosti certifikátu.

1. Nejprve je třeba vytvořit šablonu události (Event Template) pro její aktivaci při snížení hodnoty čítače pod určitou stanovenou hranici. V Event Configuration vytvoříme dvě nové šablony s názvy, dejme tomu CertificateExpireDate_Threshold_Activate se stavem Warning:

Sledování platnosti certifikátů ve Windows na NetXMS

a obdobnou CertificateExpireDate_Threshold_Deactivate se stavem Normal.

2. Dále přejdeme k vlastnostem čítače a na kartě Tresholds nastavíme hranici:

Sledování platnosti certifikátů ve Windows na NetXMS

kde vybíráme naše vytvořené události CertificateExpireDate_Threshold_Activate a CertificateExpireDate_Threshold_Deactivate, nastavujeme počet vzorků (Samples) na 1 (konkrétně pro tento čítač nemá smysl nastavovat více), hodnotu na 30 (dní), například, a co je důležité, nastavujeme čas opakování události. Pro certifikáty v produkci nastavím jednou za den (86400 sekund), jinak bychom se utopili v oznámeních (což se mimochodem už jednou stalo, a to tak, že se za víkend přetížil e-mailový účet). Na dobu ladění má smysl nastavit méně, například 60 sekund.

3. V Action Configuration vytváříme šablonu e-mailu s upozorněním, něco takového:

Sledování platnosti certifikátů ve Windows na NetXMS

Všechny tyto %m, %S atd. — jsou makra, do kterých budou vloženy hodnoty z našeho parametru. Podrobněji jsou popsána v příručce NetXMS.

4. A nakonec, spojujeme předchozí body, v Event Processing Policy vytváříme pravidlo, podle kterého bude vytvořen Alarm a odesláno e-mail:

Sledování platnosti certifikátů ve Windows na NetXMS

Uložíme politiku, vše, můžeme testovat. Nastavíme práh výše, pro kontrolu. Můj nejbližší certifikát vyprší za 723 dní, pro kontrolu jsem nastavil 724. V důsledku obdržíme takový alarm:

Sledování platnosti certifikátů ve Windows na NetXMS

a takové upozornění e-mailem:

Sledování platnosti certifikátů ve Windows na NetXMS

Teď už máme opravdu vše. Samozřejmě by bylo možné nastavit dashboard, vytvořit grafy, ale pro certifikáty by to byly poněkud bezvýznamné a nudné přímé čáry, na rozdíl od grafů zatížení procesoru nebo paměti, například. Ale o tom někdy příště.

Zdroj: habr.com

Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster