feat(fleet): re-key a subordinate CA live via one orchestrated RPC#45
Merged
Conversation
…root) resolveParentByCN maps a self-signed root to itself, which would ask the root to re-sign its own key under a subordinate profile. Guard child==parent and return FailedPrecondition.
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
Adds
FleetService.RekeyNode, a single operator-gated RPC that re-keys a subordinate CA end to end. Mirroring the SUBORDINATE path ofApproveEnrollment, the manager runs the whole ferry internally: it has the child mint a new key + CSR (BeginKeyRotation), resolves the parent from the child's issuer CN (resolveParentByCN), routes the CSR to the parent for signing under the request profile (SignSubordinateCSR), and delivers the signed chain back to the child (CompleteKeyRotation). It reusesrunSubordinateFerry's chain-field mapping so there is no DER/PEM mismatch, closes every dialed connection, and appends exactly onerekeyedaudit event on success.Authz is checked before any dial or audit: a viewer is denied, an unknown child is a not-found, and a parent that is not a known fleet node is a clear failed-precondition (a manual ferry is out of scope for v1.0.0; the two-tier case has the parent in-fleet). No audit is written on any failure path.
nodeclient.ClientgainsBeginKeyRotation/CompleteKeyRotation(the node-side RPCs already exist).Closes #29
Part of #24
Verification
How this was verified
task ci(gofmt, vet, golangci-lint 0 issues, all tests) andtask license(0/39 changed).internal/fleet/rekey_test.gocovers the viewer-denied, unknown-node, parent-not-in-fleet, happy-path (ferry order + chain mapping + response + single audit), and node-step-error (mapped error, no audit) cases.Merge order
Depends on CryptOS-PKI/api#56 (adds the
RekeyNodeproto/stubs). api must merge first. This branch temporarily pins api at its branch pseudo-version so the manager builds; the pin will be moved to the api merged-main pseudo-version once api#56 lands (thechore(deps): bump api for RekeyNodecommit).