SSH Certificates and API Keys Diverge on Revocation and Blast Radius
SSH certificates and API keys both answer one question: is this caller who it claims to be? Past that they diverge hard. Certificates expire on their own and concentrate trust in a signing authority. API keys sit in config files for years. The revocation mechanics and the blast radius that follows are design outcomes, not accidents, and each model gets one thing badly wrong.
Two Credential Models, Two Failure Modes
An OpenSSH certificate is a public key plus a signature from a certificate authority, carrying a list of principals, a validity window, and optional restrictions such as source-address binding or forced commands. The host trusts the CA, not the individual key. That inversion is the whole point: onboarding a new engineer means signing a certificate, not editing every authorized_keys file in the fleet.
An API key is a bearer secret. Whoever holds the string is the caller. The common definition is broad enough to cover everything from a single-tenant token to a scoped OAuth credential, and most internal systems implement the simplest version: a random string mapped to an account row in a database.
The failure modes follow from those shapes. Certificate systems fail when the signing key leaks or when the validity window is set too generously. Key systems fail slowly, through accumulation: keys copied into CI variables, pasted into a notebook, committed to a repo, and never deleted when the project dies.
There is a third difference that gets less attention: what each credential can prove about intent. A certificate is minted in response to a request, at a moment in time, by an identity that the signing service authenticated first. An API key is often created once and then passed around by copy-paste, so the chain from creation to use is broken almost immediately. That distinction shapes everything below, because revocation is easy when you know who holds a credential and nearly impossible when you do not.
How SSH Certificates Bound Exposure
A well-run certificate deployment issues credentials with lifetimes measured in hours. A developer requests a certificate in the morning, works through the day, and the credential is dead by evening whether or not anyone remembered to clean up. Expiry does the revocation work that humans forget to do.
Principals are the other lever. A certificate can be signed for a specific set of usernames or roles, so a credential minted for a staging host does not authenticate against production even if the host trusts the same CA. Source-address restrictions and forced commands tighten it further, and both are checked by the server at authentication time rather than by the client.
The concentration of trust is the cost. The CA private key becomes the single most valuable file in the infrastructure. Anyone who holds it can mint a certificate for any principal on any host that trusts it, with any validity window they like. Key revocation lists exist in OpenSSH, but in practice they are rarely maintained, which makes the CA key the real control point. A related piece on signature checks and forged tokens covers why verification paths deserve the same scrutiny as the credentials themselves.
Signing services such as HashiCorp Vault's SSH secrets engine, Teleport, and step-ca exist mostly to make that control point manageable: they hold the CA key behind an API, log every issuance, and enforce maximum lifetimes so an operator cannot quietly sign a certificate valid for a year. Running your own CA by hand is possible and instructive for a small fleet, but the moment two people need to sign certificates you want the issuance path to be a service with its own audit log rather than a shell command on someone's laptop.
API Keys and the Long Tail of Leaks
API keys tend to outlive the projects and sometimes the employees that created them. A key generated for a one-off migration in a previous role stays valid because nobody owns the deletion. The inventory problem is genuinely hard: the issuing service knows which keys exist, but the consuming side is scattered across laptops, CI runners, and vendor dashboards.
Automated scanning helps and does not finish the job. GitHub's secret scanning and similar services catch recognizable token formats in public repositories, and push protection can block a commit before it lands. None of that covers a key pasted into a private wiki, a support ticket, or a screenshot. Detection is also asymmetric: providers see their own token patterns, not your internal ones.
Rotation is where the model strains. Many internal APIs issue keys with coarse scopes, so a service that only needs to read one resource holds a credential that can also write to others. Rotating a broadly scoped key means coordinating every consumer at once, which is exactly the kind of change that gets deferred. The key survives another quarter.
Versioning the key helps more than it first appears. If the issuing service keeps two valid values per credential — a current one and a previous one — a consumer can be migrated on its own schedule while the old value still works, and the old value is then retired after a fixed grace period. That turns rotation from a flag day into a rolling change, and it is the single design decision that most reduces the temptation to let a key live forever.
Revocation Mechanics Compared
SSH leans on expiry rather than explicit revocation. That works when lifetimes are short and fails when they are not; a certificate issued for thirty days is effectively unrevocable in most deployments because nobody maintains the revocation list. The practical answer is to shorten the window until revocation stops mattering.
API keys rely on delete-and-reissue. The issuing service can invalidate a key instantly, which sounds stronger than the certificate case until you count the places the old value lives. Cached credentials are the recurring problem for both models: an application that loaded a key at startup keeps using it after deletion, and a long-lived SSH connection stays authenticated after the certificate behind it expires.
Detection lag dominates real-world impact in both cases. The gap between a credential leaking and someone noticing is usually measured in days or weeks, not minutes. Shortening the credential's life is the only control that works without depending on detection, which is why expiry beats revocation in practice even though it looks weaker on paper.
The two models also differ in what revocation costs to get wrong. Deleting an API key that a live consumer still depends on produces an outage immediately, so operators learn to hesitate before pressing the button. Letting a certificate expire produces the same outage on a schedule everyone can see in advance. The certificate model moves the failure from a human decision made under pressure to a calendar event that can be tested in staging.
Blast Radius Is an Architecture Choice
Per-host principals limit lateral movement in a certificate deployment. A stolen certificate for a staging bastion does not open production, provided the principals and host trust configuration were scoped deliberately. The same certificate also carries an audit trail: the CA log records who requested it, for which principals, and when.
Shared API keys collapse boundaries. A single key used by several services means an incident on one becomes an incident on all, and the audit log attributes every call to the same identity. Per-tenant or per-service keys cost more operational effort but restore the ability to answer who did what.
Audit granularity differs too. Certificate issuance is a discrete, loggable event with a named requester and a stated purpose. Key usage is a stream of requests tagged with an opaque string. The certificate side gives you a shorter list to review; the key side gives you volume without attribution. Teams that treat failure budgets as an operational control will recognize the same pattern here: the useful signal comes from bounding the system, not from watching it harder.
One more asymmetry matters when you plan an incident response. With certificates, the containment action is to stop trusting the CA or tighten the principals, and the effect is fleet-wide and immediate. With keys, containment means finding every consumer, which is the same inventory problem that made the key leak in the first place. The model that is harder to operate day to day is the one that is easier to contain on a bad day.
Practical Steps for Both Systems
Set SSH certificate lifetimes under a day for interactive access and shorter for automation, then verify that hosts actually reject expired certificates rather than trusting a cached session.
Protect the CA private key with an HSM or an equivalent managed signing service, and keep it off the same hosts that run the SSH daemons it signs for.
Inventory API keys by owner, creation date, and last use, and delete anything with no recorded use in the past quarter. The list is usually shorter than expected and more embarrassing.
Automate rotation on a fixed schedule so that rotating a key is a routine deploy rather than an incident, and log every issuance and revocation event with the requester's identity attached.
Finally, test the expiry path deliberately. Issue a short-lived certificate, let it lapse, and confirm the server rejects it instead of accepting the cached session. Do the same with a revoked API key against a running client. Both systems fail quietly when the enforcement point is not where you assumed it was, and the only way to know is to watch it fail on purpose.