Back to blog
SRE & Performance September 8, 2026

Automated SSL/TLS Certificate Expiry Monitoring: Preventing Security Outages and Handshake Errors

Automate WhatsApp Alerts
Start Free ➔

Automated SSL/TLS Certificate Expiry Monitoring: Preventing Security Outages and Handshake Errors

An expired X.509 TLS certificate instantly transforms healthy, highly available infrastructure into an inaccessible failure state. Web browsers block user traffic with ERR_CERT_DATE_INVALID, automated API clients terminate sessions with SSLHandshakeException, and microservices fail with certificate verify failed errors.

Despite automated Certificate Authorities (Let's Encrypt, ZeroSSL, AWS Certificate Manager), certificate outages remain a persistent cause of high-severity production incidents. Automation failures frequently occur when a certificate is renewed successfully by an ACME client on disk but fails to reload into the memory of the ingress proxy (Nginx, Envoy, HAProxy), or when DNS propagation delays cause ACME DNS-01 challenge validation to fail silently.

Site Reliability Engineers must monitor the served certificate on the wire across all global endpoints, load balancers, and SNI hostnames.

Client Application / Browser
   │
   ├── 1. Anycast DNS Resolution (A / AAAA / CNAME)
   │
   ▼
Edge Proxy / Cloud Load Balancer (ALB / Cloudflare / Envoy)
   │
   ├── 2. TLS 1.3 Handshake & Server Name Indication (SNI)
   │
   ├── 3. X.509 Certificate Chain Transmission (Leaf ──► Intermediate ──► Root)
   │
   ▼
Client Cryptographic Validation
   ├── [VALID]: NotBefore <= CurrentTime <= NotAfter ──► Decrypt & Transfer HTTP Payload
   └── [EXPIRED / INVALID SAN]: Terminate Connection ──► Immediate P1 Outage

1. Why Certificate Monitoring Must Inspect the Wire

A common operational anti-pattern is monitoring certificates by reading .crt or .pem files on a local filesystem or querying a cloud provider API. Disk-based checks miss critical operational failure modes:

  • Missing Process Reloads: cert-manager updates the Kubernetes Secret on disk, but the Nginx Ingress or Envoy process never received a SIGHUP or hot reload signal, continuing to serve the expired in-memory certificate.
  • Intermediate Chain Omissions: The leaf certificate is valid, but the web server failed to send the intermediate Certificate Authority (CA) certificate. Modern desktop browsers may backfill intermediates via Authority Information Access (AIA), but mobile clients, cURL, and Go/Node.js API workers immediately throw handshake errors.
  • SNI and Multi-Tenant Mismatches: When hundreds of domains share a single load balancer IP, a client sending an unsupported or unconfigured SNI header receives the default fallback certificate, causing SAN mismatch failures.
  • Split-Horizon and Regional Inconsistencies: The primary US-East load balancer receives the renewed certificate, but the EU-Central failover cluster or secondary CDN edge continues serving the old certificate due to propagation lag.

Testing your live certificate expiration, SANs, and chain validity right now? Inspect any public domain instantly with our interactive SSL Inspector Tool.


2. The SRE Certificate Expiry Alerting Policy

To eliminate emergency midnight rotations, establish an automated alerting threshold matrix based on the minimum remaining certificate lifetime ($T_{\text{remaining}}$):

$$ T_{\text{remaining}} = T_{\text{NotAfter}} - T_{\text{now}} $$

For multi-host fleets and Kubernetes clusters, calculate fleet-wide alert triggers on the minimum value across all endpoints:

$$ T_{\text{fleet_min}} = \min(T_1, T_2, \dots, T_n) $$

SRE Certificate Validity Threshold Matrix

Remaining Validity ($T_{\text{remaining}}$)Operational StatusSRE Action RequiredAlert Severity
$> 30\text{ Days}$HealthyNormal continuous monitoringNone
$15 - 30\text{ Days}$WarningConfirm automated ACME renewal pipeline triggeredLow (Slack / Teams)
$7 - 14\text{ Days}$At RiskAudit ACME challenge logs and cert-manager statusMedium (Ticket)
$3 - 7\text{ Days}$CriticalExecute manual certificate rotation runbookHigh (Page On-Call)
$< 72\text{ Hours}$EmergencyImmediate break-glass rotation; notify engineering leadP1 (Urgent Page)
$\le 0\text{ Hours}$Outage ConditionIncident response activated; client traffic blockedSEV-1 Outage

3. Deep Certificate Inspection with OpenSSL

Use the openssl CLI to extract full cryptographic metadata, expiration timestamps, Subject Alternative Names (SANs), and intermediate chains directly from live network sockets.

3.1 Extracting Expiration Date and Subject Alternative Names

Always specify the -servername flag to ensure the remote proxy routes the TLS handshake to the correct virtual host:

HOST="api.example.com"

echo | openssl s_client \
  -connect "${HOST}:443" \
  -servername "${HOST}" \
  -showcerts 2>/dev/null | \
openssl x509 \
  -noout \
  -dates \
  -subject \
  -issuer \
  -ext subjectAltName

3.2 Calculating Remaining Validity in Unix Seconds

# Extract expiration date and convert to seconds remaining
EXPIRY_DATE=$(echo | openssl s_client -connect "${HOST}:443" -servername "${HOST}" 2>/dev/null | \
  openssl x509 -noout -enddate | cut -d= -f2)

EXPIRY_EPOCH=$(date -d "${EXPIRY_DATE}" +%s)
CURRENT_EPOCH=$(date +%s)
DAYS_REMAINING=$(( (EXPIRY_EPOCH - CURRENT_EPOCH) / 86400 ))

echo "Certificate for ${HOST} expires in ${DAYS_REMAINING} days (${EXPIRY_DATE})"

4. Production Automated Monitoring Script

Deploy this production-ready Bash monitoring probe to automated cron jobs, CI/CD pipelines, or container sidecars to output Prometheus-compatible metrics and alert on threshold breaches:

#!/usr/bin/env bash
# Production SRE SSL/TLS Certificate Expiry Probe
set -euo pipefail

TARGET_HOST="${1:-example.com}"
TARGET_PORT="${2:-443}"
SNI_NAME="${3:-$TARGET_HOST}"
TIMEOUT_SECONDS=5

# Fetch certificate from network endpoint
RAW_CERT=$(timeout "${TIMEOUT_SECONDS}" openssl s_client \
  -connect "${TARGET_HOST}:${TARGET_PORT}" \
  -servername "${SNI_NAME}" \
  -showcerts </dev/null 2>/dev/null) || {
    echo "ERROR: Failed to establish TLS connection to ${TARGET_HOST}:${TARGET_PORT} (SNI: ${SNI_NAME})"
    exit 2
}

# Parse expiration date
END_DATE_STR=$(echo "$RAW_CERT" | openssl x509 -noout -enddate 2>/dev/null | cut -d= -f2)
if [[ -z "$END_DATE_STR" ]]; then
  echo "ERROR: Unable to parse X.509 enddate for ${SNI_NAME}"
  exit 2
fi

EXPIRY_EPOCH=$(date -d "${END_DATE_STR}" +%s)
CURRENT_EPOCH=$(date +%s)
SECONDS_REMAINING=$(( EXPIRY_EPOCH - CURRENT_EPOCH ))
DAYS_REMAINING=$(( SECONDS_REMAINING / 86400 ))

# Output Prometheus-compatible metric
cat <<EOF
# HELP ssl_certificate_expiry_seconds Timestamp of certificate expiration in seconds remaining
# TYPE ssl_certificate_expiry_seconds gauge
ssl_certificate_expiry_seconds{host="${TARGET_HOST}",sni="${SNI_NAME}",port="${TARGET_PORT}"} ${SECONDS_REMAINING}
# HELP ssl_certificate_expiry_days Days remaining until certificate expiration
# TYPE ssl_certificate_expiry_days gauge
ssl_certificate_expiry_days{host="${TARGET_HOST}",sni="${SNI_NAME}",port="${TARGET_PORT}"} ${DAYS_REMAINING}
EOF

# Exit with alert status
if (( DAYS_REMAINING < 3 )); then
  echo "CRITICAL: Certificate for ${SNI_NAME} expires in ${DAYS_REMAINING} days!" >&2
  exit 1
elif (( DAYS_REMAINING < 14 )); then
  echo "WARNING: Certificate for ${SNI_NAME} expires in ${DAYS_REMAINING} days." >&2
  exit 0
else
  echo "OK: Certificate for ${SNI_NAME} is valid for ${DAYS_REMAINING} days." >&2
  exit 0
fi

Converting recurring certificate monitoring schedules into standard cron syntax? Build and validate your monitoring cron expressions using our Cron Translator.


5. Prometheus and Blackbox Exporter Integration

The standard cloud-native pattern for monitoring public and internal certificates is the Prometheus Blackbox Exporter using the http_2xx or tcp_connect probe modules.

5.1 Prometheus Blackbox Exporter Configuration

# blackbox.yml
modules:
  https_tls_probe:
    prober: http
    timeout: 5s
    http:
      method: GET
      fail_if_ssl: false
      fail_if_not_ssl: true
      tls_config:
        insecure_skip_verify: false

5.2 Prometheus Alerting Rules

# rules/ssl_alerts.yml
groups:
  - name: ssl_certificate_alerts
    rules:
      - alert: SSLCertificateExpiringSoon
        expr: probe_ssl_earliest_cert_expiry - time() < 14 * 24 * 3600
        for: 1h
        labels:
          severity: warning
          team: sre
        annotations:
          summary: "TLS Certificate expiring within 14 days for {{ $labels.instance }}"
          description: "The SSL/TLS certificate served by {{ $labels.instance }} expires in {{ $value | humanizeDuration }}. Check automated renewal pipeline."

      - alert: SSLCertificateExpiringCritical
        expr: probe_ssl_earliest_cert_expiry - time() < 3 * 24 * 3600
        for: 10m
        labels:
          severity: critical
          team: on-call
        annotations:
          summary: "EMERGENCY: TLS Certificate expires in under 72 hours for {{ $labels.instance }}"
          description: "The certificate on {{ $labels.instance }} is about to expire ({{ $value | humanizeDuration }} remaining). Immediate rotation required."

6. Kubernetes & cert-manager Expiry Auditing

In Kubernetes clusters managed by cert-manager, monitoring must inspect both the custom resource status and the secret mounted into ingress pods.

# 1. Audit all cert-manager Certificate resources across all namespaces
kubectl get certificate -A -o custom-columns=\
NAMESPACE:.metadata.namespace,\
NAME:.metadata.name,\
READY:.status.conditions[?(@.type=="Ready")].status,\
EXPIRY:.status.notAfter,\
RENEWAL_TIME:.status.renewalTime

# 2. Extract and decode the actual TLS certificate from a specific Secret
kubectl get secret production-tls-secret -n ingress-nginx \
  -o jsonpath='{.data.tls\.crt}' | \
  base64 -d | \
  openssl x509 -noout -dates -subject -issuer

7. Troubleshooting Runbook: Resolving Certificate Failures

When certificate alerts trigger or clients experience TLS handshake rejections, execute this twelve-step diagnostic sequence:

  1. Verify the exact hostname, port, and IP address reported by the failing client.
  2. Execute openssl s_client -connect <host>:443 -servername <host> to inspect the served certificate directly from an external network.
  3. Check NotBefore and NotAfter timestamps to confirm whether the certificate is expired or invalid due to client clock skew.
  4. Inspect Subject Alternative Names (SAN) to confirm the requested domain is explicitly listed.
  5. Verify that intermediate CA certificates are returned in the correct hierarchical order (Leaf $\rightarrow$ Intermediate $\rightarrow$ Root).
  6. Compare certificate serial numbers across multiple geographic regions and load balancers to detect partial deployment rollouts.
  7. Test both IPv4 (curl -4) and IPv6 (curl -6) endpoints to ensure dual-stack proxies serve identical certificates.
  8. Inspect ACME / Let's Encrypt renewal logs for failed HTTP-01 routing or DNS-01 challenge record propagation timeouts.
  9. Confirm that ingress controllers or web servers (Nginx, Envoy, Apache) executed a graceful configuration reload (nginx -s reload).
  10. Validate that Kubernetes cert-manager has not hit rate limits with the upstream Certificate Authority.
  11. Bypass CDN edge caching to ensure the origin shield server is not serving a stale cached certificate to edge nodes.
  12. Calculate allowable downtime and error budget consumption using the SLA Calculator.

8. SRE Certificate Health Matrix

Verification CheckStandard Expected StateFailure IndicatorRoot Cause
Handshake ProtocolTLS 1.3 or TLS 1.2SSL_ERROR_UNSUPPORTED_VERSIONLegacy client or disabled cipher suites
Validity WindowCurrent time between NotBefore & NotAfterCERT_HAS_EXPIREDAutomated renewal failed or did not reload
SAN CoverageExact domain or matching wildcard presentERR_CERT_COMMON_NAME_INVALIDDomain migrated without updating SAN list
Chain CompletenessIntermediate CA present in handshakeSEC_ERROR_UNKNOWN_ISSUERMissing intermediate bundle in web server config
Revocation StatusOCSP Stapling OCSP Response: successfulREVOKED / OCSP TimeoutCA revoked compromised key or OCSP responder down

9. Engineering Implementation Checklist

  • Implement Black-Box Wire Probes: Monitor the certificate served over port 443 across all public and internal hostnames.
  • Enforce SNI Inspection: Ensure monitoring probes pass explicit SNI server names during TLS negotiation.
  • Configure Multi-Tier Alerts: Set warning alerts at 14 days and critical pages at 72 hours remaining validity.
  • Verify Intermediate CA Bundling: Ensure web servers transmit the full certificate chain excluding the root CA.
  • Automate Post-Renewal Reloads: Ensure automated ACME renewal scripts execute seamless proxy reloads (nginx -s reload).
  • Audit Dual-Stack Endpoints: Test certificate validity across both IPv4 and IPv6 Anycast edge addresses.
  • Monitor cert-manager Metrics: Scrape certmanager_certificate_expiration_timestamp_seconds in Kubernetes.
  • Document Emergency Rotation: Maintain break-glass runbooks for manual CA issuance during automated pipeline failures.

Related Security & Reliability Guides

To maintain resilient TLS infrastructure and prevent connection outages, consult these guides:

Zero-Code Uptime Alerts

Stop Finding Out About Outages from Angry Users

Get instant WhatsApp & Discord alerts the second your API, website, or server goes down. Setup in 30 seconds with 60-second checks.

WhatsApp & Discord 60-Second Checks Free Forever Plan
Try Pingzo Free

Know before your users do

Connect official WhatsApp notification channels, Discord webhooks, Telegram bots, and public status pages. Start in 30 seconds.

Create Free Monitor