Home/Blog/How can I check if a certificate is expired or will expire soon?
Cybersecurity

How can I check if a certificate is expired or will expire soon?

Monitor certificate expiration dates, implement automated alerting, and prevent service disruptions from expired SSL/TLS certificates.

By Inventive HQ Team
How can I check if a certificate is expired or will expire soon?

The Importance of Certificate Expiration Monitoring

When an SSL/TLS certificate expires, HTTPS connections fail. Browsers display security warnings, users can't access the site, and services relying on HTTPS are disrupted. Despite this serious consequence, certificate expiration remains one of the most common causes of unexpected downtime in production systems. Many organizations have experienced the embarrassment of a high-profile service going down because someone forgot to renew a certificate.

Preventing certificate expiration problems requires both automated monitoring and renewal processes. You need to know well in advance when certificates will expire so you have time to renew them, and you need systems in place to automatically check expiration dates and alert you before it's too late.

Manual Certificate Expiration Checking

Using OpenSSL:

# Check expiration of a certificate file
openssl x509 -in certificate.crt -noout -dates

# Output:
# notBefore=Jan 15 12:34:56 2024 GMT
# notAfter=Apr 14 12:34:56 2024 GMT

# Extract just the expiration date
openssl x509 -in certificate.crt -noout -enddate

# Output:
# notAfter=Apr 14 12:34:56 2024 GMT

Checking a live HTTPS server's certificate:

# Connect to server and retrieve certificate
openssl s_client -connect example.com:443 -servername example.com < /dev/null | openssl x509 -noout -dates

# For just the expiration date:
openssl s_client -connect example.com:443 -servername example.com < /dev/null | openssl x509 -noout -enddate

Using curl:

# Check certificate expiration from a URL
curl -vI https://example.com 2>&1 | grep "expire date"

# Output:
# *    expire date: Apr 14 12:34:56 2024 GMT

Using Python:

from datetime import datetime
import ssl

def check_certificate_expiration(hostname, port=443):
    context = ssl.create_default_context()
    try:
        with context.create_connection((hostname, port), timeout=10) as sock:
            with context.wrap_socket(sock, server_hostname=hostname) as ssock:
                cert = ssock.getpeercert()
                expiration = datetime.strptime(
                    cert['notAfter'],
                    '%b %d %H:%M:%S %Y %Z'
                )

                days_until_expiration = (expiration - datetime.now()).days

                print(f"Certificate expires: {expiration}")
                print(f"Days until expiration: {days_until_expiration}")

                if days_until_expiration < 0:
                    print("CRITICAL: Certificate is EXPIRED")
                elif days_until_expiration < 30:
                    print(f"WARNING: Certificate expires in {days_until_expiration} days")
                else:
                    print(f"OK: Certificate is valid for {days_until_expiration} more days")

                return expiration, days_until_expiration
    except Exception as e:
        print(f"Error checking certificate: {e}")
        return None, None

# Usage
check_certificate_expiration('example.com')

Using JavaScript (Node.js):

const https = require('https');
const tls = require('tls');

function checkCertificateExpiration(hostname) {
  const options = {
    hostname: hostname,
    port: 443,
    method: 'HEAD'
  };

  const req = https.request(options, (res) => {
    const cert = res.socket.getPeerCertificate();
    const expirationDate = new Date(cert.valid_to);
    const now = new Date();
    const daysUntilExpiration = Math.floor((expirationDate - now) / (1000 * 60 * 60 * 24));

    console.log(`Certificate expires: ${expirationDate}`);
    console.log(`Days until expiration: ${daysUntilExpiration}`);

    if (daysUntilExpiration < 0) {
      console.log('CRITICAL: Certificate is EXPIRED');
    } else if (daysUntilExpiration < 30) {
      console.log(`WARNING: Certificate expires in ${daysUntilExpiration} days`);
    } else {
      console.log(`OK: Certificate is valid for ${daysUntilExpiration} more days`);
    }

    res.resume();
  });

  req.on('error', (err) => {
    console.error(`Error checking certificate: ${err.message}`);
  });

  req.end();
}

// Usage
checkCertificateExpiration('example.com');

Automated Certificate Expiration Monitoring

For production systems, manual checking isn't sufficient. You need automated monitoring that regularly checks expiration dates and alerts you before expiration.

Monitoring Tools:

  1. Uptime/Monitoring Services:
    • Uptimerobot
    • Pingdom
    • New Relic
    • Datadog

These services monitor HTTPS endpoints and can alert when certificate expiration is approaching (typically configurable for 30, 14, 7, and 1-day warnings).

  1. Certificate Management Tools:
    • Sectigo (formerly Comodo)
    • DigiCert
    • GlobalSign

Most commercial CA platforms offer monitoring and automated renewal.

  1. Open Source Tools:

    • Certbot (from Let's Encrypt)
    • Acme.sh
    • cert-manager (Kubernetes)
  2. Custom Scripts: Create monitoring scripts that check certificates on a schedule.

Example Monitoring Script (Bash):

#!/bin/bash

HOSTNAME="example.com"
ALERT_THRESHOLD_DAYS=30
EMAIL_ALERT="[email protected]"

# Get certificate expiration date
EXPIRATION=$(echo | openssl s_client -servername $HOSTNAME -connect $HOSTNAME:443 2>/dev/null | openssl x509 -noout -enddate | cut -d= -f2)

# Convert to seconds since epoch
EXPIRATION_EPOCH=$(date -d "$EXPIRATION" +%s)
NOW_EPOCH=$(date +%s)

# Calculate days until expiration
DAYS_UNTIL=$((($EXPIRATION_EPOCH - $NOW_EPOCH) / 86400))

# Check and alert
if [ $DAYS_UNTIL -lt 0 ]; then
    echo "CRITICAL: Certificate for $HOSTNAME is EXPIRED" | mail -s "CRITICAL: Certificate Expired" $EMAIL_ALERT
elif [ $DAYS_UNTIL -lt $ALERT_THRESHOLD_DAYS ]; then
    echo "WARNING: Certificate for $HOSTNAME expires in $DAYS_UNTIL days" | mail -s "WARNING: Certificate Expiring" $EMAIL_ALERT
else
    echo "OK: Certificate for $HOSTNAME is valid for $DAYS_UNTIL more days"
fi

Add this to cron to run regularly:

# Check certificate expiration daily
0 9 * * * /path/to/check_cert_expiration.sh

Example Monitoring with Prometheus (Node Exporter): The Node Exporter has a textfile_collector that can run scripts reporting metrics.

Create a script that outputs Prometheus metrics:

#!/bin/bash

HOSTNAME="example.com"

# Get certificate expiration in Unix timestamp
EXPIRATION=$(echo | openssl s_client -servername $HOSTNAME -connect $HOSTNAME:443 2>/dev/null | openssl x509 -noout -enddate | cut -d= -f2)
EXPIRATION_EPOCH=$(date -d "$EXPIRATION" +%s)

# Output Prometheus metric
echo "# HELP certificate_expires_seconds_unix Certificate expiration time in Unix epoch"
echo "# TYPE certificate_expires_seconds_unix gauge"
echo "certificate_expires_seconds_unix{hostname=\"$HOSTNAME\"} $EXPIRATION_EPOCH"

Then Prometheus can alert when the expiration time is approaching:

groups:
  - name: certificates
    rules:
    - alert: CertificateExpiresSoon
      expr: (certificate_expires_seconds_unix - time()) / 86400 < 30
      for: 1h
      annotations:
        summary: "Certificate expires in less than 30 days"

Kubernetes Certificate Monitoring

For Kubernetes clusters, certificate expiration is a common operational challenge:

Using cert-manager:

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: example-cert
spec:
  secretName: example-tls
  issuerRef:
    name: letsencrypt-prod
  dnsNames:
  - example.com
  - www.example.com
  # Auto-renew 30 days before expiration
  renewBefore: 720h  # 30 days

Monitoring with Prometheus:

apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: certificate-alerts
spec:
  groups:
  - name: certificates
    interval: 30s
    rules:
    - alert: KubernetesCertificateExpiresSoon
      expr: certmanager_certificate_renewal_errors_total > 0
      for: 1h
      annotations:
        summary: "Certificate renewal error detected"

    - alert: KubernetesCertificateExpires
      expr: certmanager_certificate_expiration_timestamp_seconds - time() < 604800
      # Triggers 7 days before expiration
      for: 1h
      annotations:
        summary: "Certificate expires in less than 7 days"

Automated Certificate Renewal

Prevention is better than cure. Use automated renewal instead of manual renewal:

Let's Encrypt with Certbot:

# Install certbot
apt-get install certbot python3-certbot-nginx

# Get certificate
certbot certonly --nginx -d example.com -d www.example.com

# Set up auto-renewal (installed by default)
systemctl enable certbot.timer
systemctl start certbot.timer

# Check renewal status
certbot renew --dry-run

Certbot automatically renews certificates 30 days before expiration.

Docker-based Renewal:

FROM certbot/certbot
WORKDIR /etc/letsencrypt
VOLUME /etc/letsencrypt
ENTRYPOINT ["certbot", "renew", "--webroot", "-w", "/var/www/html"]

Run as a cron job:

docker run --rm \
  -v /etc/letsencrypt:/etc/letsencrypt \
  -v /var/www/html:/var/www/html \
  certbot/certbot \
  renew

Monitoring Across an Organization

For enterprises with many certificates:

Certificate Inventory: Maintain a database of all certificates:

  • Hostname
  • Certificate authority
  • Expiration date
  • Renewal date
  • Owner contact

Centralized Monitoring: Use CMDB (Configuration Management Database) tools:

  • Splunk
  • ServiceNow
  • Custom dashboard

Alerting Strategy: Set up alerts at multiple thresholds:

  • 90 days before expiration: Info
  • 30 days before expiration: Warning
  • 7 days before expiration: Critical alert to responsible team
  • Expired: Critical incident

Reporting: Generate monthly reports of certificate status across the organization.

Troubleshooting Certificate Expiration Issues

Problem: Certificate Shows as Expired but Browser Accepts It: Likely cause: Your system time is incorrect. Certificates are time-based. Solution: Sync system time: ntpdate -s time.nist.gov

Problem: Certificate Renewal Failed: Causes:

  • DNS not pointing to verification server
  • Firewall blocking challenge port
  • Disk space exhausted

Solution: Check renewal logs and DNS configuration.

Problem: Intermediate Certificate Missing: If the certificate chain is incomplete, browsers may reject it. Solution: Include intermediate certificate in certificate bundle.

Best Practices

  1. Automate everything: Use Let's Encrypt and certbot or equivalent for automatic renewal
  2. Multiple alert levels: Alert progressively as expiration approaches
  3. Test renewal: Regularly test that renewal processes work
  4. Monitor across your entire organization: Know every certificate you operate
  5. Use DNS-based validation: More reliable than HTTP validation
  6. Shorter certificate lifetime: Modern certificates are often 3-12 months instead of 1-3 years, encouraging automation

Conclusion

Certificate expiration doesn't have to cause downtime. With proper monitoring (automated checking at multiple thresholds), automated renewal (using Let's Encrypt or similar), and good organizational practices (maintaining certificate inventory, understanding the renewal process), you can ensure your certificates never unexpectedly expire. The best approach is to fully automate both monitoring and renewal, treating certificate management as a solved technical problem rather than a manual operational burden.

Need Expert Cybersecurity Guidance?

Our team of security experts is ready to help protect your business from evolving threats.