Mastering Certificate Expiration Alerts with PowerShell for Enhanced IT Security

Key takeaways

  • Automated alerts: The script provides automated alerts for certificates nearing expiration.
  • Customizable parameters: Users can set parameters for expiration time frames and self-signed certificate exclusion.
  • Enhanced security: Timely alerts help maintain security by preventing expired certificate-related vulnerabilities.
  • Compatibility and requirements: Supports Windows 7 and Server 2008 onwards, with specific PowerShell version and privilege requirements.
  • Scalability: More scalable and customizable compared to GUI-based certificate management tools.
  • Proactive compliance: Aids in maintaining compliance by ensuring certificates are renewed on time.
  • Integration with MSP tools: Can be integrated with MSP solutions like NinjaOne for comprehensive IT management. 

Managing digital certificates is a crucial aspect of IT security and compliance. Overlooking certificate expiration can lead to significant security risks, system outages, and loss of trust. A proactive approach to certificate management is essential in maintaining the integrity and reliability of IT systems.

Background

This PowerShell script is a versatile tool for IT professionals and Managed Service Providers (MSPs). It alerts users about local certificates nearing expiration, with options to ignore self-signed, long-expired, or very short-term certificates. This script is particularly relevant in environments where certificate expiry can cause disruptions or security vulnerabilities. 

The script:

<#
.SYNOPSIS
    Alerts when a local certificate will expire in a configurable number of days. Can optionally ignore self-signed certificates, certificates that have been expired for a long time and certificates that were only valid for an extremely short time frame.
.DESCRIPTION
    Alerts when a local certificate will expire in a configurable number of days. 
    Can optionally ignore self-signed certificates, certificates that have been expired for a long time 
    and certificates that were only valid for an extremely short time frame.
.EXAMPLE
    (No Parameters)
    
    Checking for certificates that were valid before 10/10/2023 09:07:23 and will expire before 11/11/2023 09:07:23.
    No Certificates were found with an expiration date before 11/11/2023 09:07:23 and after 07/13/2023 09:07:23.

PARAMETER: -DaysUntilExpiration "ReplaceWithNumber"
    Alerts if a certificate is set to expire within the specified number of days.
.EXAMPLE
    -DaysUntilExpiration "366"
    
    Checking for certificates that were valid before 10/10/2023 09:08:14 and will expire before 10/12/2024 09:08:14.

    WARNING: Expired Certificates found!

    ### Expired Certificates ###

    SerialNumber                     HasPrivateKey ExpirationDate        Subject
    ------------                     ------------- --------------        -------
    0AA60783EBB5076EBC2D12DA9B04C290         False 6/10/2024 4:59:59 PM  CN=Insecure.Com LLC, O=Insecure.Com...
    619DCC976458E38D471DC3DCE3603C2C          True 3/29/2024 10:19:00 AM CN=KYLE-SRV22-TEST.test.lan
    0AA60783EBB5076EBC2D12DA9B04C290         False 6/10/2024 4:59:59 PM  CN=Insecure.Com LLC, O=Insecure.Com...
    7D5FC733E3A8CF9344CDDFC0AB01CCB9          True 4/9/2024 9:53:53 AM   CN=KYLE-SRV22-TEST.test.lan
    4EDC0A79D6CD5A8D4D1E3705BC20C206          True 4/9/2024 9:58:06 AM   CN=KYLLE-SRV22-TEST.test.lan

PARAMETER: -MustBeValidBefore "ReplaceWithNumber"
    Only alert on certificates that are older than X days. This is primarily to silence alerts about certificates that were only valid for 24 hours in their entire lifetime.

PARAMETER: -Cutoff "ReplaceWithNumber"
    Don't alert on certificates that have been expired for longer than X days (default is 91 days).

PARAMETER: -IgnoreSelfSignedCerts
    Ignore certificates where the subject of the certificate and the issuer of the certificate are identical.

.OUTPUTS
    None
.NOTES
    Minimum OS Architecture Supported: Windows 7, Server 2008
    Release Notes: Initial Release
By using this script, you indicate your acceptance of the following legal terms as well as our Terms of Use at https://www.ninjaone.com/terms-of-use.
    Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms. 
    Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party. 
    Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library or website belonging to or under the control of any other software provider. 
    Warranty Disclaimer: The script is provided “as is” and “as available”, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations. 
    Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks. 
    Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script. 
    EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).
#>

[CmdletBinding()]
param (
    [Parameter()]
    [String]$ExpirationFromCustomField = "certExpirationAlertDays",
    [Parameter()]
    [int]$DaysUntilExpiration = 30,
    [Parameter()]
    [int]$MustBeValidBefore = 2,
    [Parameter()]
    [int]$Cutoff = 91,
    [Parameter()]
    [Switch]$IgnoreSelfSignedCerts = [System.Convert]::ToBoolean($env:ignoreSelfSignedCerts)
)
begin {
    # Retrieve script variables from the dynamic script form.
    if ($env:expirationFromCustomFieldName -and $env:expirationFromCustomFieldName -notlike "null") { $ExpirationFromCustomField = $env:expirationFromCustomFieldName }
    if ($env:daysUntilExpiration -and $env:daysUntilExpiration -notlike "null") { $DaysUntilExpiration = $env:daysUntilExpiration }
    if ($env:certificateMustBeOlderThanXDays -and $env:certificateMustBeOlderThanXDays -notlike "null") { $MustBeValidBefore = $env:certificateMustBeOlderThanXDays }
    if ($env:skipCertsExpiredForMoreThanXDays -and $env:skipCertsExpiredForMoreThanXDays -notlike "null") { $Cutoff = $env:skipCertsExpiredForMoreThanXDays }

    function Test-IsElevated {
        $id = [System.Security.Principal.WindowsIdentity]::GetCurrent()
        $p = New-Object System.Security.Principal.WindowsPrincipal($id)
        $p.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)
    }

    # If using the custom field option, check for the default value and replace it if necessary.
    if ($PSVersionTable.PSVersion.Major -gt 2) {
        $CustomField = Ninja-Property-Get -Name $ExpirationFromCustomField 2>$Null
    }

    if ($CustomField -and $DaysUntilExpiration -eq 30 -and (Test-IsElevated) -and $PSVersionTable.PSVersion.Major -gt 2) {
        Write-Host "Retrieved value of $CustomField days from Custom Field $ExpirationFromCustomField. Using it for expiration value."
        $DaysUntilExpiration = $CustomField
    }
    elseif (-not (Test-IsElevated) -or $PSVersionTable.PSVersion.Major -le 2) {
        Write-Warning "Skipping CustomField retrieval due to either incompatible PowerShell version or lack of elevation."
    }
}
process {
    # Calculate expiration and cutoff dates.
    $ExpirationDate = (Get-Date "11:59pm").AddDays($DaysUntilExpiration)
    $CutoffDate = (Get-Date "12am").AddDays(-$Cutoff)
    $MustBeValidBeforeDate = (Get-Date "12am").AddDays(-$MustBeValidBefore)

    # Retrieve all certificates.
    $Certificates = Get-ChildItem -Path "Cert:\" -Recurse

    Write-Host "Checking for certificates that were valid before $MustBeValidBeforeDate and will expire before $ExpirationDate."
    
    # Filter down to certificates that are expired in our desired date range
    $ExpiredCertificates = $Certificates | Where-Object { $_.NotAfter -le $ExpirationDate -and $_.NotAfter -gt $CutoffDate -and $_.NotBefore -lt $MustBeValidBeforeDate }

    # If we're asked to ignore self signed certs we'll filter them out
    if ($IgnoreSelfSignedCerts -and $ExpiredCertificates) {
        Write-Host "Removing Self-Signed certificates from list."
        $ExpiredCertificates = $ExpiredCertificates | Where-Object { $_.Subject -ne $_.Issuer }
    }

    if ($ExpiredCertificates) {
        Write-Host ""
        Write-Warning "Expired Certificates found!"
        Write-Host ""

        $Report = $ExpiredCertificates | ForEach-Object {
            # Subject can be a long property, we'll truncate it to maintain readability
            New-Object PSObject -Property @{
                SerialNumber   = $_.SerialNumber
                HasPrivateKey  = $_.HasPrivateKey
                ExpirationDate = $_.NotAfter
                Subject        = if ($_.Subject.Length -gt 35) { $_.Subject.Substring(0, 35) + "..." }else { $_.Subject }
            }
        }

        Write-Host "### Expired Certificates ###"
        $Report | Format-Table -AutoSize | Out-String | Write-Host

        exit 1
    }
    else {
        Write-Host "No Certificates were found with an expiration date before $ExpirationDate and after $CutoffDate."
    }
}
end {
    
    
    
}

 

Access over 300+ scripts in the NinjaOne Dojo

Get Access

Detailed breakdown

The script operates in a few distinct stages:

  • Initialization: It begins by setting default parameters, such as the number of days until certificate expiration and various cutoffs. These can be overridden by environment variables.
  • Environment checks: The script checks for necessary privileges and PowerShell version compatibility, adjusting its behavior accordingly.
  • Data processing: It retrieves all certificates from the local store and filters them based on expiration, validity period, and whether they are self-signed, as per the provided parameters.
  • Reporting: If expired certificates are found, it generates a report listing their details, otherwise, it indicates no concerning certificates were found.

Visual aids like flowcharts could effectively illustrate these stages, making the process more comprehensible.

Potential use cases

Consider an MSP overseeing an organization’s IT infrastructure. They deploy this script to regularly scan for certificates nearing expiration. This early alert system enables timely renewals, avoiding service interruptions or security breaches.

Comparisons

This PowerShell approach is more customizable and integrated than GUI-based certificate management tools. It allows for automation and is more scalable for large enterprises compared to manual checks.

FAQs

  • How does the script determine which certificates to alert on?
    The script uses parameters like expiration date, validity period, and self-signed status to filter certificates.
  • Can this script run on any Windows machine?
    It supports Windows 7 and Server 2008 onwards but requires certain privileges and PowerShell versions for full functionality.
  • Is it possible to customize the alert criteria?
    Yes, the script allows for customizing parameters like days until expiration and cutoff periods.

Implications

Failure to renew certificates can lead to security vulnerabilities and loss of customer trust. This script helps maintain an optimal security posture by proactively managing certificate renewals.

Recommendations

  • Regularly schedule the script to run, ensuring timely alerts.
  • Customize the parameters to fit the specific needs of your IT environment.
  • Ensure appropriate privileges and environment settings for accurate execution.

Final thoughts

In the context of comprehensive IT management, tools like NinjaOne can augment the capabilities of this script. NinjaOne offers integrated solutions that can work alongside such scripts to streamline IT operations, enhance security, and ensure compliance.

Next Steps

Building an efficient and effective IT team requires a centralized solution that acts as your core service deliver tool. NinjaOne enables IT teams to monitor, manage, secure, and support all their devices, wherever they are, without the need for complex on-premises infrastructure.

Learn more about NinjaOne Remote Script Deployment, check out a live tour, or start your free trial of the NinjaOne platform.

Categories:

You might also like

×

See NinjaOne in action!

By submitting this form, I accept NinjaOne's privacy policy.

NinjaOne Terms & Conditions

By clicking the “I Accept” button below, you indicate your acceptance of the following legal terms as well as our Terms of Use:

  • Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms.
  • Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party.
  • Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library belonging to or under the control of any other software provider.
  • Warranty Disclaimer: The script is provided “as is” and “as available”, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations.
  • Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks.
  • Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script.
  • EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).