TLS Cert LCM

Certificate Discovery and Inventory

Find every TLS certificate across your estate — by network scan, ADC config pull, or file import — and normalize them into one deduplicated, lifecycle-tracked inventory that never touches a private key during discovery.

You can't renew what you can't see. Before Versus can manage a certificate's lifecycle, it has to know the certificate exists — and in most environments certificates accumulate on load balancers, application hosts, and cloud edges faster than any spreadsheet can track. Certificate Discovery finds them, and the Inventory is where they all land: one canonical, deduplicated record per unique certificate, no matter how many places it was found.

This is the foundation of Versus' certificate lifecycle management (CLM). Everything downstream — renewal, deployment, expiry alerting, compliance scoring — reads from this inventory.


The inventory model

Every discovered, imported, or Versus-issued certificate normalizes into a single entity: the certificate record. The primary deduplication key is the SHA-256 fingerprint of the DER-encoded certificate, so the same certificate found on ten devices, pulled from a config, and uploaded as a file all collapse to one record — with each place it was seen tracked as a source on that record.

Each record carries the certificate's identity and posture, all parsed from the certificate itself:

GroupFields
Identitysubject DN, SANs (typed: dns/ip/email/uri), serial, fingerprint (SHA-256), SPKI fingerprint
Chainissuer DN, issuing CA, ordered chain refs, chain-complete flag, is-CA flag
Cryptokey algorithm (RSA / ECDSA / EdDSA / ML-DSA / SLH-DSA), key size, curve, signature algorithm, post-quantum status
Validitynot-before, not-after, lifecycle state
Provenancesources (driver + reference + first/last seen), first-seen, last-seen

The SPKI fingerprint (a hash of the SubjectPublicKeyInfo) is stored alongside the certificate fingerprint. Because it identifies the public key rather than the certificate, it links rekey lineage and, at import time, lets Versus match a supplied private key to the certificate it belongs to without ever trusting a filename.

Discovery classifies post-quantum readiness too: records are tagged classical, hybrid, or pqc, and the key-algorithm vocabulary already includes ML-DSA (CRYSTALS-Dilithium) and SLH-DSA (SPHINCS+), so a PQC migration audit is a query, not a project.


The three discovery drivers

Discovery runs as a job against one of three drivers. Each driver's only job is to produce raw certificate bytes and hand them to a shared reconciliation pipeline (below) — the parsing, deduplication, and lifecycle logic is identical no matter where a certificate came from.

Network scan

The scan driver opens a TLS connection to each host or host:port target and extracts the leaf certificate presented in the handshake. It deliberately does not verify the server chain, so it still captures self-signed, expired, and misissued certificates — exactly the ones you most want to find.

{
  "driver": "network_scan",
  "config": {
    "targets": ["www.corp.example", "10.0.0.10:8443", "vip-01.dc1"],
    "ports":   [443, 8443],
    "timeout": 10
  }
}

Targets without an explicit :port are scanned on every port in ports (default 443). The job checkpoints after each target, so a long scan resumes where it left off rather than starting over.

Endpoint pull (ADCs)

The endpoint-pull driver connects to managed application delivery controllers and reads the certificates installed on the device — along with a binding hint that records where each certificate lives (which profile, vserver, or template). F5 BIG-IP and Citrix NetScaler have native pullers today; any other device falls back to a TLS handshake against its management address.

{
  "driver": "endpoint_pull",
  "config": { "device_ids": [12, 15] }
}

Leave device_ids empty to pull from every enabled device.

Import

The import driver ingests certificate material you already hold — inline PEM, base64 DER, or a PKCS#7 bundle — and is also exposed as a dedicated upload endpoint that accepts .pem, .crt, .cer, .der, .p12/.pfx, and .p7b files. See Operator workflow below.

Discovery never handles private keys. The network-scan and endpoint-pull drivers have a hard invariant: no code path requests, receives, or logs private-key material, even where the vendor API could return it. The import driver ignores any private-key block in a PEM unless you explicitly opt in to key import on the upload endpoint. See Collector Security for how that boundary is enforced across the platform.


How reconciliation works

Whatever the driver, each discovered certificate becomes a discovery event — the raw DER bytes plus a driver name, a source reference, and (for endpoint pull) a binding hint. Events flow through one idempotent pipeline:

  1. Parse. The DER is decoded once. Versus computes the fingerprint and SPKI hash, reads subject/issuer/serial/validity, detects the key algorithm and size, extracts typed SANs, and reads Basic Constraints to flag CA certificates. A certificate that won't parse is logged and skipped — it never creates a junk record.
  2. Upsert on fingerprint. If the fingerprint is new, a record is created in the discovered state. If it already exists, the record is updated in place and this driver + source reference is merged into its sources list (refreshing last_seen), so re-running a scan never duplicates anything.
  3. Classify by expiry. For unmanaged records, the lifecycle state is derived purely from the validity window — active, expiring (within 30 days), or expired — and any change is written as an audit transition. Records already under management keep their managed state.
  4. Stitch the chain. Versus links a leaf's issuer to an existing CA record by matching issuer DN to a known CA's subject DN, building the leaf-to-root chain as those CAs are themselves discovered or imported.
  5. Record bindings. When the event carries a binding hint, an endpoint binding is created or refreshed, tying the certificate record to a specific install location on a device.

Because the whole pipeline keys on the fingerprint and every lifecycle change is written through an append-only, idempotency-keyed transition log, you can scan the same network every hour without churn — new certificates appear, seen certificates get a refreshed timestamp, and nothing is double-counted.

Endpoint bindings

A binding answers "where is this certificate actually serving?" It maps a certificate record to a device plus a typed location:

Binding typeWhere
f5_clientssl_profileF5 BIG-IP client-SSL profile
netscaler_ssl_vserverCitrix NetScaler SSL vServer
a10_ssl_templateA10 Networks SSL template
alteon_ssl_policyRadware Alteon SSL policy
avi_sslkeyandcertVMware NSX ALB SSL key & cert
kemp_vs_certKemp LoadMaster VS certificate
genericAnything else

Bindings are what let a renewal target exactly the profiles already serving a certificate, rather than guessing.


Operator workflow

Discovery and inventory are driven from the CLM API under /api/clm/. All endpoints require an authenticated session; multi-tenant deployments scope every record to the calling tenant.

Create and run a discovery job.

POST /api/clm/discovery-jobs/
{ "driver": "network_scan",
  "config": { "targets": ["vip-01.dc1", "vip-02.dc1"], "ports": [443] },
  "schedule": "0 3 * * *" }

POST /api/clm/discovery-jobs/{id}/run/

The run kicks off in the background and returns immediately; poll the job to watch status and stats (scanned, found, new, updated, errors) climb. An optional schedule cron expression marks a job for recurring runs. A running job can be stopped with POST /api/clm/discovery-jobs/{id}/cancel/.

Import a file directly (multipart or JSON) without defining a job:

POST /api/clm/certificates/import/
  [email protected]   format=pkcs12   password=•••••
  import_key=true    owner="payments-team"   tags="prod,pci"

The response reports how many certificates were imported, updated, and skipped. Set import_key=true only when you intend to escrow the private key — Versus matches it to the right certificate by SPKI hash and stores it envelope-encrypted in the Secret Vault.

Browse and filter the inventory.

GET /api/clm/certificates/?state=expiring
GET /api/clm/certificates/?expires_within_days=45
GET /api/clm/certificates/?is_ca=true
GET /api/clm/certificates/?owner=payments&search=example.com

The list is searchable by subject DN, serial, fingerprint, and owner, and sortable by expiry, state, or compliance score. Each row reports its days-until-expiry, binding count, and whether it's already under management. Fetch a single record for the full detail — chain, sources, bindings, and the complete transition history.

Fold device certificates in. If you already discovered certificates through device inventory elsewhere in Versus, POST /api/clm/certificates/sync-from-devices/ bulk-imports every one that has PEM data into the CLM inventory, so the two views converge.


From discovery to management

A discovered record is a passive observation. To bring one under active lifecycle management — renewal, redeployment, expiry contacts — you adopt it:

POST /api/clm/certificates/{id}/adopt/
{ "key_mode": "renew", "ca_account": 3 }

Adoption creates a managed certificate carrying the CN, SANs, expiry, and CA that discovery already parsed. Two key modes cover the realistic cases:

  • key_mode: "renew" — no private key is adopted; a fresh key and certificate are minted at the first renewal. This is the safe default when discovery only ever saw the public certificate.
  • key_mode: "upload" — you supply the matching key as PEM or a PKCS#12 bundle, so the existing certificate can be deployed immediately.

From there the managed certificate flows into the rest of TLS Cert LCM: it's picked up by the renewal scanner (which honors ACME Renewal Information where the CA supports it, and otherwise a configurable days-before-expiry window) and pushed to its deployment targets. See Certificate Renewal and Certificate Deployment.

Records you never intend to manage can be marked unmanaged so they stay in inventory for reporting without cluttering renewal queues. A bulk POST /api/clm/certificates/refresh_expiry/ re-evaluates lifecycle states across the whole inventory on demand; the same reconciliation runs on a schedule to keep expiring and expired states current.


Where it sits in the platform

Certificate discovery is the read side of CLM, and it's deliberately conservative: it observes broadly (unverified TLS, any port, any format) but touches nothing sensitive (no private keys, no config writes). That separation is what makes it safe to point at production continuously.

  • Inventory feeds automation. Managed certificates run through the Workflow engine for renewal and deployment, so a certificate found by a 3 a.m. scan can be renewed and redeployed without a human ever transcribing a fingerprint.
  • Keys live in the vault. Any escrowed key material is envelope-encrypted and gated behind RBAC and a logged reason — see Secret Vault.
  • It rides the same trust boundary as everything else. Device pulls reach your network through the same outbound-only collector plane described in Platform Architecture.

Related