Automating SSL Certificate Monitoring with Python and SSLyze

Certificate expiry rarely causes a subtle incident. A checkout page, customer portal or API endpoint can start failing within minutes, often while the team is focused on something else. Automating the checks removes the dependence on a calendar reminder and provides a reliable signal before an outage begins.

SSLyze is well suited to this work because it speaks TLS directly and reports certificate details alongside protocol and cipher configuration. Python can wrap each scan, normalise the results, compare them with previous runs and send an alert when a deadline or policy threshold is crossed. This automation should complement, rather than replace, a dependable certificate renewal process.

Australian teams often operate a mixture of .com.au domains, newer .au namespaces, cloud services and on-premises systems across Sydney, Melbourne, Brisbane and regional offices. An inventory must distinguish origin servers from CDN edges because a public hostname can present several certificates. That distinction matters when an apparent expiry is actually an isolated edge-node fault.

Monitoring must also respect local obligations. Where the Privacy Act 1988 applies, keep customer records out of scan results; IP addresses and diagnostic logs can still contain personal information, so apply access controls and sensible retention. The Australian Signals Directorate’s Essential Eight also provides a useful security baseline for the monitoring host, including patching, backups and administrative controls.

What SSLyze can inspect

A certificate scan can expose the leaf certificate’s expiry window, subject, issuer, serial number, public-key algorithm and deployment details. SSLyze can also collect the presented chain and hostname information, giving your Python layer enough context to decide whether an endpoint meets policy rather than merely reporting a date.

Broader TLS scans add protocol support, cipher suites, renegotiation behaviour, compression, session resumption and OCSP stapling. These findings matter because a valid certificate can still sit behind obsolete TLS settings. Keep certificate lifecycle alerts separate from broader security findings so routine upgrades do not obscure an imminent renewal failure.

SSLyze is a scanner, not an authoritative certificate inventory. It sees what a particular connection receives, which may differ by resolver, region or CDN edge. Store the hostname, port, resolved address, scan timestamp and scanner version with every result, then repeat unexpected findings from another network before escalating them.

Designing the monitoring workflow

Begin with a declarative inventory containing each public hostname, port, owning team, environment and renewal method. Record whether DNS-01, a managed load balancer or manual deployment provides the certificate. That metadata turns raw expiry data into an actionable alert and prevents the monitoring job from paging the wrong person.

Run a broad inventory scan once, then schedule routine checks daily. Increase frequency when a certificate enters a defined renewal window, but avoid scanning every endpoint every hour without reason. Most public sites sit behind CDNs and WAFs, so randomise start times slightly to reduce burst traffic and make the job less conspicuous from monitored networks.

A command-line job should behave predictably in every environment. The same preference for repeatable routines appears in specialist software such as the Nikon Coolscan utility, although certificate monitoring belongs in its own isolated service account and dependency environment.

Parsing scanner results with Python

Invoke SSLyze through Python’s subprocess module with an argument list, never a shell string. Give every run a timeout, capture standard error and write JSON to a unique file. A failed TCP connection, TLS handshake or scanner process must produce a monitoring error rather than being mistaken for an expired certificate.

import json
import subprocess
from pathlib import Path

result_file = Path("/var/lib/sslyze/example.com.au.json")
process = subprocess.run(
    [
        "sslyze",
        "--cert_info=example.com.au:443",
        f"--json_out={result_file}",
    ],
    capture_output=True,
    text=True,
    timeout=90,
    check=False,
)

if process.returncode != 0:
    raise RuntimeError(process.stderr or "SSLyze failed")

payload = json.loads(result_file.read_text())

The exact JSON nesting can change between SSLyze releases, so isolate extraction in one adapter function and maintain a fixture-based test for it. Walk the server scan results to find the certificate command result, then emit a stable internal record containing the hostname, expiry date, issuer and hostname status. Store that normalised schema separately from the scanner-specific payload.

Essential monitoring checks

The certificate lifecycle list should cover more than the final expiry date:

  • Expiry thresholds at 30, 14, 7 and 1 day
  • Activation dates, hostname matches and wildcard scope
  • Issuer, chain and public-key algorithm changes
  • Certificate serial changes after renewal
  • OCSP stapling and revocation signals where supported

The transport and job-health list should make configuration drift and monitoring failures visible:

  • TLS 1.2 minimum and TLS 1.3 support
  • Exclusion of obsolete cipher suites and compression
  • Stable hostname, port, resolver and CDN routing
  • Scan completion, runtime and scanner-version changes
  • Separation of network failure from certificate failure

Each alert should state the affected hostname, certificate expiry, days remaining and responsible owner. Include the previous successful scan time so recipients can distinguish an expiring certificate from an endpoint that SSLyze simply could not reach. Preserve enough diagnostic context to investigate the change without attaching an entire verbose scan to every message.

Running the service reliably

Use systemd timers on Linux hosts or cron in a container, and run the scanner as an unprivileged account with a fixed working directory. Store output atomically, apply retention to old JSON files and schedule retries with exponential backoff. A failed job should generate its own alert because silence after a deployment can otherwise look like good news.

Australian sites often depend on NBN connections, with staff also moving between fixed office networks and mobile hotspots during the day. A timeout from one location can be a local broadband problem rather than a certificate fault. Record the source address and compare a retry from a second network before declaring an endpoint down.

Existing operations software can carry the alert. Karl’s Nagios and SNMP monitoring demonstrates how Nagios and SNMP fit together in a home network, and the same approach works for a small business. Expose certificate age and scan freshness as checks, then map them onto the normal notification path.

Put the monitoring service into production

Package the wrapper as a version-controlled command with a small configuration file, an inventory file and a local test endpoint. Add unit tests for expiry calculations and a live canary host with a known renewal date. Keep credentials out of the repository, and use a dedicated API token with permission to send only the required alerts.

Choose the host for reliability rather than raw computing power. A low-power mini PC, cloud instance or small rack server can all work, but power, storage and replacement-part availability differ across the Australian market. Karl’s hardware vendor directory provides a practical reference when the monitoring appliance needs to be replaced or expanded.

Roll out the service in stages: first scan a handful of critical domains, verify the alert wording, then add the remaining services. Publish a runbook that names the certificate owner, renewal lead time and rollback action. Automate collection and comparison while leaving deployment approval with the team controlling each certificate.

Create the inventory today and run the first scheduled scan against your highest-impact .com.au or .au hostname. Confirm that a deliberate test alert reaches the right person, then extend the same tested path to every production endpoint.

Experience

Information Technology Consulting

Independent Practice

Provides IT consulting services focused on infrastructure planning, cloud migration strategy, and systems architecture. Engagements draw on years of hands-on sysadmin and development experience across Linux, Windows, and hybrid environments.

K9 Search & Rescue Volunteer

Ongoing

Active participant in K9 Search & Rescue operations, combining technical logistics skills with field support for canine search teams.

Karl Katzke's Blog

October 2006 – May 2014

Published a long-running personal technology blog covering cloud vs. in-house infrastructure, F# and Mono on OSX, hardware vendor critiques, RAID card performance analysis, and sysadmin storytelling. Notable posts include "When Sysadmins Ruled the Earth" (May 15, 2014) and "Getting Started with F# and Mono on OSX" (December 22, 2012).

Credentials

A small badge icon with a shield shape in muted blue tones on a light background

Systems Administration

Deep experience with Linux (RHEL, SLES, CentOS), high-availability clusters, and STONITH configurations.

A small badge icon with a gear shape in muted blue tones on a light background

Cloud Infrastructure

Practical knowledge of AWS EC2, reserved instances, and cost analysis for cloud vs. on-premises deployments.

A small badge icon with a code symbol in muted blue tones on a light background

Development

Proficient in F#, PHP (Symfony), and cross-platform tooling including Mono and MonoDevelop on OSX.

Studies

F# & Functional Programming

Self-directed, 2012

Explored strongly typed functional programming with F# on OSX using the Mono runtime. Published a detailed getting-started guide covering toolchain setup and cross-platform game development research.

High-Availability & Cluster Management

Professional Development, 2009

Configured and documented crm_mon email alerting for STONITH events on SLES11-HAE clusters, integrating with Nagios monitoring for production environments.

Hardware & Storage Performance

Ongoing

Conducted hands-on benchmarking of SATA/SAS RAID controllers including HighPoint RocketRaid 2740 and LSI/SuperMicro AOC-USASLP2-H8iR, comparing against software RAID configurations.

Skills

A small icon representing a server with clean geometric lines in slate blue

Linux Administration

RHEL, SLES, CentOS — package management, kernel tuning, HA clustering, and monitoring integration.

A small icon representing a cloud shape with clean geometric lines in slate blue

Cloud Architecture

AWS EC2, reserved-instance planning, cost modeling, and hybrid infrastructure strategy.

A small icon representing code brackets with clean geometric lines in slate blue

F# & .NET/Mono

Functional programming on OSX, MonoDevelop toolchain, and cross-platform game-dev exploration.

A small icon representing a database cylinder with clean geometric lines in slate blue

PHP & Symfony

Web application development with the Symfony framework and the broader PHP ecosystem.

A small icon representing a storage drive with clean geometric lines in slate blue

Storage & RAID

SATA/SAS controller evaluation, md RAID configuration, and performance benchmarking.

A small icon representing a shield with clean geometric lines in slate blue

High Availability

Pacemaker, STONITH, crm_mon alerting, and Nagios integration for production cluster monitoring.