What is this?

This knowledgebase contains questions and answers about PRTG Network Monitor and network monitoring in general.

Learn more

PRTG Network Monitor

Intuitive to Use. Easy to manage.
More than 500,000 users rely on Paessler PRTG every day. Find out how you can reduce cost, increase QoS and ease planning, as well.

Free Download

Top Tags


View all Tags

Trying To Get Multi-Result PowerShell As Channels With Limits

Votes:

0

Kind of a PS newb, but trying to get a single sensor to go out and check a list of URLs for SSL cert, exipiring date and how many days left until expired. I would like to set each site as a channel, then have a threshold of 120 days as warning and 30 days as error/down. I have been using this script as a feed for another script, having both of them run at a certain interval and then email results monthly, but would like to move the process to PRTG. I have the following script, found on Stack Overflow:

$WebsiteURLs= @("google.com","aol.com","yahoo.com","espn.com")
$WebsitePort=443
$Threshold=120
$Severe=30
$ID=0
Write-Host "#	Website_URL:	Current Certificate:	Expiration Date:	Days Remaining:	Errors:"
foreach ($WebsiteURL in $WebsiteURLs){
$CommonName=$WebsiteURL
$ID+=1
Try{
$Conn = New-Object System.Net.Sockets.TcpClient($WebsiteURL,$WebsitePort) 
Try {
$Stream = New-Object System.Net.Security.SslStream($Conn.GetStream(),$false, {
param($sender, $certificate, $chain, $sslPolicyErrors) 
return $true
})
$Stream.AuthenticateAsClient($CommonName) 

$Cert = $Stream.Get_RemoteCertificate()
$CN=(($cert.Subject -split "=")[1] -split ",")[0]
$ValidTo = [datetime]::Parse($Cert.GetExpirationDatestring())

$ValidDays = $($ValidTo - [datetime]::Now).Days
$MyFontColor="darkgreen"
if ($ValidDays -lt $Threshold) {
$MyFontColor="darkyellow"
} 
if ($ValidDays -lt $Severe) {
$MyFontColor="red"
}
Write-Host "$ID	$WebsiteURL	$CN	$ValidTo	$ValidDays" -ForegroundColor $MyFontColor
}
Catch { Throw $_ }
Finally { $Conn.close() }
}
Catch {
Write-Host "$ID	$WebsiteURL	" $_.exception.innerexception.message -ForegroundColor red
}

}

Ideally, I would like to show:

SiteCert Expires In
aGoogle.com187 days

I've tried to read through the forums and at the API guide, but am kind of lost. I know that I need to pipe my output to an XML format, then add the PRTG XML parsing code, but that is where I am lost. I am still in a trial with PRTG and would love to have this set up for the demo to my director for budget approval! Thank you for any help or suggestions!

custom-script-exe custom-sensor powershell prtg script xml

Created on Nov 8, 2018 9:58:41 PM

Last change on Nov 12, 2018 8:04:02 AM by  Luciano Lingnau [Paessler]



Best Answer

Accepted Answer

Votes:

9

Here is your script:

param(
    $WebsiteURLs= @("google.com","aol.com","yahoo.com","espn.com"),
    $LimitMinDaysWarning=30,
    $LimitMinDaysError=5
)

$WebsitePort=443
$Threshold=120
$Severe=30
$ID=0

#Limits:

$XML = "<PRTG>"
$TextError = ""
foreach ($WebsiteURL in $WebsiteURLs){
    $CommonName=$WebsiteURL
    $ID+=1
    Try{
        $Conn = New-Object System.Net.Sockets.TcpClient($WebsiteURL,$WebsitePort) 
        Try {
            $Stream = New-Object System.Net.Security.SslStream($Conn.GetStream(),$false, {
                param($sender, $certificate, $chain, $sslPolicyErrors) 
                return $true
            })
            $Stream.AuthenticateAsClient($CommonName) 

            $Cert = $Stream.Get_RemoteCertificate()
            $CN=(($cert.Subject -split "=")[1] -split ",")[0]
            $ValidTo = [datetime]::Parse($Cert.GetExpirationDatestring())

            $ValidDays = $($ValidTo - [datetime]::Now).Days
            $MyFontColor="darkgreen"
            if ($ValidDays -lt $Threshold) {
                $MyFontColor="darkyellow"
            } 
            if ($ValidDays -lt $Severe) {
                $MyFontColor="red"
            }
            $XML += "<result><channel>$WebsiteURL</channel><value>$ValidDays</value><CustomUnit>days</CustomUnit><LimitMinWarning>$LimitMinDaysWarning</LimitMinWarning><LimitMinError>$LimitMinDaysError</LimitMinError></result>"
        } Catch { 
            Throw $_ 
        } Finally { 
            $Conn.close() 
        }
    } Catch {
        $XML += "<result><channel>$WebsiteURL</channel><value>-999</value><CustomUnit>days</CustomUnit><LimitMinWarning>$LimitMinDaysWarning</LimitMinWarning><LimitMinError>$LimitMinDaysError</LimitMinError></result>"
        If ($TextError.Length -gt 0) {
            $TextError += " / "
        }
        $TextError += "$WebsiteURL"
    }
}
If ($TextError.Length -gt 0) {
    $XML += "<text>Not reached pages: $TextError</text>"
}
$XML += "</PRTG>"

Function WriteXmlToScreen ([xml]$xml) #just to make it clean XML code...
{
    $StringWriter = New-Object System.IO.StringWriter;
    $XmlWriter = New-Object System.Xml.XmlTextWriter $StringWriter;
    $XmlWriter.Formatting = "indented";
    $xml.WriteTo($XmlWriter);
    $XmlWriter.Flush();
    $StringWriter.Flush();
    Write-Output $StringWriter.ToString();
}
WriteXmlToScreen "$XML"

The result would look like this:

<PRTG>
  <result>
    <channel>google.com</channel>
    <value>66</value>
    <CustomUnit>days</CustomUnit>
    <LimitMinWarning>30</LimitMinWarning>
    <LimitMinError>5</LimitMinError>
  </result>
  <result>
    <channel>aol.com</channel>
    <value>143</value>
    <CustomUnit>days</CustomUnit>
    <LimitMinWarning>30</LimitMinWarning>
    <LimitMinError>5</LimitMinError>
  </result>
  <result>
    <channel>yahoo.com</channel>
    <value>96</value>
    <CustomUnit>days</CustomUnit>
    <LimitMinWarning>30</LimitMinWarning>
    <LimitMinError>5</LimitMinError>
  </result>
  <result>
    <channel>espn.com</channel>
    <value>-999</value>
    <CustomUnit>days</CustomUnit>
    <LimitMinWarning>30</LimitMinWarning>
    <LimitMinError>5</LimitMinError>
  </result>
  <text>Not reached pages: espn.com</text>
</PRTG>

To make it more usable - you can input parameters from PRTG like this:

@("domain.com","domain2.com","domain3.com")

or this for limits - warning 60 and error 10 - you could name them but this should work as well...

@("domain.com","domain2.com","domain3.com") 60 10

Hope this helps... pretty nice idea :-) love it :-) might even post it :-)

Florian Rossmark

www.it-admins.com

Edit: Posted it here: https:www.it-admins.com/monitor-multiple-website-certificates-with-a-single-prtg-sensor/

Created on Nov 9, 2018 7:13:39 PM

Last change on Nov 9, 2018 7:32:38 PM by  Erhard Mikulik [Paessler Support]



7 Replies

Votes:

0

Hello there,

The current output is outputting line by line, for the EXE/XML Advanced sensor the output (Write-Host) at the end of the script needs to look like this for example so that PRTG can parse it: <prtg> <result> <channel>Google</channel> <value>10</value> </result> <result> <channel>Yahoo</channel> <value>20</value> </result> </prtg>

See also here an example.

Alternatively: Why not simply use the SSL Certificate Sensor? :)

Kind regards,

Erhard

Created on Nov 9, 2018 8:51:17 AM by  Erhard Mikulik [Paessler Support]

Last change on Nov 9, 2018 8:52:31 AM by  Erhard Mikulik [Paessler Support]



Votes:

0

Thank you for the guidance. I tried adding that to the end of the script, then for each URL I want to check, I added another instance of:

<result>
        <channel>www.urltocheck.com</channel>
        <value>10</value>
    </result>

After making those changes and saving, the sensor now sends back this error:

XML: XML Parser mismatch: Wanted </:String)>, got </channel> -- JSON: The returned JSON does not match the expected structure (Invalid JSON.). (code: PE231)

The only channel listed as available to use is downtime as well, if that helps.

Again, thanks for the assistance.

Created on Nov 9, 2018 2:50:56 PM

Last change on Nov 12, 2018 8:02:38 AM by  Luciano Lingnau [Paessler]



Accepted Answer

Votes:

9

Here is your script:

param(
    $WebsiteURLs= @("google.com","aol.com","yahoo.com","espn.com"),
    $LimitMinDaysWarning=30,
    $LimitMinDaysError=5
)

$WebsitePort=443
$Threshold=120
$Severe=30
$ID=0

#Limits:

$XML = "<PRTG>"
$TextError = ""
foreach ($WebsiteURL in $WebsiteURLs){
    $CommonName=$WebsiteURL
    $ID+=1
    Try{
        $Conn = New-Object System.Net.Sockets.TcpClient($WebsiteURL,$WebsitePort) 
        Try {
            $Stream = New-Object System.Net.Security.SslStream($Conn.GetStream(),$false, {
                param($sender, $certificate, $chain, $sslPolicyErrors) 
                return $true
            })
            $Stream.AuthenticateAsClient($CommonName) 

            $Cert = $Stream.Get_RemoteCertificate()
            $CN=(($cert.Subject -split "=")[1] -split ",")[0]
            $ValidTo = [datetime]::Parse($Cert.GetExpirationDatestring())

            $ValidDays = $($ValidTo - [datetime]::Now).Days
            $MyFontColor="darkgreen"
            if ($ValidDays -lt $Threshold) {
                $MyFontColor="darkyellow"
            } 
            if ($ValidDays -lt $Severe) {
                $MyFontColor="red"
            }
            $XML += "<result><channel>$WebsiteURL</channel><value>$ValidDays</value><CustomUnit>days</CustomUnit><LimitMinWarning>$LimitMinDaysWarning</LimitMinWarning><LimitMinError>$LimitMinDaysError</LimitMinError></result>"
        } Catch { 
            Throw $_ 
        } Finally { 
            $Conn.close() 
        }
    } Catch {
        $XML += "<result><channel>$WebsiteURL</channel><value>-999</value><CustomUnit>days</CustomUnit><LimitMinWarning>$LimitMinDaysWarning</LimitMinWarning><LimitMinError>$LimitMinDaysError</LimitMinError></result>"
        If ($TextError.Length -gt 0) {
            $TextError += " / "
        }
        $TextError += "$WebsiteURL"
    }
}
If ($TextError.Length -gt 0) {
    $XML += "<text>Not reached pages: $TextError</text>"
}
$XML += "</PRTG>"

Function WriteXmlToScreen ([xml]$xml) #just to make it clean XML code...
{
    $StringWriter = New-Object System.IO.StringWriter;
    $XmlWriter = New-Object System.Xml.XmlTextWriter $StringWriter;
    $XmlWriter.Formatting = "indented";
    $xml.WriteTo($XmlWriter);
    $XmlWriter.Flush();
    $StringWriter.Flush();
    Write-Output $StringWriter.ToString();
}
WriteXmlToScreen "$XML"

The result would look like this:

<PRTG>
  <result>
    <channel>google.com</channel>
    <value>66</value>
    <CustomUnit>days</CustomUnit>
    <LimitMinWarning>30</LimitMinWarning>
    <LimitMinError>5</LimitMinError>
  </result>
  <result>
    <channel>aol.com</channel>
    <value>143</value>
    <CustomUnit>days</CustomUnit>
    <LimitMinWarning>30</LimitMinWarning>
    <LimitMinError>5</LimitMinError>
  </result>
  <result>
    <channel>yahoo.com</channel>
    <value>96</value>
    <CustomUnit>days</CustomUnit>
    <LimitMinWarning>30</LimitMinWarning>
    <LimitMinError>5</LimitMinError>
  </result>
  <result>
    <channel>espn.com</channel>
    <value>-999</value>
    <CustomUnit>days</CustomUnit>
    <LimitMinWarning>30</LimitMinWarning>
    <LimitMinError>5</LimitMinError>
  </result>
  <text>Not reached pages: espn.com</text>
</PRTG>

To make it more usable - you can input parameters from PRTG like this:

@("domain.com","domain2.com","domain3.com")

or this for limits - warning 60 and error 10 - you could name them but this should work as well...

@("domain.com","domain2.com","domain3.com") 60 10

Hope this helps... pretty nice idea :-) love it :-) might even post it :-)

Florian Rossmark

www.it-admins.com

Edit: Posted it here: https:www.it-admins.com/monitor-multiple-website-certificates-with-a-single-prtg-sensor/

Created on Nov 9, 2018 7:13:39 PM

Last change on Nov 9, 2018 7:32:38 PM by  Erhard Mikulik [Paessler Support]



Votes:

0

Hi ffejeroni,

Check out Florian's suggestion first, he is THE man when it comes to stuff like that ^^

Thank you, Florian, as always :)

Kind regards,

Erhard

Created on Nov 9, 2018 7:16:42 PM by  Erhard Mikulik [Paessler Support]



Votes:

0

Thanks so much! So I was missing the units and warning/error parameters then on top of the XML output portion. I have lots to learn!

If you do share, the main script came from here: https://stackoverflow.com/questions/28386579/modifying-ssl-cert-check-powershell-script-to-loop-through-multiple-sites#_=_

Just making sure to give credit where it's due! Thanks so much, this should get me on the right track and will help me figure out how this all works.

Created on Nov 9, 2018 7:21:18 PM



Votes:

2

Did share it - here: https://www.it-admins.com/monitor-multiple-website-certificates-with-a-single-prtg-sensor/

Found the source already and mentioned it there as well... that's a keeper... for that reason I have my blog where I share stuff like that...

There are many more you might find useful... :-)

Florian

Created on Nov 9, 2018 7:29:24 PM



Votes:

0

Thanks for chipping in, Florian, we appreciate it, as always :)

Kind regards,

Erhard

Created on Nov 9, 2018 7:31:54 PM by  Erhard Mikulik [Paessler Support]

Last change on Nov 9, 2018 9:04:26 PM by  Erhard Mikulik [Paessler Support]




Disclaimer: The information in the Paessler Knowledge Base comes without warranty of any kind. Use at your own risk. Before applying any instructions please exercise proper system administrator housekeeping. You must make sure that a proper backup of all your data is available.