在Windows上的NetXMS上监视证书到期

最近,我们的任务是监视Windows服务器上证书的有效期。 好吧,在证书多次变成南瓜之后,我又起床了,而负责续签的大胡子同事正在休假。 在那之后,我们怀疑了什么并决定考虑一下。 由于我们正在慢慢引入NetXMS监视系统,因此它已成为该任务的主要且从原则上讲是唯一的候选者。

最终获得的结果如下:



这个过程本身就更进一步了。

走吧 NetXMS中没有用于使证书到期的内置计数器,因此您需要创建自己的计数器并使用脚本向其提供数据。 当然,在Powershell上是Windows。 该脚本应读取操作系统中的所有证书,从此处获取以天为单位的到期日期,并将此编号传输到NetXMS。 通过他的经纪人。 让我们从他开始。

选项一 ,最简单。 仅获取证书在最近的日期之前过期的天数。

为了使NetXMS服务器了解我们的自定义参数的存在,它必须从代理接收它。 否则,由于缺少此参数,因此无法添加。 因此,在nxagentd.conf代理配置文件中,我们添加了一个名为HTTPS.CertificateExpireDateSimple的外部参数行,在其中编写了要运行的脚本:

ExternalParameter = HTTPS.CertificateExpireDateSimple: powershell.exe -File "\\server\share\NetXMS_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:\NetXMS\etc\nxagentd.conf.d LogFile = {syslog} FileStore = C:\NetXMS\var 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 "\\server\share\NetXMS_CertExpireDateSimple.ps1" 

之后,您需要保存配置并重新启动代理。 您可以从NetXMS控制台执行此操作:打开配置(编辑代理的配置文件),编辑,执行“保存并应用”,结果将发生完全相同的事情。 如果绝对没有等待的强度,则重新读取配置(“轮询”>“配置”)。 这些步骤之后,您应该可以添加我们的自定义参数。

在NetXMS控制台中,我们转到实验服务器的“ 数据收集配置” ,我们将在该服务器上监视证书并在该服务器上创建新参数(将来,在设置之后,有必要将其传输到模板中)。 我们从列表中选择HTTPS.CertificateExpireDateSimple,输入带有友好名称的Description,将类型设置为Integer并设置轮询间隔。 使其太短以至于不会用不必要的信息阻塞数据库是没有意义的,检查时等待太长时间会很不方便。 对于证书,我通常设置600秒。 在调试时,将其缩短为30秒是有意义的,例如:



一切准备就绪,只要足够。 您可以检查...不,为时过早。 现在,我们当然什么也得不到。 只是因为脚本尚未编写。 我们纠正了这一遗漏。 该脚本只会给出一个数字,即证书过期之前剩余的天数。 所有可用的最小的。 示例脚本:

 try { #       $lmCertificates = @( Get-ChildItem -Recurse -path 'Cert:\LocalMachine\My' -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 } 

原来是这样的:



723天,证书过期将近两年。 这是合乎逻辑的,因为我最近在Exchange测试平台上重新签署了证书。

这是一个简单的选择。 也许有人会对此感到满意,但是我们想要更多。 我们将任务设置为自己,以名称的形式获取服务器上所有证书的列表,并为每个证书查看证书过期之前剩余的天数。

第二种选择 ,稍微复杂一点。

再次,我们编辑代理配置,并在其中代替其他与ExternalParameter的行一起编写另外两个:

 ExternalList = HTTPS.CertificateNames: powershell.exe -File "\\server\share\netxms_CertExternalNames.ps1" ExternalParameter = HTTPS.CertificateExpireDate(*): powershell.exe -File "\\server\share\netxms_CertExternalParameter.ps1" -CertificateId "$1" 

ExternalList中,我们仅获得字符串列表。 在我们的例子中,是带有证书名称的字符串列表。 这些行的列表我们可以获取脚本。 列表名称为HTTPS.CertificateNames

脚本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:\LocalMachine\My' | 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)" } } 

ExternalParameter中,我们已经从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:\LocalMachine\My\$($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(*) ,然后(注意!)将星号更改为{instance} 。 这一点很重要,您可以为每个实例(证书)创建一个单独的计数器。 其余的与以前的版本相同:



为了使计数器成为创建对象,在“实例发现”选项卡上,从列表中选择“代理列表”,然后在“列表名称”字段中,从脚本HTTPS.CertificateNames输入我们的ExternalList的名称。

几乎准备就绪,请稍等一下,如果完全无法等待,则强制轮询>配置和轮询>实例发现。 结果,我们获得了所有带有到期日期的证书:



需要什么? 好吧,是的,只有完美主义蠕虫会以悲伤的眼神以柜台的名义注视着这个不必要的拇指指纹,并且无法完成本文。 要养活他,请再次打开计数器属性,然后在“实例发现过滤器脚本”字段的“实例发现”选项卡上,添加以NXSLNetXMS内部语言)编写的脚本:

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

这将过滤指纹:



为了显示过滤条件,请在“描述”字段的“常规”选项卡上,将CertificateExpireDate:{instance}更改为CertificateExpireDate:{instance-name}



一切,最后KDPV的完成:



美丽吗

仍然需要配置警报,以便在证书在其逻辑末期到期时通过邮件到达警报。

1.首先,您需要创建一个事件模板,以在将计数器值减小到我们设置的某个阈值时将其激活。 在“ 事件配置”中,创建两个具有名称的新模板,例如带有警告状态的CertificateExpireDate_Threshold_Activate



以及具有正常状态的类似CertificateExpireDate_Threshold_Deactivate

2.接下来,转到计数器属性,然后在“阈值”选项卡上设置阈值:



在其中选择创建的事件CertificateExpireDate_Threshold_Activate和CertificateExpireDate_Threshold_Deactivate,设置测量次数(样本)为1(具体来说,没有设置特定的计数器),例如,该值为30(天),重要的是,我们设置了事件重复时间。 对于生产中的证书,我每天设置一次(86400秒),否则您可能会淹没在警报中(顺便说一下,警报发生了一次,而且周末邮箱已满)。 对于调试,可以将时间设置得更短一些,例如60秒。

3.在“操作配置”中,创建警报消息模板,例如:



所有这些%m,%S等 -将替换我们参数中的值的宏。 它们在NetXMS 手册中有更详细的描述。

4.最后,结合前面的几点,在事件处理策略中创建一条规则,通过该规则将创建警报并发送消息:



我们遵守政策,一切都可以测试。 设置更高的阈值进行验证。 我最近的证书在723天后过期,我设置了724进行验证,结果收到以下警报:



以及这样的邮件警报:



现在就这些了。 当然,您可以设置仪表板,构建图形,但是对于证书来说,这将是毫无意义且无聊的直线,例如,不同于CPU或内存负载的图形。 但是,另一回事。

Source: https://habr.com/ru/post/zh-CN460193/


All Articles