4

I have a simple script to show all certificates on a server, I would like to expand that script to then remove all expired certificates

I have tried several scripts from MS and 3rd parties to find a remove certs but have had no luck with them working properly

The first code I am using is:

Get-ChildItem Cert:\ -Recurse

This Powershell script shows all certificates on a server.

Example output is below for each certificate. I want to target the NotAfter field and have the script then remove the certificate if it's old than todays date

Subject: Issuer: Thumbprint: FriendlyName: NotBefore: NotAfter: Extensions

I would also like to do this for a list of servers, have the script run on each server in a text document, query all certificates, then remove the certs that are expired and move on to the next server.

I have seen some code targeting the date like the following:

ForEach-Object -begin { $now = get-date } -process { if ($PSItem.NotAfter -lt $now ) { $PSItem } } | Remove-Item

I would like the script to go out and query a servers certificates, then deletes out the expired certificates

aztech
  • 71
  • 2
  • 5
  • 9

1 Answers1

7

What you are after is this. This should work perfectly for you. You were close in your logic, just the execution seemed to be a bit off.

$ListOfServers = Get-Content "c:\temp\serv.txt"

Foreach($Server in $ListOfServers) {
    Invoke-Command -ComputerName $Server -ScriptBlock {
        # Get Certificate list and assign to a variable
        $Certs = Get-ChildItem "Cert:\LocalMachine\My" -Recurse

        # Loop through each object in $Certs
        Foreach($Cert in $Certs) {
            # If The objects property "NotAfter" is older than the current time, delete
            If($Cert.NotAfter -lt (Get-Date)) {
                $Cert | Remove-Item
            }
        }
    }
}

Edited based on comment to prevent accidental destruction of all certs.

To get a list of all cert storage locations.

(Get-ChildItem -Path "Cert:" -Recurse `
    | Where-Object {($_).GetType().Name -eq 'X509Store'}).Name
Drew
  • 3,814
  • 2
  • 9
  • 28
  • Note that you shall not execute the script outside of Personal (My) cert store. There is a number of expired CA certificates required by an operating system. – Crypt32 May 15 '19 at 04:24
  • Good call. I have since edited the answer to ensure that only the `\My` certs are returned. – Drew May 15 '19 at 05:32
  • That worked great for the Certificates\Personal\Certificates, if I wanted to do the same in a different folder like Trusted Root Certification Authorities or any of the others, what name would I use in place of MY, is there a list that has the name of each of these that I can sub into the script? And thank you for taking the time to answer my question and share your knowledge I greatly appreciate it – aztech May 15 '19 at 22:36
  • @aztech I have added a little bit of a one-liner that will allow you to get the names of the cert stores. – Drew May 15 '19 at 23:13
  • that works perfect thank you. One last question, if I wanted to run the script against a group of servers listed on a text file how would I do that since it already has a foreach statement in it, I wasnt sure where to place another foreach statement – aztech May 28 '19 at 18:12
  • @crypt32 you mentioned not running this out of the MY location and that the OS still needs some expired certs, are those expired certs in a specific store? Where would I find them? I ask for education on my part – aztech May 28 '19 at 18:15
  • They are stored at least in trusted root CAs, 3rd party root CAs, intermediate CAs stores. – Crypt32 May 28 '19 at 19:06
  • I am trying the following but when I run it from a server with elevated privileges in Powershell ISE it says completed but when I check the server I'm targeting the Personal store still shows expired: certs$serverlist = @("c:\temp\serv.txt") Foreach ($Serv in $serverlist) { $Certs = Get-ChildItem "Cert:\LocalMachine\My" -Recurse Foreach($Cert in $Certs) {     # If The objects property "NotAfter" is older than the current time, delete     If($Cert.NotAfter -lt (Get-Date)) {         $Cert | Remove-Item     } } } – aztech May 28 '19 at 22:48
  • Updated code. I would recommend not running any of this code or at least running it past someone who knows what they are doing. Your comment showed that you are trying to run a foreach loop on a single string in an array and did not actually get the content from the text file. – Drew May 28 '19 at 23:31