Skip to main content

PowerShell function to retrieve a list of SSL/TLS certificates installed on the system (Windows only).

function Get-Cert
{
    <#
    .SYNOPSIS
        Retrieves certificates from a local or remote system.

    .DESCRIPTION
        Retrieves certificates from a local or remote system. Also includes the
        time until expiration and allows for filtering of certificates and includes
        archived certificates.

    .PARAMETER Computername
        A single or list of computernames to perform search against.

    .PARAMETER StoreName
        The name of the certificate store name that you want to search.

    .PARAMETER StoreLocation
        The location of the certificate store.

    .PARAMETER IncludeArchive
        Includes certificates that have been archived.

    .PARAMETER Issuer
        Filter by certificate issuer.

    .PARAMETER Subject
        Filter by certificate subject.

    .PARAMETER Thumbprint
        Filter by certificate thumbprint.

    .EXAMPLE
        PS > Get-Cert -Computername 'boe-pc' -StoreLocation LocalMachine -StoreName My

        Thumbprint                                 Subject
        ----------                                 -------
        F29B6CB248E3395B2EB45FCA6EA15005F64F2B4E   CN=SomeCert
        B93BA840652FB8273CCB1ABD804B2A035AA39877   CN=YetAnotherCert
        B1FF5E183E5C4F03559E80B49C2546BBB14CCB18   CN=BOE
        65F5A012F0FE3DF8AC6B5D6E07817F05D2DF5104   CN=SomeOtherCert
        63BD74490E182A341405B033DFE6768E00ECF21B   CN=www.example.com

        Lists all certificates

    .EXAMPLE
        PS > Get-Cert -Computername 'boe-pc' -StoreLocation LocalMachine -StoreName My -Subject '*Boe*'

        Thumbprint                                 Subject
        ----------                                 -------
        B1FF5E183E5C4F03559E80B49C2546BBB14CCB18   CN=BOE

        Lists certificates that contain the subject 'Boe'

    .LINK
        https://github.com/proxb/PowerShell_Scripts/blob/master/Get-Certificate.ps1

    .NOTES
        Name: Get-Certificate
        Author: Boe Prox
        Version History:
            1.3 //Boe Prox
                -Added parameters for filtering
                -Removed parametersetnames
                -Fixed computername output in verbose streams
            1.0 //Boe Prox
                -Initial Version
    #>
    [CmdletBinding()]
    param (
        [Parameter(ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)]
        [Alias('PSComputerName', '__Server', 'IPAddress', 'Server')]
        [string[]]
        $ComputerName = $env:COMPUTERNAME,

        [Parameter()]
        [System.Security.Cryptography.X509Certificates.StoreLocation]
        $StoreLocation = 'LocalMachine',

        [Parameter()]
        [System.Security.Cryptography.X509Certificates.StoreName]
        $StoreName = 'My',

        [Parameter()]
        [switch]
        $IncludeArchived,

        [Parameter()]
        [string]
        $Issuer,

        [Parameter()]
        [string]
        $Subject,

        [Parameter()]
        [string]
        $Thumbprint
    )
    begin
    {
        $whereList = New-Object System.Collections.ArrayList

        if ($PSBoundParameters.ContainsKey('Issuer'))
        {
            $whereList.Add('$_.Issuer -LIKE $Issuer') | Out-Null
        }

        if ($PSBoundParameters.ContainsKey('Subject'))
        {
            $whereList.Add('$_.Subject -LIKE $Subject') | Out-Null
        }

        if ($PSBoundParameters.ContainsKey('Thumbprint'))
        {
            $whereList.Add('$_.Thumbprint -LIKE $Thumbprint') | Out-Null
        }

        if ($whereList.count -gt 0)
        {
            $where = [scriptblock]::Create($whereList -join ' -AND ')
            Write-Debug "WhereBlock: $($where)"
        }
    }

    process
    {
        foreach ($computer in  $ComputerName)
        {
            try
            {
                Write-Verbose ('Connecting to \\{0}\{1}\{2}' -f $computer, $StoreLocation, $StoreName)

                $certStore = New-Object System.Security.Cryptography.X509Certificates.X509Store -ArgumentList "\\$($computer)\$($StoreName)", $StoreLocation

                if ($PSBoundParameters.ContainsKey('IncludeArchived'))
                {
                    $flags = [System.Security.Cryptography.X509Certificates.OpenFlags]'ReadOnly', 'IncludeArchived'
                }
                else
                {
                    $flags = [System.Security.Cryptography.X509Certificates.OpenFlags]'ReadOnly'
                }

                $certStore.Open($flags)

                if ($whereList.count -gt 0)
                {
                    $certificates = $certStore.Certificates | Where-Object $where
                }
                else
                {
                    $certificates = $certStore.Certificates
                }

                $certificates | ForEach-Object {
                    $Days = Switch ((New-TimeSpan -End $_.NotAfter).Days)
                    {
                        { $_ -gt 0 } { $_ }
                        Default { 'Expired' }
                    }

                    $_ | `
                        Add-Member -MemberType NoteProperty -Name ExpiresIn -Value $Days -PassThru | `
                        Add-Member -MemberType NoteProperty -Name ComputerName -Value $computer -PassThru
                }
            }
            catch
            {
                Write-Warning "$($computer): $_"
            }
        }
    }
}