Skip to content

Latest commit

 

History

39 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

cert-patrol

CI License: MIT Rust

X.509 certificate chain monitor for IoT device fleets.

CLI fleet scan output

Overview

cert-patrol is a command-line tool for monitoring TLS certificate health across distributed IoT device fleets. In industrial IoT deployments — SCADA systems, smart grid controllers, medical devices, connected vehicles — expired or misconfigured certificates cause silent communication failures that are difficult to diagnose at scale.

cert-patrol connects to each device endpoint, extracts the full certificate chain, and validates it against configurable security policies:

  • Expiry monitoring — detect certificates expiring within a configurable window
  • Chain validation — verify the chain is complete and anchored to a trusted root
  • Cryptographic compliance — flag weak RSA keys (<2048-bit), small EC keys (<256-bit), and SHA-1 signatures
  • TLS version audit — confirm devices negotiate TLS 1.2 or 1.3, flag deprecated versions
  • SAN verification — ensure certificate Subject Alternative Names match the expected hostname
  • Cipher suite analysis — classify negotiated cipher suites as strong/acceptable/weak, flag RC4, 3DES, NULL, EXPORT ciphers
  • Protocol version detection — check for TLS 1.0/1.1 support, flag deprecated versions
  • OCSP and CRL checking — extract OCSP responder URLs, CRL distribution points, check revocation status
  • Key usage validation — verify Extended Key Usage matches server/client auth requirements
  • Fleet-wide reporting — JSON, CSV, and colored terminal table output for integration with monitoring pipelines
  • Continuous monitoring — watch mode with configurable rescan intervals and alert delivery
  • Fleet diff — compare reports over time to detect certificate changes, renewals, and expirations
  • Certificate inventory — deduplicate certificates across hosts, show which cert is used where
  • Alerting — configurable thresholds with file and webhook alert sinks
  • Certificate pinning — maintain SPKI hash pins per host, detect unexpected certificate changes
  • Prometheus metrics — export fleet health metrics in exposition format for monitoring pipelines
  • Host tagging — organize fleet hosts with arbitrary key:value tags for filtering and grouping
  • Quiet mode — machine-readable exit-code-only output for CI/CD integration
  • Optional TUI dashboard — interactive terminal UI with Ratatui (compile with --features tui)

Installation

cargo install --path .

With TUI support:

cargo install --path . --features tui

Or build from source:

cargo build --release
cargo build --release --features tui

Usage

Scan hosts from a file

Create a hosts file with one host:port entry per line:

# hosts.txt — production IoT fleet
gateway-01.factory.local:8883
gateway-02.factory.local:8883
scada-controller.plant.local:443
mqtt-broker.edge.local:8883
ota-server.cloud.example.com:443

Scan all hosts with colored output:

cert-patrol scan -f hosts.txt

With options:

cert-patrol scan -f hosts.txt --warn-days 60 --timeout 15 --concurrency 64 --output json

Output formats

# Colored terminal table (default)
cert-patrol scan -f hosts.txt --output table

# JSON output
cert-patrol scan -f hosts.txt --output json

# CSV output for spreadsheet import
cert-patrol scan -f hosts.txt --output csv

Cipher suite analysis

cert-patrol scan -f hosts.txt --check-ciphers

Reports each host's negotiated cipher suite with strength classification (STRONG/ACCEPTABLE/WEAK) and flags deprecated TLS protocol versions.

Group results

# Group by base domain
cert-patrol scan -f hosts.txt --group-by domain

# Group by certificate issuer
cert-patrol scan -f hosts.txt --group-by issuer

# Group by expiry time range
cert-patrol scan -f hosts.txt --group-by expiry

Certificate inventory

Show deduplicated certificates across the fleet:

cert-patrol scan -f hosts.txt --inventory

Continuous monitoring (watch mode)

Rescan the fleet every N minutes, detect status changes, send alerts:

# Rescan every 5 minutes, write alerts to file
cert-patrol scan -f hosts.txt --watch 5 --alert-file /var/log/cert-alerts.log

# Rescan every 10 minutes, send alerts to webhook
cert-patrol scan -f hosts.txt --watch 10 --alert-webhook https://hooks.slack.com/...

# Both file and webhook alerts
cert-patrol scan -f hosts.txt --watch 5 --alert-file alerts.log --alert-webhook https://hooks.example.com/certs

Fleet diff

Compare two JSON reports to see what changed:

# Generate a baseline report
cert-patrol report -f hosts.txt --json-output baseline.json

# Later, generate a new report and diff against baseline
cert-patrol scan -f hosts.txt --diff baseline.json

# Or diff two saved reports
cert-patrol diff -a baseline.json -b current.json
cert-patrol diff -a baseline.json -b current.json --output json

Validate a local PEM file

cert-patrol check-file -f /etc/ssl/certs/device.pem --hostname gateway-01.factory.local

Generate a fleet report

cert-patrol report -f hosts.txt --json-output fleet-report.json
cert-patrol report -f hosts.txt --check-ciphers --group-by issuer --inventory

Certificate pinning

Track certificate public key hashes per host. On subsequent scans, cert-patrol alerts if a certificate has changed unexpectedly (potential MITM or unplanned rotation):

# First scan records pins
cert-patrol scan -f hosts.txt --pin-db pins.json

# Subsequent scans compare against stored pins
cert-patrol scan -f hosts.txt --pin-db pins.json

Prometheus metrics export

Export fleet health metrics in Prometheus exposition format for integration with Grafana, Alertmanager, or any Prometheus-compatible monitoring stack:

cert-patrol scan -f hosts.txt --prometheus /var/lib/node_exporter/cert_patrol.prom

Exported metrics include cert_patrol_cert_days_until_expiry, cert_patrol_cert_valid, cert_patrol_tls_version, and fleet-level aggregates.

Host tagging

Organize fleet hosts with tags for filtering and reporting:

cert-patrol scan -f hosts.txt --tag env:prod --tag team:platform --prometheus metrics.prom

Tags are propagated to Prometheus metric labels.

Quiet mode

Suppress all output, communicate only via exit codes (useful in CI/CD):

cert-patrol scan -f hosts.txt --quiet
echo $?  # 0=ok, 1=warnings, 2=errors

Interactive TUI dashboard

TUI dashboard

Launch the terminal dashboard (requires --features tui):

# Via dedicated subcommand
cert-patrol tui -f hosts.txt

# Or via --tui flag on scan
cert-patrol scan -f hosts.txt --tui

# With auto-refresh
cert-patrol tui -f hosts.txt --watch 5

TUI keybindings:

  • q — quit
  • r — rescan fleet
  • / — filter hosts
  • Enter — show certificate details
  • Esc — close detail panel
  • Tab — switch panel focus
  • s — cycle sort column
  • j/k or arrows — navigate

Without the tui feature, --tui prints a message to recompile with --features tui.

Example output

cert-patrol fleet report  |  5 hosts scanned  |  2026-04-03 14:22:01 UTC
valid: 3  expiring: 1  expired: 1  warnings: 0  errors: 0

╭──────────────────────────────────┬──────────┬──────────────────────────────┬───────────┬─────────────┬─────────────────────╮
│ Host                             │ Status   │ Subject                      │ Days Left │ TLS         │ Issues              │
├──────────────────────────────────┼──────────┼──────────────────────────────┼───────────┼─────────────┼─────────────────────┤
│ gateway-01.factory.local:8883    │ VALID    │ CN=gateway-01.factory.local  │ 247       │ TLSv1_3     │ none                │
│ gateway-02.factory.local:8883    │ EXPIRING │ CN=gateway-02.factory.local  │ 12        │ TLSv1_3     │ expires in 12 days  │
│ scada-controller.plant.local:443 │ EXPIRED  │ CN=scada-controller          │ -34       │ TLSv1_2     │ certificate expired  │
│ mqtt-broker.edge.local:8883      │ VALID    │ CN=mqtt-broker.edge.local    │ 364       │ TLSv1_3     │ none                │
│ ota-server.cloud.example.com:443 │ VALID    │ CN=ota-server.cloud.example  │ 180       │ TLSv1_3     │ none                │
╰──────────────────────────────────┴──────────┴──────────────────────────────┴───────────┴─────────────┴─────────────────────╯

  [#########################...............] 60% healthy

Exit codes

Code Meaning
0 All hosts valid
1 Expiring certificates or warnings detected
2 Expired certificates or connection errors

Architecture

src/
├── main.rs           — CLI entry point, argument parsing, command dispatch
├── models.rs         — Data types: CertInfo, ScanResult, FleetReport, ValidationIssue
├── scanner.rs        — TLS connection and certificate extraction per host
├── validator.rs      — Certificate chain validation, expiry, key size, SAN checks
├── fleet.rs          — Fleet-wide concurrent scanning with semaphore control
├── report.rs         — JSON and plain table report generation
├── display.rs        — Colored terminal output, CSV, grouping, inventory
├── cipher_check.rs   — Cipher suite strength analysis, protocol version detection
├── ocsp.rs           — OCSP responder/CRL extraction, key usage validation
├── monitor.rs        — Continuous monitoring loop with change detection
├── diff.rs           — Fleet report diffing (added/removed/renewed/expired)
├── alerts.rs         — Alert generation and delivery (file, webhook)
├── pinning.rs        — Certificate SPKI pinning database (JSON-backed)
├── prometheus.rs     — Prometheus exposition format metrics export
└── tui/              — Optional Ratatui TUI (behind "tui" feature)
    ├── mod.rs
    ├── app.rs        — Application state and event loop
    └── widgets.rs    — Widget rendering (summary bar, host table, detail panel)

CI/CD integration

cert-patrol returns non-zero exit codes suitable for CI/CD pipelines:

# GitLab CI example
cert-check:
  stage: security
  script:
    - cert-patrol scan -f fleet-hosts.txt --warn-days 30 --output json > report.json
    - cert-patrol scan -f fleet-hosts.txt --diff baseline.json || true
  artifacts:
    paths:
      - report.json
  allow_failure: false

Webhook alert format

Alerts sent to webhooks are JSON POST requests:

{
  "tool": "cert-patrol",
  "version": "1.1.0",
  "timestamp": "2026-04-03T14:22:01Z",
  "severity": "CRITICAL",
  "host": "scada-controller.plant.local:443",
  "message": "certificate expired",
  "details": "expired 34 days ago, subject: CN=scada-controller"
}

Configuration

All configuration is via command-line flags:

Flag Default Description
--warn-days 30 Days before expiry to flag as EXPIRING
--timeout 10 Connection timeout in seconds
--concurrency 32 Maximum parallel connections
--output table Output format: table, json, or csv
--check-ciphers off Analyze cipher suite strength
--check-ocsp off Check OCSP revocation status
--group-by none Group results: domain, issuer, expiry
--inventory off Show deduplicated certificate inventory
--watch N off Continuous monitoring every N minutes
--diff FILE none Compare against previous JSON report
--alert-file none Write alerts to file
--alert-webhook none POST alerts to webhook URL
--pin-db FILE none Certificate pin database file (SPKI hash tracking)
--prometheus FILE none Export Prometheus exposition format metrics
--tag KEY:VALUE none Host tag for fleet organization (repeatable)
--quiet / -q off Suppress output, exit code only
--tui off Launch interactive TUI (requires --features tui)

Cargo features

Feature Description
(default) Full CLI tool without TUI
tui Enables Ratatui-based interactive terminal dashboard

FAQ

How do certificates work on 4000 gateways?

Every gateway communicates with the cloud/server via TLS (encrypted connection, like HTTPS). For this, each gateway needs an X.509 certificate — a digital identity card. Yes, each gateway has its own unique certificate (plus the CA certificate that signed it). 4000 gateways = 4000 certificates.

What's the problem with certificate expiry?

Certificates have an expiration date (typically 1 year). When a certificate expires, the gateway can no longer connect to the server → the client loses telemetry → angry phone call. With 4000 devices, some certificate is always about to expire.

How does cert-patrol help?

cert-patrol scan --hosts fleet.txt    # scan all 4000 hosts

Result: a table with every host, certificate status, days until expiry. Red = expired, yellow = expiring within 30 days, green = OK. Webhook to Slack: "Gateway GW-3847 certificate expires in 7 days!" You renew it before anyone notices.

License

MIT License. Copyright (c) 2026 isecwire GmbH.

About

X.509 certificate chain monitor for IoT device fleets. Scans hosts concurrently for expiry, weak keys, deprecated TLS, cipher strength, OCSP/CRL status and SAN mismatches. Supports SPKI pinning, fleet diff, Prometheus export, webhook alerts, host tagging and an optional Ratatui TUI dashboard. Written in Rust.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages