Мониторинг срока действия внешних сертификатов в NetXMS
Posted by Retifff на 05.02.2024
Вообще, я хотел не эту статью писать, а другую, но в ней будет использоваться как раз мониторинг срока действия внешних сертификатов, поэтому придётся сначала эту написать.
Вообще про мониторинг сертификатов, которые находятся на серверах с Windows , я уже писал: Мониторинг срока действия сертификатов в Windows на NetXMS. Но мониторить сертификаты бывает нужно не только на Windows-машинах, но и на Linux, на каких-то балансировщиках, апплаинсах, внутренних сайтах и на каких-то внешних ресурсах (сайтах в Интернете, к примеру). Именно поэтому в этой статье разберём подробно, как этот мониторинг настроить.
- Использование встроенных счетчиков NetXMS
- Использование скрипта для автоматического создания счетчиков под каждый сертификат
1 Использование встроенных счетчиков NetXMS
Они появились примерно с 4-й версии, раньше не было. Очень удобно стало.
Давайте создадим два счётчика. Выбираем в качестве жертвы какую-то ноду с Windows, у меня это контроллер домена dc01 в тестовой среде. Естественно, сначала нужно поставить на него агента.
1.1 Открываем Data Collection Configuration ноды, создаем первый счётчик (подробно, как это сделать, можно прочитать в моей первой статье на эту тему Настройка счётчиков в NetXMS), выбираем метрику и в фильтре вводим «certificate». Нам выдается список имеющихся метрик для мониторинга сертификатов:
Выбираем там «Days until expiration of X.509 certificate of remote TLS service». Заполняем поля, в поле «Metric», в скобках надо будет заменить звездочку (*) на имя хоста и порт, через запятую. Для примера я взял сайт https://netxms.com/. В поле «Display name» можно написать что-то более понятное для нас, чем то, что туда автоматически подставляется:
Интервал в продакшене я использую 1200 секунд, здесь слишком часто делать опрос необходимости нет.
1.2 Второй счетчик создаём аналогично, с метрикой «Expiration date (YYYY-MM-DD) of X.509 certificate of remote TLS service»:
В общем-то всё. В тонкости я вникать не буду, порог на первом счетчике настроить труда не составит. Получится примерно так:
По второму счетчику, обратите внимание, что там тип строка, следовательно, какого-то вменяемого порога срабатывания настроить мы не сможем. А с первым без проблем, ставим 30 дней, к примеру, всё как в прошлой статье Настройка оповещений при приближении конца срока действия сертификата.
Всё довольно просто и понятно. Сложнее становится, когда сертификатов много и под каждый создавать отдельный счетчик откровенно лень. Тем более, что получается, нужно на один сертификат два счетчика, один с датой истечения срока сертификата (просто на него смотреть удобней), второй с количеством дней, оставшихся до этой даты.
Тогда на помощь приходит второй вариант. Он, в общем-то, основан на первой моей статье про мониторинг сертификатов, только с адаптацией под внешние сертификаты.
2 Использование скрипта для автоматического создания счетчиков под каждый сертификат
2.1 В конфиге агента пишем такие две строчки (не забудьте перезапустить агента, после редактирования конфига, это можно сделать прямо из консоли NetXMS, как и редактировать конфиг агента):
ExternalList = CertExpDaysLeftList: powershell.exe -NoLogo -STA -NoProfile -NonInteractive -File "\\test-company.mooo.com\SYSVOL\test-company.mooo.com\scripts\NetXMS_CheckExternalCertificateExpiration.ps1" -List
ExternalMetricProvider = powershell.exe -NoLogo -STA -NoProfile -NonInteractive -File "\\test-company.mooo.com\SYSVOL\test-company.mooo.com\scripts\NetXMS_CheckExternalCertificateExpiration.ps1":600
Обратите внимание, что в конфиге агента используется ExternalMetric вместо ExternalParameter в прошлой статье. Параметры ExternalParameter и ExternalParameterProvider стали уже Deprecated, вместо них теперь ExternalMetric и ExternalMetricProvider с 4-й версии NetXMS.
С ExternalParameter я столкнулся с тем, что скрипт может работать не очень быстро, особенно, если мониторится много сертификатов. Также могут быть какие-то сетевые проблемы в это время. В результате получается, что в сервер NetXMS приходит битая информация. А с ExternalMetricProvider скрипт возвращает ряд метрик и их значений, они кэшируется агентом, а агент возвращает их серверу по запросу (раз в 600 секунд в моем случае, интервал задаётся через двоеточие).
Таким образом, ExternalMetric есть смысл использовать при быстрых скриптах, а ExternalMetricProvider — при долгих.
Ещё один тонкий момент, пишите эти параметры в основной секции. Я один раз написал их в секции [FILEMGR] и очень долго не мог понять, почему у меня не создаются инстансы, была ошибка:
Failed to get instance list
при выполнении при Poll > Instance Discovery.
Т.е. выглядеть конфиг должен примерно так:
2.2 Теперь сам скрипт. В отличие от прошлой статьи, скрипт у меня используется один, но может выполнять обе задачи (в зависимости от того, подавать ему на вход параметр «List» или нет), и формировать список строк с именами и датами сертификатов и получать количество дней для каждого.
#Список внешних хостов для мониторинга
param(
[Parameter(Mandatory = $false)]
[Switch]$List,
[Parameter(Mandatory = $false)]
[String[]]$Hosts = @(
'netxms.com',
'netxms.org',
'ya.ru',
'google.com')
)
#Задаем префикс, который будет являться названием метрики и отражатся в начале Description cчетчика
$prefix = 'CertificateExpireDateExternal'
#Функция получения сертификата внешнего хоста
function Get-RemoteSslCertificate {
[CmdletBinding()]
param (
[Parameter(Mandatory=$true)]
[string]
$ComputerName,
[int]
$Port = 443
)
$Certificate = $null
$TcpClient = New-Object -TypeName System.Net.Sockets.TcpClient
try {
$TcpClient.Connect($ComputerName, $Port)
$TcpStream = $TcpClient.GetStream()
$Callback = { param($sender, $cert, $chain, $errors) return $true }
[System.Security.Authentication.SslProtocols]$protocol = [System.Security.Authentication.SslProtocols]::Tls12
$SslStream = New-Object -TypeName System.Net.Security.SslStream -ArgumentList @($TcpStream, $true, $Callback) -ErrorAction Stop
try {
$SslStream.AuthenticateAsClient($computername,$null,$protocol,$false)
$Certificate = $SslStream.RemoteCertificate
}
finally {
$SslStream.Dispose()
}
}
finally {
$TcpClient.Dispose()
}
if ($Certificate) {
if ($Certificate -isnot [System.Security.Cryptography.X509Certificates.X509Certificate2]) {
$Certificate = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList $Certificate -ErrorAction Stop
}
}
return $Certificate
}
foreach($h in $Hosts) {
$destAddress = $h
$destPort = 443
if ($destAddress.Contains(':')) {
$destPort = [UInt32]::Parse($destAddress.SubString($destAddress.IndexOf(':') + 1))
$destAddress = $destAddress.SubString(0, $destAddress.IndexOf(':'))
}
try {
$cert = Get-RemoteSslCertificate -ComputerName $destAddress -Port $destPort -ErrorAction Stop
}
catch {
if (-not $list.IsPresent) {
Write-Output ([String]::Format("{0}({1} - {2})={3}",
$prefix,
$destAddress,
'connection failed',
'1'))
}
else {
write-output ([String]::Format("{0} - {1}", $destAddress, 'connection failed'))
}
continue
}
if (-not $List.IsPresent) {
$reportLine = [String]::Format("{0}({1} - {2})={3}",
$prefix,
$destAddress,
$cert.NotAfter.ToString('dd.MM.yyyy'),
[Math]::Max(0, [Math]::Floor(($cert.NotAfter - [DateTime]::Now).TotalDays)).ToString()
)
}
else {
$reportLine = [String]::Format("{0} - {1}",
$destAddress,
$cert.NotAfter.ToString('dd.MM.yyyy'))
}
Write-Output $reportLine
}
В первой секции, «Список внешних хостов для мониторинга
» мы задаём список хостов, сертификаты которых требуется мониторить. У меня для примера взяты четыре сайта:
netxms.com
netxms.org
ya.ru
google.com
Вы вместо них вводите свои значения. Обратите внимание, что в скрипте, после каждого нужна запятая, кроме последнего имени, самого нижнего. Скрипт можете разместить где угодно, хоть локально на выбранной ноде, хоть на файловой шаре. Я обычно кладу их в папку SYSVOL домена, так они везде доступны и близко к нодам. При расположении в SYSVOL и прочих сететевых шарах, учтите Execution Policy для Powershell и прочие моменты для удачного запуска скриптов. Не забудьте только в конфиге ноды прописать полный путь к скрипту.
2.3 Далее создаём счётчик, в котором в поле Metric вводим:
CertificateExpireDateExternal({instance})
А в поле Display name:
CertificateExpireDateExternal: {instance}
Обратите внимание, что название метрики (CertificateExpireDateExternal в данном случае) должно строго совпадать со значением переменной $prefix скрипта. В итоге счётчик будет выглядеть примерно так:
Кстати, если вы нажмете кнопку справа от поля Metric и попытаетесь там найти CertificateExpireDateExternal, то потерпите неудачу. Поэтому придётся вводить вручную.
2.4 Дальше, идём на вкладку Instance Discovery, там в поле Instance discovery method выбираем Agent List, а в поле List name пишем CertExpDaysLeftList. Это имя должно строго совпадать с именем параметра ExternalList в конфиге агента:
Нажимаем кнопку «Apply and Close» и в принципе счётчик готов.
2.5 Теперь нам нужно, чтобы создались инстансы для каждого сертификата, для чего для ноды выполняем Poll > Instance Discovery (вообще, по умолчанию это само происходит раз в 600 секунд, можно и подождать, но неохота). Это должно отработать как-то так:
Довольно часто здесь можно получить ошибку «Failed to get instance list», про которую я писал выше. К сожалению, причин её возникновения может быть довольно много и я не смогу их все здесь описать. Надо проверять работу скрипта на ноде просто из Powershell, по тому пути, который у вас в конфиге ноды, смотреть Execution Policy и т.п.
В Data Collection Configuration ноды должны создаться инстансы наших счетчиков, в количестве 4-х штук:
А в Last Values ноды, соответсвенно, должны появиться наши четыре счетчика:
Обратите внимание, что у нас в имени счетчика видно название сертификата и дата его срока действия, а в значении, соответственно, количество дней, оставшихся до этой даты. Получается три в одном 🙂 Естественно, в этом случае легко будет настроить порог срабатывания оповещения.
Т.е. всё, что нам надо, это заносить имена хостов в powershell-скрипт, дальше уже всё будет делаться автоматически.
Оставьте комментарий