Nemrég felmerült a feladat, hogy figyelemmel kísérjük a tanúsítványok lejárati idejét a Windows szervereken. Hát, ami azt illeti, a tanúsítványok többször is 'tökéletessé' váltak, éppen akkor, amikor a meghosszabbításért felelős, szakállas kolléga szabadságon volt. Ezután valami gyanússá vált, ezért azon kezdtünk el gondolkodni, hogy mit tegyünk. Mivel lassan bevezetjük a NetXMS felügyeleti rendszert, ez lett a fő és lényegében az egyetlen jelölt a feladatra.
A végső eredmény a következő formában készült el:

A folyamat pedig folytatódik.
Lássunk hozzá. A NetXMS-ben nincs beépített számláló, ami a tanúsítványok lejáratát figyeli, ezért saját magunknak kell létrehoznunk egyet, és szkripteket kell használnunk az adatok biztosításához. Természetesen Powershellben, hiszen ez Windows. A szkriptnek le kell olvasnia az operációs rendszeren található összes tanúsítványt, meg kell kapnia a lejárati időt napokban, és ezt az értéket át kell adnia a NetXMS-nek. Az ügynökén keresztül. Ezzel kezdjük.
Első verzió, a legegyszerűbb. Egyszerűen meg kell kapni a nappont a legközelebbi lejáratú tanúsítványhoz.
Ahhoz, hogy a NetXMS szerver tudomást szerezzen a saját egyedi paraméterünkről, azt az ügynöktől kell megkapnia. Ellenkező esetben ezt a paramétert nem lehet hozzáadni, mert nem áll rendelkezésre. Ezért a konfigurációs fájlba nxagentd.conf hozzáadunk egy külső paraméter sort, aminek a neve HTTPS.CertificateExpireDateSimple, amiben megadjuk a szkript futtatását:
ExternalParameter = HTTPS.CertificateExpireDateSimple: powershell.exe -File "servershareNetXMS_CertExpireDateSimple.ps1"Tekintettel arra, hogy a szkript hálózaton keresztül fut, ne feledkezzünk meg az , és az egyéb "-NoLogo -NoProfile -NonInteractive" opciókról, amelyeket a kód jobb olvashatósága érdekében elhanyagoltam.
Ennek eredményeként az ügynök konfigurációja így néz ki:
#
# 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"Ezután el kell menteni a konfigurációt, és újra kell indítani az ügynököt. Ezt meg lehet tenni a NetXMS konzoljából: nyissa meg a konfigurációt (Edit agent’s configuration file), szerkessze, majd végezze el a Save&Apply műveletet, így pedig ugyanaz történik. A konfiguráció újraolvasásához (Poll > Configuration) is hozzá lehet nyúlni, ha nincs kedve várni. Ezek után lehetőség nyílik a saját paraméterünk hozzáadására.
A NetXMS konzoljában menjünk a Data Collection Configuration a kísérleti szerver, amelyen a tanúsítványokat fogunk figyelni, és ott új paramétert hozunk létre (a beállítások után érdemes lesz átkonvertálni sablonokba). Kiválasztjuk a HTTPS.CertificateExpireDateSimple-t a listából, megadjuk a Description-t egy érthető névvel, az típust Integer-re állítjuk, és beállítjuk a lekérdezés intervallumát. A hibakeresési időszakra érdemes rövidebbre állítani, például 30 másodpercre. Minden kész, egyelőre ennyi elég.
Lehet ellenőrizni… nem, még korai. Jelenleg természetesen semmit nem kapunk. Csak azért, mert a szkript még nincs megírva. Ezt a mulasztást javítjuk. A szkript egyszerűen csak egy számot fog adni, a hátralévő napok számát a tanúsítvány lejáratáig. A legkisebb értéket az összes közül. Példa a szkriptre:
try {
# Lekérdezzük az összes tanúsítványt a tanúsítványtárolóból
$lmCertificates = @( Get-ChildItem -Recurse -path 'Cert:LocalMachineMy' -ErrorAction Stop )
# Ha nincsenek tanúsítványok, visszatérünk "10 évvel"
if ($lmCertificates.Count -eq 0) { return 3650 }
# Lekérdezzük a tanúsítványok lejárati dátumát
$expirationDates = @( $lmCertificates | ForEach-Object { return $_.NotAfter } )
# Lekérdezzük a legközelebbi lejárati dátumot az összesből
$minExpirationDate = ($expirationDates | Measure-Object -Minimum -ErrorAction Stop ).Minimum
# A legközelebbi lejárati dátumot konvertáljuk hátralévő nappá lefelé kerekítve
$daysLeft = [Math]::Floor( ($minExpirationDate - [DateTime]::Now).TotalDays )
# Visszatérünk az értékkel
return $daysLeft
}
catch {
return -1
}Így alakul:

723 nap, a tanúsítvány lejáratáig még majdnem két év van hátra. Logikus, mert a tesztkörnyezet tanúsítványait nemrég újra kibocsátottam.
Ez egy egyszerűbb megoldás volt. Talán valakit így is kielégít, de nekünk többre volt szükségünk. A célunk az volt, hogy egy lista készül az összes tanúsítványról a szerveren, név szerint, és lássuk, hány nap van még a tanúsítvány lejáratáig.
Második lehetőség:, kicsit bonyolultabb.
Újra szerkesztjük az ügynök konfigurációt, és ahelyett, hogy egy sort írnánk be az ExternalParameter-rel, két másikat írunk be:
ExternalList = HTTPS.CertificateNames: powershell.exe -File "serversharenetxms_CertExternalNames.ps1"
ExternalParameter = HTTPS.CertificateExpireDate(*): powershell.exe -File "serversharenetxms_CertExternalParameter.ps1" -CertificateId "$1"A ExternalList csak egy string lista jön létre. A mi esetünkben egy string lista a tanúsítványok neveivel. Ezt a string listát a szkript generálja. A lista neve - HTTPS.CertificateNames.
A NetXMS_CertNames.ps1 szkript:
#Список возможных имен сертификатов
$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)"
}
}De már a ExternalParameter Bemenetként az ExternalList listájából származó sorokat adunk, míg kimenetként megkapjuk a megfelelő számú napot mindegyikhez. Az azonosító a tanúsítvány Thumbprint-je. Vegye figyelembe, hogy a HTTPS.CertificateExpireDate ebben a változatban csillagot (*) tartalmaz. Ez arra szükséges, hogy elfogadja a külső változókat, pontosan a CertificateId-t.
A NetXMS_CertExpireDate.ps1 szkript:
#Определяем входящий параметр $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)"
}A szerver Data Collection Configuration részlegében új paramétert hozunk létre. A Parameter mezőben kiválasztjuk a saját HTTPS.CertificateExpireDate(*) a listából, és (figyelem!) a csillagot kicseréljük {instance}. Ez a fontos lépés lehetővé teszi egy külön számláló létrehozását minden egyes példányhoz (tanúsítványhoz). A többi mező kitöltése úgy történik, mint az előző verzióban:

Ahhoz, hogy legyen miből számlálókat létrehozni, az Instance Discovery fülön az Agent List-et kell kiválasztanunk a listából és a List Name mezőbe beírni az ExternalList nevünket a szkriptből – HTTPS.CertificateNames.
Majdnem kész! Kicsit várjunk, vagy kényszeríthetjük a Poll > Configuration és Poll > Instance Discovery végrehajtását, ha valóban nem tudunk várni. Eredményképpen megkapjuk a tanúsítványainkat a lejárati dátumokkal:
Ez jó? Igen, csak a perfekcionizmus kis férge szomorúan néz a számláló nevében lévő felesleges Thumbprint-ra, és nem engedi befejezni a cikket. Hogy megnyugtassuk, újra megnyitjuk a számláló tulajdonságait, és az Instance Discovery fülön az "Instance discovery filter script" mezőbe beírjuk a (a NetXMS belső nyelve) szkriptet:
instance = $1;
if (instance ~= "^(.*)s-s[T:[a-zA-Z0-9]+]$")
{
return %(true, instance, $1);
}
return true;ami kiszűri a Thumbprint-et:

Ahhoz, hogy szűrve jelenítsük meg, a General fülön a Description mezőbe átírjuk a CertificateExpireDate: {instance}-t CertificateExpireDate: {instance-name}:

Minden, végre célegyenesben vagyunk:
Gyönyörű, nem igaz?
Még a figyelmeztetések beállítása van hátra, hogy e-mailt kapjunk, amikor a tanúsítvány határideje közeledik a logikai végéhez.
1. Először is, szükséges egy eseménymintát (Event Template) létrehozni, hogy aktiválja azt, amikor a számláló értéke egy általunk megadott küszöb alá csökken. A Esemény konfigurációban két új mintát hozunk létre, nevezzük őket például: CertificateExpireDate_Threshold_Activate Figyelmeztetés státussal:

és egy hasonlót: CertificateExpireDate_Threshold_Deactivate Normál státussal.
2. Ezután a számláló tulajdonságaihoz megyünk, és a Tresholds fülön beállítjuk a küszöböt:

Itt kiválasztjuk a létrehozott eseményeinket CertificateExpireDate_Threshold_Activate és CertificateExpireDate_Threshold_Deactivate, beállítjuk a mérések számát (Samples) 1-re (e konkrét számláló esetén nem érdemes többet beállítani), 30 (nap) értékre például, és ami fontos, beállítjuk az esemény ismétlési idejét. A termelési környezetben lévő tanúsítványoknál napi egyszer, 86400 másodpercenként állítom be, különben el lehet merülni a figyelmeztetésekben (ami egyszer meg is történt, olyan mértékben, hogy a levelező fiók betelt a hétvégén). A hibakeresési időszakban érdemes kevesebbre állítani, 60 másodperc például.
3. A Művelet konfiguráció létrehozunk egy értesítő e-mail sablont, valami ilyesmit:

Ezek az %m, %S és hasonlók – makrók, amelyekbe a mi paraméterünk értékei lesznek behelyettesítve. Részletesen le vannak írva a NetXMS.
4. És végül, a korábbi pontokat egyesítve, a Eseményfeldolgozási politika létrehozunk egy szabályt, amely alapján riasztás keletkezik és e-mail kerül kiküldésre:
Mentjük a politikát, ennyi, lehet tesztelni. Beállítunk egy magasabb küszöböt a teszteléshez. Nekem a legközelebb esedékes tanúsítvány 723 nap múlva jár le, a teszteléshez 724-re állítottam. Az eredmény a következő riasztás lesz:

és ilyen értesítést kapunk e-mailben:

Na most már tényleg ennyi. Persze be lehetett volna állítani a műszerfalat, grafikonokat készíteni, de a tanúsítványok esetében ezek elég értelmetlen és unalmas egyenes vonalak lennének, eltérően a CPU vagy memória terhelésének grafikonjaitól. De erről majd egy másik alkalommal.
Forrás: habr.com
