在 NetXMS 上監控 Windows 中的憑證過期日期

最近我們面臨監控Windows伺服器上憑證有效期的任務。 好吧,在證書多次變成南瓜後我是如何起床的,而當時負責更新證書的大鬍子同事正在休假。 在那之後,我和他懷疑了一些事情,決定考慮一下。 由於我們正在慢慢實施 NetXMS 監控系統,因此它已成為該任務的主要候選者,原則上也是唯一候選者。

最終得到結果,形式如下:

在 NetXMS 上監控 Windows 中的憑證過期日期

這個過程本身仍在繼續。

去。 NetXMS 中沒有針對過期憑證的內建計數器,因此您需要建立自己的計數器並使用腳本為其提供資料。 當然,在Powershell上,這是Windows。 該腳本應讀取作業系統中的所有證書,以取得其到期日期(以天為單位),並將該數字傳遞給 NetXMS。 透過他的經紀人。 這就是我們要開始的地方。

方案一,最簡單。 只需取得距證書到期日期最近的天數即可。

為了讓 NetXMS 伺服器知道我們的自訂參數的存在,它必須從代理程式接收它。 否則,該參數因不存在而無法新增。 因此,在代理設定檔中 nxagentd.conf 我們新增一個名為的外部參數字串 HTTPS.CertificateExpireDateSimple,我們在其中註冊腳本的啟動:

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

考慮到腳本是透過網路啟動的,您需要記住 執行政策,也不要忘記其他“-NoLogo -NoProfile -NonInteractive”,為了更好的程式碼可讀性,我省略了它。

結果,代理配置看起來像這樣:

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

之後,您需要儲存配置並重新啟動代理程式。 您可以從 NetXMS 控制台執行此操作:開啟設定(編輯代理程式的設定檔),編輯它,執行“儲存並套用”,結果實際上會發生相同的事情。 如果您根本沒有力氣等待,請重新讀取設定(輪詢 > 設定)。 完成這些步驟後,您應該可以添加我們的自訂參數。

在 NetXMS 控制台中,前往 數據採集配置 我們將在實驗伺服器上監視憑證並在那裡建立一個新參數(將來,在配置之後,將其傳輸到模板是有意義的)。 從清單中選擇 HTTPS.CertificateExpireDateSimple,輸入具有明確名稱的說明,將類型設為整數並配置輪詢間隔。 出於調試目的,縮短時間是有意義的,例如 30 秒。 一切都準備好了,現在就夠了。

你可以檢查一下……不,現在還太早。 當然,現在我們什麼都得不到。 很簡單,因為劇本還沒寫好。 讓我們修正這個遺漏。 該腳本將僅顯示一個數字,即在證書到期之前剩餘的天數。 可用的最小的。 範例腳本:

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
}

結果是這樣的:

在 NetXMS 上監控 Windows 中的憑證過期日期

還有723天,距離證書到期還有將近兩年的時間。 這是合乎邏輯的,因為我最近為 Exchange 測試平台重新頒發了憑證。

這是一個簡單的選擇。 也許有人會對此感到滿意,但我們想要更多。 我們為自己設定的任務是按名稱取得伺服器上所有憑證的列表,並為每個憑證查看距離憑證過期的剩餘天數。

第二個選項,稍微複雜一些。

我們再次編輯代理配置,並在那裡編寫另外兩個內容,而不是帶有外部參數的行:

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

В 外部列表 我們只是得到一個字串列表。 在我們的例子中,是帶有憑證名稱的字串清單。 我們將使用該腳本收到這些行的清單。 列表名稱 - HTTPS.憑證名稱.

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

並且已經在 外部參數 我們輸入來自ExternalList列表的行,並在輸出中得到每行相同的天數。 標識符是證書的指紋。 請注意,HTTPS.CertificateExpireDate 在此變體中包含星號 (*)。 這是必要的,以便它接受外部變量,只是我們的CertificateId。

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

在伺服器的資料收集配置中,我們建立一個新參數。 在參數中我們選擇我們的 HTTPS.CertificateExpireDate(*) 從列表中,(注意!)將星號更改為 {實例}。 這一重要點將允許您為每個實例(憑證)建立一個單獨的計數器。 其餘內容與上一版本一樣填寫:

在 NetXMS 上監控 Windows 中的憑證過期日期

為了能夠從中建立計數器,您需要在“實例發現”標籤上從清單中選擇“代理清單”,然後在“清單名稱”欄位中輸入腳本中的外部清單的名稱 - HTTPS.CertificateNames。

快準備好了,稍等一下,或者如果完全不可能等待,則強制輪詢 > 配置和輪詢 > 實例發現。 結果,我們得到了所有帶有有效期的證書:

在 NetXMS 上監控 Windows 中的憑證過期日期

你需要什麼? 好吧,是的,只有完美主義的蠕蟲用悲傷的眼睛看著這個不必要的指紋,以櫃檯的名義,不讓我完成這篇文章。 要提供它,請再次開啟計數器屬性,然後在「實例發現」標籤上的「實例發現篩選器腳本」欄位中,新增編寫為 NXSL (NetXMS內部語言)腳本:

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

這將過濾指紋:

在 NetXMS 上監控 Windows 中的憑證過期日期

若要顯示已篩選的內容,請在「一般」標籤上的「說明」欄位中,將「CertificateExpireDate: {instance}」變更為 憑證過期日期:{實例名稱}:

在 NetXMS 上監控 Windows 中的憑證過期日期

就是這樣,最後是 KDPV 的終點:

在 NetXMS 上監控 Windows 中的憑證過期日期

不就是美嗎?

剩下的就是設定警報,以便在證書過期時透過電子郵件發送警報。

1. 首先,我們需要建立一個事件模板,以便在計數器值減少到我們設定的某個閾值時啟動它。 在 事件配置 讓我們建立兩個新模板,其名稱如下 證書過期日期_閾值_激活 具有警告狀態:

在 NetXMS 上監控 Windows 中的憑證過期日期

和類似的 憑證過期日期_閾值_停用 狀態正常。

2. 接下來,轉到計數器屬性並在「閾值」標籤上設定閾值:

在 NetXMS 上監控 Windows 中的憑證過期日期

我們選擇我們建立的事件CertificateExpireDate_Threshold_Activate和CertificateExpireDate_Threshold_Deactivate,將樣本數(Samples)設為1(特別是對於這個計數器,設定更多沒有意義),例如,該值為30(天),並且重要的是,設定事件重複時間。 對於生產中的證書,我每天設定一次(86400秒),否則你可能會淹沒在通知中(順便說一句,發生過一次,以至於週末郵箱已滿)。 對於調試時間,將其設置得較低(例如 60 秒)是有意義的。

3。 在 動作配置 建立通知信模板,如下所示:

在 NetXMS 上監控 Windows 中的憑證過期日期

所有這些 %m、%S 等等。 — 我們參數中的值將被替換為的巨集。 它們在中進行了更詳細的描述 手動的 網路XMS。

4.最後,結合前面的幾點,得到 事件處理政策 建立一條規則,根據該規則將建立警報並發送一封信:

在 NetXMS 上監控 Windows 中的憑證過期日期

我們保存策略,一切都可以測試。 我們把閾值設高一點來檢查。 我最近的證書還有723天過期,我把它設定為724來檢查,結果,我們得到以下警報:

在 NetXMS 上監控 Windows 中的憑證過期日期

以及此電子郵件通知:

在 NetXMS 上監控 Windows 中的憑證過期日期

現在一切都確定了。 當然,可以設定儀表板並建立圖表,但對於證書來說,這些有點毫無意義且無聊的直線,與處理器或記憶體負載的圖表不同。 但是,稍後再詳細討論這一點。

來源: www.habr.com

添加評論