Repository navigation
feat(operators): credential requests, complete, deny and a client-side request page - #145
Merged
Merged
Conversation
…e request page The manager no longer signs operator credentials (IssueOperatorCredential is gone), so the Operators page could not issue anything. It now follows the external operator CA model: - Request credential: a P-384 key and CSR made in the browser with a mandatory encrypted key backup and a passphrase shown once, or a CSR the holder made. Shows the CSR, the extension section and the openssl ca command the manager returns. - Pending requests tab with cancel, and Complete: record the signed certificate and, when the browser can open the key backup, build the PKCS#12 with the same passphrase. - Deny at the Fleet Manager replaces revoke: RFC 5280 reasons 0-10 except 7, a note, and the reminder to revoke at the CA as well. - Kind, issuer, denylisted, CRL-revoked and last-seen columns. - An anonymous /request-credential page that makes the key, backup and CSR, and later the PKCS#12, with no network calls. - Messages for every 1600-1611 code and sub-reason. The TypeScript stubs are refreshed to api main. Signed-off-by: Bugs5382 <12115015+Bugs5382@users.noreply.github.com>
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
The manager no longer signs operator credentials: the operator CA is external, and the api contract (CryptOS-PKI/api#132) replaced
IssueOperatorCredentialwith credential requests and a denylist revoke. The Operators page still called the removed RPC, so it could not issue anything against a current manager. This brings it onto the request, sign out of band, record model.Refs #144
extensionRequest) or a CSR the holder made. Browser keys go through a mandatory key backup step: a 24-character passphrase from a 64-symbol alphabet is shown once with a copy button, and Continue stays disabled until the encrypted PKCS#8 backup (fleetos-<level>-<email>.key.pem) is downloaded. Only then is the request filed and the CSR shown, with the extension section and theopenssl cacommand the manager returns. An uploaded CSR whose CN isn't the holder's email is refused in the browser.FleetOS <level> (<email>)friendly name. Record certificate… imports one made entirely at the CA.operatorCAPathor first run) instead of namingoperator_ca_node./request-credential, outside the login gate and linked from it: makes the key, key backup and CSR, and later builds the PKCS#12 from the backup and the signed certificate. It makes no network calls and doesn't import the Fleet Manager client.errorReason()readsx-cryptos-error-reason, andsrc/lib/fleet/error-copy.tsmaps every 1600-1611 code and sub-reason (including STALE_OCSP, NO_CRL, REVOKED_OCSP, OCSP_UNKNOWN, OCSP_UNREACHABLE, OCSP_INVALID) to a message. The new screens show those messages with the code to quote.assemblePkcs12takes an optional friendly name (PKCS#9 bag attribute on the key and leaf bags).operator-issue-dialog.tsx(and its test) andoperator-revoke-dialog.tsx.src/gen/fleet/is refreshed to apimain(29b56ec), which addsbootstrap_pb.ts,errors_pb.tsandoperator_ca_pb.ts.wire-fields.test.tspins the new credential, request and operator CA fields.Tests removed or changed (the behaviour they covered is gone or intentionally changed):
src/components/operator-issue-dialog.test.tsx, all four tests: the issue dialog is removed.src/lib/operators.test.ts: theissueOperatorCredentialtests (mock issue, unknown level, empty CSR, live issue) and therevokeOperatorCredentialtests (mock revoke, live revoke error). Replaced by tests for create, list, cancel, record and deny; the level and empty-CSR checks moved to request creation.src/pages/operators.test.tsx: the Issue action became Request credential, the empty state no longer says the manager only lists what it issued, and the 1400 view no longer namesoperator_ca_node.Merge order: with or after CryptOS-PKI/cryptos-manager#152 (credential requests, record, denylist revoke); against a manager without it the new RPCs are refused. Either order with #143: both refresh
src/gen/fleet/. Whichever merges second keeps this PR's copy, generated from apimain, which is a superset of #143's (it already carriesConfirmAdoptionFingerprintand the newAdoptNodeResponsefields), so both keep compiling.AGENTS.mdandwire-fields.test.tsmay need a trivial rebase too.Docs: companion CryptOS-PKI/docs#74 (two new task pages and the web UI page). README and AGENTS.md are updated here. Next PRs for #144: the Operator CAs page and banners, then the first-run wizard.
Verification
How this was verified
src/lib/fleet/error-copy.test.ts(every code and each code/sub-reason pair has its own message),src/lib/crypto/key-backup.test.ts(64-symbol 24-character passphrase, PEM and DER round trip, wrong passphrase, key/certificate match, PKCS#12 opens with the backup's passphrase),src/lib/crypto/pkcs12.test.ts(friendly name),src/lib/operators.test.ts,src/components/key-backup-step.test.tsx(no Continue before the download, passphrase gone on remount, nothing in storage),src/components/credential-request-wizard.test.tsx,src/components/credential-complete-dialog.test.tsx,src/components/operator-deny-dialog.test.tsx,src/pages/operators.test.tsx,src/pages/credential-request.test.tsx, plus the App and auth gate route tests.fetch, capture every Connect request body, and assert that neither the PKCS#8 key (base64, base64url, a slice of it), the JWKd, the passphrase nor the backup appears.fetch,XMLHttpRequest.open,sendBeaconand the Fleet Manager client are spied and never called across the whole flow.openssl pkey,openssl pkcs12 -info), and the CSR shows the requested extensions with the level extension non-critical.npm run lint,npm test(85 files, 488 tests),npm run buildandtask licensepass locally.