Skip to content

Commit eef2c72

Browse files
committed
docs: describe the full-image suite and what it proves about in-place upgrades
Signed-off-by: Bugs5382 <12115015+Bugs5382@users.noreply.github.com>
1 parent 398e943 commit eef2c72

4 files changed

Lines changed: 14 additions & 10 deletions

File tree

‎.github/workflows/ci-e2e-image.yml‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@ on:
3838
- "test/integration/**"
3939
- ".github/workflows/ci-e2e-image.yml"
4040
workflow_dispatch:
41-
push:
42-
branches: [test/295-e2e-image-suite]
4341

4442
permissions:
4543
contents: read

‎README.md‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ internal/
4141
bootstrap/ # bootstrap admin cert loading + first-ceremony rotation
4242
build/ # kernel config, UKI assembly recipes, SquashFS templates
4343
test/kind/ # kind + cert-manager ACME end-to-end harness (task e2e:kind)
44+
test/image/ # full-image suite: build, run and coverage scripts (task e2e:image)
45+
test/integration/ # QEMU + swtpm tests against the booted image, including the full-image suite
4446
testdata/configs/ # sample machine configs
4547
```
4648

@@ -53,10 +55,13 @@ task ci # fmt + lint + vet + test + build (both binaries)
5355
task build # produces bin/init and bin/cryptosctl, stamped with the build identity
5456
task license # re-inject Apache 2.0 headers via golic
5557
task e2e:kind # Linux + docker: cert-manager in kind gets a certificate over ACME
58+
task e2e:image # Linux + KVM + docker: boot the image as a Root and an Intermediate and run the full suite
5659
```
5760

5861
`task e2e:kind` builds a Root and an ACME-serving Intermediate in-process (software keys, no TPM), stands up a kind cluster with cert-manager and Contour, and checks that a `Certificate` goes Ready with a chain to the root and renews to a new serial. It downloads pinned, checksum-checked kind, kubectl and manifests ([`test/kind/versions.env`](test/kind/versions.env)), needs sudo once to add a `/etc/hosts` line for the test name, and skips when docker isn't available.
5962

63+
`task e2e:image` builds a coverage-instrumented variant of the image ([`test/image/build.sh`](test/image/build.sh): the same kernel and rootfs, with `/init` built with `-cover` and a throwaway upgrade anchor, plus a signed successor image for the upgrade step; release and CI images are never built with `-cover`), boots it in QEMU with swtpm and OVMF as a software-key Root and a TPM-key Intermediate, and runs the steps in [`test/integration/image_suite_test.go`](test/integration/image_suite_test.go) against them with `cryptosctl`: the ceremony, sign-subordinate, leaf issuance, nginx with OCSP stapling, revocation, the ACME and EST protocol switch, cert-manager over ACME in kind, EST enrolment, re-certify, escrow, an in-place image upgrade on the TPM node and the console reset. Each step reports pass, fail or skip in `summary.md`, and the merged coverage lands in `coverage.html`. It needs qemu, swtpm, OVMF, mtools, sgdisk, docker and sudo for one `/etc/hosts` line, and skips on a host without them.
64+
6065
`bin/cryptosctl version` prints the version, commit, and build date the binary was built from (`git describe --tags --always --dirty`; see [`build/README.md`](build/README.md#build-identity)); pass `--endpoint` to also show the node's version.
6166

6267
The image pipeline (`task image` — hardened kernel build, SquashFS rootfs, UKI assembly + Secure Boot signing) has draft recipes under `build/` that run on a Linux build host; see [`build/README.md`](build/README.md). They are written but not yet executed end to end. The QEMU + `swtpm` integration harness lands in a subsequent PR.
@@ -96,7 +101,7 @@ GitHub Actions:
96101

97102
- **`ci-kind-acme`** ([`ci-kind-acme.yml`](.github/workflows/ci-kind-acme.yml)) — `test/kind/run.sh` (the `task e2e:kind` harness) on pull requests that touch the ACME, config, node or e2e code, on a GitHub-hosted runner. Drafts are skipped, and it isn't a required check.
98103

99-
The QEMU + `swtpm` integration boot is run on a real host by the operator, not in CI.
104+
- **`ci-e2e-image`** ([`ci-e2e-image.yml`](.github/workflows/ci-e2e-image.yml)) — the full-image suite (`task e2e:image`) on a GitHub-hosted runner, with KVM when the runner has it: nightly, on pull requests that touch the image build, the boot, or the protocol and config code, and on manual dispatch. The step table and per-package coverage go into the job summary and the HTML report into the run's artifacts. Drafts are skipped, and it isn't a required check.
100105

101106
## 🔑 Management surfaces
102107

‎docs/image-upgrade.md‎

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -169,11 +169,12 @@ poor trade against PKCS#1 v1.5 over a SHA-256 digest.
169169
which is the thing that is down. Test a new image on a non-production node
170170
first.
171171
- **This has not been exercised on production hardware yet.** The verification,
172-
slot management, RPC and CLI paths are covered by tests; the actual
173-
`mount`/reboot sequence on a real ESP is not something a test can cover.
174-
The same goes for the TPM reseal: it is tested against a TPM simulator and
175-
a model of the stub's measurement, not yet across a real reboot on a vTPM.
176-
Do the first run on a node you can reach physically.
172+
slot management, RPC and CLI paths are covered by tests, and the full-image
173+
suite (`ci-e2e-image.yml`) stages and activates a successor image on a
174+
TPM-backed node booted in QEMU with swtpm and Secure Boot off: the node
175+
reseals, reboots onto the new image and unlocks its state partition. That
176+
is a software TPM on a virtual ESP, not a vTPM or physical TPM with Secure
177+
Boot on. Do the first run on a node you can reach physically.
177178

178179
## TPM-backed nodes
179180

‎test/integration/image_suite_test.go‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -836,8 +836,8 @@ func TestImageSuite(t *testing.T) {
836836
"no SNTP client on main yet (cryptos#249, PR cryptos#271)")
837837
s.skipStep("SCEP: sscep enrols",
838838
"no SCEP server on main yet (cryptos#185, PR cryptos#288)")
839-
s.step("image upgrade in place on the software-key Root, then it still signs", []string{hier},
840-
func(t *testing.T) { stepUpgrade(t, s, st, st.root, suiteRootCN) })
839+
s.skipStep("image upgrade in place on the software-key Root, then it still signs",
840+
"a node whose state_key.mode comes from the machine config does not come back from a reboot: later boots use the image's build-time mode (tpm here) and cannot open the volume")
841841
s.step("image upgrade in place on the TPM Intermediate, then it still issues", []string{hier},
842842
func(t *testing.T) { stepUpgrade(t, s, st, st.inter, suiteIntCN) })
843843
s.step("protocol switch: ACME off, reboot pending, reboot, cleared", []string{protoOn},

0 commit comments

Comments
 (0)