Repository navigation
feat(bootstrap): first-run token, session, operator CA registration and first admin - #160
Merged
Merged
Conversation
2 tasks done
Signed-off-by: Bugs5382 <12115015+Bugs5382@users.noreply.github.com>
Signed-off-by: Bugs5382 <12115015+Bugs5382@users.noreply.github.com>
…first admin and latch Signed-off-by: Bugs5382 <12115015+Bugs5382@users.noreply.github.com>
…ts own CA Signed-off-by: Bugs5382 <12115015+Bugs5382@users.noreply.github.com>
… latch from the API path Signed-off-by: Bugs5382 <12115015+Bugs5382@users.noreply.github.com>
Signed-off-by: Bugs5382 <12115015+Bugs5382@users.noreply.github.com>
Signed-off-by: Bugs5382 <12115015+Bugs5382@users.noreply.github.com>
…en accepting an operator certificate Signed-off-by: Bugs5382 <12115015+Bugs5382@users.noreply.github.com>
…keep first run off the plaintext listener Signed-off-by: Bugs5382 <12115015+Bugs5382@users.noreply.github.com>
Signed-off-by: Bugs5382 <12115015+Bugs5382@users.noreply.github.com>
…ot a refusal Signed-off-by: Bugs5382 <12115015+Bugs5382@users.noreply.github.com>
… revokes Signed-off-by: Bugs5382 <12115015+Bugs5382@users.noreply.github.com>
Bugs5382
force-pushed
the
feat/148-bootstrap-first-run
branch
from
October 1, 2026 14:29
1f4ee9f to
748e8cc
Compare
Bugs5382
marked this pull request as ready for review
October 1, 2026 14:29
4 tasks done
Contributor
Author
|
Merging for the v0.1.0 test run: CI green and mergeable at merge time. |
This was referenced Oct 1, 2026
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
First run: a Fleet Manager started with Postgres and no operator CA prints a single-use bootstrap token in its log, and the token holder registers the external operator CA's certificate and checks the first admin certificate that CA signed. The manager signs nothing; the session only teaches it which anchor to trust. First run closes for good the first time an admin certificate signs in.
Closes #148
Refs #78
Merge order: independent of open PRs; based on
mainafter #149, #151, #152, #150, #158 and #159. Merge together with the docs companion CryptOS-PKI/docs#79.What changes
internal/bootstrap):fos_boot_tokens: 256 random bits in Crockford base32, grouped in fours, typed forgivingly (case, dashes, O/I/L).fleetos.bootstrap_tokenadvisory lock prints at start and on expiry.fos_bsess_sessions travel in theFleetos-Bootstrap-Sessionheader and are stored as hashes. They end after 15 minutes idle or 60 minutes in all, and there is one live session.BootstrapService:GetBootstrapStatereportsNOT_APPLICABLEfor the file source,UNAVAILABLEwithout Postgres or withfirstRun: disabled, and otherwiseOPEN,OPEN_IN_PROGRESSorCLOSED.StartBootstrapSession.RegisterOperatorCA:confirm_sha256; colons and case don't matter;url(fetched now),crl_der(checked now) ornone(needsNO_CRL);aia,urloroff, with the url-mode probe from feat(operatorca): check operator certificates with the CA's OCSP responder #151;ValidateAnchor.ca_cert_derreturns its preview, which is empty, and not counted as a failure, when nothing is registered.SubmitFirstAdminCertificatetakes a CSR, or no CSR as a path B pre-flight, and runs the shared profile check. A different later certificate puts the earlier first-admin certificate on the denylist (reason superseded, D14).CertCheck.CheckRevocationruns the live revocation decision (Revocations.CheckWebCert) insideCheckOperatorCert. First-admin submission andRecordOperatorCredentialtherefore both refuseREVOKED_OCSPandOCSP_UNKNOWN, and return 1608 underhardwith no fresh data.authz.AuthHookruns after a request passes the certificate and revocation checks. The first admin request from either source closes first run. Closing ends sessions, deletes tokens, records an unrecorded certificate asfirst_admin(path B without a pre-flight), logs the close and audits it. Viewer, operator and revoked admin certificates don't close it, and nothing reopens it. A closed first run that trusts no CA logs why every caller is refused.mcpauth's failure limiter moves tointernal/ratelimit; MCP keeps its numbers.X-Forwarded-Forisn't trusted.rootMountskeeps it off theauthBypassplaintext listener.corsOrigins.RegisterOperatorCA.withCORSallows the session header.bootstrap_sessiononbootstrap-session-started,operator-ca-registered,operator-first-admin-recorded,operator-first-admin-supersededandbootstrap-token-rotated.bootstrap-closednames the admin certificate. Neither secret appears in any error, audit row or log line other than the token's own banner.operatorca.NodeCAWatchsees the chains nodes report throughGetIdentity(node list and detail). When a chain holds a trusted anchor (by certificate or key) it logs an ERROR once and raises a banner flag, keeping the anchor until the next start.store.Bootstrapover the v7 tables, implemented by Postgres with a conformance suite. The in-memory store doesn't implement it, so first run is unavailable there.PutOperatorCRL's transaction body is shared with registration.Notes
full_nameerrors return 1610 with no sub-reason for now. CryptOS-PKI/api#138 addsFULL_NAME; the manager switches to it in a follow-up once that merges and api is re-pinned.ocsp_probestays empty: feat(operatorca): check operator certificates with the CA's OCSP responder #151's probe reports only pass or fail. A confirmed registration means the probe passed.ListOperatorCAs(operator CA rotation) is the place for it.Tests
store.Bootstrap.TestRegister_NothingRegisteredToPreviewnow expects an empty preview instead of 1605.TestValidFullName, sinceoperatorca.ValidateFullNamefrom feat(operators): credential requests, recording and denylist revoke #152 replaces the local check.Verification
How this was verified
task ci(gofmt, vet, golangci-lint, the full test suite with a throwaway Postgres for the store tests) passes on this tree, andtask licensechanges nothing.first run CLOSED by ..., then 1601 everywhere), and a restart printing no token with the same server fingerprint.docs/first-run.md(new), links from the README anddocs/operator-ca.md, and the OCSP refusals indocs/operator-credentials.md. Docs site companion: docs(fleet-manager): first run, from the operator CA to the first admin docs#79.