Skip to content

stage1: split config-gen into a deploy tool; extract shared metadata + ed25519 libs#12

Merged
HarryR merged 2 commits into
mainfrom
feat-extract-metadata-signer
Jul 5, 2026
Merged

stage1: split config-gen into a deploy tool; extract shared metadata + ed25519 libs#12
HarryR merged 2 commits into
mainfrom
feat-extract-metadata-signer

Conversation

@HarryR

@HarryR HarryR commented Jul 5, 2026

Copy link
Copy Markdown
Collaborator

Splits deployment-config generation out of the on-instance stage1 binary into a separate host-side deploy tool, and extracts the wire types + ed25519 signer into shared crates so "what we emit" and "what we verify" cannot drift. Repos stay fully separate (stage0 keeps its own config.rs/sig.rs).

New crates

  • metadata - the _stage1/_stage2 wire types (UrlList, ArchConfig, StageConfig, UserData) + Verify + validate(Profile), extracted from the stage1 bin. The stage1 verifier and the deploy emitter both depend on it (one source of truth). Carries the JSON schema + the validate() test table. Profile::Stage0 is http-only; Stage1 allows https.
  • ed25519-sign - the ed25519 wire primitive: sign_payload + verify + sha256_hex. Extracted from mkuki/sign.rs (mkuki re-exports it as mkuki::sign) with stage1's sig.rs verify folded in, so mkuki (sign), deploy (sign) and stage1 (verify) share one crate.
  • deploy - lockboot-deploy create / validate / modify. create signs (or hashes) the UKI + stage2, composes mirror URL lists from repeated --base-url, and emits an upload-ready dir + a merged user-data.json carrying _stage1 + _stage2. validate checks a doc via the shared validate(); modify adds/removes mirror base URLs.

Slimmed

  • stage1 bin: on-instance runtime only. Removed make_config*/emit_config and the --make-config* CLI; keeps --attest, --url/--file, PID1 boot, admission, measurement. Uses the metadata + ed25519-sign crates. Runtime behavior unchanged.
  • Makefile: exclude the host-only deploy tool from the payload-target cross-build.

Verification

  • Unit tests: ed25519-sign (2) + metadata (12) + deploy (3), all pass; both arches compile.
  • Smoke: create -> signed 2-mirror _stage1+_stage2 + signed args; validate clean; modify add/remove mirrors.
  • End-to-end: the full chain (stage0 -> UKI -> stage1 -> example-stage2) boots and powers off cleanly against the deploy tool's OWN signed output - both ed25519 hops + signed remote args verified.

Note: deploy validate uses the authoritative Rust validate(). Wiring the jsonschema crate + a combined user-data schema + fixtures (to machine-check the shipped JSON schema) is left as a small follow-up.

Depends on nothing; the sibling stage0 fallback-URL change (lockboot/stage0#1) already merged.

Generated with Claude Code

HarryR and others added 2 commits July 5, 2026 11:23
…a + ed25519 libs

The stage1 runtime binary was dual-purpose (boot on-instance AND generate deployment
config via --make-config). Split config generation into a separate host-side tool so the
on-instance binary carries only runtime concerns, and share the wire types + signer so
"what we emit" and "what we verify" cannot drift.

- crates/metadata (new): the _stage1/_stage2 wire types (UrlList, ArchConfig, StageConfig,
  UserData) + Verify + validate(Profile), extracted from the stage1 bin. The stage1
  verifier and the deploy emitter both depend on it (one source of truth). Carries the
  JSON schema + the validate() test table. Profile::Stage0 is http-only; Stage1 allows https.
- crates/ed25519-sign (new): the ed25519 wire primitive: sign_payload + verify + sha256_hex.
  Extracted from mkuki/sign.rs (mkuki re-exports it as `mkuki::sign`) with stage1's sig.rs
  verify folded in, so mkuki (sign), deploy (sign) and stage1 (verify) share one crate.
- crates/deploy (new): `lockboot-deploy` create/validate/modify. `create` signs (or hashes)
  the UKI + stage2, composes mirror URL lists from repeated --base-url, and emits an
  upload-ready dir + a merged user-data.json carrying _stage1 + _stage2. `validate` checks a
  doc via the shared validate(); `modify` adds/removes mirror base URLs.
- stage1 bin: slimmed to on-instance runtime only. Removed make_config*/emit_config and the
  --make-config* CLI; keeps --attest, --url/--file, PID1 boot, admission, measurement. Uses
  the metadata + ed25519-sign crates. Runtime behavior unchanged.
- Makefile: exclude the host-only deploy tool from the payload-target cross-build.

Repos stay fully separate: stage0 keeps its own config.rs/sig.rs (minimal root-of-trust
audit surface); the shared crates live in the stage1 repo, consumed by its own crates.

Verified: ed25519-sign (2) + metadata (12) + deploy (3) unit tests pass; both arches
compile; the full chain (stage0 -> UKI -> stage1 -> example-stage2) boots and powers off
cleanly against the deploy tool's OWN signed output: both ed25519 hops + signed remote args.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Two hardening fixes from the boot-path security review:

- Install a panic hook that routes any panic through the same poweroff()
  as a returned error. As PID 1 an unhandled panic would abort into a
  kernel panic and skip the log-drain wait; now every failure (error or
  panic) converges on one shutdown path so its logs reach the serial
  console before power-off.

- download_binary returns reqwest's owned Bytes instead of .to_vec(), and
  download_first/admit_from/admit_payload thread Bytes through. This drops
  a full-length copy of the stage2 payload (and the signature / signed-args
  blobs). Bytes derefs to [u8], so admission and PCR 14 measurement see
  identical bytes and are unchanged.

Verified: full chain boots and powers off cleanly in both sha256 and
ed25519 modes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@HarryR HarryR merged commit 764b6f5 into main Jul 5, 2026
4 checks passed
@HarryR HarryR deleted the feat-extract-metadata-signer branch July 5, 2026 16:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant