Skip to the main content.

ScriptRunner Blog

Teams-Webhooks via PowerShell – Modern Alerting (part 3/3)

Table of Content

Post Featured Image

Teams Adaptive Cards:
Certificate Monitoring with PowerShell

If you are one of the admins who never had problems or downtimes because of an expired certificate, then you are either extremely lucky or you have a damn good grip on your certificate management. In many companies, there are now and then problems with expired certificates, whose validity is only checked as soon as they have already expired and the service is no longer accessible.

To prevent this from happening to you (anymore), I'll give you a PowerShell script that checks servers for expiring certificates. Admittedly, the script for reading the certificates is quite uninteresting, almost irrelevant. Because much more exciting and important is the way you are notified about the expiration of the certificates. In the previous parts of this series, I showed you how you can easily send notifications or alerts to teams via PowerShell (you can read about that here: part 1, part 2) . However, we always focused on the pure information level, which is sufficient in many cases. In this article, I want to show you how to send so-called "Adaptive Cards". These have the advantage that you can add buttons to the messages, which gives you new, elegant possibilities to react to alarms.

  • Your server memory is full? No problem! Get notified via PowerShell and implement a button to extend the memory! You can press this button from your smartphone while waiting at the coffee machine or taking your child to school.

  • You want to automatically convert alerts into tickets? Add a button to the Teams Card that allows you to create new entries in your ticket system via HTTP request and add the information from the Teams message.
  • A server in Azure stopped unexpectedly? Get notified and restart it with a click in Teams.

As you can see, there are several use cases where a direct response from the message can be useful. In this article, we build a script that reads the certificates on various servers and checks if they will expire in the next 100 days, sending a message to Teams. This message has a button that will take us directly to the certificate settings of the respective server in the Windows Admin Center, thus allowing us to make changes.

The message we will design looks like this:

So soll unsere Nachricht aussehen - expiration alert

Example of a message with a button 

Preparation

Again, we need a Teams channel that can receive WebHooks. (In the previous parts of this article series, the configuration was described in more detail). If you're hardcore, you can of course design the Teams message using JSON. However, since this is a fairly simple requirement, we can make our lives much easier: The PSTeams module allows you to design the card with simple PowerShell cmdlets, so you don't have to torture yourself with JSON. In our case, of course, an installation of the Windows Admin Center is still required; but you are of course free in what action you want to react to the alert about the button, if you don't use the WAC. The command to show us all certificates on a server that will expire in the next 100 days is:


Get-Childitem Cert: -Recurse -ExpiringInDays 100 | 
    Select-Object FriendlyName, Issuer, Thumbprint, NotBefore, NotAfter, PSParentPath

So now we have all the information we need to start designing the AdaptiveCard. The code at the beginning of the script looks like this:


# Array with Computers, that should be monitored
$TargetComputers = @("Server01")
# TeamsID - URL generated by Teams
$TeamsID = ""
# URL of Windows Admin Center
$WACURL = "<https://localhost:6516/>"

# ModuleCheck: Installs PSTeams if not available
if(-not (Get-Module -ListAvailable PSTeams)) {
Install-Module -Name PSTeams -Force
}
else {
Write-Verbose "PSTeams is already installed."
}

 

Designing the Teams-Card with PSTeams

Three objects from PSTeams are relevant for us: Sections, Facts and Buttons. Sections serve the logical and visual demarcation, subordinated to them are facts as well as buttons. Facts contain all the information we want to display about teams. Buttons open websites or otherwise make HTTP requests.

In our case the certificate attributes are facts. The friendlyname of a certificate, as well as the thumbprint, etc. is represented as a fact and subordinated to a section. A section always contains exactly one certificate. A team message always refers to only one server, therefore we need only one button in the entire card, which leads us to the server entry in the Windows Admin Center. This button has its own section.

So now we have to query all servers from the array "$TargetComputers" - we do this with a foreach loop, so that we can get the corresponding certificate data from the respective server directly afterwards:


$scriptBlock = {
Get-ChildItem Cert:\\LocalMachine -Recurse -ExpiringInDays 100 |
Select-Object FriendlyName, Issuer, Thumbprint, NotBefore, NotAfter, PSParentPath
}
foreach ($computer in $TargetComputers) {
# Getting all certificates of specified computer, that will expire in the next 100 days
[array]$ExpiringCerts = Invoke-Command -ComputerName $computer -Credential $cred -ScriptBlock $scriptBlock }

The $ExpiringCertificates variable now contains all certificates that will expire in the next 100 days. Now you have to distribute this information to the different sections as described above. To do this, create an empty array, which we fill with sections one by one. Within the already described ForEach loop we create another ForEach loop, which iterates over all certificates, creates a new section per certificate, fills this section with the facts (i.e. the attributes of the current certificate) and then adds the newly created section to the section array. So in the end, we now have an array with all the information (divided into Sections) and could send it directly to Teams. But before that, we create one last Section that contains the button for the Windows Admin Center. We modify the link that the button calls for each server, because in the URL we can define which computer/server should be opened in the Admin Center. So our code now looks like this:

 


# Array with Computers, that should be monitored
$TargetComputers = @("Server01")
# TeamsID - URL generated by Teams
$TeamsID = ""
# URL of Windows Admin Center
$WACURL = "<https://localhost:6516/>"


# ModuleCheck: Installs PSTeams if not available
if(-not (Get-Module -ListAvailable PSTeams)) {
Install-Module -Name PSTeams -Force
}
else {
Write-Verbose "PSTeams is already installed."
}


# Iterating through every computer in $TargetComputers
foreach ($computer in $TargetComputers) {
# Getting all certificates of specified computer, that will expire in the next 100 days
[array]$ExpiringCerts = Invoke-Command -ComputerName $computer -Credential $cred -ScriptBlock {
Get-ChildItem Cert:\\LocalMachine -Recurse -ExpiringInDays 100 |
Select-Object FriendlyName, Issuer, Thumbprint, NotBefore, NotAfter, PSParentPath
}


# Checking, whether there are any certificates expiring in the specified timespan before proceeding
if ($ExpiringCerts.Count -gt 0){


# Creating Sections with embedded Facts (Certificate Information) for Teams
$Sections = @()
foreach ($cert in $ExpiringCerts) {
$facts = @()
$cert |
Get-Member |
Where-Object MemberType -eq NoteProperty |
ForEach-Object {
$facts += New-TeamsFact -Name $_.Name -Value "**$($cert.($_.Name))**"
}
$Sections += New-TeamsSection -ActivityDetails $facts
}


# Gets server-URL within Windows Admin Center and Teams-Button to access it
$WACURLServer = $WACURL + "servermanager/connections/server/" + $computer + "/tools/certificates"
$Button = New-TeamsButton -Name 'Edit Certificates' -Link $WACURLServer -Type 'ViewAction'
$Section = New-TeamsSection -Buttons $Button


# Send Card
$Sections += $Section
$Count = $ExpiringCerts.count
Send-TeamsMessage -URI $TeamsID -Color Red -Sections $Sections `
-MessageTitle "Alert: $count Certificates on $computer expire within the next 100 days!"
}
}

 

Conclusion 

So now when we run this code and there are expiring certificates on the machines, we get the teams card shown above. You have now created your own alerting for your certificates in just a few minutes 😉


Additional Notes:
If all certificates in your organization were issued through a central CA, it makes more sense not to query each individual server for its certificates, but to run a central query on the CA. The 100 days given is not a recommendation on my part, as this number is far too large in my eyes. I chose the 100 days only for demonstration purposes, to have some hits in any case. In my opinion, a period of 15-30 days is recommended for monitoring, although of course this should be evaluated differently from environment to environment.

 



Related Links



Related posts

10 min read

My top 10 ways to use Teams PowerShell

6 min read

Teams-Webhooks via PowerShell – Modern Alerting (part 3/3)

3 min read

Teams-Webhooks via PowerShell – Modern Alerting (part 2/3)

About the author: