Monitor SSL Certificates using Orchestrator

One of the worse things that can happen is your website goes down because of an expired SSL certificate. This is one of the easiest things to fix, and a problem that will make you bang your head against your desk when you forget. This blog post will detail a simple Orchestrator runbook to monitor the expiration date of your SSL certificates. We will program the runbook to alert you at certain number of days when the certificate will expire.

The only prerequisite you need for this runbook is the SC Operations Manager Integration Pack.


So let’s jump right in. Here is an overview of what your runbook will look like.



We will start with a simple “Monitor Date/Time”. This step simply executes the runbook on a pre-determined schedule. Next, we pull all current SSL alerts. This is so we can dump them in the next step, which prevents us from receiving multiple alerts about the same server. Next, we get all of our servers with an SSL certificate. I populate a text file with all of my servers that have SSL certificates, and Orchestrator gathers the file. Orchestrator then compares this list to the servers found in the previous step, and dumps the computers from the previous step. Next, we get the expiration date of our certificates, and if they expire within our determined time frame, we proceed to the final step and generate an OpsMan alert.

Monitor Date/Time

This step is very easy. Simply drag the “Monitor Date/Time” activity from the “Scheduling” node into your runbook. Double-click it, and set when you want it to run. I have mine set to run once a day at 6:00AM. Once a day is probably fine.


Get Current SSL Alerts

Next, drag a “Run .Net Script” activity from the “System” node into your runbook. Open it up and change the “Type” to PowerShell.


Next, paste this code into “Script” box:

$b = PowerShell {
& ‘C:\Integration Packs and Add-Ons\OpsMan-PowerShell-Module\OperationsManager\Startup.ps1’

$alerts = get-scomalert | Where-Object -FilterScript { $_.Name -like “SSL*” }

ForEach ($alert in $alerts) {
If ( $alert.ResolutionState -eq 0 ) { write-host $alert.CustomField2 }

$c = $b | select-string “<domain name>” | get-unique
$d = $c[1..( $c.length -1 )]

So what is going on here? First, we must launch a new PowerShell session. This is because of the second line in the script. We are actually loading the OpsMan PowerShell module. For those that don’t know, Orchestrator operates in PowerShell v2. The OpsMan module requires PowerShell v3 to run. We use the OpsMan module in the fourth line to pull the current SSL alerts. To load this module, either install the OpsMan console on your runbook servers, or do what I did and copy the PowerShell folder from a computer with the OpsMan console to a directory on your runbook server. The PowerShell folder is found in the OpsMan console install directory. It is simply called “PowerShell”, and should be in the root of the installation directory (by default “C:\Program Files\System Center Operations Manager 2012”).

So in the fourth line, we are gathering all of the current SSL alerts. My alerts say “SSL Certificate Expiration – “. If you want your alerts to say something else, change the “SSL*” at the end of the fourth line to match what you name your alerts (you must keep the * wildcard).

Next, we pass all of the alerts through a ForEach loop to determine if they are open or closed. If an alert if open, it has a resolution state of 0. We do not want to alert again if the server already has an alert open about it. The IF statement simply writes the server name, which is then stored in variable $b. I am pulling the server name from CustomField2 of the OpsMan alert. As you’ll see later, I write the server name to CustomField2 so that I can pull it back out during this process. This has to be done because all alerts generated from Orchestrator are entered by your management server, so that is the only way to get the affected computer to OpsMan.

Finally, we have to do some string cleanup. When the OpsMan PowerShell module is loaded, you get this written to the PowerShell prompt:


We must trim all of the welcome stuff off and only have server names. That is what the select-string option does. You need to replace with your domain name, something like This will allow PowerShell to only pick up server names to pass along. Next, the get-unique command will not pull duplicate names.

Finally, the select-string command adds your management server name (blacked out in my screenshot) at the top of the list. The last command removes it from the array.

Next, we need to publish variable $d. To do that, go to the “Published Data” node and add a new one. Fill it out like this:


Finally, we need to “flatten” this data so that it does not generate an array. For those who are new to Orchestrator, an array executes the remainder of the runbook as many times as there are items in the array. We do not want to split the runbook just yet. To flatten the output, go to the “Run Behavior” node and check the “Flatten” box. Leave a comma as the separator.


Get SSL Servers

Drag another “Run .Net Script” into your runbook. Change its type to PowerShell, and paste this code into the script box:

$a = @()
$alerts = @()

$servers = get-content “<file server>\ssl-servers.txt”

ForEach ($server in $servers) {
$a += $server

$alerts = PowerShell {
$alertsflat= “{d from “Get Current SSL Alerts”}”

$new = compare-object $alerts $a | select-object -expandproperty InputObject

Again, we have a few things going on here. First, we are pulling our list of SSL servers. This is a simple text files that have the servers listed on individual lines. Replace my green text with the appropriate path. Next, we feed that list into a ForEach loop that adds it to an array.

Next, we split the flattened array from the previous step back into array. Unfortunately, the split string option is a PowerShell v3 option, so we must launch a new PowerShell session. This session then splits the string of computers separated by commas back out into an array. Be sure to replace my blue text with the actual Published Data from the previous step.

Finally, we compare our server list to our active alert list and dump anything that has an alert. The compare-object cmdlet outputs array items that are not in both arrays, which is what we need. Publish the $new variable like we did in the previous step.

Capture Expired Certs

Now we will find certificates that are close to expiring. Drag another “Run .Net Script” activity into your runbook. Set the type to PowerShell and paste this code into the Script box:

$b = invoke-command -computername “{new from “Get SSL Servers”}” -scriptblock {
$deadline = (get-date).AddDays(30)
sl Cert:\LocalMachine\My
$expire = (Get-ChildItem).NotAfter
$warning = $expire.AddDays(-30)
If ($warning -lt $deadline ) { get-childitem }

$name = $b.PSComputerName

I have my script set to alert me at 30 days. You can set that based on your organization’s requirements. To modify the days, change both .AddDays to the length you need.

The first important thing to notice here is that we using the invoke-command cmdlet. For this to work, port 445 must be open from your Orchestrator server to your servers running SSL certificates. Again, be sure to replace the blue text with the actual published data from the previous step.

The $deadline variable takes today’s date and adds 30 days to it. This is how many days out we want to be alerted. Next, we change locations to the “My” folder in the local machine certificate store. The “My” folder is the Personal Store, which is where I elect to store my certificates. If you store them in a different store, change this accordingly. Next, we get the expiration date of the SSL certificate by accessing the “NotAfter” property. Now we set our warning threshold. This should match the same value of days defined in the $deadline variable, only negative. Finally, we compare the two. If the warning date is less than the deadline, we grad the certificate information and output it.

Finally, we grab the computer name assigned to the certificate for use in the alert.

Generate Critical Alert

Finally we need to create our OpsMan alert. To do this, drag the “Create Alert” activity into your runbook. Open it up and select your SCOM connection.

Fill out the options accordingly. Remember to add the Name, Description, and CustomField2 fields to your activity. Fill out these fields to your requirements expect for CustomField2, which should be the Published Data of name from “Capture Expired Certs”.



Contact Us

On Key

More Posts

Mastering Azure AD Connect - A Comprehensive Guide by WME
Active Directory

Mastering Azure AD Connect – A Comprehensive Guide

Modern businesses are fast moving toward cloud-based infrastructure. In fact, cloud-based business is not just a trend anymore but a strategic necessity. Microsoft’s Azure Active Directory (Azure AD) has become a frontrunner in this domain. It

Read More »
Security Best Practices in SharePoint
Office 365

Security Best Practices in SharePoint

Microsoft SharePoint is an online collaboration platform that integrates with Microsoft Office. You can use it to store, organize, share, and access information online. SharePoint enables collaboration and content management and ultimately allows your teams to

Read More »
The Ultimate Guide to Microsoft Intune - Article by WME
Active Directory

The Ultimate Guide to Microsoft Intune

The corporate world is evolving fast. And with that, mobile devices are spreading everywhere. As we venture into the year 2024, they have already claimed a substantial 55% share of the total corporate device ecosystem. You

Read More »
Protecting Microsoft 365 from on-Premises Attacks
Cloud Security

How to Protect Microsoft 365 from On-Premises Attacks?

Microsoft 365 is diverse enough to enrich the capabilities of many types of private businesses. It complements users, applications, networks, devices, and whatnot. However, Microsoft 365 cybersecurity is often compromised and there are countless ways that

Read More »
Be assured of everything

Get WME Services

Stay ahead of the competition with our Professional IT offerings.