AuthBox documentation — User guide

Documentation embedded in this build.

Revocation, and how to need it less

Two things have to be true before a revocation means anything. Somebody has to be able to publish it, and every verifier has to actually consult it. Almost all of the difficulty lives in the second one, and it is the half that is easiest to ship without noticing you have not: a deployment where nothing is revoked and a deployment where revocation is never checked look identical from the outside.

This page covers both halves, and then the part that matters more than either — the certificate profile whose purpose is to make revocation something you reach for rarely. The framing is deliberate: revocation you rarely need beats revocation you cannot check. Every claim below names how you would check it, because a claim you cannot test is worth what you paid for reading it.

Checking is required, and an unreadable source denies

Revocation lists are checked at the handshake, on by default, and they fail closed. A revocation source that cannot be read is not evidence that there are no revocations; it is a reason to stop admitting certificates until it can be read again.

The same picture is available from the command line, without waiting for a handshake to fail:

authboxctl crl status -dir /var/lib/authbox/crl -anchors /etc/authbox/ca.pem

The online answer, fed by the issuance ledger

Lists are the airgap-friendly baseline. Where a network exists, this deployment also answers OCSP, and it answers it as the CA rather than as a bystander: it knows what it signed and what it revoked.

authboxctl ocsp issue-signer -anchors ca.pem -out ocsp-signer.pem \
    -keystore /var/lib/authbox/keys -passphrase-file pass -signer-key-id ocsp-signer

Requesting a revocation, when nothing online may sign one

The signing key is offline, and it stays offline. What is online is the queue: a place for "please revoke serial N" to live that is not somebody's memory or a message thread.

authboxctl revoke request 284837219194 -reason "laptop stolen"
authboxctl get revocations > revocations.json

Then, on the host where the key lives:

authboxctl crl generate -anchors ca.pem -dir crl-out \
    -keystore /var/lib/authbox/keys -passphrase-file pass \
    -from-requests revocations.json

Copy the result back with authboxctl crl import, and the pending rows it covers close themselves. The whole loop is written out in CRL distribution.

Proving it to somebody who does not trust you

A revocation story that only you can see is an operational tool. This one is also evidence.

The point for revocation specifically: "this certificate was issued, then" and "this revocation was requested, by whom, and when" are both demonstrable to somebody with no reason to believe you.

Needing it less: the short-lived profile

Everything above is the machinery for a credential that outlives its usefulness. The better answer for a service is a credential that does not.

The short-lived issuance profile gives leaves hours of validity — 12h by default, with a floor of 1h, below which ordinary clock skew starts denying honest peers. It is mintable only through an invitation whose subject the deployment already permits to renew itself, carrying the autorenew attribute described in Living with your certificate. The renewal window opens at the leaf's half-life, and each renewal is a possession-authenticated call to POST /enroll/renew — ledgered, logged, and OCSP-answerable like any other issuance. Every leaf is still writer-issued; nothing signs locally, so "who issued this" stays a one-hop question.

What that buys is a different withdrawal mechanism. Taking away self-renewal is deleting one attribute; it takes effect at the next request, there is no list to sign, carry, and distribute, and the exposure left behind is the hours-long tail of the current leaf rather than the months-long tail of a long-lived one. If you need that tail closed too, the CRL is still there and still works. And withdrawing possession — a stolen key, a compromised host — still means revocation, because a holder who kept a copy of the key does not need your permission to go on using it. Nothing about short validity is a substitute for that.

The cost is real, and it is a chosen trade rather than an oversight: a writer outage longer than the leaf validity takes the fleet down with it. A fleet renewing at a six-hour half-life has that much tolerance for the writer being unreachable. Inside an enclave, where the writer is always reachable and shares a failure domain with the services renewing against it, that is an acceptable bargain; across a link you do not control it is a bad one. Choose it with that sentence in front of you, and set the validity against how long you would be willing to be down.

Not the same question: suspending a person

Most of what an organization actually does on a Tuesday is not "this key is compromised". It is "this person left", "this person is on leave", "this account is paused pending an investigation" — and reaching for revocation there answers a question nobody asked.

Suspension is the state for that, and it is the opposite of revocation on every axis that matters:

Revocation Suspension
What it is about one certificate one entity — the person or service
Reversible no, and never was yes, by a signed reinstatement
Takes effect when a signed list reaches each relying party at the next request, everywhere
Needs an offline signature yes, the CRL no
Carries a justification a free-text request field required, structurally
Preserves standing irrelevant — it is about the key yes: memberships, attributes, grants

authboxctl entity suspend "CN=…" -reason "separated 2026-08-30, HR case 4411" pauses the account. Everything it held stays exactly where it was: memberships, attributes, access-list standing, and brokerage grants, which are frozen rather than voided — no approver's record is rewritten, and each one authorizes again the moment the pause lifts. That preservation is the whole reason the state exists instead of deleting the entity, which destroys the record of who had access at the moment it removes the access.

Certificates are untouched by default, and the short-lived argument above is why. A suspended subject cannot renew — the refusal sits where every identity is resolved, and /enroll/renew is one of the doors it covers — so under the short-lived profile the suspension is self-cleaning within one validity period: the current leaf expires on its own schedule and no successor is ever issued. No list to sign, carry and distribute, for a withdrawal that was never about the key.

Where you do want the certificates gone as well, -request-revocations opts in. It files one revocation request per still-live serial onto the queue an operator signs offline — filed, not fulfilled, exactly like every other revocation intent in this system. Nothing is revoked by the suspension itself, and the certificates keep working until a signed list covering them arrives.

Two things suspension is not. It is not the deny list: identity.deny_list is the local, immediate, file-authored, survives-every-bundle break-glass override, and it stays that. Suspension lives with the record's owner and syncs with the record, so an upstream's suspension arrives at every downstream in the ordinary authority bundle, and a local suspension of an upstream-owned record is refused rather than silently reverted by the next one. And it is not a remedy for possession compromise: a holder who kept a copy of the key does not need an account to be active to use it against somebody who is not asking this deployment. A stolen key is still a revocation.

One thing to know before you write the reason: the suspended person can read it. It is shown to them, and only to them, on the self-disclosure page they get when their own credential is refused — see Troubleshooting: forbidden. That is deliberate: one honestly-labelled reason field, rather than a public/private pair inviting a second and unaccountable channel. Write it knowing who reads it.

Two tiers, and which one a credential belongs in

Most deployments run both, and that is the intended shape rather than a migration state. The question to ask about an identity is not "how long should this certificate last" but "if I needed this credential to stop working within the hour, what would I actually do" — then pick the tier whose answer you can live with.

Where to look next