PowerShell - Get a list of Used and Unused SSL files (based on SSL profile usage)

Problem this snippet solves:

There are many times where being able to determine which SSL files on the BIG-IP are or are not being used would be very beneficial (especially when trying to do some spring cleaning or old configurations).

So this script aims to provide a simple way to use PowerShell and iControlRest to determine which SSL (cert and key) files are or are not being used in any SSL profiles (client or server).

How to use this snippet:

Prerequisites:

  • You will need to be on BIG-IP v11.4 or newer, as that's when iControlRest was introduced.
  • You will also need a Windows machine and PowerShell v3 or newer (v4 or v5).

Paste this code into your PowerShell console and then run it with at least the hostname (or IP) of your BIG-IP, and it will prompt you for credentials and return the list of used and unused ssl cert and key files.

Note: If you use an IP address, you should really include the

-IgnoreCertErrors
flag as well, since it won't work by default without a valid cert.

Examples:

  • Get-F5SslCertKeyFilesByStatus mybigip.example.com;
  • Get-F5SslCertKeyFilesByStatus 10.10.10.10 -IgnoreCertErrors;
  • Get-F5SslCertKeyFilesByStatus -f5HostIp mybigip.example.com;
  • Get-F5SslCertKeyFilesByStatus -f5HostIp 10.10.10.10 -IgnoreCertErrors;
  • $cred = (Get-Credentials); Get-F5SslCertKeyFilesByStatus -f5HostIp 10.10.10.10 -f5Cred $cred -IgnoreCertErrors;

Code :

function Get-F5SslCertKeyFilesByStatus {
    [CmdletBinding()]
    Param($f5HostIp, $f5Cred, [switch]$IgnoreCertErrors = $false)
    Begin {
        Write-Verbose "Get-F5SslCertKeyFilesByStatus";

        if ($IgnoreCertErrors) {
            Write-Verbose "  Ignoring certficate errors";
            Add-Type @"
                using System.Net;
                using System.Security.Cryptography.X509Certificates;
                public class TrustAllCertsPolicy : ICertificatePolicy {
                    public bool CheckValidationResult(
                        ServicePoint srvPoint, X509Certificate certificate,
                        WebRequest request, int certificateProblem) {
                        return true;
                    }
                }
"@;
            [System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy;
        }
 
        function Invoke-F5Rest ($path) {
            $url = "https://$($f5HostIp)/mgmt/tm$path";
            Write-Verbose "    GET: '$url'";
            $ret = @($(Invoke-RESTMethod -Method GET -Uri $url -Credential $f5Cred -Verbose:$false).items);
            Write-Verbose "      Returned $($ret.Count) items";
            $ret;
        }
    }
    Process {
        # Grab all the stuff we'll need from the BIG-IP
        Write-Verbose "  Grabbing data from BIG-IP";
        $clientSslProfiles  = Invoke-F5Rest '/ltm/profile/client-ssl?$select=name,fullPath,caFile,cert,chain,clientCertCa,key,proxyCaCert,proxyCaKey,certKeyChain';
        $serverSslProfiles  = Invoke-F5Rest '/ltm/profile/server-ssl?$select=name,fullPath,caFile,cert,chain,key';
        $certFiles          = Invoke-F5Rest '/sys/crypto/cert';
        $keyFiles           = Invoke-F5Rest '/sys/crypto/key';
        $crlFiles           = Invoke-F5Rest '/sys/crypto/crl';
 
        # Process the data
        Write-Verbose "  Processing the returned data";
        $usedCerts          = @(($clientSslProfiles | %{ @($_.caFile, $_.cert, $_.chain, $_.clientCertCa, $_.proxyCaCert) + $($_.certKeyChain | %{ $_.cert, $_.chain; }) }) `
                                    + ($serverSslProfiles | %{ @($_.cert, $_.caFile, $_.chain) } ) `
                                    | Select-Object -Unique);
        Write-Verbose "    Used certs: $($usedCerts.Count)";
        $usedKeys           = @(($clientSslProfiles | %{ @($_.key, $_.proxyCaKey) + $($_.certKeyChain | %{ $_.key }) }) `
                                    + ($serverSslProfiles | %{ $_.key }) `
                                    | Select-Object -Unique);
        Write-Verbose "    Used keys: $($usedCerts.Count)";

        $usedCertFiles      = $certFiles | ?{ $usedCerts -contains $_.fullPath }    | Select-Object -ExpandProperty fullPath;
        $unusedCertFiles    = $certFiles | ?{ $usedCerts -notcontains $_.fullPath } | Select-Object -ExpandProperty fullPath;
        $usedKeyFiles       = $keyFiles  | ?{ $usedKeys -contains $_.fullPath }     | Select-Object -ExpandProperty fullPath;
        $unusedKeyFiles     = $keyFiles  | ?{ $usedKeys -notcontains $_.fullPath }  | Select-Object -ExpandProperty fullPath;
 
        # Return lists
        [PSCustomObject]@{
            Unused = [PSCustomObject]@{
                CertFiles = $unusedCertFiles;
                KeyFiles  = $unusedKeyFiles;
            };
            Used = [PSCustomObject]@{
                CertFiles = $usedCertFiles;
                KeyFiles  = $usedKeyFiles;
            };
        };
    }
}

Tested this on version:

11.5
Updated Jun 06, 2023
Version 2.0
  • What version are you running? If you set the variables manually and step through the commands, do you see data coming back from the REST requests? You could also try running '$VerbosePreference = "Continue"' and then trying again. You should see verbose logging on screen of the amount of data received from the REST commands.
  • Sorry for the delay life got in the way. I launch the script using the following syntax. .\Get-F5SslCertKeyFilesByStatus-f5HostIp 10.x.x.x -IgnoreCertErrors No errors displayed on the screen. I am running powershell version 4.0 and 11.6.hf5 on the LTM.
  • William: I've updated the code block. Try using that instead and also adding the "-Verbose" flag. You should get some logging that may help determine what's happening.
  • Thanks Michael I know this is operator error. I tested the update and got the same result with -Verbose set. So I commented the first line and the last brace on the end out and the get prompted for user ID and password for each GET. I do get a count of cert key and crl but no data under the used/unused headers.
  • Unfortunately I don't have an 11.6 device to test this on, but you may be able to run the code step by step and see what data you get at each step.
  • Hi Michael,

     

    I tried to run your script on Big-IP v13 but it does not get any data back. The code above have been saved as a .ps1 file and i get it trough "Get-F5SslCertKeyFilesByStatus 10.xxx.xxx.xxx -IgnoreCertErrors".

     

    It tries to get data because i receive a logon prompt 7 or 8 times and then returns the empty values (see picture).

     

     

    Any idea if it still works or is the version to old? (maybe new Rest commands)