Repository navigation
feat(agent): serve fog-agent over mTLS (listener, principal, renew, poll) - #189
Merged
Merged
Conversation
…new, poll) An enrolled fog-agent now proves itself on every request with its client certificate, renews it, and polls, as it does against FOG 1.6. The same agent binary works against both. - api/hooks/agent-tls: fog-node's own HTTPS listener on custom.agentTlsPort (default 8443; 0 turns it off). It serves the same Express app, requests a client certificate but never requires one, and sends the agent CA and root as the acceptable CA list that Go needs. A busy port or missing PKI logs one warning, and fog-node keeps running. At lift it makes or renews only the server certificate. It never creates or rotates an agent CA (that is setup's job). - api/policies/agentPrincipal: verifies the leaf against the agent CA and the root in code, plus every date in the chain and clientAuth. Failures get the 1.6 401 bodies. A plain-HTTP request is never an agent. - POST /agent/v1/renew writes the 1.6 "certificate renewed to ..." audit row (authSource agent). POST /agent/v1/poll is the minimal 1.6 answer: integer poll_interval, and ISO server_time. - Sessions are off for /agent/v1/. The installer asks for the port and the server certificate SANs. ensurePki moved to api/lib/agent-pki-files. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
An enrolled fog-agent now proves itself on every request with its client certificate, renews it, and polls. It does this against fog-node exactly as it does against FOG 1.6, with the same agent binary. Brief:
2026-11-10-agent-mtls. Wire reference: the 1.6 enrollment contract, sections 1.3, 1.5, 1.6, 4.4 and 5.api/hooks/agent-tls): fog-node's own HTTPS listener oncustom.agentTlsPort(default 8443;0turns it off). It serves the same Express app as port 1337.npm run setup.agentPrincipalpolicy: verifies the leaf against the agent CA and the root in code, checks the dates of the whole chain and checks clientAuth, as 1.6openssl_x509_checkpurposedoes. A failure gets the 1.6401 {reason}bodies. A plain-HTTP request is never an agent.POST /agent/v1/renew: the 1.6 statuses and bodies. It writes the 1.6agent.enrollaudit row "certificate renewed to …, key …" (authSourceagent).POST /agent/v1/poll: the minimal 1.6 answer.poll_intervalis an integer ((int)in 1.6; the Go agent declaresint).server_timeis ISO 8601, as 1.6format('c')sends it. It writes no audit row (1.6 has none)./agent/v1/, so polls create no Redis sessions.docs/install.mdhas an "Agent port" section.ensurePkimoved toapi/lib/agent-pki-files.js, so runtime code no longer requirestools/.Test
npm test: 421 passing. The new tests aretest/integration/agent-mtls.test.js,test/hooks/agent-tls.test.js(including the lift/lower races and the missing-PKI path) and the server-certificate tests. Each was made to fail with its fix removed.npm run test:uiandnpm run test:install: green.openssl s_client: the chain verifies againstroot.pem, and the acceptable client CA names are "FOG Agent CA" and "FOG Server CA".The real fog-agent, end to end
Commands and verbatim log excerpts (enroll, poll, renew, interval, re-enroll)
Real fog-agent end to end against feat/agent-mtls
Run on 2026-11-10 against the current uncommitted tree in ~/fog-node-mtls,
after the server_time change and the lift-time ensureServerCert change.
Agent: ~/fog-agent/bin/fog-agent. The database is the worktree's dev database (config/local.js).
Every block below headed
<file>.logis copied from that file in/e2e/. Each line is verbatim. A line left out is
named in the text above its block. The previous run is in
prev-run/.Setup
Before the run,
node $H setting getprintednull: FOG_CLIENT_CHECKIN_TIME did not exist.After the lift, the pki folder held only the seven base files, with no timestamped file:
the lift made no agent CA and did not re-issue the server certificate.
(a) enroll: pending, then issued after an admin approve
enroll1.log:
pending.log:
approve.log:
enroll2.log (the
certificate_pemline, a public certificate chain, is left out for length):(b) one clean poll; server_time matches +00:00
poll1.log:
Checks on the logs:
(c) renew, and its audit row
renew.log:
audit.log (this run's row; the second line of the file, a row from the previous run, is left out):
(e) FOG_CLIENT_CHECKIN_TIME = "90.5" gives poll_interval 90
setting-set.log:
poll-905.log:
setting-unset.log:
setting-get.log:
(d) host deleted: the next poll re-enrolls
delete-host.log:
poll-deleted.log:
Cleanup
cleanup.log:
The Setting is absent again, as it was before the run (setting-get.log). The audit
rows and the
agentIdcounter stay, because the trail is append-only.A grep for a PEM private-key header gives 0 for every log in this folder and for this file.
The words token and secret appear only in two Sails route names in server.log and in the
description of admin.js above, never with a value.
🤖 Generated with Claude Code