Skip to content

feat(launcher): hardened reproducible TDX image build pipeline#75

Open
0xHansLee wants to merge 3 commits into
feat/impl-tdx-backendfrom
feat/launcher
Open

feat(launcher): hardened reproducible TDX image build pipeline#75
0xHansLee wants to merge 3 commits into
feat/impl-tdx-backendfrom
feat/launcher

Conversation

@0xHansLee

Copy link
Copy Markdown
Collaborator

Summary

Adds launcher/ — the build pipeline and runtime layout that turns story-kernel into a production-grade Intel TDX validator image. The image is byte-for-byte reproducible, boots a measured, read-only root, and exposes no remote entry path, so the sealed validator keys cannot be read back even by a root user on the host.

Stacked on #68. This branch is based on feat/impl-tdx-backend (the TDX attestation backend). Please set the PR > base branch to feat/impl-tdx-backend and review/merge #68 first — the diff here is launcher-only.

What's included

Path Purpose
launcher/mkosi/ mkosi image definition: package set, skeleton rootfs, systemd units (kernel service, swtpm, RTMR3 extend, binary measurement), tmpfiles, post-install
launcher/build/ build.sh, pinned builder Dockerfile.builder, and verify-reproducible.sh (byte-identical re-build check)
launcher/hardening/ Layer-3 hardening applied into the image (no SSH server, masked gettys, locked accounts)
launcher/boot/, launcher/initrd/ UKI boot configuration and initrd inputs
launcher/attestation/ Post-boot helper to extract RTMR3 from a fresh quote and derive the binary commitment
launcher/tests/ Build-pipeline tests (binary-commitment, cmdline diff, manifest, systemd units, shellcheck) + run-all.sh
launcher/docs/ Operator guide, auditor/reproducibility guide, architecture, threat model

Also un-ignores launcher/build/ in .gitignore (it is build tooling, not build output) and points the legacy enclave/tdx/setup/production-image.md to the launcher docs.

Image properties

  • Reproducible: two independent builds from the same source produce a byte-identical disk image (pinned builder digest, fixed seeds, deterministic filesystem hashing). verify-reproducible.sh asserts this.
  • Measured boot: the kernel binary is measured into RTMR3 (yielding the on-chain binary_commitment) and into PCR 12; key sealing is bound to that measured state.
  • Integrity-protected root: root filesystem is read-only dm-verity.
  • No remote entry path: no SSH daemon, all login consoles masked, root and system accounts locked; only the kernel gRPC port is exposed.
  • UKI boot: kernel + initrd + command line in a single unified image so the command line is part of the measurement.

Build & verify

# Build the TDX image (inside the pinned builder container)
make build-tdx
( cd launcher/mkosi && mkosi build )

# Confirm the build is byte-identical reproducible
./launcher/build/verify-reproducible.sh

# Run the launcher build tests
./launcher/tests/run-all.sh

Test plan

  • verify-reproducible.sh passes (two builds byte-identical)
  • launcher/tests/run-all.sh passes (binary-commitment / cmdline / manifest / systemd-unit / shellcheck)
  • Image boots on a TDX VM; measured boot produces the expected binary_commitment
  • No remote shell reachable on a booted instance (SSH refused, consoles masked)

Docs

See launcher/docs/operator-guide.md (deliver → verify → launch → register → upgrade → recover) and launcher/docs/auditor-guide.md (reproducibility procedure and commitment derivation).

@wiz-837b06c6da

wiz-837b06c6da Bot commented Jun 17, 2026

Copy link
Copy Markdown

Wiz Scan Summary

Scanner Findings
Vulnerability Finding Vulnerabilities -
Data Finding Sensitive Data -
Secret Finding Secrets -
IaC Misconfiguration IaC Misconfigurations 1 High 24 Medium 1 Low
SAST Finding SAST Findings -
Software Management Finding Software Management Findings -
Total 1 High 24 Medium 1 Low

View scan details in Wiz

To detect these findings earlier in the dev lifecycle, try using Wiz Code VS Code Extension.

@jinn-agent

jinn-agent Bot commented Jun 17, 2026

Copy link
Copy Markdown

This revision addresses several prior findings (verify-rtmr3.sh dd cap, verify-reproducible.sh missing files, swtpm service ordering). The SealToFile atomic-write upgrade in enclave/tee.go is correct: temp file in same directory, explicit chmod, sync before rename, best-effort defer cleanup. The supportedProviders comment clarification in providers.go is accurate. A few new issues found below.

Coverage note: the launcher/mkosi/mkosi.postinst, all mkosi.repart/*.conf, and the mkosi.skeleton/ systemd units are not in the diff's commentable lines for this revision, so runtime boot-chain issues in those files can't be commented on directly.


Review iteration 4 · Commit 4ea39a9 · 2026-07-15T00:51:55Z

@jinn-agent jinn-agent Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


_Superseded by new review iteration._~~

_Superseded by new review iteration._~~

_Superseded by new review iteration._~~

_Superseded by new review iteration._~~

_Superseded by new review iteration._~~

_Superseded by new review iteration._~~

_Superseded by new review iteration._~~

_Superseded by new review iteration._

Comment thread launcher/initrd/scripts/early-rtmr3-stub.sh Outdated
Comment thread launcher/attestation/verify-rtmr3.sh
@0xHansLee
0xHansLee force-pushed the feat/impl-tdx-backend branch from b56583d to b9dd9f2 Compare June 20, 2026 07:12
@0xHansLee
0xHansLee force-pushed the feat/launcher branch 2 times, most recently from b84a7ab to c0c8911 Compare June 20, 2026 07:43

@jinn-agent jinn-agent Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


_Superseded by new review iteration._~~

_Superseded by new review iteration._~~

_Superseded by new review iteration._~~

_Superseded by new review iteration._~~

_Superseded by new review iteration._~~

_Superseded by new review iteration._~~

_Superseded by new review iteration._

Comment thread launcher/mkosi/mkosi.skeleton/etc/systemd/system/story-kernel-swtpm.service Outdated

@jinn-agent jinn-agent Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


_Superseded by new review iteration._~~

_Superseded by new review iteration._~~

_Superseded by new review iteration._~~

_Superseded by new review iteration._~~

_Superseded by new review iteration._~~

_Superseded by new review iteration._

Comment thread launcher/mkosi/mkosi.skeleton/etc/systemd/system/story-kernel-swtpm.service Outdated

@jinn-agent jinn-agent Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


_Superseded by new review iteration._~~

_Superseded by new review iteration._~~

_Superseded by new review iteration._~~

_Superseded by new review iteration._~~

_Superseded by new review iteration._

@0xHansLee
0xHansLee force-pushed the feat/impl-tdx-backend branch from bef9a75 to 89a3aa1 Compare June 22, 2026 02:23
@0xHansLee
0xHansLee force-pushed the feat/launcher branch 2 times, most recently from a6b22c2 to 31198da Compare June 22, 2026 02:31
@0xHansLee
0xHansLee force-pushed the feat/impl-tdx-backend branch from 89a3aa1 to 302cbf1 Compare June 23, 2026 10:06

@jinn-agent jinn-agent Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


_Superseded by new review iteration._~~

_Superseded by new review iteration._~~

_Superseded by new review iteration._~~

_Superseded by new review iteration._

Comment thread .github/workflows/launcher-reproducible.yml

@jinn-agent jinn-agent Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


_Superseded by new review iteration._~~

_Superseded by new review iteration._~~

_Superseded by new review iteration._

@jinn-agent jinn-agent Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


_Superseded by new review iteration._~~

_Superseded by new review iteration._

Comment thread .github/workflows/launcher-reproducible.yml
Add an mkosi-based build that produces a byte-identical, reproducible launcher image: a custom kernel, a read-only dm-verity root, Layer-3 hardening (no remote shell, locked accounts), and UKI boot. Includes the build scripts and a reproducibility guard, attestation/RTMR3 helpers, operator and auditor documentation, and build tests. Point the legacy production-image guide to the launcher docs and un-ignore launcher/build/ so the pipeline is tracked.

@ramtinms ramtinms left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me

Build the custom TDX kernel with CONFIG_MODULE_SIG=n (lockdown LSM
disabled so it cannot re-select signing), so the kernel — and therefore
platform_commitment — is reproducible byte-for-byte with no private
signing key. Adds launcher/kernel/ (pinned .config + build-kernel.sh)
and a CI job that builds it twice and asserts identical + keyless output.

Consolidate the launcher docs around the validated GCP CVM flow: merge
the GCP deployment guide into operator-guide.md, describe sealing on the
GCP confidential-VM vTPM (PCR 7/11/12), and drop intermediate
trial/decision narrative.

@jinn-agent jinn-agent Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found 1 critical issue(s) that need attention.

Superseded by new review iteration.

Comment thread launcher/build/verify-reproducible.sh
Address security-review findings on the TDX backend and launcher image.

Sealing:
- Bind each sealed DKG file to its logical slot ({round}/{codeCommitment}/
  {file}) via a PathBindingSealer, so a host with write access to the data
  partition cannot relocate a sealed blob to another slot or replay a stale
  round's blob into the current one. Verified by unseal-time identity check.
- Make SealToFile atomic (temp file + rename) and serialize load-or-generate
  key paths, so concurrent requests for the same round cannot orphan a
  registered pubkey without a matching sealed private key.

Boot integrity:
- Wire dm-verity into the measured boot via mkosi.repart (root + root-verity
  partitions). mkosi injects the roothash into the UKI command line, so the
  rootfs is read-only and its roothash is bound into platform_commitment.
  build.sh now reads that roothash and fails closed if none is produced.

Platform vTPM:
- Seal against the platform vTPM (/dev/tpmrm0) only. Drop the vestigial in-TD
  swtpm service, tpm2-abrmd, and the vtpm-proxy module. measure-binary now
  asserts /dev/tpmrm0.

Module lockdown:
- Disable kernel module loading after boot (kernel.modules_disabled=1) as a
  keyless, reproducibility-neutral second wall behind the no-root-entry
  property, and make story-kernel hard-require the lockdown unit so a failed
  lockdown fails the node closed instead of booting with module loading still
  enabled. Drop MODULE_FORCE_LOAD and serial SysRq from the kernel config.

Supply chain:
- Pin the kernel tarball to the GPG-verified upstream sha256 (autosigner@
  kernel.org) and always rebuild the source tree from clean so the pin cannot
  be bypassed by a reused workdir.

Also: fail-closed length guard + argv keccak in verify-platform.sh,
post-condition asserts in hardening/install.sh, reduced console log level,
a systemd-unit test guard for the lockdown dependency, and corrected
sealing/verity/report-data comments and docs.

@jinn-agent jinn-agent Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found 1 critical issue(s) that need attention.

Comment thread .github/workflows/launcher-reproducible.yml
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.

3 participants