Because CRL validity is so important to the functionality of your PKI, it's important to have proactive monitoring of the validity of your CRLs. Particularly in situations where you're using smart cards for logon, having a CRL go stale can be a very disruptive experience to end users.
In my session at IT Forum in Barcelona this week, I'm showing some of the new manageability features of Certificate Services in WS08. One of the major investments for CertSrv in this release is manageability, including integration with MOM/SCOM. One of the features I'm demonstrating is the extensibility of SCOM to help with monitoring the freshness of CRLs. The following scripts can be used to alert you to the status of CRLs before they go stale, allowing you to avoid outages before they happen. They can be integrated with MOM/SCOM for centralized alerting and reporting or just run by themselves.
Here's how the scripts work:
- checkCrlFreshness.cmd calls wget.exe (you'll need to download this separately) and downloads the CRL from whatever location you specify
- checkCrlFreshness.cmd then calls compareNextUpdateToNow.vbs
- compareNextUpdateToNow.vbs calls certutil "nameOfCrl" and scrapes the NextUpdate: line from its output
- compareNextUpdateToNow.vbs then compares the hourly NextUpdate value to whatever value is passed by checkCRLFreshness.cmd when it calls compareNextUpdateToNow.vbs
- if the NextUpdate value is < the threshold value (i.e. the CRL's expiration is below your minimum value), an alert is written to the application log on the machine where the script is run
SCOM can then be leveraged to watch the event logs for this particular event and then alert or take whatever other action you've specified. Note that if you're running the scripts on Vista or WS08, you can also take advantage of the new Windows eventing infrastructure to run a task or send an email when the event occurs, without having to have MOM/SCOM involved at all.
The nice thing about this script is that it can easily work against any HTTP CDP. So, you can use it to monitor CRLs inside or outside of your organization, including those of partners or service providers that you might depend on.
Scripts are provided as is, us at your own risk, no support, etc, etc…
:: CRL freshness monitoring master script
:: downloads all relevant CRLs with wget, calls VBScript to compare NextUpdate time with current system time to determine freshness
:: John Morello, Windows Server Division
:: uses wget to download CRL; -r says to overwrite existing copy, -nH --cut-dirs=1 says to save in current directory (removes --cut-dirs value from end of URI)
:: wget must be in same directory as this script or in %Path%
wget.exe -r -nH --cut-dirs=1 "http://ws08rc0.pki.test/certenroll/pki-ws08rc0-ca.crl"
:: calls compareNextUpdateToNow.vbs to compare time difference between Now() and NextUpdate value in CRL
:: if difference is < the second parameter (in hours), compareNextUpdateToNow.vbs writes warning to AppEvent
cscript compareNextUpdateToNow.vbs "pki-ws08rc0-ca.crl" 336
' CRL date comparison script
' takes 2 command line parameters, the name of the CRL and the acceptable age threshold
' if NextUpdate time from CRL is not > acceptable threshold (or other error condition exists), writes event to AppEvent
' Robert Deluca, Windows Server Division
' John Morello, Windows Server Division
' check if command line parameters were passed
If WScript.Arguments.Count < 2 Then
wscript.echo "Usage: cscript crldatecheck.vbs <CRL filename> <age threshold in hours>"
' assign params to variables
CRLFilename = WScript.Arguments.Item(0)
ThresholdHours = CInt(WScript.Arguments.Item(1))
' Create wscript.shell object for exec
Set WshShell = CreateObject("WScript.Shell")
' Execute certutil
Set oExec = WshShell.Exec("certutil """ & CRLFilename & """")
' Wait for certutil to finish running
Do While oExec.Status = 0
' Read certutil output until end of stream or found the NextUpdate: line
Found = false
Do While (Not Found) And (Not oExec.StdOut.AtEndOfStream)
DateString = oExec.StdOut.ReadLine
Found = instr(DateString,"NextUpdate: ") = 1
' exit if the proper line wasn't found
NoNextUpdateFoundMessage = "Failure to read Next Update time from CRL."
If Not Found Then
wscript.echo "Failure to read Next Update time from CRL."
WshShell.LogEvent 2, NoNextUpdateFoundMessage
' remove the header from the line
DateString = Replace(DateString,"NextUpdate: ","")
' exit if the rest of the string isn't recognized as a date
If Not IsDate(DateString) Then
wscript.echo "Date not recognized as valid."
' convert the string to a date variable
d = CDate(DateString)
' calculate hours until NextUpdate
HoursUntilUpdate = DateDiff("h",Now,d)
' display update and threshold information
Message = "Next CRL update is in " & HoursUntilUpdate & " hours. Threshold is " & ThresholdHours & " hours."
' update time is below acceptable threshold, write message to screen and event log
If HoursUntilUpdate < ThresholdHours Then
wscript.echo "Time is below acceptable threshold! Writing warning to event log."
WshShell.LogEvent 2, Message
wscript.echo "Unknown failure! Manually verify CRL and diagnose run time failure."
WshShell.LogEvent 2, Message