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, ThumbprintThat 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, ThumbprintMany 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 -AutoSizeTo 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:
| Service | How to find the certificate in use |
|---|---|
| IIS | netsh http show sslcert (field “Certificate Hash”) or IIS Manager → site → Bindings |
| RDP | Get-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 HTTPS | winrm enumerate winrm/config/listener (value “CertificateThumbprint”) |
| Exchange | Get-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 Server | SQL 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
RDP certificates: check, replace and enroll from your own CA
Get rid of the warning that the identity of the remote computer cannot be verified: deploy RDP certificates from your own CA via Group Policy.
LDAPS certificates on domain controllers: check and renew
Which certificate does a domain controller use for LDAPS, when does it expire and how do you swap it without a reboot? Includes a PowerShell test for port 636.
Autoenrollment not renewing certificates? A checklist
Group Policy, template permissions, CA connectivity, event log: work out step by step why certificates are not renewed automatically.
Expired CRL: an emergency runbook for Microsoft PKI
Wi-Fi, VPN or logons failing because a CRL expired? How to publish a new CRL – including from the offline root – and prevent the next outage.