Search code examples
powershellcsvcertificate

Get certificates to expire in one month or less


I want to get all local machine certificates that will expire in one month at maximum and store their information in a .csv file. I used this code but it stores also some other certificates that will expire in more than a month.

Here is the code I've written:

$testPath = 'Cert:\LocalMachine\'
$testDetail = Get-ChildItem -Path $testPath -Recurse | Where-Object {
    $_.PSIsContainer -ne $true
} | ForEach-Object {
    $DaysLeft = (New-TimeSpan -Start $StartDate -End $_.NotAfter).Days

    $FinalDate = Get-Date $_.NotAfter -Format 'dd/MM/yyyy hh:mm'
    $Usages = ($_.Extensions | Where-Object {$_.KeyUsages}).KeyUsages
    if ($Usages) {
        # get at most two parts out of the $_.Issuer string
        $issuer = '{0}, {1}' -f ([regex] 'O=([^,]+)').Match($_.Issuer).Groups[1].Value, 
                                ([regex] 'CN=([^,]+)').Match($_.Issuer).Groups[1].Value
        $issuer = $issuer.Trim(", ")

        [PSCustomObject]@{
            Issuer             = $issuer.TrimStart('"')
            Usages             = $Usages.ToString() -replace ',', ';'
            Expire_Date        = $FinalDate
            Days_Remaining     = "$DaysLeft"
            Status_Description = "About to expire"
        }
    }
}
$testDetail | Where {
    $_.Days_Remaining -lt 30 -and
    $_.Usages -ne "" 
} | Export-Csv -NoTypeInformation -Path 'C:\SECnology\Data\Files\other1\Certificate_Status.csv'

Solution

  • What you have to do is to filter based on NotAfter property. There might be several options based on what exactly you want to achieve:

    # All certs which expiration date is before Friday, July 19, 2019 00:00:01
    # This will include already expired certificates too
    $_.NotAfter -le (Get-Date).Date.AddDays(30)
    
    # All certs which expiration date is before Friday, July 19, 2019 00:00:00
    # and after Wednesday, June 19, 2019 00:00:00
    # This will include certificates that expired today
    $_.NotAfter -le (Get-Date).Date.AddDays(30) -and $_.NotAfter -ge (Get-Date).Date
    

    General principles:

    1. Use -ge or -gt for specifing start date. The difference is only whether you want to include the exact date or not (so one second of difference)
    2. Similarly, use -le or -lt for specifying end date
    3. (Get-Date) will give you current date and time, while (Get-Date).Date), today's date at 00:00:00:
    PS> Get-Date
    
    Wednesday, June 19, 2019 12:16:57
    
    PS> (Get-Date).Date
    
    Wednesday, June 19, 2019 00:00:00
    

    Once you clarify the exact conditions, use the rules above to construct your query and add it to your Where-Object as @Ansgar mentioned in the comments:

    Where-Object {
      -not $_.PSIsContainer -and $_.NotAfter -le (Get-Date).Date.AddDays(30)
    }