You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: .ai-docs/TEE_CICD_Supply_Chain_Hardening.md
+68-19Lines changed: 68 additions & 19 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,10 +1,10 @@
1
1
# CI/CD Supply-Chain Hardening for Morpheus Docker Images
2
2
3
-
**Last updated:** 2026-04-22
3
+
**Last updated:** 2026-04-29
4
4
**First successful run (Phase 1a — signing):**[#22920492249](https://github.com/MorpheusAIs/Morpheus-Lumerin-Node/actions/runs/22920492249)
5
5
**First end-to-end run (Phase 1b — deploy + verify):**[#22969993910](https://github.com/MorpheusAIs/Morpheus-Lumerin-Node/actions/runs/22969993910)
6
6
7
-
> **v7.0.0 release status.** The CI/CD hardening described here is the foundation that every downstream trust check depends on. Both **Phase 1c** (consumer-side proxy-router verification of the P-Node) and **Phase 2** (P-Node verifies its own backend LLM) have shipped on top of it — see [`TEE_Attestation_Architecture.md`](TEE_Attestation_Architecture.md) §7.4 and §7.7for the code-level flow. The CI/CD pipeline itself remains unchanged from Phase 1b in this release; v7 is the *consumer* of the artifacts this pipeline produces.
7
+
> **v7.x release status (with AMD SEV-SNP).** The CI/CD hardening described here is the foundation that every downstream trust check depends on. Both **Phase 1c** (consumer-side proxy-router verification of the P-Node) and **Phase 2** (P-Node verifies its own backend LLM) have shipped on top of it — see [`TEE_Attestation_Architecture.md`](TEE_Attestation_Architecture.md) §7.4 and §7.7. **As of this release the pipeline now also publishes AMD SEV-SNP launch-digest goldens (one per portal template), pins SecretVM `v0.0.27-alpha.1`for both TDX and SEV rootfs, and bakes the proxy-router's privacy-sensitive `LOG_LEVEL_*` fields into the cosign-signed manifest's `baked_env` block.** The new SEV path mirrors the TDX one — Python compute script in CI (`compute-sev-measurement.py`) backed by the runtime Go source-of-truth (`sev_gctx.go`) with a parity test gating drift between the two.
8
8
9
9
---
10
10
@@ -90,24 +90,25 @@ The SBOM is attached to the image in GHCR as an OCI artifact and travels with th
90
90
91
91
### 4. TEE Attestation Manifest
92
92
93
-
This is the most important new artifact. It's a signed JSON document that records everything needed to verify a TEE deployment:
93
+
This is the most important new artifact. It's a signed JSON document that records everything needed to verify a TEE deployment, on **both** Intel TDX and AMD SEV-SNP platforms:
"small": "<96-char-hex SEV launch digest, vCPU=1>",
160
+
"medium": "<96-char-hex SEV launch digest, vCPU=2>",
161
+
"large": "<96-char-hex SEV launch digest, vCPU=4>",
162
+
"2xlarge": "<96-char-hex SEV launch digest, vCPU=8>",
163
+
"4xlarge": "<96-char-hex SEV launch digest, vCPU=16>"
164
+
}
138
165
}
139
166
}
140
167
}
@@ -147,9 +174,14 @@ This manifest is signed with cosign and attached to the image using `cosign atte
147
174
-**Image provenance**: Which commit, branch, workflow run, and timestamp produced this image. You can trace back to the exact source code.
148
175
-**Image chain**: The TEE image's digest AND the base image's digest. You can verify both independently.
149
176
-**Config integrity**: SHA256 hashes of `docker-compose.tee.yml` and `Dockerfile.tee`. If either file was modified between the build and a deployment, the hashes won't match.
150
-
-**Baked configuration**: The exact environment variables frozen into the image. A verifier can confirm that `PROXY_STORE_CHAT_CONTEXT=false` (no chat logging) and `ENVIRONMENT=production` are immutable — not overridable at runtime. The `network` field ("mainnet" or "testnet") and corresponding blockchain values (contract addresses, chain ID, blockscout URL) are set at build time based on the branch: `main` → mainnet (Base Mainnet 8453), `test` → testnet (Base Sepolia 84532). All other hardened settings are identical across networks.
177
+
-**Baked configuration**: The exact environment variables frozen into the image. A verifier can confirm that:
178
+
-`PROXY_STORE_CHAT_CONTEXT=false` (no chat logging) and `ENVIRONMENT=production` are immutable — not overridable at runtime.
179
+
- The four `LOG_LEVEL_*` fields (`APP=info`, `TCP=warn`, `ETH_RPC=warn`, `STORAGE=warn`) are explicit, not assumed defaults — this guarantees the running TEE image is not silently elevated to `debug`-level app logging (which could expose request/prompt payloads). The pipeline hard-fails the build if `LOG_LEVEL_APP=debug` is detected in `Dockerfile.tee`.
180
+
- The `network` field ("mainnet" or "testnet") and corresponding blockchain values (contract addresses, chain ID, blockscout URL) are set at build time based on the branch: `main` → mainnet (Base Mainnet 8453), `test` → testnet (Base Sepolia 84532). All other hardened settings are identical across networks.
151
181
-**Runtime secret boundary**: Explicitly lists the 5 variables that ARE injectable at runtime. Everything else is sealed.
152
182
-**Platform targets**: Confirms the image is built for both Intel TDX and AMD SEV-SNP TEE platforms.
183
+
-**TDX golden**: One `rtmr3` value (template-independent). Consumers compare it byte-for-byte to the live TDX quote.
184
+
-**SEV-SNP golden**: A `per_template` map with one launch digest per portal-selectable VM size (small/medium/large/2xlarge/4xlarge). Consumers parse the live quote's `family_id` (`<vmType>-<template>-sev`) to pick the correct entry — `attestation.GoldenValues.MatchSEVMeasurement` does the lookup. The asymmetry vs. TDX exists because the SEV launch digest folds in one VMSA page per vCPU; TDX RTMR3 does not.
153
185
154
186
---
155
187
@@ -267,12 +299,15 @@ This CI/CD hardening is the **foundation layer** for the full TEE attestation lo
267
299
268
300
| File | Change |
269
301
|---|---|
270
-
|`.github/workflows/build.yml`| Cosign signing, digest capture, SBOM, attestation manifest, RTMR3 computation, auto-deploy, and post-deploy verification. Also: GitHub Actions upgraded to Node 24-compatible versions, Go version updated to 1.23.x. |
271
-
|`.github/tee/secretvm.env`| Pins SecretVM release version, rootfs variant, URL, and SHA-256. All pipeline rootfs references derive from this file. |
302
+
|`.github/workflows/build.yml`| Cosign signing, digest capture, SBOM, attestation manifest, RTMR3 computation, **SEV-SNP measurement compute (per template) + SEV registry fetch + baked-loglevel extraction with privacy hard-fail**, auto-deploy, and post-deploy verification. Also: GitHub Actions upgraded to Node 24-compatible versions, Go version updated to 1.25.x. |
303
+
|`.github/tee/secretvm.env`| Pins SecretVM release version (currently `v0.0.27-alpha.1`), rootfs variant (`rootfs-prod`), **TDX rootfs URL/SHA-256 AND SEV rootfs URL/SHA-256, plus the SEV artifact registry URL and registry vm_type**. All pipeline rootfs references derive from this file. |
272
304
|`proxy-router/scripts/compute-rtmr3.py`| Standalone RTMR3 computation script matching the `reproduce-mr` algorithm. Can be run locally for independent verification. |
273
-
|`proxy-router/Dockerfile.tee`| Bakes immutable ENV config into the TEE image. Blockchain values (diamond, token, blockscout, chain ID) are parameterized via `ARG` with mainnet defaults; overridden via `--build-arg` for testnet builds. |
274
-
|`proxy-router/docker-compose.tee.yml`| Canonical compose template for TEE deployment with 5 runtime secrets |
275
-
|`docs/02.3-proxy-router-tee.md`| Provider setup and consumer verification guide |
305
+
|`proxy-router/scripts/compute-sev-measurement.py`|**NEW** — Standalone SEV-SNP launch-digest computation script. Byte-for-byte port of `attestation/sev_gctx.go::CalcSevMeasurement`. Computes one measurement per vCPU template (small/medium/large/2xlarge/4xlarge). Parity-tested against the runtime Go via `internal/attestation/sev_python_parity_test.go`. |
306
+
|`proxy-router/internal/attestation/sev_python_parity_test.go`|**NEW** — Hermetic regression guard: runs `compute-sev-measurement.py` as a subprocess against the v0.0.27-alpha.1 prod registry fixture and asserts byte-for-byte match against `CalcSevMeasurement` for all 5 templates. Skips gracefully when `python3` is unavailable. |
307
+
|`proxy-router/internal/attestation/golden.go`| Renamed JSON tag `amd_sev` → `amd_sev_snp` to align with the manifest schema; added `SEVMeasurements.PerTemplate map[string]string`, `GoldenValues.SEVPerTemplate`, and the `MatchSEVMeasurement` helper that looks up the golden by template-keyed live measurement. |
308
+
|`proxy-router/Dockerfile.tee`| Bakes immutable ENV config into the TEE image. Blockchain values are parameterized via `ARG` with mainnet defaults; overridden via `--build-arg` for testnet builds. **Logging values (`LOG_LEVEL_APP=info`, `LOG_LEVEL_TCP=warn`, `LOG_LEVEL_ETH_RPC=warn`, `LOG_LEVEL_STORAGE=warn`, plus `LOG_COLOR=false`, `LOG_JSON=true`, `LOG_IS_PROD=true`) are baked here and surfaced into the cosign-signed manifest's `baked_env` block — the privacy gate ensures the live TEE image cannot silently revert to `debug`-level app logging.**|
309
+
|`proxy-router/docker-compose.tee.yml`| Canonical compose template for TEE deployment with 5 runtime secrets. |
310
+
|`docs/02.3-proxy-router-tee.md`| Provider setup and consumer verification guide. |
276
311
277
312
---
278
313
@@ -310,14 +345,28 @@ This CI/CD hardening is the **foundation layer** for the full TEE attestation lo
310
345
|**`GET /v1/models/attestation`**| Per-model attestation state endpoint for monitoring and forensics |**Done** — PR #699|
### Completed (this PR — SEV-SNP and v0.0.27-alpha.1 cutover)
349
+
350
+
| Step | Description | Status |
351
+
|---|---|---|
352
+
|**SecretVM `v0.0.27-alpha.1` pin**| TDX + SEV rootfs URLs and SHA-256s pinned in `.github/tee/secretvm.env` (the portal currently only allows new VM provisioning on this release) |**Done**|
353
+
|**SEV rootfs download + SHA-256 verify**|`Download SecretVM rootfs (TDX + SEV)` step pulls both ISOs; both fail-closed if the pinned SHA doesn't match |**Done**|
354
+
|**SEV artifact registry fetch**|`Fetch SecretVM SEV artifact registry` step downloads `sev.json` from `scrtlabs/secretvm-verify` and records its SHA-256 in the manifest |**Done**|
|**Per-template SEV measurements in cosign-signed manifest**|`measurements.amd_sev_snp.per_template` block under the existing `cosign attest` flow |**Done**|
357
+
|**Baked log-level fields in `baked_env`**|`Extract baked log levels from Dockerfile.tee` step reads the four `LOG_LEVEL_*` ENV lines plus `LOG_COLOR`/`LOG_JSON`/`LOG_IS_PROD` and writes them to the manifest. Hard-fails if any are missing or if `LOG_LEVEL_APP=debug` (privacy gate) |**Done**|
|**Python ↔ Go parity regression test**|`internal/attestation/sev_python_parity_test.go` runs `compute-sev-measurement.py` as a subprocess and asserts identical hex output to `CalcSevMeasurement` for all 5 templates |**Done**|
360
+
313
361
### Remaining (Lower Priority / Future)
314
362
315
363
| Area | Step | Status |
316
364
|---|---|---|
317
365
| CI/CD | Full RTMR0-2 *recomputation* in CI (today we verify RTMR0-2 by artifact-registry lookup, which is sufficient) | TODO — blocked on ACPI templates |
318
-
| CI/CD |AMD SEV-SNP measurement via `sev-snp-measure`| TODO — TDX-only today |
366
+
| CI/CD |Auto-deploy + post-deploy verification for an SEV test VM (TDX-only today; needs SEV-flavoured offsets, separate `SECRETVM_TEST_SEV_VM_UUID`, parallel `Deploy-SecretVM-Test-SEV` job) | TODO|
319
367
| CI/CD | CVE scanning (Trivy/Grype) — advisory then gating | TODO |
368
+
| CI/CD | Scheduled monitor that polls `secret-vm-build` releases AND `secretvm-verify/artifacts_registry/sev.json` for new versions, opens an issue/PR | TODO |
320
369
| Proxy-router | Verifiable per-message signing using SecretVM TEE-bound key | Deferred to Phase 2b |
321
-
| Proxy-router | Local in-process quote verification (remove `quote-parse` dependency on SCRT Labs) | Deferred to Phase 2b |
370
+
| Proxy-router | Local in-process quote verification (remove `quote-parse`/ `quote-parse-sev`dependency on SCRT Labs) | Deferred to Phase 2b |
322
371
| Proxy-router | Co-located proxy-router + LLM in a single TDX VM (collapses both hops into one RTMR3) | Deferred to Phase 2b |
323
372
| Proxy-router | NRAS alternatives for non-NVIDIA GPU vendors | Deferred to Phase 2b |
0 commit comments