Get-UnhealthyCertificateNagios.ps1

<#
.Synopsis
   Get-UnhealhtyCertificateNagios checks the local certificate store or file system for
   unhealthy SSL certificates.
.DESCRIPTION
   Get-UnhealhtyCertificateNagios checks the local certificate store or file system for
   unhealthy SSL certificates. Get-UnhealthyCertificate uses the Get-CertificateHealth
   function from the CertificateHealth module to find certificates that have
   expired or are expiring soon. It also checks for certificates using deprecated
   or vulnerable signature algorithms.
    
    
   This script is designed to work with NSclient++ and Nagios to output in a format
   to be consumed by a Nagios monitoring server. Instructions for configuring the
   NSclient++ and Nagios server check are included.
 
   The check defaults to check the LocalMachine personal certificate store for
   certificates expiring with 30-60 days. You can also check alternate certificate
   paths by specifying a different $CertificatePath. You can adjust the amount
   of days before a certificate is considered to be in a warning or critical state.
 
   Pre-requisites:
    * NSclient++ installed on Windows box.
    * check_nrpe check configured on Nagios server.
 
   Usage with NSClient++
   ---------------------
   Add an external command to your nsclient.ini:
    
   PSCheckCertificate=cmd /c echo Import-Module scripts\CertificateHealth\CertificateHealth.psm1 ; Get-UnhealthyCertificateNagios ; exit($lastexitcode) | powershell.exe -command -
 
   If you'd like to create a global exclusion list to not be monitored, add them to the
   ExcludedThumbprint.txt at the root of the module and set your nsclient.ini to below:
 
   PSCheckCertificate=cmd /c echo Import-Module scripts\CertificateHealth\CertificateHealth.psm1 ; Get-UnhealthyCertificateNagios -ExcludedThumbprint $ExcludedThumbprint ; exit($lastexitcode) | powershell.exe -command -
 
   Create a nagios service check:
   $USER1$/check_nrpe -H $HOSTADDRESS$ -u -t 90 -c $ARG1$
   ($ARG1$ = PSCheckCertificate)
 
.NOTES
   Created by: Jason Wasser
   Modified: 1/14/2016 10:17:58 AM
 
   Version 1.5
 
   Changelog:
    v 1.5
     * fixed - missing $WarningKeySize and $CriticalKeySize when calling Get-CertificateHealth
    v 1.4
     * Added key size check
    v 1.3
     * Script renamed to use PowerShell approved verb.
     * Script now part of CertificateHealth module and uses associated functions.
    v 1.2
     * Added Hashing Algorithm to prepare for sha1 deprecation.
    v 1.0
     * Initial Script
.PARAMETER ComputerName
    Specify a remote computer or default to local computer.
.PARAMETER WarningDays
    Specify the amount of days before the certificate expiration should be in
    warning state.
.PARAMETER CriticalDays
    Specify the amount of days before the certificate expiration should be in
    critical state.
.PARAMETER CertificatePath
    Specify the path to the certificate store.
.PARAMETER ExcludedThumbprint
    Array of thumbprints of certificates that should be excluded from being checked.
    This would be used if there is a certificate that is expired, but do not need
    to be notified about it.
.PARAMETER WarningAlgorithm
   Array of algorithms that are deprecated.
.PARAMETER CriticalAlgorithm
   Array of algorithms with known vulnerabilities.
.PARAMETER CritialKeySize
   Certificates with key size less than this value will be considered critical.
.PARAMETER WarningKeySize
   Certificates with key size less than this value and greater than the CriticalKeySize
   will be considered warning.
.EXAMPLE
   Get-UnhealthyCertificates
   Checks the computer personal certificate store for unhealthy certificates.
.LINK
   https://gallery.technet.microsoft.com/scriptcenter/Certificate-Health-b646aeff
#>

#Requires -Version 2.0
function Get-UnhealthyCertificateNagios 
    {
    [CmdletBinding()]
    Param
    (
        # Name of the server, defaults to local
        [Parameter(Mandatory=$false,
                    ValueFromPipelineByPropertyName=$true,
                    Position=0)]
        [string]$ComputerName=$env:COMPUTERNAME,
        [int]$returnStateOK = 0,
        [int]$returnStateWarning = 1,
        [int]$returnStateCritical = 2,
        [int]$returnStateUnknown = 3,
        [int]$WarningDays = 60,
        [int]$CriticalDays = 30,
        [string[]]$Path = 'Cert:\LocalMachine\My',
        [string[]]$ExcludedThumbprint,#=@('DFE816240B40151BBCD7529D4C55627A8CE1671C')
        [string[]]$WarningAlgorithm=('sha1RSA'),
        [string[]]$CriticalAlgorithm=('md5RSA'),
        [int]$CriticalKeySize=1024,
        [int]$WarningKeySize=2048,
        [switch]$Recurse=$false
    )

    Begin
    {
    }
    Process
    {
    
        # Get the certificates from the specified computer.
        try {
            $Certificates = Get-CertificateHealth -Path $Path -WarningDays $WarningDays -CriticalDays $CriticalDays -WarningAlgorithm $WarningAlgorithm -CriticalAlgorithm $CriticalAlgorithm -ExcludedThumbprint $ExcludedThumbprint -WarningKeySize $WarningKeySize -CriticalKeySize $CriticalKeySize -Recurse:([bool]$Recurse.IsPresent) -ErrorAction Stop
            }
        # Catch all exceptions
        catch {
            Write-Output "Unable to get certificates from $ComputerName.|" ; exit $returnStateUnknown
            }
    
        # Filter warning and critical certificates.
        $WarningCertificates = $Certificates | Where-Object -FilterScript {$_.ValidityPeriodStatus -eq 'Warning' -or $_.AlgorithmStatus -eq 'Warning' -or $_.KeySizeStatus -eq 'Warning'}
        $CriticalCertificates = $Certificates | Where-Object -FilterScript {$_.ValidityPeriodStatus -eq 'Critical' -or $_.AlgorithmStatus -eq 'Critical' -or $_.KeySizeStatus -eq 'Critical'}

        # If we have either warning or critical certificates, generate list and output status code.
        if ($WarningCertificates -or $CriticalCertificates) {
            
            # If we have critical AND warning certificates, generate list and output status code.
            if ($CriticalCertificates -and $WarningCertificates) {
                Write-Verbose 'Critical certificates and warning certificates found.'
                
                if ($CriticalCertificates.Count) {
                    $CertificatesMessage = "$($CriticalCertificates.Count) Critical Certificates found:`n"
                    }
                else {
                    $CertificatesMessage = "Critical Certificate found:`n"
                    }

                foreach ($CriticalCertificate in $CriticalCertificates) {
                    $CertificatesMessage += "$($CriticalCertificate.Subject) `($($CriticalCertificate.SignatureAlgorithm) $($CriticalCertificate.KeySize) bits`) expires $($CriticalCertificate.NotAfter) $($CriticalCertificate.Days) days.`n"
                    }

                if ($WarningCertificates.Count) {
                    $CertificatesMessage += "$($WarningCertificates.Count) Warning Certificates found:`n"
                    }
                else {
                    $CertificatesMessage += "Warning Certificate found:`n"
                    }

                foreach ($WarningCertificate in $WarningCertificates) {
                    $CertificatesMessage += "$($WarningCertificate.Subject) `($($WarningCertificate.SignatureAlgorithm) $($WarningCertificate.KeySize) bits`) expires $($WarningCertificate.NotAfter) $($WarningCertificate.Days) days.`n"
                    }
                Write-Output "$CertificatesMessage|" ; exit $returnStateCritical
                }

            # If we have only critical certificates.
            elseif ($CriticalCertificates) {
                Write-Verbose 'Critical certificates found.'
                
                
                if ($CriticalCertificates.Count) {
                    $CertificatesMessage = "$($CriticalCertificates.Count) Critical Certificates found:`n"
                    }
                else {
                    $CertificatesMessage = "Critical Certificate found:`n"
                    }

                foreach ($CriticalCertificate in $CriticalCertificates) {
                    $CertificatesMessage += "$($CriticalCertificate.Subject) `($($CriticalCertificate.SignatureAlgorithm) $($CriticalCertificate.KeySize) bits`) expires $($CriticalCertificate.NotAfter) $($CriticalCertificate.Days) days.`n"
                    }
                Write-Output "$CertificatesMessage|" ; exit $returnStateCritical
                }
            # If we have only warning certificates.
            elseif ($WarningCertificates) {
                Write-Verbose 'Warning certificates found.'
                
                if ($WarningCertificates.Count) {
                    $CertificatesMessage += "$($WarningCertificates.Count) Warning Certificates found:`n"
                    }
                else {
                    $CertificatesMessage += "Warning Certificate found:`n"
                    }

                foreach ($WarningCertificate in $WarningCertificates) {
                    $CertificatesMessage += "$($WarningCertificate.Subject) `($($WarningCertificate.SignatureAlgorithm) $($WarningCertificate.KeySize) bits`) expires $($WarningCertificate.NotAfter) $($WarningCertificate.Days) days.`n"
                    }
                Write-Output "$CertificatesMessage|" ; exit $returnStateWarning
                }
            else {}
            }
        else {
            # No problems found
            Write-Output "Certificates OK.|" ; exit $returnStateOK
            }
    }
    End
    {
    }
}