How To Build a Batch to Monitor for Expiring SSL Certificates

The CheckTLS //email/testTo: ("TestReceiver") test looks at email servers, discovering and reporting on a multitude of settings and features. One of which is the expiration date of each of the SSL certificate used by the server.

The CheckTLS //email/testBatch ("BatchTest") function can store and run //email/testTo: ("TestReceiver") on most internet hosts. Stored tests can include all kinds of instructions for what and how to test, and what and how to report the results.

//email/testTo: ("TestReceiver") and //email/testBatch ("BatchTest") are very customizable in what they target, what they test, and what they return.

As an example of the simple power that these two tests have together, here we describe how to use them to create a SSL Certificate Expiration Monitoring service. This example is useful in and of itself, and it also provides a starting point for many other tests and monitors that your business may use.

We will use //email/testTo: ("TestReceiver") in XML mode, meaning its results will be in a computer-readable (XML) format, and we will use the XML_CERTDETAIL Output Format to tell //email/testTo: ("TestReceiver") to include information about each of the SSL certificates that it finds. If you are not familiar with //email/testTo: ("TestReceiver"), we encourage you to experiment with it and with its settings to better understand how this SSL Certificate Expiration Monitoring service works, and to discover what other things the tool can do to help your organization.

The Part that TestReceiver Does

To build our SSL Certificate Expiration Monitoring service, we will use two of the fields that //email/testTo: ("TestReceiver") in XML_CERTDETAIL format includes in the XML output: <NotValidAfter>Nov 8 12:45:27 2025 GMT</NotValidAfter> <SecondsUntilExpired>12700969</SecondsUntilExpired>

If you have explored the XML_CERTDETAIL Output Format as suggested above, you know that //email/testTo: ("TestReceiver") returns a very large XML file with lots of information in it. For our Monitoring service, we only want to know the domains that have an expiring SSL certificate, and we only want to know which SSL certificate(s) on which MX host(s) are expired or expiring soon (30 days) and their expiration date. So we use the []XSLT feature of //email/testTo: ("TestReceiver") to compute a “how many days until the SSL certificate expires” value, and then use that value to only select just the SSL certificates that expire within 30 days (or have already expired). The XSLT then reports just the MX host and SSL certificate fields and not all the other stuff in the big XML document.

Example Expired Certificate Result

So the end result is just a list of any expiring SSL certificates that looks like this: <CheckTLS> <Results test="BatchTest_receiver" version="V03.25.02" format="xml-certdetail" id="84" description="Expiring Certs TR XSL"> <Result> <Expiring TARGET="checktls.com"/> </Result> <Result> <Expiring xmlns:xs="http://www.w3.org/2001/XMLSchema" TARGET="expired.badssl.com"> <Cert> <HOST>expired.badssl.com[104.154.89.105]</HOST> <CERT>1</CERT> <EXPIRE>Aug 8 21:17:05 2018 GMT</EXPIRE> <DAYS>-2502</DAYS> </Cert> <Cert> <HOST>expired.badssl.com[10.20.30.40]</HOST> <CERT>1</CERT> <EXPIRE>Aug 8 21:17:05 2018 GMT</EXPIRE> <DAYS>-2502</DAYS> </Cert> </Expiring> </Results> </CheckTLS>

The above shows that checktls.com has no expiring SSL certificates, but the domain expired.badssl.com has two – both are the same MX name but that name resolved to two different IP addresses, both of which used the same expired SSL certificate.

The Part that BatchTest Does

Let’s see exactly what the //email/testBatch ("BatchTest") that does our monitoring looks like and how it works.

Batch Source File

<BatchTest TestType="receiver"> <Target XSL="https://www2-do.checktls.com/XSL/Expiring-Cert-TR.xsl">DEFAULT</Target> <Target>checktls.com</Target> <Target>iamgroup.ca</Target> <Delivery> <To>expiringcerts@checktls.com</To> <Format>xml-certdetail</Format> </Delivery> </BatchTest>

The first line tells Batch that we want to do a //email/testTo: ("TestReceiver").

The second line tells Batch that every <Target> from now on needs to have an XSL attribute added to it. Batch knows to add this XSL attribute to every Target that follows because the value of the <Target> node is "DEFAULT". The XSL attribute itself points to an xsl file on our servers that does the record selection (only expired SSL certificates) and only outputs the MX host and certificate fields. Note that there could be more than one DEFAULT <Target>, each of which replaces any existing DEFAULT and only applies to the <Target> nodes below it. More on the XSL file below.

The <Target> lines are the domains that we are monitoring for expiring SSL certificates.

The <Delivery> section says to email the list of expiring SSL certificates to the mailbox expiringcerts, and it specifies that we need the XML_CERTDETAIL Output Format (because that is the smallest Output Format that includes the SSL certificate’s expiration date).

What XSLT Does

The XSL file that the DEFAULT <Target> caused to be added to every <Target> looks like this: 1. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema"> 2. <xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/> 3. <xsl:variable name="target" select="/CheckTLS/eMailAddress"/> 4. <xsl:template match="/CheckTLS"> 5. <Expiring TARGET="{ $target }"> 6. <xsl:apply-templates select="./MX"/> 7. </Expiring> 8. </xsl:template> 9. <xsl:template match="MX"> 10. <xsl:variable name="host" select="./@name"/> 11. <xsl:variable name="address" select="./@address"/> 12. <xsl:for-each select="Certs[*]/Cert[SecondsUntilExpired < 30*24*60*60]"> 13. <xsl:variable name="days" select="round( SecondsUntilExpired div (24*60*60) )"/> 14. <Cert> 15. <HOST><xsl:value-of select="$host"/>[<xsl:value-of select="$address"/>]</HOST> 16. <CERT><xsl:value-of select="@number"/></CERT> 17. <EXPIRE><xsl:value-of select="NotValidAfter"/></EXPIRE> 18. <DAYS><xsl:value-of select="$days"/></DAYS> 19. </Cert> 20. </xsl:for-each> 21. </xsl:template> 22. </xsl:stylesheet>

Describing how XSLT translates one XML file into another XML file is beyond the scope of this document. But briefly:

Line 3 extracts the <Target> and saves it in a variable named "target".
Line 5 outputs a node named <Expiring> with the name of the Target.
Line 6 loops through all the MX nodes found for the Target domain (lines 9-21).
  Line 10 and 11 extract the MX host and address for this MX to variables.
  Line 12 loops through any MX that expires within 30 days (lines 13-19).
    Line 13 turns the seconds until expiration into days.
    Line 14 outputs a node named <Cert> that contains (lines 25-18).
      Line 15 outputs the MX host and address.
      Line 16 outputs certificate's position in the certificate chain.
      Line 17 outputs when the certificate expires.
      Line 18 outputs how many days until the certificate expires.
    Line 19 outputs the <Cert> closing tag.

Building the Batch

Ok, so now how do we use those things to actually monitor some <Targets>? Given the above examples and some understanding of what each piece does and how they all fit together, having CheckTLS monitor your particular list of one or more domains is just three easy steps:

Use //email/testBatch ("BatchTest") to create a new batch using the example Batch Source File given above. Change the <To> address to your own email. Change the <Target> nodes to be the domains you want to test -- your own and/or your important trading partners (you may want to group targets into several Batches). Be sure your XML source code validates. See the BatchTest documentation in the test instructions, and also see About Batch for specifics.

In all likelyhood none of the <Targets> that you put in your Batch have expiring certificates. So how do you know your Batch will work if and when a certificate does get close to expiring? Add this target line to your Batch: <Target Port="443" StopAfter="CONNECT" DirectTLS="1">expired.badssl.com</Target>

Note we included this line in our Example Expired Certificate Result above so you can see what it does. Once you are comfortable that your batch is working as expected you can remove the expired.badssl.com <Target>.

Scheduling the Batch

After you have a working Batch you can schedule it to run periodically. Since the default warning period is 30 days, we suggest you schedule the Batch to run weekly so you have at least 3 weeks to renew any certificates that the Batch finds are about to expire. Batches are scheduled in the same //email/testBatch ("BatchTest") as you use to create and maintain Batches. From the start page in //email/testBatch ("BatchTest"), select the Batch you want to schedule and click the Edit Schedule button.

To schedule a Batch to run weekly, set the Schedule fields like this:

Edit Schedule
  1. (1-31 or "*" means any/every day)
     Day Of Month = 0 disables scheduling
  2. (Sun=0 or 7, "*" means any/every day)
  3. (0-23 or "*" means every hour)
  4. (0-59 or "*" means every minute)

These settings say to run the Batch on any day in the month (Day Of Month = "*"), on Monday (Day Of Week = "1"), at 3:00AM (Hour Of Day = "3", Minute Of Hour = "0").

That's it! You should get an email early Monday mornings with a list of any SSL certificates that will expire in the next 30 days. If no SSL certificates are expiring (the most likely result), you will still get the email showing all the domains that were checked, with none of them listed as expiring. This is a good fail-safe so you know the Batch actually did run as it was supposed to.