Surveillance de la date d'expiration du certificat dans Windows sur NetXMS

Récemment, nous avons été confrontés à la tâche de surveiller la durée de validité des certificats sur les serveurs Windows. Eh bien, comment je me suis levé après que les certificats se soient transformés à plusieurs reprises en citrouille, au moment même où le collègue barbu chargé de leur renouvellement était en vacances. Après cela, lui et moi avons soupçonné quelque chose et avons décidé d'y réfléchir. Depuis que nous mettons lentement en œuvre le système de surveillance NetXMS, il est devenu le principal et, en principe, le seul candidat pour cette tâche.

Le résultat a finalement été obtenu sous la forme suivante :

Surveillance de la date d'expiration du certificat dans Windows sur NetXMS

Et le processus lui-même se poursuit.

Aller. Il n'y a pas de compteur intégré pour les certificats expirés dans NetXMS, vous devez donc créer le vôtre et utiliser des scripts pour lui fournir des données. Bien sûr, sur Powershell, il s'agit de Windows. Le script doit lire tous les certificats du système d'exploitation, prendre leur date d'expiration en jours à partir de là et transmettre ce numéro à NetXMS. Par l'intermédiaire de son agent. C'est par là que nous commencerons.

Option One, le plus simple. Obtenez simplement le nombre de jours jusqu'à la date d'expiration du certificat avec la date la plus proche.

Pour que le serveur NetXMS connaisse l'existence de notre paramètre personnalisé, il doit le recevoir de l'agent. Dans le cas contraire, ce paramètre ne pourra pas être ajouté en raison de son absence. Par conséquent, dans le fichier de configuration de l'agent nxagentd.conf nous ajoutons une chaîne de paramètres externe appelée HTTPS.CertificateExpireDateSimple, dans lequel on inscrit le lancement du script :

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

Étant donné que le script est lancé sur le réseau, vous devez vous rappeler Politique d'exécution, et n'oubliez pas non plus l'autre « -NoLogo -NoProfile -NonInteractive », que j'ai omis pour une meilleure lisibilité du code.

En conséquence, la configuration de l'agent ressemble à ceci :

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

Après cela, vous devez enregistrer la configuration et redémarrer l'agent. Vous pouvez le faire depuis la console NetXMS : ouvrez la configuration (Modifier le fichier de configuration de l'agent), éditez-la, exécutez Save&Apply, ce qui aura pour résultat, en fait, la même chose. Relisez ensuite la configuration (Sondage > Configuration), si vous n’avez pas du tout la force d’attendre. Après ces étapes, vous devriez pouvoir ajouter notre paramètre personnalisé.

Dans la console NetXMS, accédez à Configuration de la collecte de données serveur expérimental sur lequel nous allons surveiller les certificats et y créer un nouveau paramètre (à l'avenir, après configuration, il sera logique de le transférer vers des modèles). Sélectionnez HTTPS.CertificateExpireDateSimple dans la liste, entrez une description avec un nom clair, définissez le type sur Integer et configurez l'intervalle d'interrogation. À des fins de débogage, il est logique de le raccourcir, 30 secondes par exemple. Tout est prêt, ça suffit pour l'instant.

Vous pouvez vérifier... non, c'est trop tôt. Maintenant, bien sûr, nous n’obtiendrons rien. Tout simplement parce que le scénario n’est pas encore écrit. Corrigeons cette omission. Le script affichera simplement un nombre, le nombre de jours restant jusqu'à l'expiration du certificat. Le plus minimal de tous disponibles. Exemple de script :

try {
    # Получаем все сертификаты из хранилища сертификатов
    $lmCertificates = @( Get-ChildItem -Recurse -path 'Cert:LocalMachineMy' -ErrorAction Stop )
     
    # Если сертификатов нет, вернуть "10 лет"
    if ($lmCertificates.Count -eq 0) { return 3650 }
 
    # Получаем Expiration Date всех сертификатов
    $expirationDates = @( $lmCertificates | ForEach-Object { return $_.NotAfter } )
 
    # Получаем наиболее близкий Expiration Date из всех
    $minExpirationDate = ($expirationDates | Measure-Object -Minimum -ErrorAction Stop ).Minimum
 
    # Конвертируем наиболее близкий Expiration Date в количество оставшихся дней с округлением в меньшую сторону
    $daysLeft = [Math]::Floor( ($minExpirationDate - [DateTime]::Now).TotalDays )
 
    # Возвращаем значение
    return $daysLeft
}
catch {
    return -1
}

Il se trouve comme ceci:

Surveillance de la date d'expiration du certificat dans Windows sur NetXMS

723 jours, soit près de deux ans avant l'expiration du certificat. C’est logique, car j’ai réédité des certificats pour le banc de test Exchange assez récemment.

C'était une option facile. Probablement, quelqu'un en sera satisfait, mais nous en voulions plus. Nous nous sommes donné pour tâche d'obtenir une liste de tous les certificats sur le serveur, par nom, et pour chacun de voir le nombre de jours restant jusqu'à l'expiration du certificat.

La deuxième option, un peu plus compliqué.

Encore une fois, nous éditons la configuration de l'agent et là, au lieu de la ligne avec ExternalParameter, nous en écrivons deux autres :

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

В ListeExterne nous obtenons simplement une liste de chaînes. Dans notre cas, une liste de chaînes avec des noms de certificats. Nous recevrons une liste de ces lignes à l'aide du script. Liste de noms - 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)"
    }
}

Et déjà dans Paramètre Externe Nous saisissons les lignes de la liste ExternalList et, en sortie, nous obtenons le même nombre de jours pour chacune. L'identifiant est l'empreinte du certificat. Notez que HTTPS.CertificateExpireDate contient un astérisque (*) dans cette variante. Ceci est nécessaire pour qu'il accepte des variables externes, juste notre CertificateId.

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

Dans la configuration de collecte de données du serveur, nous créons un nouveau paramètre. Dans Paramètre, nous sélectionnons notre HTTPS.CertificateExpireDate(*) de la liste, et (attention !) remplacez l'astérisque par {exemple}. Ce point important vous permettra de créer un compteur distinct pour chaque instance (certificat). Le reste est renseigné comme dans la version précédente :

Surveillance de la date d'expiration du certificat dans Windows sur NetXMS

Afin d'avoir quelque chose à partir duquel créer des compteurs, dans l'onglet Découverte d'instance, vous devez sélectionner Liste d'agents dans la liste et dans le champ Nom de la liste, entrez le nom de notre liste externe à partir du script - HTTPS.CertificateNames.

Presque prêt, attendez un peu ou forcez Poll > Configuration et Poll > Instance Discovery s'il est totalement impossible d'attendre. De ce fait, nous obtenons tous nos certificats avec des durées de validité :

Surveillance de la date d'expiration du certificat dans Windows sur NetXMS

De quoi avez-vous besoin? Eh bien oui, seul le ver du perfectionnisme regarde avec des yeux tristes cette empreinte inutile au nom du comptoir et ne me laisse pas terminer l'article. Pour l'alimenter, ouvrez à nouveau les propriétés du compteur et dans l'onglet Découverte d'instance, dans le champ « Script de filtre de découverte d'instance », ajoutez celui écrit dans NXSL (langage interne NetXMS) :

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

qui filtrera Thumbprint :

Surveillance de la date d'expiration du certificat dans Windows sur NetXMS

Et pour l'afficher filtré, dans l'onglet Général du champ Description, remplacez CertificateExpireDate : {instance} par CertificateExpireDate : {nom-instance}:

Surveillance de la date d'expiration du certificat dans Windows sur NetXMS

Ça y est, enfin la ligne d'arrivée de KDPV :

Surveillance de la date d'expiration du certificat dans Windows sur NetXMS

Est-ce la beauté ?

Il ne reste plus qu'à paramétrer les alertes pour qu'elles arrivent par email à l'expiration du certificat.

1. Nous devons d’abord créer un modèle d’événement pour l’activer lorsque la valeur du compteur diminue jusqu’à un seuil que nous avons défini. DANS Configuration d'événement créons deux nouveaux modèles avec des noms comme CertificatExpireDate_Threshold_Activate avec statut d'avertissement :

Surveillance de la date d'expiration du certificat dans Windows sur NetXMS

et similaire CertificateExpireDate_Threshold_Deactivate avec un statut normal.

2. Ensuite, accédez aux propriétés du compteur et définissez le seuil dans l'onglet Seuils :

Surveillance de la date d'expiration du certificat dans Windows sur NetXMS

où nous sélectionnons nos événements créés CertificateExpireDate_Threshold_Activate et CertificateExpireDate_Threshold_Deactivate, définissons le nombre d'échantillons (Samples) sur 1 (en particulier pour ce compteur, il ne sert à rien d'en définir plus), la valeur est de 30 (jours), par exemple, et, surtout, définissons le temps de répétition de l'événement. Pour les certificats en production, je l'ai réglé une fois par jour (86400 secondes), sinon vous risquez de vous noyer dans les notifications (ce qui d'ailleurs s'est produit une fois, à tel point que la boîte mail était pleine pendant le week-end). Pour le temps de débogage, il est judicieux de le régler plus bas, 60 secondes par exemple.

3. En Configuration des actions créez un modèle de lettre de notification, comme ceci :

Surveillance de la date d'expiration du certificat dans Windows sur NetXMS

Tous ces %m, %S, etc. — des macros dans lesquelles les valeurs de notre paramètre seront substituées. Ils sont décrits plus en détail dans manuel NetXMS.

4. Et enfin, en combinant les points précédents, en Politique de traitement des événements créer une règle selon laquelle une alarme sera créée et une lettre sera envoyée :

Surveillance de la date d'expiration du certificat dans Windows sur NetXMS

Nous sauvegardons la politique, tout peut être testé. Fixons le seuil plus haut pour vérifier. Mon certificat le plus proche expire dans 723 jours, je l'ai réglé sur 724 pour vérifier. En conséquence, nous obtenons l'alarme suivante :

Surveillance de la date d'expiration du certificat dans Windows sur NetXMS

et cette notification par e-mail :

Surveillance de la date d'expiration du certificat dans Windows sur NetXMS

C'est tout sûr maintenant. Il serait bien sûr possible de mettre en place un tableau de bord et de construire des graphiques, mais pour les certificats, il s'agirait de lignes droites quelque peu dénuées de sens et ennuyeuses, contrairement aux graphiques de charge du processeur ou de la mémoire, par exemple. Mais nous en reparlerons une autre fois.

Source: habr.com

Ajouter un commentaire