Skip to content

feat(e2e): drive a real SCEP enrolment and the full image lifecycle - #213

Merged
Bugs5382 merged 4 commits into
mainfrom
feat/207-scep-image-lifecycle
Oct 16, 2026
Merged

Bugs5382 merged 4 commits into
mainfrom
feat/207-scep-image-lifecycle

Conversation

@Bugs5382

@Bugs5382 Bugs5382 commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

What and why

The live write-path run (test/e2e/esxi) gets the two pieces #207 asks for, and the changes it needs to run against the QEMU suite's nodes on CI (#38):

  • A real SCEP device enrolment. A small RFC 8894 client (scepdevice.go, on github.com/smallstep/scep and its pkcs7 package) enrols with a fresh RSA 3072 identity through a challenge minted by the manager. One enrolment is approved through the manager and the device collects its certificate with CertPoll; a second is rejected and the device gets FAILURE. Both are checked on the node: the approved serial is in the node's own ListIssued, and the rejected enrolment has left its queue. It needs E2E_SCEP_URL and a require_approval SCEP profile; without them it skips with the reason. I took the dependency because SCEP needs CMS envelopes and signed attributes, far more code to write by hand.
  • The whole image lifecycle. Stage, activate and wait until the node is back running the new image, roll back, activate again and wait until it's back on the image it started on. Before, rollback was sent while the node was still rebooting.
  • Escrow. Export and import are separate steps. The export can target a software-key node (E2E_ESCROW_NODE), because a TPM-held CA key is never exportable. The import now runs after the enrolment step that links the spare, the only point at which the manager can address it.
  • Protocol toggle. SetNodeProtocol switches ACME and EST only, so toggling SCEP was always refused. The step now toggles whichever of EST and ACME the node has on, and finds the catalog adapter by kind, since the catalog matches by name and starts empty on a fresh manager.
  • Harness settings. E2E_MANAGER_LISTEN moves the throwaway manager off a port the host already uses, and E2E_RESULTS_FILE writes the step results as JSON so a harness can report each one.

The appliance PR that runs this in the QEMU suite will close both issues.

Refs #207
Refs #38

Verification

  • Lint clean (CI)
  • Tests pass (CI): new unit tests for the config settings, the results file, the SCEP profile and enrolment matching, the escrow source, and the SCEP client against an independent fake server
  • Build succeeds (CI)
  • Documentation updated: docs/e2e-esxi.md (what it proves, new settings, CI scope) and the e2e:esxi task description

How this was verified

CI is the proof: Go CI runs fmt, vet, golangci-lint, build and the unit tests. The live run against real nodes is proven by the cryptos-appliance full-image suite once that PR pins this commit; its step table reports each step of this run.

The live write-path run now enrols two real RFC 8894 SCEP devices
through challenges minted by the manager, approves one and rejects the
other through the manager, and checks both outcomes from the device and
on the node. The device client uses github.com/smallstep/scep and its
pkcs7 package: SCEP needs CMS envelopes and signed attributes, and
writing those by hand would be far more code than the dependency.

The image step runs the whole lifecycle: stage, activate and wait for
the node to come back on the new image, roll back, activate again and
wait for it to come back on the image it started on. Before, rollback
was sent while the node was still rebooting.

The escrow export can target a software-key node (E2E_ESCROW_NODE),
since a TPM-held CA key is never exportable, and the import now runs
after the enrolment step that links the spare, the only point at which
the manager can address it. The SCEP steps run before the protocol
toggle, whose switch-off drops the node's stored pki.scep block.

E2E_MANAGER_LISTEN moves the throwaway manager off a port the host
already uses, and E2E_RESULTS_FILE writes the step results as JSON for
a harness to report each one.

Refs #207
Refs #38

Signed-off-by: Bugs5382 <12115015+Bugs5382@users.noreply.github.com>
@Bugs5382 Bugs5382 added this to the v0.1.0 milestone Oct 16, 2026
@Bugs5382 Bugs5382 added the enhancement New feature (feat). Minor version bump. label Oct 16, 2026
@Bugs5382 Bugs5382 self-assigned this Oct 16, 2026
Refs #207

Signed-off-by: Bugs5382 <12115015+Bugs5382@users.noreply.github.com>
The adapter catalog matches by name and a fresh manager's catalog is
empty, so SetAdapterEnabled("scep") always came back not found. The
protocol step now finds the SCEP adapter by its kind and says when the
catalog has none, and still proves the node's own SCEP switch.

Refs #38

Signed-off-by: Bugs5382 <12115015+Bugs5382@users.noreply.github.com>
SetNodeProtocol switches ACME and EST only, so the step's SCEP toggle
was refused every time. The step now toggles whichever of EST and ACME
the primary node has on, on (already on) and then off, checking the
node's stored switch each time, and skips when neither is on: switching
one off drops its stored settings, and switching one on without them is
refused by the node.

Refs #38

Signed-off-by: Bugs5382 <12115015+Bugs5382@users.noreply.github.com>
@Bugs5382
Bugs5382 merged commit a2dd853 into main Oct 16, 2026
12 of 13 checks passed
@Bugs5382
Bugs5382 deleted the feat/207-scep-image-lifecycle branch October 16, 2026 15:23
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.

1 participant