CRL Freshness PowerShell cmdlet

capture20160429205147798 Overview

One of the critical functions of running a healthy PKI is ensuring that certificate revocation data is always available and always fresh. Nearly every customer I work with has experienced some form of application or system outage due to CRL’s not being fresh or available.

Most PKI administrators overcome the availability issue by either including multiple CRL distribution points into their certificates or placing them behind a network load balancers. In principal, this approach works extremely well, however it is still critical to ensure that all paths have fresh and up-to-date CRL information.

Short Version

It’s a PowerShell cmdlet for you to check for both availability and freshness of all HTTP based CRL’s, even those behind load balancers. Full log and email based alerts. Customize it to meet your needs. After importing the module, a “get-help get-crlfreshness” will give you everything you need, detailed steps further below.

Download the script here and rename to .psm1 before using import-module.

What does the cmdlet actually do?

Designed for the monitoring base CRLs via HTTP paths, it allows admins to directly query the status of a CDP and CRL freshness for either a single or batch of CDP’s that are critical for your organisation. It allows for the directory querying of web servers via IP address (whilst preserving the host header) so you can confirm that all web servers have fresh CRL data available no matter which one the load balancer directs clients to.

The primary mechanism for determining if a CRL is expiring is comparing the “Next CRL Publish” extension against the current time.  This extension when present, indicates the next time when a CA intends to publish an updated version of the CRL. The script will flag a CRL as “expiring” if the current time is more than 30 minutes after this time.

Not all CAs will publish this extension into their CRLs. In this scenario, the script will simply default to give warnings at 4 days from the CRL expiration. The cmdlet also has the ability to completely override the warning period with a value of your choosing. This can be useful if as above the “Next CRL Publish” is missing or you only want to receive a warning when the time gets closer to the CRL actually expiring.

If any errors are found, the script will simply send an email using the details configured in the PowerShell module itself.

First Steps

Download the script here and strip the .txt from the extension. Update the file (it’s just text) with the appropriate email sender/recepient and server fields to ensure you will receive email alerts in the event of errors.

During testing, you might also want to manually set the time forward to confirm logging and alerting behaviour. You can do this at approximately line 95. Don’t forget to remove it prior to production use.

Oh … I live in the land down under, our days are more pushy and come before the months in our dates. I have absolutely no idea how this will work in other locales. I used .ToLocalTime() where possible, so hopefully it’s cool. Drop me a comment if you have issues.

Checking a single CDP

As the cmdlet is distributed in a PowerShell module, the first thing we need to do is import the module then execute the cmdlet itself. The single mode execution has 3 parameters with only the “CDP” parameter being mandatory. The following command demonstrates the basic usage with all parameters:

CDP – The URL path to the CRL file to be checked.
ServerIP – The IP to use directly. If omitted, a DNS lookup is performed.
WarningHours – Use to define or override the warning period

Import-Module .\CRLFreshCheck.psm1 -Function Get-CRLFreshness
Get-CRLFreshness -CDP ""

The following shows the result of the script. If there were any errors, it would attempt to send an email alerting you.


A Real World Example

Using the batch mode of the cmdlet, we can queue up multiple CDP’s to check and confirm that all the CRL in your CDP’s are fresh and available. The following example will demonstrate using the script to check a couple of our most common public CAs, “Microsoft IT SSL SHA1” and “Microsoft IT SSL SHA2”.

The diagram below shows the basic CDP design as stated in their certificate chains. At present, both of the Issuing CA’s distribute copies of their CRL’s to multiple web servers. A quick DNS lookup shows that “” is available on 2 IP’s and “” is available on one. Now, this is only the public view, there may be even more servers in the back-end, but this view is a good demonstration platform to show you how the script works. Note: These IP addresses listed below will most likely change in the future.

CRL Fresh Check Sample PKI


To use batch mode in the cmdlet, we need to first create a simple CSV file (in this case MSIT.csv) which will give all the inputs for the cmdlets to run. Even if not used, ServerIP and Warning hours need to be included as a blank and the integer zero respectively.

Baltimore CyberTrust Root,,,0
Baltimore CyberTrust Root,,,120
Microsoft IT SSL SHA1,,,0
Microsoft IT SSL SHA1,,,0
Microsoft IT SSL SHA1,,,0
Microsoft IT SSL SHA1,,,0
Microsoft IT SSL SHA1,,,0
Microsoft IT SSL SHA2,,,0
Microsoft IT SSL SHA2,,,0
Microsoft IT SSL SHA2,,,0
Microsoft IT SSL SHA2,,,0
Microsoft IT SSL SHA2,,,0

And now we can simply execute the cmdlet in batch mode against our MSIT.csv file.

Import-Module .\CRLFreshCheck.psm1 -Function Get-CRLFreshness
Get-CRLFreshness -Batch -InputFIle .\MSIT.csv

As per the output below, it will attempt to download each of the CRL’s from the server and paths listed in the CSV. Any failures will be sent by email and also logged in the log file. A sample log file the gets generated can be seen here in the CRLFreshCheck.log.


Wrapping Up

Hopefully you will find the script useful in your environment. Even if you only have a single CDP location, the script can help monitor for any issues that may arise. I would love to hear from you if your using the script in production, success stories are even better!


Comments (6)

  1. RavindranK says:

    Thanks for sharing ! 🙂

  2. Jesper Nøhr says:

    this is very useful. Thank you for sharing!

  3. Jesper Nøhr says:

    Hi Russell, thank you for sharing this!

  4. Josh Aigen says:

    I have a large CRL (1.5MB) and the script takes 10 minutes to run (for InitializeDecode).
    Any ideas on making it more efficient?

    1. Great question Josh. I have never dealt with a CRL that large. Is it a publicly accessible CRL that we could test directly with?

Skip to main content