– new HTML template
– added two informations : Root and Subordinate CA CRL expiration dates in the report

Purpose :

This project is a simple script to monitor the certificate expiration. When a certificate is about to expire (1 month), a report is sent by email

Pre-requesite :

  • Public Key Infrastructure PowerShell module (http://pspki.codeplex.com/)
  • Locate your CRL files path and names (the default path used is C:\Windows\System32\certsrv\CertEnroll)

Installation :

  • Connect on your PKI CA server (issuing CA) using RDP
  • Download and install the PKI Powershell module
  • Create the folder : C:\Scripts
  • Create a script filename C:\Scripts\adcs_exp.ps1 with the following source code:
#Get input strings
[string] $computername = "$ENV:COMPUTERNAME",
[string] $reportfile = "$ENV:USERPROFILE\Desktop\acert_certificate_expiration_report.html",
[string] $cert_path = "C:\Windows\System32\certsrv\CertEnroll",
[string] $crl_root_filename = "root.crl",
[string] $crl_sub_filename = "issuing.crl"

#Start stopwatch
$totalTime = New-Object -TypeName System.Diagnostics.Stopwatch

#Send mail function
Function send_mail([string]$message,[string]$subject) {
$emailFrom = "from@mail.com"
$emailCC = "cc@mail.com"
$emailTo = "to@mail.com"
$smtpServer = "smtp_server.mail.com"
Send-MailMessage -SmtpServer $smtpServer -To $emailTo -Cc $emailCC -From $emailFrom -Subject $subject -Body $message -BodyAsHtml -Priority High

Write-Host "ADCS Certificate Expiration Report Tool " -ForegroundColor "Yellow"
Write-Host "by Fredrik ""DXter"" Jonsson (dxter@poweradmin.se)" -ForegroundColor "Yellow"

if(Get-Module -ListAvailable -Name PSPKI | Where-Object { $_.name -eq "PSPKI" })
#Import PSPKI PowerShell module
if(Get-Module -Name PSPKI | Where-Object { $_.name -eq "PSPKI" })
Write-Host "PSPKI PowerShell module already imported…" -ForegroundColor "Yellow"
Write-Host "Importing PSPKI PowerShell module…" -ForegroundColor "Yellow"
Import-Module -Name PSPKI

#Set variables
Write-Host "Setting variables…" -ForegroundColor "Yellow"
$caname = $computername.ToLower()
$domaindns = $ENV:USERDNSDOMAIN.ToLower()
$todaysdate = Get-Date
$findaldate = $todaysdate.AddMonths(2)
$htmlpre = "<font face='Calibri' color='black'><i><P>Generated by user: $ENV:USERNAME</P>
<font face='Calibri' color='black'><i><P>Root CA CRL expiration date : <font face='Calibri' color='red'>$((Get-CRL $cert_path\$crl_root_filename ).NextUpdate)</font></font>
<font face='Calibri' color='black'><i>Subordinate CA CRL expiration date : <font face='Calibri' color='red'>$((Get-CRL $cert_path\$crl_sub_filename).NextUpdate)</font></font>
<font face='Calibri' color='black'><i><b><P>The following certificates expire before $findaldate</P>
$htmlpost = "<P>Certificate expiration information retrived from $caname.$domaindns</P>"
$htmltitle = "Certificate expiration information from $caname.$domaindns"
$htmlinput = Get-CertificationAuthority "$caname.$domaindns" | Get-IssuedRequest -Filter "NotAfter -ge $(Get-Date)", "NotAfter -le $((Get-Date).AddMonths(1))"

#Generate report
$a = "<HTML><HEAD>
<style type='text/css'>
table {font-family:verdana,arial,sans-serif;font-size:12px;color:#333333;border-width: 1px;border-color: #729ea5;border-collapse: collapse;}
table th {font-family:verdana,arial,sans-serif;font-size:12px;background-color:#acc8cc;border-width: 1px;padding: 8px;border-style: solid;border-color: #729ea5;text-align:left;}
table tr {font-family:verdana,arial,sans-serif;background-color:#d4e3e5;}
table td {font-family:verdana,arial,sans-serif;font-size:12px;border-width: 1px;padding: 8px;border-style: solid;border-color: #729ea5;}

Write-Host "Generating report…" -ForegroundColor "Yellow"
$htmlinput | ConvertTo-Html -Property RequestID,RequesterName,CommonName,NotBefore,NotAfter,SerialNumber -Pre $htmlpre -Post $htmlpost  -head $a | Out-File -FilePath $reportfile
$message = gc $reportfile

#Send report by email
send_mail $message "Certificate expiration report $todaysdate ($caname)"

#Open report
Write-Host "Opening report…" -ForegroundColor "Yellow"
#Invoke-Item $reportfile

#Warning if PSPKI is not installed
Write-Host "PSPKI is not installed. Please install it from http://pspki.codeplex.com/ " -ForegroundColor "Yellow"

#Stop stopwatch
$ts = $totalTime.Elapsed
$totalTime = [system.String]::Format("{0:00}:{1:00}:{2:00}",$ts.Hours, $ts.Minutes, $ts.Seconds)
Write-Host "Process total time: $totalTime" -ForegroundColor Yellow


  • Launch a powershell command prompt and execute the command : set-executionpoilicy unrestricted
  • Schedule a task with the following parameters:
    • Run whether user is logged on or not
    • Run with highest privileges
    • Trigger : Monthly / Runs on the first and third Monday every months
    • Actions : Start a program > powershell -file “C:\Scripts\adcs_exp.ps1”
Monitor certificate expiration

Leave a Reply

Your email address will not be published. Required fields are marked *