Share via


Monitoring Expiring Certificates using SCOM

Managing too many certificates in your Certificate Server? Unable to keep track of when they'd expire? Don't worry! Here's a simple and smart way of proactively monitoring them through SCOM. A completely customizable solution so that you can configure it based on your needs! Sounds exciting? Read further.

Our Strategy:

Our solution for monitoring ceritifcates is based on a script that provides us information about the expiring ceritificates. For each ceritifcate that expires, our script will create an event in the Applications Log. With the help of a SCOM rule, we shall read those events and subsequently notify them as an alert.

The 'Magic' Script

Though there's nothing magic about it, this script is the core part of our solution. It is based on the certutil.exe that is shipped with Windows OS. The certutil provides us an easy way of querying and obtaining information about Certificates. In Windows 2008+ we can export the result set into a CSV which would have made stuff simpler. But, such options are not available in Windows Server 2003. I've designed the script to be compatible for all the OSs. Read through the script, you should be able to get most of it. Don't copy this script from the page. I've pasted it here so that you can have a glance. If you wish to download the script, you can find it at the bottom of this blog post.

' Certificate Expiration Monitoring Script - CertMonitor
' Written by sanjeevgopinath@live.com

' Place the file under C:\CertMonitor\ folder. If you want wish to place it in a different folder, change the dump_file_path variable

' This script is given on an as-is basis without any kind of warranties.
' ##########################
' Type : DAY BASED
' Description : Lists certificates that will expire in the next 1 day.
' ##########################

' ---- VARIABLE DECLARATIONS ----
dim file_obj ' // Holds the Scripting.FileSystemObject for file handling purposes.
dim line_extract ' // From the file read, we extract line by line
dim cert_count ' // Holds the current count of certificates found by the script.
dim event_desc ' // Holds the EventCreate event description
dim file_txt ' // Contains the File Handle for the Temporary file
'---------------------------------

' -------- INITIALIZATIONS --------
certutil_params="SerialNumber,CommonName,RequestID,RequesterName,NotBefore,NotAfter,CertificateTemplate"
dump_file_path="C:\CertMonitor\Day_Log.txt"
script_type="day"
event_id=101
NewDate = DateAdd("d",1,Date)
' To Add some more parameters add it after 11:59 PM" like this --> & "YOUR CONDITION" & """"
restrict_param=" -restrict ""NotAfter>=" & NewDate & " 12:00 AM,NotAfter<" & NewDate & " 11:59 PM" & """"
' Creating Object to work with Shell
Set WshShell = CreateObject("WScript.Shell")
' Running the Certutil command and dumping the output in dump_file_path
cmd_complete="cmd /C certutil -view " & restrict_param & " -out """ & certutil_params & """ > " & dump_file_path
WScript.Echo cmd_complete
cmd_status = WshShell.Run(cmd_complete, 1, true)
' Logging event for the start of script execution.
Set cmd_status = WshShell.Exec("eventcreate /t information /l application /id 100 /d ""Running Certutil -view for " & script_type & " based rule. This is just an informational alert generated by the Certificate Expiry Monitoring Script."" /so ""CertMonitor""")
' Initializing the file handlers
Set file_obj = CreateObject("Scripting.FileSystemObject")
Set file_txt = file_obj.OpenTextFile(dump_file_path,1,False)
' Low Index contains the Certificate Details starting position from the top.
low_index = 0
' High Index holds the position of end of Certificate details.
high_index = 0
' At any given point, cert count tells how many certificates the script has parsed so far.
cert_count = 0
' Initializing the event description
event_desc = "Certificate Details : "
' Sub Str is a temporary string used for trimming and removing the quotes
sub_str = ""
' ------------------------------------

' --- LOGIC STARTS HERE ---------------
' Extracting line by line using split. chr(10) represents newline.
line_extract = Split(file_txt.ReadAll(), chr(10))
' For every line in the dump file
For i = 0 To UBound(line_extract)
 ' If the line is equal to a Carriage Return, it may represent end of Certificate.
 If line_extract(i) = VbCr Then
  ' The initial part of CertUtil contains information about the fields. We ignore it by not counting the first occurence
  If cert_count > 0 Then
   ' This loop extracts all the certificate information and concatenates it in event_desc
   ' low_index + 1 is used so that we remove the "ROW #" line
   For j = low_index + 1 To high_index
    ' This removes unnecessary spaces.
    sub_str = trim(line_extract(j))
    ' This removes all the quotes so that the quotes aren't closed by themselves. For e.g. in EventCreate
    sub_str = Replace(sub_str, """", "")
    ' The last character is a new line / NULL character. If that's present, we won't get full event description.
    event_desc = event_desc + " " + Left(sub_str,Len(sub_str)-1)
   Next
   event_desc = event_desc + " This event was generated by the Certificate Expiry Monitoring Script."
   ' Logs the event in the Application Log
   Set event_return = WshShell.Exec("eventcreate /t error /l application /id " & event_id & " /so CertMonitor /d """ & event_desc & """")
   ' Waiting for the Command to complete
   Do While event_return.Status = 0
    WScript.Sleep 100
    WScript.StdOut.Write(event_return.StdOut.ReadAll())
    WScript.StdErr.Write(event_return.StdErr.ReadAll())
   Loop
   ' Reinitializing event_desc so that we don't have the previous values.
   event_desc = "Certificate Details : "
  End If
  ' Incrementing the low_index to point to the starting of next certificate.
  low_index = i + 1
  ' Incrementing cert_count value as we parsed one paragraph (one para is imagined to contain cert details) completely.
  cert_count = cert_count + 1
 Else
  ' If we find the summary information, we stop the script then and there.
  If instr(1,line_extract(i),"Row Index",0) > 0 Then Exit For
 End If
 ' Incrementing as we go line by line
 high_index = high_index + 1
Next

How does it work?

The script is expected to run once everyday. To confirm if it ran, you can check the Application log for 100 EventId. When the script runs, it queries for all the expiring certificates and puts the result it in a temporary file. Since the first part of the result is junk, we omit it and just take the part where we have information about expiring certs. For each certificate entry, it creates a 101 event in the Application Log. If you want to change the event id, you can change the value specified for the event_id variable. Also, in this script we just query few parameters like serial number, etc. If you want to delete or add few more parameters, you can change the certutil_params variable.

Say, if you want to extend monitoring and be notified before a week or a month, you can do the following...

Change the value 1 in NewDate = DateAdd("d",1,Date) to 7 if you want to be notified before a week and 30 if you want to be notified before a month.

You can also change the event id when you wish to monitor for week and month. This way, you can configure the rules to alert with respective priorities. For example Day = High, Week = Medium.

What is required from SCOM side?

Create an alert generating rule to monitor for NT Events 100 and 101 (or the event Id you have specified). To be very precise, you can specify that the Event Source is 'CertMonitor'.

If you want to know how to create a alert generating rule for monitoring events from the NT Event Log, read this : https://technet.microsoft.com/en-us/library/bb309568

As the rule may run on all Windows Computers, restrict it to run only on the cert servers or the servers where you need to monitor expiring certificates.

How do I schedule the script?

You can use Windows Task Scheduler for scheduling the script to run once everyday. For more info : https://technet.microsoft.com/en-us/library/cc748993

day.vbs