Skip to main content
Version: 0.11

Certificates

Overview

Certificate operations (CertOps) adds a managed-certificate layer on top of the certificate tokens you already track in TokenTimer. Cert-category tokens (ssl_cert, tls_cert, code_signing, client_cert) are first-class assets: they appear in the Tokens list, Control Center, and token detail views. CertOps enriches those tokens with key locality, issuer, source, and observed deployment and rotation history.

TokenTimer control plane never stores, receives, or generates private keys; customer-side agents may generate keys locally. The platform stores only public certificate material (fingerprints, serial numbers, issuers, subjects, SANs, validity dates, chains) and external key references. Requests that contain private key material are rejected with HTTP 422.

  • Tokens: existing cert tokens keep working for alerting and expiry tracking.
  • Managed certificates: authoritative lifecycle records linked one-to-one with cert tokens when CertOps is enabled.
  • Public material only: inventory and API responses never include private keys.

Enabling CertOps

CertOps is off by default on self-hosted installs. Turn it on with the environment variable below, then restart the API and worker processes so the setting is picked up.

CERTOPS_ENABLED=true

When CertOps is disabled, CertOps API endpoints return 404 and inventory enrichments do not appear in the dashboard. When enabled, cert rows in the Tokens list and token detail show managed fields and observation history.

For the full list of environment variables, see the Configuration Reference.

Managed certificate inventory

A managed certificate is the authoritative lifecycle record for a tracked certificate in a workspace. It is linked one-to-one with a cert-category token so existing alerting, filtering, and token workflows keep working without a separate inventory screen.

Lifecycle status values:

  • discovered: first seen through observation or import, not yet confirmed active.
  • provisioning: created by an issue job and awaiting its first certificate. It flips to active when the job succeeds, and stays at provisioning if the job fails.
  • active: currently valid and in use.
  • renewing: a newer instance was observed while the previous one was still valid.
  • expiring: within the workspace alert threshold window.
  • expired: past its not-after date.
  • revoked: explicitly marked as revoked.
  • decommissioned: retired from active tracking.

You see managed certificate data on enriched cert rows in the Tokens list and on the CertOps panel in token detail. The Certificates tab of Certificate operations (/certops/certificates) is also a real inventory view: a paginated, filterable table of managed certificates (filter by status or source), with Set up renewal, Detach, and Retire actions per row where eligible (see Bringing an existing certificate under automatic renewal). A row whose renewal-setup attempt failed also carries a separate inline Retry link next to its renewal badge (retries that specific setup intent, not the certificate's whole lifecycle). Revoked and decommissioned certificates are hidden by default there; a Retired toggle with a live count shows them back. The Renewal automation tab lists certificates too, but only the ones with a renewal profile and only in expiry order, so it is a schedule rather than an inventory.

Importing a certificate

Import public certificate material through the existing Import tokens flow (paste or upload a public PEM) or through the CertOps API. Only public certificate data is accepted; payloads that include a private key are rejected with HTTP 422.

  • UI: open Import tokens, choose the public PEM import card when CertOps is enabled, and submit the certificate chain.
  • API: register a single certificate with POST /api/v1/workspaces/:id/certops/certificates or bulk import with POST /api/v1/workspaces/:id/certops/imports.
  • Idempotent: re-importing the same certificate fingerprint updates the existing managed record instead of creating a duplicate.

Use import when you have a certificate file but no HTTPS endpoint monitor to observe it.

Endpoint monitoring bridge

When you monitor an HTTPS endpoint or domain, the worker observes the public certificate currently served there. If the monitor has a linked token, that observation is recorded into CertOps inventory using a token-first rule: the bridge runs only when a token_id is present, including auto-created ssl_cert tokens.

Each endpoint monitor keeps exactly one managed certificate (stable identity keyed by monitor source and reference). When the served certificate rotates, that single record is updated in place with the new fingerprint, serial, and validity dates, and a new observation instance is appended to history.

  • Observer only: an endpoint monitor watches what is deployed and never modifies the target. Deployment and renewal happen through CertOps automation (agents, cert-manager, or your own executors), not through monitors.
  • Linked token: the monitor must reference a cert token for CertOps enrichment to run.
  • Rotation: detected when a later check reports different public material at the same monitor.

Certificate history

Each managed certificate keeps a timeline of observed certificate instances. An instance captures public observation fields at a point in time: when it was seen, subject, issuer, serial number, fingerprint, and source.

  • Re-observing the same fingerprint refreshes the existing instance row (last seen timestamp and status).
  • A new fingerprint at the same monitor appends a new instance row, giving you rotation history under one managed certificate.
  • View instances in token detail or fetch them with GET /api/v1/workspaces/:id/certops/certificates/:certId/instances.

Renewals and approvals

Inventory tracks what is deployed; renewing a certificate is a job, not an inventory edit. See Certificate Automation for renewal scheduling, manual renew vs bulk renew, and job status transitions (including the pending_approval state a job sits in while awaiting sign-off). See Approval gates and Certificate renewal failures for the approval and alerting detail.

What gets written to certPath

An agent-executed renewal deploys the full chain (leaf certificate plus intermediates) to certPath by default, not the leaf alone - a leaf-only certificate is untrusted by any client that does not separately fetch intermediates. If a target needs the leaf and the chain in separate files, configure chainPath instead: see First-time issuance for both.

Requesting a certificate TokenTimer does not track yet is also a job: an issue job, which creates the managed certificate at status provisioning and fills it in from the agent's evidence when the job succeeds. See First-time issuance.

Not every certificate in inventory can be renewed for you

This is the single most common surprise in CertOps, so it is worth stating plainly: appearing in your inventory does not mean TokenTimer can renew it. Inventory answers "what is out there"; renewal requires something on your side that actually holds the private key and can write a new one.

Every managed certificate has a key custody mode, which records where its private key lives:

Key custodyWhere the key livesCan TokenTimer run a renew/deploy/reload/revoke job?
agent-localOn the agent host that discovered itYes
proxy-agent-localOn a proxy host managed by an agentYes
os-store-managedInside Windows CNG, on the agent host (a windows-iis target's certificate store + IIS binding)Yes
cert-manager-managedIn your Kubernetes cluster, owned by cert-managerNo, cert-manager renews it. TokenTimer observes and reports (see CertOps with ACME and cert-manager)
appliance-managed, hsm-managed, vault-managedIn an appliance, HSM, or VaultNo, the owning system renews it
not setNowhere TokenTimer knows aboutNo, it was only observed

That last row is the one people hit. A certificate discovered by an endpoint monitor or the domain checker was seen from the outside, over the network. TokenTimer knows its subject, issuer, expiry, and fingerprint, and will alert you before it expires, but it has never had any access to the host serving it and no agent has custody of its key. There is nothing to renew with.

Creating a renew, deploy, reload, or revoke job against such a certificate fails immediately:

{
"error": "This certificate has no agent-manageable key custody (it was only observed, e.g. via an endpoint or domain monitor) and cannot be assigned an agent-executed renew job",
"code": "CERTOPS_CERTIFICATE_NOT_AGENT_DEPLOYABLE"
}

This is a deliberate fail-fast at creation time. The alternative, which earlier builds did, was worse: the job was accepted, some agent eventually claimed it, discovered it had no key or path to work with, and failed. You got a cert_renewal_failed alert that looked like a broken renewal when in fact the renewal was never possible.

To make an observed certificate renewable, give an agent real custody of it: install the agent on the host that actually serves the certificate. Its filesystem discovery will find the certificate on disk and register it with agent-local custody, at which point renewal jobs work normally. Observation and custody then coexist: the endpoint monitor keeps verifying what is really being served from the outside, which is how you confirm a renewal actually took effect.

Custody makes a certificate eligible for renewal; it does not by itself make it auto-renew. Automatic renewal additionally needs a linked renewal profile, which is derived for you only when TokenTimer issued the certificate. See Renew certificates automatically.

The renewal badge tells you which case you are in

Because custody and auto-renewal are two different things, every certificate carries a renewal badge computed server-side from the renewal scheduler's own inputs. It uses the same profile-completeness check the scheduler admits on, so it cannot show "Auto-renews" for a certificate the scheduler would skip.

BadgeMeaning
Auto-renewsEligible, configured, and scheduled. Shows the renewal date and the lead time in days
Auto-renewal offEligible and configured, but somebody switched automatic renewal off on its profile. It will expire. Deliberate rather than broken, so it is not flagged as a fault, but it still needs a manual renewal. See Switching automatic renewal off
No auto-renewalAgent-deployable but with no usable renewal profile. It will expire. This is the state to act on
Monitored onlyNo agent custody, so renewal is not possible here. Working as designed
Renewal not applicableRetired, or renewal is owned by another system such as cert-manager
Renewal unknownThe state could not be determined. Treated as a caution, not an all-clear, so a stale or unreachable API cannot render a false reassurance

The two grey states and the two that mean "this will expire" are deliberately distinct. "Monitored only" is a certificate you were never going to renew here. "No auto-renewal" is a certificate you probably believe is managed and is not. "Auto-renewal off" is a certificate somebody chose not to renew, which is supported, but the certificate still expires on schedule.

Retiring a certificate

Removing a tracked certificate is retire-first, not a silent delete. Call POST /api/v1/workspaces/:id/certops/certificates/:certId/retire with status decommissioned (planned removal) or revoked (explicitly revoked).

  • The managed certificate moves to the chosen terminal status.
  • The linked cert token receives a mirrored lifecycle status.
  • The managed certificate row, its instances, and audit trail are preserved for compliance review.
  • A managed-backed certificate cannot be hard-deleted from the token surface; use Retire instead.

Hard purge remains available only for manually created cert tokens that are not backed by a managed certificate record.

API reference

CertOps endpoints are workspace-scoped and available when CertOps is enabled. All paths are under /api/v1/workspaces/:id/certops:

  • GET .../certificates list managed certificates
  • POST .../certificates register a public certificate
  • GET .../certificates/:certId certificate detail
  • GET .../certificates/:certId/instances observation history
  • POST .../certificates/:certId/retire retire a certificate
  • POST .../imports bulk import public certificates

See the API reference for authentication, request bodies, and response shapes.

Example: list certificates in a workspace

curl -s \
-H "Authorization: Bearer YOUR_API_KEY" \
"https://your-tokentimer.example/api/v1/workspaces/WORKSPACE_ID/certops/certificates"