This article applies to PRTG Network Monitor 12 or later
Monitoring a Windows CA Certificate
I found a way to monitor certification-expiry that should be useful for you.
Note: You will be able to monitor certificates on the machine running the PRTG Probe only; you cannot monitor certificates on remote machines with this!
Please copy&paste the following script in a file with the extension .ps1 and place it in the Custom Sensors\EXEXML sub directory of your PRTG program directory. In the PRTG web interface, add a new EXE/Script (Advanced) sensor using this script.
The sensor without any parameter returns the expiry time in days of any certificates installed on your probe computer. You can filter the stores by using the -store <your store name> parameter.
It will be usefull for us if you can give us some feedback if and how the sensor works.
# begin of script #
Param( $store='all' )
# To get this script running with PRTGNetworkMonitor you need to enable RemoteSigned-scripting for 32bit-processes.
# This can be done with running 'c:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe "Set-ExecutionPolicy RemoteSigned"' on a system with default paths
# the logic behind this sensor is based on the basics from http://blogs.technet.com/b/heyscriptingguy/archive/2011/02/16/use-powershell-and-net-to-find-expired-certificates.aspx
# Examples of Parameters-string in sensorsettings
# -store AuthRoot
# possible values see $stores-variable + 'all' or leave the field empty for default ('all')
# !!! the storenames are casesensitiv !!!
# declare script-wide variables
$script:starttime = Get-Date
$script:table = $null
$script:resultText = "OK"
$stores = @('AddressBook', 'AuthRoot', 'CertificateAuthority', 'My', 'Root', 'TrustedPeople', 'TrustedPublisher')
function main {
switch ($store)
{
'all' {
foreach($certStore in $stores){
$storeRef = New-Object System.Security.Cryptography.X509Certificates.X509Store($certStore,"LocalMachine")
$storeRef.Open("ReadOnly")
foreach($certificate in $storeRef.Certificates) {
addCertificate -certificate $certificate -storename $storeRef.name
}
}
}
default {
$storeRef = New-Object System.Security.Cryptography.X509Certificates.X509Store($store,"LocalMachine")
$storeRef.Open("ReadOnly")
foreach($certificate in $storeRef.Certificates) {
addCertificate -certificate $certificate -storename $storeRef.name
}
}
}
# add the execution-time to channels
$row = $table.NewRow();
$row.channel = "ExecutionTime";
$row.unit = "TimeSeconds";
$row.SpeedTime = "Second";
$row.float = "1";
$row.ShowChart = "0";
$row.ShowTable = "0";
$row.Value = "$([Math]::Round((new-timespan $starttime).totalseconds,1))";
$table.Rows.Add($row)
# forward the generated table to xml-generator and store the result
$retval = $table | New-Xml -RootTag prtg -ItemTag result -ChildItems Channel,Value,Unit,CustomUnit,Warning,Error,speedtime,volumesize,mode,showchart,showtable,float -ResultTag $resultText
write-host $retval
}
function addCertificate {
param($certificate, $storeName)
$value = ($certificate.notAfter - ($script:starttime)).Days
if (($script:store -eq 'all') -and ($storeName -ne '')) { $prefix = "$($storeName) - " }
if ($value -ne '') {
$row = $table.NewRow();
if ($certificate.friendlyName -ne '') {
$row.channel = "$prefix$($certificate.friendlyName)";
} else {
$row.channel = "$prefix$($certificate.GetName())";
}
$row.value = $value
$row.unit = "Custom"
$row.customUnit = "Days"
$table.Rows.Add($row)
}
}
function prepareResultTable {
# create a table to store the information only if not yet done
# all available values predefined, in the result only the active values will apear
if ($script:table -eq $null) {
$script:table = New-Object system.Data.DataTable "result"
$col1 = New-Object system.Data.DataColumn channel,string
$col2 = New-Object system.Data.DataColumn value,string # a Integer or float value preconverted into a string!
$col3 = New-Object system.Data.DataColumn unit,string # BytesBandwidth/BytesMemory/BytesDisk/Temperature/Percent/TimeResponse/TimeSeconds/Custom/Count/CPU (%)/BytesFile/SpeedDisk/SpeedNet/TimeHours
$col4 = New-Object system.Data.DataColumn customUnit,string
$col5 = New-Object system.Data.DataColumn warning,string # 0/1 (no/yes) 0
$col6 = New-Object system.Data.DataColumn SpeedSize,string # One/Kilo/Mega/Giga/Tera/Byte/KiloByte/MegaByte/GigaByte/TeraByte/Bit/KiloBit/MegaBit/GigaBit/TeraBit
$col7 = New-Object system.Data.DataColumn VolumeSize,string # siehe Speedsize
$col8 = New-Object system.Data.DataColumn SpeedTime,string # Second/Minute/Hour/Day
$col9 = New-Object system.Data.DataColumn Mode,string # Absolute/Difference
$col10 = New-Object system.Data.DataColumn ShowChart,string # 0/1 (no/yes) 1
$col11 = New-Object system.Data.DataColumn ShowTable,string # 0/1 (no/yes) 1
$col12 = New-Object system.Data.DataColumn Float,string # 0/1 (no integer/yes float) 0
$table.columns.add($($col1))
$table.columns.add($($col2))
$table.columns.add($($col3))
$table.columns.add($($col4))
$table.columns.add($($col5))
$table.columns.add($($col6))
$table.columns.add($($col7))
$table.columns.add($($col8))
$table.columns.add($($col9))
$table.columns.add($($col10))
$table.columns.add($($col11))
$table.columns.add($($col12))
}
}
# this function produces a well-formated xml-output out of a given table
function New-Xml
{
param($RootTag="ROOT",$ItemTag="ITEM", $ChildItems="*", $resultTag, $Attributes=$Null)
Begin {
$xml = "<$RootTag>`n"
}
Process {
$xml += " <$ItemTag>`n"
foreach ($child in $_ | Get-Member -Type *Property $childItems)
{
$Name = $child.Name
if ("$($_.$name)" -ne "") {
$xml += " <$Name>$($_.$Name)</$Name>`n"
}
}
$xml += " </$ItemTag>`n"
}
End {
if ([string]$resultTag -ne $false) {
$xml += " <text>$resultTag</text>`n"
}
$xml += "</$RootTag>`n"
$xml
}
}
# print a xml-errormessage
function printErrorXml($errortext = $script:resultText) {
$errorXml = "<prtg>`n"
$errorXml += " <error>1</error>`n"
$errorXml += " <text>$errortext</text>`n"
$errorXml += "</prtg>`n"
[System.Console]::WriteLine($errorXml)
disconnect($session)
exit
}
prepareResultTable
main
exit
#end of script #
Add comment