Repository navigation
feat(adopt): confirm the installed node's fingerprint before trusting it - #150
Merged
Merged
Conversation
This was referenced Sep 30, 2026
Merged
After a node installs and reboots during adoption it presents a new management certificate that nothing links to the maintenance certificate the operator confirmed. Adoption no longer pins it on first use. It captures the certificate, streams the awaiting-fingerprint-confirmation phase with its SHA-256 and the adoption ID, and waits for ConfirmAdoptionFingerprint. A matching fingerprint (case, colons and spaces ignored) resumes the adoption, and only then is the certificate pinned and the node dialed against it. A mismatch, no confirmation within 15 minutes, or the client going away fails the adoption with nothing pinned, recorded or registered. Confirmations and refusals are audited with the operator. The new RPC is excluded from the MCP catalog. Closes #144 Refs #135 Signed-off-by: Bugs5382 <12115015+Bugs5382@users.noreply.github.com>
Bugs5382
force-pushed
the
feat/144-adopt-fingerprint-confirm
branch
from
October 1, 2026 13:31
377d8d1 to
ef26df3
Compare
Bugs5382
marked this pull request as ready for review
October 1, 2026 13:31
Contributor
Author
|
Merging for the v0.1.0 test run: CI green and mergeable at merge time. |
4 tasks done
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 and why
When the manager adopts a node, the node installs, reboots and comes back with a new management certificate. Nothing links that certificate to the maintenance certificate the operator confirmed with
PreviewAdoption. Until now the manager pinned it on first use and only showed its fingerprint in the progress. Now the adoption pauses until an admin confirms the installed node's fingerprint against theMgmt SHA-256line on the node's console. This uses the contract from CryptOS-PKI/api#133.awaiting-fingerprint-confirmationwithpresented_cert_sha256. Every streamed message carriesadoption_id.ConfirmAdoptionFingerprint{adoption_id, cert_sha256}resumes the adoption when the fingerprint equals the presented one (case, colons and whitespace ignored). Only then is that certificate written as the node'sserver.crtand the node dialed against it. After the ceremony a root's chain is recorded as before, over that verified connection.InvalidArgument. Nothing is pinned, no CA chain is recorded, the node isn't registered and there is nonode-adoptedevent.DeadlineExceeded), or the client going away (the wizard's cancel): the adoption stops with nothing recorded.adoption_id:NotFound.node-adoption-fingerprint-confirmed(ok) andnode-adoption-fingerprint-rejected(denied), with the operator who sent it, the node, the endpoint and both fingerprints.Replicas: the waiting adoption is held in memory by the replica running the stream, like the protocol-switch reboot tracker. With
replicaCountabove 1, a confirmation that lands on another replica getsNotFoundand has to be sent again. The chart defaults to one replica.docs/node-trust.mdstates this in a warning.Existing tests changed:
TestRunAdoption_Root_PinsRunningCertAndRecordsCAChainandTestRunAdoption_Subordinate_PinsRunningCertWithoutChaincovered the trust-on-first-use pin that this change removes. With it they block waiting for a confirmation, so they now confirm through a smallconfirmingSinkhelper and still check the same pin and chain results.TestCatalog_MatchesTheFleetServiceContractfailed on the new RPC until the catalog row was added.Closes #144
Refs #135
Merge order: this re-pins api for the manager to api
main(29b56ec), which has CryptOS-PKI/api#133 (this contract) and api#135 (Go 1.26.8). It sits on managermainafter #149 and #152. Merge this together with the docs companion CryptOS-PKI/docs#71 and with CryptOS-PKI/cryptos-web#143 (the wizard's confirm step). Without web#143, the current wizard stalls on the new phase until the 15-minute wait expires.Docs:
docs/node-trust.md("What adoption records"),docs/mcp.mdand the README. Docs site companion: CryptOS-PKI/docs#71.Verification
How this was verified
internal/fleet/adopt_confirm_test.gowere written first. They cover:established, and both audit events;InvalidArgument, error phase, noserver.crt, noca.crt, no node, no dial, the rejected audit event, andNotFoundon a second confirm;adoption_idon every streamed message, withpresented_cert_sha256only on the paused phase.main(cd3a52f),task ci(gofmt, vet, golangci-lint with 0 issues,go test ./...) passes with a throwaway Postgres 18 andMANAGER_TEST_DATABASE_URLset, so the store integration tests ran too.task licensepasses.go test -race -count=3on the adoption tests passed before the rebase.