Skip to content

ops(spire): durable x509pop node attestation (TODO 36) - #18

Merged
NetworkTheoryAppliedResearchInstitute merged 1 commit into
mainfrom
feat/spire-x509pop
Jul 13, 2026
Merged

NetworkTheoryAppliedResearchInstitute merged 1 commit into
mainfrom
feat/spire-x509pop

Conversation

@NetworkTheoryAppliedResearchInstitute

Copy link
Copy Markdown
Contributor

Durable SPIRE node attestation (#6 of the operator-readiness plan; SoHoLINK TODO 36).

Problem

join_token is single-use. When the agent SVID expires while the agent is down (a reboot, a multi-hour outage), the agent restarts, re-attests with the already-consumed token, and crash-loops on "join token does not exist or has already been used" — dropping the orchestrator into SPIFFE-degraded mode. This recurred 2026-07-09 and twice on 2026-07-13, each needing a manual token rotation + workload-entry re-registration.

Fix — x509pop

x509pop derives the agent's SPIFFE ID from a leaf-certificate fingerprint. The ID is stable across restarts and there is no consumable token, so the crash-loop cannot occur by construction.

  • deploy/spire/server.conf — add the x509pop NodeAttestor (ca_bundle_path); join_token kept as a break-glass fallback.
  • deploy/spire/agent.conf — switch the agent to x509pop (leaf cert + key).
  • docker-compose.yml — mount the CA bundle into spire-server and the leaf cert/key into spire-agent (from ${SPIRE_X509POP_DIR:-./deploy/spire/x509pop}); drop the -joinToken command args.
  • .gitignore — deploy/spire/x509pop/ (host-local trust material, treated like .env; certs never committed).
  • deploy/spire/x509pop-migration.md — cert-gen + apply + re-register + rollback runbook.

Verification

  • Both configs pass spire-server validate / spire-agent validate.
  • The generated CA→agent chain verifies (openssl verify → OK).
  • docker compose config parses.

Applying to prod (deliberate step — not in this PR)

The live cutover is host-side per the runbook: generate the certs into deploy/spire/x509pop/, recreate the SPIRE pair, re-register the orchestrator workload entry under the new stable parent ID, recreate the orchestrator, then verify identity:ready and that an agent restart re-attests with no token. Rollback restores join_token. Blast radius of a bad apply is bounded to SPIFFE-degraded mode (public site stays up; node routes 503) — recoverable by rollback, and there are no live SPIFFE node consumers today.

Author does not self-merge — for review.

join_token is single-use: an SVID expiry + agent restart crash-loops on
"token already used", dropping the orchestrator into SPIFFE-degraded mode.
Recurred 2026-07-09 and twice 2026-07-13, each needing manual token rotation
+ workload-entry re-registration.

x509pop derives the agent SPIFFE ID from a leaf-cert fingerprint: stable across
restarts, no consumable token, so the crash-loop cannot occur.

- deploy/spire/server.conf: add the x509pop NodeAttestor (ca_bundle_path);
  join_token kept as a break-glass fallback attestor.
- deploy/spire/agent.conf: switch the agent to x509pop (leaf cert + key).
- docker-compose.yml: mount the CA bundle into spire-server and the leaf
  cert/key into spire-agent (from ${SPIRE_X509POP_DIR:-./deploy/spire/x509pop});
  drop the -joinToken command args.
- .gitignore: deploy/spire/x509pop/ (host-local trust material, like .env).
- deploy/spire/x509pop-migration.md: cert-gen + apply + re-register + rollback
  runbook.

Both configs pass `spire-{server,agent} validate`; the generated CA/agent chain
verifies (openssl verify OK); docker compose config parses. The live cutover is
a deliberate host-side step per the runbook (certs are not committed); rollback
restores join_token. Blast radius of a bad apply is bounded to degraded mode.

Signed-off-by: Jodson Graves <info@ntari.org>
@NetworkTheoryAppliedResearchInstitute
NetworkTheoryAppliedResearchInstitute merged commit de0fe0f into main Jul 13, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant