If an SSL certificate expires on a web server, RD Gateway, or WSUS server, the service is usually no longer available. To avoid such situations, you should continually check the expiration of certificates. This can be done with a PowerShell script.

For web servers that are accessible via the public Internet, there are numerous online services that can check at regular intervals when certificates expire and then notify the webmaster in good time. In the company network, many monitoring tools can take over this task.

If you are limited to the onboard tools for this purpose, you can use PowerShell. With the help of a relatively simple script, all servers can be scanned for certificates that will soon reach their expiration date.

Retrieving all servers from the AD ^

The following example reads all computers running Windows Server from Active Directory and remotely accesses their certificate store under LocalMachinemy. It displays all certificates that expire in less than 14 days or that have already expired.

To prevent the script from hanging when a server is not reachable, the Test-Connection cmdlet checks whether the target host is online.

$cred = Get-Credential
$c = 0
$servers = Get-ADComputer -Filter "OperatingSystem -like 'Windows Server*'"
$servers | foreach{
 $p = ($c++/$servers.count) * 100
 Write-Progress -Activity "Checking $_" -Status "$p % completed" -PercentComplete $p;
 if(Test-Connection -ComputerName $_.DNSHostName -Count 2 -Quiet){
    Invoke-Command -ComputerName $_.DNSHostName -Credential $cred `
    {dir Cert:\LocalMachine\my | ? NotAfter -lt (Get-Date).AddDays(14)}
  }
}

If necessary, you could restrict the list of servers by specifying certain OUs with the SearchBase parameter; alternatively, you could read them from a text file.

Subscribe to 4sysops newsletter!

Interactive execution of the script to check the expiration date of certificates

Interactive execution of the script to check the expiration date of certificates

Conclusion ^

The script is intended for interactive execution and shows the progress of the operation with Write-Progress. You could, of course, also customize it to run as a Scheduled Task and be notified by email if a certificate is about to expire.

avatar
7 Comments
  1. Fred Beck 1 year ago

    This is great!

    BTW Script fails with errors looking for

    Cert:LocalMachinemy

    Your screenshot is slightly different from the script you posted

    Cert:LocalMachine\my

  2. Ramkumar 8 months ago

    Do we have to run the above script on AD server or we have to run this Script on all the servers individually ?

    • Wolfgang Sommergut 8 months ago

      You can run the script from any workstation with the PowerShell AD module installed.

  3. Florian Braune 7 months ago

    Hi Wolfgang,

    any chance to get the certs FriendlyName instead of the ThumbPrint?

    Thanks

  4. Ziv 6 months ago

    Hi Wolfgang

    Thanks for the script. It's awesome!

    I think it's worth adding a few more lines ( But I don't know how... )
    
    1. Find the CA who expired 30 days ago and / or expires within 30 days.
    2. Add a column of the certificate name.
    
    3. Assuming I did a scheduled task that run PS1
       How can I attach the results to the email?
       How to make it so that only if there is expire CA it will send mail?

     

    Thanks 

    B.R

    Ziv

  5. olivier 6 months ago

    Hi Wolfgang

    As always interresting post, some comments that i would like to be constructive

    • Don't use DOS command when an equivalent PS cmdlet exists (i.e.  dir)
    • Don't use alias (i.e. dir, ?)
    • Name parameters (i.e. NotAfter should be -Property NotAfter)
    • Avoid, as much as possible, one-liner code.
    • Use correct formating (Carriage return after a pipeline and indentation)

    Why these proposal ? your readers are not all powershell experts, but a wider audience. Aliases are fine when passing a command line, but it is not recommended to use them in scripts.  Naming parameter is recommended by the best practices. One-liner code is not always appropriate to debug. Correct formating makes the code more readable and understandable.

    then the code should be :

    Get-ChildItem -Path Cert:\LocalMachine\my |
        Select-Object -Property friendlyName, Thumbprint, Subject, NotAfter |
        Where-Object -Property NotAfter -LT (get-date).AddDays(-14)

    @Florian Brune : to meet your need, I've added the property FriendlyName to the output. Feel free to add/remove the properties you would like or not.

    regards

    Olivier

Leave a reply to Ziv Click here to cancel the reply

Please enclose code in pre tags

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

*

© 4sysops 2006 - 2021

CONTACT US

Please ask IT administration questions in the forums. Any other messages are welcome.

Sending

Log in with your credentials

or    

Forgot your details?

Create Account