Each agent authenticates its QUIC session with a bearer credential:
<host_id>.<generation>.<issued_unix>.<hmac-sha256>
The HMAC (keyed by the server's host_secret) covers all three fields. The
generation is compared against the host row's cred_generation on every
Hello and every report (~10s), so revocation takes effect on live
sessions within one tick.
curl -X POST -H "Authorization: Bearer $EITRI_TOKEN" \
http://server:8080/api/v1/hosts/<host_id>/revoke-credential
$EITRI_TOKEN is a personal access token (console → Settings); the call
revokes a credential on one of your own hosts.
eitri-agent join <blob> on the host,
restart the agent daemon.host.credential.revoke).host_secret leaked (the disaster case)Rotate host_secret in server.json and restart—this revokes every
host credential at once; re-enroll each host as above.
credential_max_age in server.json (Go duration, e.g. "2160h") rejects
credentials older than the window. It is checked at Hello and, like revocation,
on every report tick, so a live session cannot outlive the window. Off by default:
there is no automatic renewal channel yet, so expiry trades credential
lifetime against operator toil. Generation revocation is the primary
mechanism.
Guest SSH access uses short-lived certificates self-signed with a tenant's own
user CA (see ssh-access.md)—eitri holds no user signing key.
The short validity you sign with (eitri ssh uses 30 minutes) is the
first line of defense: a leaked cert expires on its own.
Before it does, a specific cert can be revoked at the gate by serial (tenant-scoped, idempotent):
POST /api/v1/ssh-certs/revoke {"serial": N} or {"certificate": "<cert line>"}
GET /api/v1/ssh-certs/revoked
The by-line form extracts the serial from a pasted cert. The gate rejects
revoked serials at auth, and the revocation is recorded in the audit log
(ssh-cert.revoke).
A compromised tenant user CA is the bigger event: the tenant's CA must be replaced and its VMs re-seeded to drop trust in the old one—fast CA-level revocation is an open follow-up.