Skip to content

feat(operatorca): admin rotation and CRL/OCSP settings - #162

Merged
Bugs5382 merged 4 commits into
mainfrom
feat/157-operatorca-rotation
Oct 1, 2026
Merged

Bugs5382 merged 4 commits into
mainfrom
feat/157-operatorca-rotation

Conversation

@Bugs5382

@Bugs5382 Bugs5382 commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

What and why

Operator CA changes after first run go through admin FleetService RPCs. Until now they answered Unimplemented. This PR serves them.

  • ListOperatorCAs (operator): active first, then retiring, then retired. Each row has the fingerprint, notAfter, CRL source and the CRL the manager holds (thisUpdate, nextUpdate, number, revoked count, fetched_at, last error, stale). It also has the OCSP mode and URL, this replica's last OCSP error, acknowledgements and warnings. A config-file CA is listed read-only with managed_by_config.
  • RegisterOperatorCA (admin): runs the first-run checks (anchor rules, CRL source with fetch and verify, OCSP mode with the url probe), returns a preview, then takes confirm_sha256. In one store transaction the new CA becomes active and the previous active CA becomes retiring, so both stay trusted and revocation-checked during the overlap. A second registration while a CA is retiring gives 1605 ROTATION_IN_PROGRESS.
  • RetireOperatorCA (admin): refuses the active CA (1609). It also refuses the caller's own CA unless i_understand_self_lockout is set; that refusal is a plain FailedPrecondition that names the flag. Certificates under a retired CA are refused from their next request.
  • SetOperatorCACRLSource (admin): url, crl_der (upload) or none with NO_CRL. A new URL or CRL must verify against the CA first.
  • UploadOperatorCRL (admin): verified and anti-rollback checked through the revocation engine, then stored with an epoch bump.
  • SetOperatorCAOCSP (admin): off, aia or url. url must pass the responder probe, and the response reports who signed the probe answer.

Every write:

  • is admin-gated;
  • is audited (operator-ca-registered, operator-ca-retired, operator-ca-crl-source-changed, operator-crl-uploaded, operator-ca-ocsp-changed);
  • rebuilds the trust store on the writing replica and moves the trust version, so the other replicas follow within one poll;
  • returns 1607 while operatorCAPath is set.

An upload CRL source is refused under operatorRevocationPolicy: hard, because the manager would refuse to start with that combination.

Supporting changes:

  • store: RotateOperatorCA, SetOperatorCACRLSource and SetOperatorCAOCSP, atomic in Postgres. The CRL write is split into a transaction helper, the same helper feat(bootstrap): first-run token, session, operator CA registration and first admin #160 adds. The in-memory store refuses them, as it does registered rows.
  • storetest.MemoryTrust: an in-memory operator trust store for other packages' tests, checked against the same contract as Postgres.
  • operatorca:
    • CheckCRLChoice and CheckOCSPChoice, the shared registration checks;
    • OCSPClient.ProbeResult, which returns the signer;
    • a per-CA last OCSP error;
    • each replica drops a CA's cached OCSP answers when that CA's OCSP settings change.
  • cmd/manager wires in the CRL fetcher. The probe uses the revocation engine's OCSP client.

Removed test: TestFleetService_UnservedOperatorCAMethodsAreUnimplemented, because the methods are now served. TestFleetService_OperatorCAMethodsNeedAnOperatorCA replaces it.

Follow-up: #160 adds the runtime node-CA flag, so ListOperatorCAs can't show it yet. Once #160 is on main it takes a few lines.

Closes #157
Refs #78

Docs: docs/operator-ca.md in this PR, plus the companion CryptOS-PKI/docs#81. Merge the two together. The docs page links to the page CryptOS-PKI/docs#75 adds, so merge docs#75 first or at the same time.

Verification

  • Lint clean
  • Tests pass
  • Build succeeds
  • Documentation updated

How this was verified

  • task ci (gofmt, vet, golangci-lint, go test) passes with the Postgres integration tests on (MANAGER_TEST_DATABASE_URL against a throwaway Postgres 18), and task license is clean.
  • 16 new test functions, plus 7 store contract subtests that run against both Postgres and the in-memory fake. Each failed first for the right reason:
    • the RPCs answered Unimplemented;
    • the store methods returned "not implemented";
    • operatorca had no probe signer, no last OCSP error and no cache clearing.
  • I read the web Operator CAs page (feat(operator-cas): an Operator CAs page with registration, retirement, CRL and OCSP settings cryptos-web#146) against these handlers. Its request fields, the response fields it reads, and its handling of 1605, 1607 and 1609 all match.

@Bugs5382 Bugs5382 self-assigned this Oct 1, 2026
@Bugs5382
Bugs5382 marked this pull request as ready for review October 1, 2026 14:39
@github-actions github-actions Bot added the enhancement New feature (feat). Minor version bump. label Oct 1, 2026
… the OCSP probe signer and last error

Signed-off-by: Bugs5382 <12115015+Bugs5382@users.noreply.github.com>
…CRL source, CRL upload and OCSP mode

Signed-off-by: Bugs5382 <12115015+Bugs5382@users.noreply.github.com>
… CRL and OCSP settings

Signed-off-by: Bugs5382 <12115015+Bugs5382@users.noreply.github.com>
@Bugs5382
Bugs5382 force-pushed the feat/157-operatorca-rotation branch from 01cf13c to a0ea99e Compare October 1, 2026 21:22
…writes

Rebased onto the restructured main: the first-run fake store now has to implement the RotateOperatorCA, SetOperatorCACRLSource and SetOperatorCAOCSP methods this change adds to store.OperatorTrust. First run never calls them, so they refuse.

Signed-off-by: Bugs5382 <Bugs5382@users.noreply.github.com>
@Bugs5382

Bugs5382 commented Oct 1, 2026

Copy link
Copy Markdown
Contributor Author

Closing summary (after the org restructure): rebased onto cryptos-manager main. The imports now use the cryptos-manager and cryptos-node stub paths, and the first-run fake store gained the three new OperatorTrust methods, which refuse because first run never calls them. task ci passes locally against Postgres, and all checks are green.

@Bugs5382
Bugs5382 merged commit 0a7853e into main Oct 1, 2026
9 checks passed
@Bugs5382
Bugs5382 deleted the feat/157-operatorca-rotation branch October 1, 2026 21:24
@Bugs5382 Bugs5382 added this to the v0.1.0 milestone Oct 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature (feat). Minor version bump.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(operatorca): admin rotation and CRL/OCSP settings

1 participant