Skip to content

Revocation (CRL/OCSP)

Revoking a certificate is only useful if clients learn about it. Ampora ships both CRL and OCSP and will embed the URLs of both in every agent leaf cert it issues, so you only have to enable them once.

Endpoints

Endpoint Purpose Auth
GET /pki/crl.der DER-encoded CRL none (public-readable)
GET /pki/crl.pem PEM-encoded CRL none
POST /pki/ocsp OCSP responder (RFC 6960) none
GET /pki/ocsp/{base64-encoded-request} OCSP via GET (RFC 5019) none
GET /pki/trust-bundle.pem Active + Trusted CA leaves as PEM chain none

These are intentionally anonymous — clients (including agents and any third party validating certs) need to be able to reach them without a prior trust relationship.

Settings

CertificateAuthority:
  CrlDistributionPoint: "https://AMPORA_HOST/pki/crl.der"
  OcspResponderUrl:     "https://AMPORA_HOST/pki/ocsp"

These two URLs end up embedded in every issued cert as the CDP (CRL Distribution Point) and AIA (Authority Information Access) extensions. Set them before issuing any certs you intend to revoke; changing them later does not retro-fit existing leaves.

If your Ampora server lives behind a reverse proxy, the URLs in settings should be the externally reachable form (the URL agents see), not localhost.

Freshness windows

Knob Default Trade-off
CRL nextUpdate 15 min Lower = faster propagation, more endpoint traffic
OCSP staple lifetime 4 h Lower = faster propagation, more responder load
HTTP Cache-Control on CRL 60 s Mirrors the publisher cadence

The default 15-minute CRL nextUpdate is a deliberate compromise: short enough that a revocation propagates within a typical incident-response window, long enough that scrapers do not flood the endpoint.

Operating CRL

The CRL publisher service runs on the leader instance, signs the latest CRL with the active CA signing key, and persists it. The endpoint serves the persisted blob directly — no per-request signing, no live-DB queries — so it is fast and cacheable.

A 60 s HTTP cache header on /pki/crl.{der,pem} is honoured by intermediate caches (your CDN, reverse proxy, agent-side caches) — set your CDN's TTL accordingly.

If the active signing key is HSM-backed (HSM/KMS), CRL refresh hits the HSM once per refresh, not once per revocation. CRLs scale.

Operating OCSP

The OCSP responder uses a separate OCSP signer cert issued by the active CA. The signer cert has its own lifetime (default 90 days) and auto-renews when within RenewalThresholdDays of expiry.

Stapling is the recommended mode:

  • Ampora's OpAMP listener requests a stapled OCSP response from the responder service in the same pod.
  • The TLS handshake includes the response, so the agent does not have to reach the responder itself.
  • This works even if the agent's network only allows outbound to the Ampora hostname.

For agents that do reach the responder, the GET form (RFC 5019) lets intermediate HTTP caches store responses. The Cache-Control: max-age=14400 header is set to the 4-hour staple lifetime by default.

Verifying revocation propagation

Revoke a test cert via Settings → Identities → Revoke and confirm:

  1. CRL contains it within ≤ 15 minutes:

    curl -s https://AMPORA_HOST/pki/crl.der | openssl crl -inform DER -text -noout | grep <serial>
    

  2. OCSP returns revoked for it:

    openssl ocsp \
      -issuer trust-bundle.pem \
      -cert revoked.pem \
      -url https://AMPORA_HOST/pki/ocsp \
      -resp_text
    

  3. The agent's next reconnect fails TLS handshake. Check the agent's own logs (opamp_extension) for the ssl: revoked certificate diagnostic.

Common issues

Symptom Cause
Revoked cert still validates Client is using a cached OCSP response; wait for the staple lifetime to expire or restart the agent
CRL endpoint returns 503 Active signing key is unreachable (HSM down, KMS quota exceeded). Check /health/ready
OCSP responder returns unknown for valid serials OCSP signer cert expired and auto-renew failed. Force-renew via the UI
Agent rejects with "no OCSP responder" The cert was issued before OcspResponderUrl was set. Re-issue

CRL distribution

/pki/crl.der is anonymous and public; if your operational stance is "no public endpoints on the management plane", front it with a CDN that serves the same path from a public hostname while keeping the management hostname locked down. Update the CDP setting to point at the CDN URL before issuing certs that should reach it.