Use PowerShell to Find Certificates that are About to Expire

Use PowerShell to Find Certificates that are About to Expire

  • Comments 10
  • Likes

Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to find certificates that are about to expire.

Hey, Scripting Guy! Question Hey, Scripting Guy! We recently implemented an internal certification authority that we use for various scenarios, such as issuing code-signing certificates for our developers and certain admins as well as for user authentication scenarios. Now, of course, we have a problem. My pointy headed boss is worried that people with certificates will not renew them properly, so he wants me to write a script that can find out when scripts are about to expire. Is this something that I can do easily?

—AR

Hey, Scripting Guy! Answer Hello AR,

Microsoft Scripting Guy, Ed Wilson, is here. Today is Tuesday, and the Scripting Wife and I are on the road for a bit. Luckily, Windows 8 phone easily sets up as a modem, and I can connect to the Internet with my laptop and check my email at scripter@microsoft.com. It is cool. The bad thing about a road trip is that it is nearly impossible to get a decent cup of tea. I made a pot before we left, so I have some decent tea—at least for a little while.

AR, dude, this is so easy…

The reason it is so easy to find certificates that are about to expire in Windows PowerShell 3.0 is because we add a dynamic parameter to the Get-ChildItem cmdlet when the cmdlet targets the Cert: PSDrive. The dynamic parameter is called –ExpiringInDays and it does exactly what you might think it would do— it reports certificates that are going to expire within a certain time frame. To find certificates that will expire within 75 days, use the command shown here.

Get-ChildItem -Path cert: -Recurse -ExpiringInDays 75

The command and the output associated with the command to find certificates that expire in 75 days are shown here.

Image of command output

I do not have to set my working location to the Cert: PSDrive, because I can specify it as the path of the Get-ChildItem cmdlet. If I need to perform more than one or two operations, I will change my working location to the Cert: PSDrive to simplify some of the typing requirements. To change to the Cert: PSDrive, I use the Set-Location cmdlet (SL is an alias, as is CS). This technique is shown here.

PS C:\> sl cert:

After I have changed my working location to the Cert: PSDrive, the Windows PowerShell prompt (by default) changes to include the Cert: drive location as shown here.

PS Cert:\>                

Finding about to expire certificates the PowerShell 2.0 way

If you are using Windows PowerShell 2.0 (or if you just like to type), you can still find certificates that are about to expire by using the Get-ChildItem cmdlet on your Cert: PSDrive, and then piping the results to the Where-Object. You need to filter on the NotAfter property of the returned certificate object. The great thing is that Windows PowerShell makes it easy to work with dates. I use the AddDays method from the DateTime object that is returned by the Get-Date cmdlet.

To gain access to the AddDays method, I group the Get-Date cmdlet first. Each certificate object crosses the pipeline to the Where-Object cmdlet. Inside the script block for the Where-Object, I look at the NotAfter property, and I check to see if it is less than a date that is 75 days in the future. Upon finding the certificates that have an expiration date of less than 75 days in the future, I send the results to the Select-Object cmdlet, where I choose the thumbprint and the subject. The following command returns certificates that have an expiration date that is before 75 days in the future.

Get-ChildItem -Recurse | where { $_.notafter -le (get-date).AddDays(75) } | select thumbprint, subject

When I run the command, the results do not compare very well with those from the previous command. The command and its resulting output are shown here.

Image of command output

The reason the output is different is because the new ExpiringInDays parameter for Windows PowerShell 3.0 does not include already expired certificates. Windows ships with expired certificates because certain executables that have been signed with a certificate, but have not been resigned with a new certificate, need the old certificate to ensure the validity of the certificate.

By modifying the command so it also filters out expired certificates, the results on my computer become the same. Here is the revised command.

Get-ChildItem -Recurse | where { $_.notafter -le (get-date).AddDays(75) -AND $_.notafter -gt (get-date)} | select thumbprint, subject

The command and the output associated with the command are shown here.

Image of command output

AR, that is all there is to using the certificate provider in Windows PowerShell to find certificates that will expire in a certain time frame. Join me tomorrow when I will talk about more cool stuff.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • I am running a Win7 x64 OS, PS v3, and .Net 3.5-4.5.  

    When I run your PS v3 example I get an error stating "Get-ChildItem : A parameter cannot be found that matches parameter name 'ExpiringInDays'". The PS v2 example runs perfectly.

    Do you know why I am getting this error?

  • @Sheila

    Windows 7 is PowerShell V2 unless you have upgraded.

    Check $PSVersionTable.PSVersion

  • Awesome! works like a charm.

    How do we get this to work for a remote server ?

  • @jrv

    I get the same result and i am running PS v3

    PS Cert:\> $PSVersionTable

    Name                           Value                                                                                                                                                                                                                            

    ----                           -----                                                                                                                                                                                                                            

    WSManStackVersion              3.0                                                                                                                                                                                                                              

    PSCompatibleVersions           {1.0, 2.0, 3.0}                                                                                                                                                                                                                  

    SerializationVersion           1.1.0.1                                                                                                                                                                                                                          

    BuildVersion                   6.2.9200.16398                                                                                                                                                                                                                  

    PSVersion                      3.0                                                                                                                                                                                                                              

    CLRVersion                     4.0.30319.296                                                                                                                                                                                                                    

    PSRemotingProtocolVersion      2.2                                                                                                                                                                                                                              

    PS Cert:\> Get-ChildItem -Path cert: -Recurse -ExpiringInDays 75

    Get-ChildItem : A parameter cannot be found that matches parameter name 'ExpiringInDays'.

    At line:1 char:36

    + Get-ChildItem -Path cert: -Recurse -ExpiringInDays 75

    +                                    ~~~~~~~~~~~~~~~

       + CategoryInfo          : InvalidArgument: (:) [Get-ChildItem], ParameterBindingException

       + FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand

    PS Cert:\>

  • This switch seems to be only supported on Windows 8 and later.

  • 1. This command lists certificates installed on the local computer. I hope that a script exists that we can run against the internal CA to show all the issued certificates that are about to expire.

    2. How do we run the command against a remote Windows Server?

  • wtb response from the scripting guys regarding "

    Get-ChildItem : A parameter cannot be found that matches parameter name 'ExpiringInDays'"

  • To see available options on any platform for any provide that produces a drive do the following.

    cd cert:

    Get-ChildItem -<tab repeatedly to see all dynamic properties>

  • How to filter the certificates with its template name ?

  • I know this can be done. I would like to report to my manager using HTML, a summary of an installed certificate on all domain computers, as well as the installation and expiration date of said certificate under the Cert:\LocalMachine\Root dir. Any suggestions?

    I am also running Win7 x64 alongside XP 32 - I know XP is going to be replaced soon with Win 7 x64; however, I would like to use a powershell script to list a certificate along with date expiration and then export that list to an HTML report for all domain computers in OU. Has anyone tried this? and if so how easy or difficult is this to acheive?