Get-NetCertificateHealth.ps1

<#
.Synopsis
    Retrieve certificate from remote system and validates it against criteria
.DESCRIPTION
    Retrieve certificate from remote system and validates it against criteria for days until expiration, algorithm, and key size
.EXAMPLE
    Get-NetCertificateHealth -IP 8.8.8.8
 
    Queries 8.8.8.8 on the default port of 443 and verfies certificate doesn't expire with 60 days, uses at least SHA256RSA and has at least 2048 key size
    It will return warning or critical results for any failing validations
.NOTES
Adapted by: Jason Wasser
Original code by: Rob VandenBrink
Inspiration
https://isc.sans.edu/forums/diary/Assessing+Remote+Certificates+with+Powershell/20645/
Modified: 1/9/2020 02:16:05 PM
Modified: 11/10/2020
    Updated help from source function of Save-NetCertificate
    Updated Verbiage in verbose statements for expired certificates
    Added CmdletBinding So that the verbose statements are useful
#>

function Get-NetCertificateHealth {
    [CmdletBinding()]
    Param (
        [Alias('IP')]
        $ComputerName,
        [int]$Port = 443,
        [int]$WarningDays = 60,
        [int]$CriticalDays = 30,
        [string[]]$WarningAlgorithm = ('sha1RSA'),
        [string[]]$CriticalAlgorithm = ('md5RSA'),
        [int]$CriticalKeySize = 1024,
        [int]$WarningKeySize = 2048
    )

    $NetCertificate = Get-NetCertificate -ComputerName $ComputerName -Port $Port
    $CertificateProperties = @{
        ComputerName       = $ComputerName + ':' + $Port
        FileName           = 'N/A'
        Subject            = $NetCertificate.Subject
        SignatureAlgorithm = $NetCertificate.SignatureAlgorithm.FriendlyName
        NotBefore          = $NetCertificate.NotBefore
        NotAfter           = $NetCertificate.NotAfter
        Days               = ($NetCertificate.NotAfter - (Get-Date)).Days
        Thumbprint         = $NetCertificate.Thumbprint
        KeySize            = $NetCertificate.PublicKey.Key.KeySize
    }
    $Certificate = New-Object -TypeName PSObject -Property $CertificateProperties

    #region Check certificate expiration

    # Check certificate is within $WarningDays
    if ($Certificate.NotAfter -le (Get-Date).AddDays($WarningDays) -and $Certificate.NotAfter -gt (Get-Date).AddDays($CriticalDays)) {
        Write-Verbose "Certificate is expiring within $WarningDays days."
        $ValidityPeriodStatus = 'Warning'
        $ValidityPeriodStatusMessage = "Certificate expiring in $($Certificate.Days) days."
    }
    # Check certificate is within $CriticalDays
    elseif ($Certificate.NotAfter -le (Get-Date).AddDays($CriticalDays) -and $Certificate.NotAfter -gt (Get-Date)) {
        Write-Verbose "Certificate is expiring within $CriticalDays days."
        $ValidityPeriodStatus = 'Critical'
        $ValidityPeriodStatusMessage = "Certificate expiring in $($Certificate.Days) days."
    }
    # Check certificate is expired
    elseif ($Certificate.NotAfter -le (Get-Date)) {
        Write-Verbose "Certificate expired: $($Certificate.Days) days."
        $ValidityPeriodStatus = 'Critical'
        $ValidityPeriodStatusMessage = "Certificate expired: $($Certificate.Days) days."
    }
    # Certificate validity period is healthy.
    else {
        Write-Verbose "Certificate is within validity period."
        $ValidityPeriodStatus = 'OK'
        $ValidityPeriodStatusMessage = "Certificate expires in $($Certificate.Days) days."
    }
    #endregion

    #region Check certificate algorithm
    if ($CriticalAlgorithm -contains $Certificate.SignatureAlgorithm) {
        Write-Verbose "Certificate uses critical algorithm."
        $AlgorithmStatus = 'Critical'
        $AlgorithmStatusMessage = "Certificate uses a vulnerable algorithm $($Certificate.SignatureAlgorithm)."
    }
    elseif ($WarningAlgorithm -contains $Certificate.SignatureAlgorithm) {
        Write-Verbose "Certificate uses warning algorithm."
        $AlgorithmStatus = 'Warning'
        $AlgorithmStatusMessage = "Certificate uses the deprecated algorithm $($Certificate.SignatureAlgorithm)."
    }
    else {
        Write-Verbose "Certificate uses acceptable algorithm."
        $AlgorithmStatus = 'OK'
        $AlgorithmStatusMessage = "Certificate uses valid algorithm $($Certificate.SignatureAlgorithm)."
    }
    #endregion

    #region Check MinimumKeySize
    Write-Verbose 'Checking minimum key length.'
    if ($Certificate.KeySize -lt $CriticalKeySize) {
        # Key Size is critical
        Write-Verbose 'Certificate key length is critical.'
        $KeySizeStatus = 'Critical'
        $KeySizeStatusMessage = "Certificate key size $($Certificate.KeySize) is less than $CriticalKeySize."
    }
    elseif ($Certificate.KeySize -lt $WarningKeySize -and $Certificate.KeySize -ge $CriticalKeySize) {
        # Key Size is warning
        Write-Verbose 'Certificate key length is warning.'
        $KeySizeStatus = 'Warning'
        $KeySizeStatusMessage = "Certificate key size $($Certificate.KeySize) is less than $WarningKeySize."
    }
    elseif ($Certificate.KeySize -ge $WarningKeySize) {
        # Key Size is OK
        Write-Verbose 'Certificate key length is OK.'
        $KeySizeStatus = 'OK'
        $KeySizeStatusMessage = "Certificate key size $($Certificate.KeySize) is greater than or equal to $WarningKeySize."
    }
    else {
        # Key Size is OK
        Write-Verbose 'Certificate key length is Unknown.'
        $KeySizeStatus = 'Unknown'
        $KeySizeStatusMessage = "Certificate key size is unknown."
    }
    #endregion
    Write-Verbose 'Adding additional properties to the certificate object.'
    $CertificateProperties = [ordered]@{
        ComputerName                = $ComputerName + ':' + $Port
        FileName = $Certificate.FileName
        Subject                     = $Certificate.Subject
        SignatureAlgorithm          = $Certificate.SignatureAlgorithm
        NotBefore                   = $Certificate.NotBefore
        NotAfter                    = $Certificate.NotAfter
        Days                        = $Certificate.Days
        Thumbprint                  = $Certificate.Thumbprint
        ValidityPeriodStatus        = $ValidityPeriodStatus
        ValidityPeriodStatusMessage = $ValidityPeriodStatusMessage
        AlgorithmStatus             = $AlgorithmStatus
        AlgorithmStatusMessage      = $AlgorithmStatusMessage
        KeySize                     = $Certificate.KeySize
        KeySizeStatus               = $KeySizeStatus
        KeySizeStatusMessage        = $KeySizeStatusMessage
    }
    $Certificate = New-Object -TypeName PSObject -Property $CertificateProperties
    $Certificate
}