An unexpected expiration of a server certificate can cause a number of problems for your users and customers: they may not be able to establish a secure connection with your site, authentication errors may occur, annoying notifications may appear in a browser, etc. In this post we’ll show you how to check the expiration date of an SSL/TLS certificate on remote sites, or get a list of expiring certificates in the local certificate store on servers or computers in your domain.
Get the Expiration Date of a Website SSL Certificate with PowerShell
Many web projects use free Let’s Encrypt SSL certificates to implement HTTPS. These certificates are issues for 90 days and must be renewed regularly. Usually, special scripts or bots update Let’s Encrypt certificates on the hosting or server side (it may be WACS in Windows or Certbot in Linux). However, sometimes automatic certificate renewal fails. I would like to have my own script that would check SSL certificate expiry dates on websites and notify me when they are about to expire. I used PowerShell to create it. Since we are checking a website’s certificate via an HttpWeb query, we don’t need administrator privileges on a remote website/server.
In the following PowerShell script, you must specify the list of website you want to check certificate expiration dates on and the certificate age when the corresponding notification starts to be displayed to you ($minCertAge
). I entered 80 days as an example.
$minCertAge = 80
$timeoutMs = 10000
$sites = @(
"https://testsite1.com/",
"https://testsite2.com/",
"https://zamarax.com/"
)
# Disable certificate validation
[Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
foreach ($site in $sites)
{
Write-Host Check $site -f Green
$req = [Net.HttpWebRequest]::Create($site)
$req.Timeout = $timeoutMs
try {$req.GetResponse() |Out-Null} catch {Write-Host URL check error $site`: $_ -f Red}
$expDate = $req.ServicePoint.Certificate.GetExpirationDateString()
$certExpDate = [datetime]::ParseExact($expDate, “dd/MM/yyyy HH:mm:ss”, $null)
[int]$certExpiresIn = ($certExpDate - $(get-date)).Days
$certName = $req.ServicePoint.Certificate.GetName()
$certThumbprint = $req.ServicePoint.Certificate.GetCertHashString()
$certEffectiveDate = $req.ServicePoint.Certificate.GetEffectiveDateString()
$certIssuer = $req.ServicePoint.Certificate.GetIssuerName()
if ($certExpiresIn -gt $minCertAge)
{Write-Host The $site certificate expires in $certExpiresIn days [$certExpDate] -f Green}
else
{
$message= "The $site certificate expires in $certExpiresIn days"
$messagetitle= "Renew certificate"
Write-Host $message [$certExpDate]. Details:`n`nCert name: $certName`Cert thumbprint: $certThumbprint`nCert effective date: $certEffectiveDate`nCert issuer: $certIssuer -f Red
#Displays a pop-up notification and sends an email to the administrator
#ShowNotification $messagetitle $message
# Send-MailMessage -From [email protected] -To [email protected] -Subject $messagetitle -body $message -SmtpServer gwsmtp.zamarax.com -Encoding UTF8
}
write-host "________________" `n
}
This PowerShell script will check SSL certificates of all websites in the list. If a certificate is found that is about to expire, it will be highlighted in the notification.
To notify an administrator that an SSL certificate is about to expire, you can add a popup notification. To do it, uncomment the script line “ShowNotification $messagetitle $message
” and add the following function:
Function ShowNotification ($MsgTitle, $MsgText) {
Add-Type -AssemblyName System.Windows.Forms
$global:balmsg = New-Object System.Windows.Forms.NotifyIcon
$path = (Get-Process -id $pid).Path
$balmsg.Icon = [System.Drawing.Icon]::ExtractAssociatedIcon($path)
$balmsg.BalloonTipIcon = [System.Windows.Forms.ToolTipIcon]::Warning
$balmsg.BalloonTipText = $MsgText
$balmsg.BalloonTipTitle = $MsgTitle
$balmsg.Visible = $true
$balmsg.ShowBalloonTip(10000)
}
You can also send an email notification using Send-MailMessage
.
Then if any expired or expiring certificates are found, you will be notified by an email and a popup message.
Then create an automatic task for the Task Scheduler to be run once or twice a week and run the PowerShell script to check expiry dates of your HTTPS website certificates. (You can create a task in the Task Scheduler to run a PS1 script file using Register-ScheduledTask cmdlet.)
How to Check for Expired Certificates in Windows Certificate Store Remotely?
You may also need a PowerShell script check the expiration dates of certificates used by cryptographic services on your domain servers (e. g., RDP/RDS , Exchange, SharePoint, LDAPS certificates, etc.) or users’ computers.
On a local computer, you can get a list of certificates using the command:
Get-ChildItem -Path cert
Powershell 3.0 has a special -ExpiringInDays
argument:
Get-ChildItem -Path cert: -Recurse -ExpiringInDays 30
In PowerShell 2.0, the same command looks like this:
Get-ChildItem -Path cert: -Recurse | where { $_.notafter -le (get-date).AddDays(30) -AND $_.notafter -gt (get-date)} | select thumbprint, subject
To check only your own certificates, use the Cert:\LocalMachine\My
container instead of Cert:
in the root folder. Thus, you won’t check Windows trusted root certificates and commercial certificates.
To find certificates that will expire in the next 30 days on all domain servers, use this PowerShell script:
$servers= (Get-ADComputer -LDAPFilter "(&(objectCategory=computer)(operatingSystem=Windows Server*) (!serviceprincipalname=*MSClusterVirtualServer*) (!(userAccountControl:1.2.840.113556.1.4.803:=2)))").Name
$result=@()
foreach ($server in $servers)
{
$ErrorActionPreference="SilentlyContinue"
$getcert=Invoke-Command -ComputerName $server { Get-ChildItem -Path Cert:\LocalMachine\My -Recurse -ExpiringInDays 30}
foreach ($cert in $getcert) {
$result+=New-Object -TypeName PSObject -Property ([ordered]@{
'Server'=$server;
'Certificate'=$cert.Issuer;
'Expires'=$cert.NotAfter
})
}
}
Write-Output $result
You will get the list of server certificates that are about to expire and you will have enough time to renew them.