Use PowerShell to Find Certificates that are About to Expire


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

Comments (18)

  1. Anonymous says:

    Awesome! works like a charm.

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

  2. Anonymous says:

    @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:>

  3. Anonymous says:

    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:LocalMachineRoot 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?

  4. jrv says:

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

  5. jrv says:

    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>

  6. jrv says:

    @Sheila

    Windows 7 is PowerShell V2 unless you have upgraded.

    Check $PSVersionTable.PSVersion

  7. sheila says:

    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?

  8. jz says:

    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?

  9. AG says:

    wtb response from the scripting guys regarding "

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

  10. gururaj says:

    How to filter the certificates with its template name ?

  11. Anon says:

    To see certs that have already expired:
    dir -ExpiringInDays 0

  12. Madhan Kumar .S says:

    Below exchange powershell checks exchange certificate expiry date.
    Get-ExchangeCertificate | where { $_.notafter -le (get-date).AddDays(10)} | select subject,thumbprint,notafter

  13. Rich says:

    Isn’t the CERT: provider checking against the certificate store of the local computer or current user, not the Certificate Authority? Is there an equivalent super-easy way to check against the CA to find out if any certificate will be expiring soon?

  14. Like AR says:

    I believe AR mentioned have a CA because, like me, they want to know how to find which issued certificates are expiring on the CA, not on clients.

    How can a list of expiring issued certificates be generated on the CA?

  15. Like AR says:

    If anyone else is looking for how to generate a list of expiring certificates on a CA (and then e-mail that list), check out "Get-ExpiringCertificates.ps1" by Ragnar Harper (internet search will turn it up).

  16. Thank you for sharing this script.
    It was helpful for me.

    I have added two parameters to the select and used sort-object like following :
    Get-ChildItem -Path cert: -Recurse | where { $_.notafter -le (get-date).AddDays(75) -AND $_.notafter -gt (get-date)} | select notafter, issuer, thumbprint, subject | sort-object notafter

    works perfectly fine

  17. obi ejiofor says:

    Is there a way to check java certificates using powershell ?

  18. Hi All,

    I am trying to generate a self Signed cert valid for 10 years for the website on my Windows 2012 using “New-SelfSignedCertificate” PowerSHell commandlet. By default the below command give the Self-Signed SSL cert valid for just 1 year. I am trying to generate the cert with 10 yrs validity using “-NotAfter” & “-NotBefore” arguments which is not working it seems.

    New-SelfSignedCertificate -DnsName test.mywebsite.com, san.mywebsite.com -CertStoreLocation cert:\LocalMachine\My -NotAfter (Get-Date).AddYears(10)

    is the command I run and the output as given below.

    PS H:\> New-SelfSignedCertificate -DnsName test.mywebsite.com, san.mywebsite.com -CertStoreLocation cert:\LocalMachine\M
    y -NotAfter (Get-Date).AddYears(10)
    New-SelfSignedCertificate : A parameter cannot be found that matches parameter name ‘NotAfter’.
    At line:1 char:115
    + … ocalMachine\My -NotAfter (Get-Date).AddYears(10)
    + ~~~~~~~~~
    + CategoryInfo : InvalidArgument: (:) [New-SelfSignedCertificate], ParameterBindingException
    + FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.CertificateServices.Commands.NewSelfSignedCertificateCo
    mmand

    PS H:\>

    Was looking at the blogs, couldn’t find any links to refer specific to this validity period setup. Please help me fix it.

    Thanks
    Kuppuraj M

Skip to main content