Skip to content

feat(agent): refuse to replace the agent root CA without --new-agent-root - #185

Merged
fog-workflows[bot] merged 1 commit into
masterfrom
feat/agent-root-guard
Nov 10, 2026
Merged

fog-workflows[bot] merged 1 commit into
masterfrom
feat/agent-root-guard

Conversation

@mastacontrola

Copy link
Copy Markdown
Member

Why

Every enrolled fog-agent pins pki/root.pem. pki/ is git-ignored, so a reinstall that wipes the app folder used to make a new root silently, and every enrolled agent would stop trusting the server. This lands before agent enrollment ships, so no agent can enroll under a root that can be silently replaced.

What

  • The root's SHA-256 fingerprint is recorded in the Setting FOG_AGENT_ROOT_FINGERPRINT. Public data only; no key goes in the database.
  • ensurePki(dir, {expectedRoot}) throws E_AGENT_ROOT_MISSING / E_AGENT_ROOT_MISMATCH before any write, and returns {rootFingerprint}.
  • setupPki (new, in tools/setup/pki.js; both npm run setup and setup:dev use it): checks against the record, prints what is wrong, how to restore pki/, and the escape hatch. npm run setup -- --new-agent-root renames the old CA files with a timestamp and makes a new root on purpose.
  • signCsr exits notConfigured when root.pem does not match the record.
  • docs/install.md: "Agent certificate authority" section (back up pki/ with the database).
  • An install set up before this change records its existing root on the next setup run; nothing is refused.

A passphrase-encrypted backup of the CA keys in the database is a separate, later PR.

Verification

  • npm test: 256 passing. npm run test:install: all checks pass.
  • Gate: with master's pki.js and sign-csr.js, the new tests fail (13 failing); restored, all pass.
  • The real installer run twice from an answers file against one database and the same config/ and pki/: both exit 0.
  • setup:dev with pki/ moved away: prints the restore message and exits 1; nothing is created.

Reviews (opus): spec and standards, two rounds; last findings (a spacing nit, an alias, the stamp export dropped from the brief) fixed.

🤖 Generated with Claude Code

…root

Every enrolled fog-agent pins pki/root.pem. If pki/ was lost, setup made a
new root without a word and every agent stopped trusting the server.

- The database records the root's SHA-256 fingerprint (Setting
  FOG_AGENT_ROOT_FINGERPRINT). It is public; no key goes in the database.
- ensurePki(dir, {expectedRoot}) throws E_AGENT_ROOT_MISSING or
  E_AGENT_ROOT_MISMATCH before it writes anything.
- setupPki (used by setup and setup:dev) passes the recorded fingerprint,
  prints how to restore pki/, and makes a new root only with
  `npm run setup -- --new-agent-root` (old files renamed with a timestamp).
- signCsr refuses (notConfigured) when root.pem differs from the record.
- docs/install.md: back up pki/ with the database; the flag and its cost.

An install set up before this change records its current root on the next
setup run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@fog-workflows
fog-workflows Bot enabled auto-merge November 10, 2026 12:48
@fog-workflows
fog-workflows Bot added this pull request to the merge queue Nov 10, 2026
Merged via the queue into master with commit c314ce3 Nov 10, 2026
6 checks passed
@fog-workflows
fog-workflows Bot deleted the feat/agent-root-guard branch November 10, 2026 13:03
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