Find expiring certificates on Windows servers

An expired certificate on a single server usually takes down exactly the service everyone depends on: the RD Gateway, the intranet site, LDAPS for the firewall or the RADIUS server behind your Wi-Fi. Windows gives you no warning. A few lines of PowerShell show you what is about to expire and which service is affected.

Where do services keep their certificates?

Server services almost always use the computer store: Cert:\LocalMachine\My in PowerShell, “Personal” in the certlm.msc console. Two exceptions:

  • The self-signed RDP certificate lives in Cert:\LocalMachine\Remote Desktop.
  • Domain controllers can also use the NTDS service store for LDAPS (see checking LDAPS certificates).

Expiring certificates on one server

Everything that expires within the next 30 days or has already expired:

$days = 30
Get-ChildItem Cert:\LocalMachine\My |
  Where-Object { $_.NotAfter -lt (Get-Date).AddDays($days) } |
  Sort-Object NotAfter |
  Select-Object NotAfter, Subject, Issuer, Thumbprint

That list is often full of leftovers: the certificate was renewed long ago and the old one is just still in the store. It's more useful to look only at the newest certificate per subject. If it still shows up, there really is no successor:

Get-ChildItem Cert:\LocalMachine\My |
  Group-Object Subject |
  ForEach-Object { $_.Group | Sort-Object NotAfter -Descending | Select-Object -First 1 } |
  Where-Object { $_.NotAfter -lt (Get-Date).AddDays(30) } |
  Select-Object NotAfter, Subject, Thumbprint

Many servers at once

With PowerShell remoting (enabled by default on Windows Server) you can query as many servers as you like in one go:

$servers = 'srv-web01', 'srv-rds01', 'dc01'
Invoke-Command -ComputerName $servers -ScriptBlock {
  Get-ChildItem Cert:\LocalMachine\My |
    Where-Object { $_.NotAfter -lt (Get-Date).AddDays(30) } |
    Select-Object NotAfter, Subject, Thumbprint
} | Sort-Object NotAfter | Format-Table PSComputerName, NotAfter, Subject -AutoSize

To get every server in the domain, use (Get-ADComputer -Filter 'OperatingSystem -like "*Server*"').DNSHostName (ActiveDirectory module from RSAT). Invoke-Command reports unreachable servers as errors and carries on with the rest.

Which service uses the certificate?

A certificate in the store doesn't mean anything uses it. Compare the thumbprint with the bindings of your services:

ServiceHow to find the certificate in use
IISnetsh http show sslcert (field “Certificate Hash”) or IIS Manager → site → Bindings
RDPGet-CimInstance -Namespace root\cimv2\TerminalServices -ClassName Win32_TSGeneralSetting -Filter "TerminalName='RDP-tcp'" | Select-Object SSLCertificateSHA1Hash – details in the RDP guide
RDS roles (Gateway, Web Access, Broker)Get-RDCertificate on the connection broker
WinRM over HTTPSwinrm enumerate winrm/config/listener (value “CertificateThumbprint”)
ExchangeGet-ExchangeCertificate | Format-List Thumbprint, Services, NotAfter
NPS / RADIUS (Wi-Fi, VPN)Network Policy Server → Network Policies → policy → Constraints → Authentication Methods → edit PEAP or EAP
SQL ServerSQL Server Configuration Manager → Network Configuration → Protocols for the instance → Properties → Certificate
LDAPS (domain controllers)See LDAPS certificates on domain controllers

Renewal: automatic or manual

Windows renews certificates from your own enterprise CA through autoenrollment – as long as Group Policy and template permissions are right. If that isn't happening, work through the troubleshooting checklist.

Keep in mind that not every service picks up the new certificate on its own:

  • Picked up automatically: RDP, if the template is set via Group Policy, and LDAPS on domain controllers.
  • IIS 8.5 and later, but only with “Enable Automatic Rebind of Renewed Certificate” turned on (IIS Manager → Server Certificates).
  • Reassign by hand: NPS, SQL Server, WinRM listeners and Exchange services.
  • Purchased public certificates always have to be renewed and installed manually.

Keep an eye on it permanently

The commands above are a snapshot. The free ADCS Health Check checks your CA certificates and CRLs, and also the computer store of the machine it runs on. It reports certificates that expire soon and have no successor yet.

More guides