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
Brings the TEE CI/CD pipeline in line with SCRT Labs' new portal-mandated
SecretVM release v0.0.27-alpha.1 and PRs #718/#720 (AMD SEV-SNP support
in proxy-router runtime). Extends the cosign-signed attestation manifest
so verifiers can match per-template SEV-SNP launch digests and prove that
verbose logging cannot leak privacy data from a TEE-deployed image.
Changes
- .github/tee/secretvm.env: pin SECRETVM_RELEASE=v0.0.27-alpha.1; add TDX
and SEV rootfs URLs/SHA-256s; add SEV artifact registry pointer
- proxy-router/scripts/compute-sev-measurement.py (new): Python port of
CalcSevMeasurement; computes SHA-384 launch digests for all 5 SecretVM
vCPU templates (small/medium/large/2xlarge/4xlarge); mirrors the
existing compute-rtmr3.py CI pattern
- proxy-router/internal/attestation/sev_python_parity_test.go (new):
hermetic Go-vs-Python parity test using a version-agnostic synthetic
fixture (artifacts_ver=parity-test-fixture-v1) so future SecretVM
bumps do not require touching the test
- proxy-router/internal/attestation/golden.go: rename JSON tag
amd_sev -> amd_sev_snp; add SEVMeasurements.PerTemplate map and
GoldenValues.SEVPerTemplate + MatchSEVMeasurement helper
- .github/workflows/build.yml:
- download both TDX + SEV rootfs ISOs (SHA-verify both)
- fetch SCRT Labs SEV artifact registry, record its SHA-256
- run compute-sev-measurement.py for all 5 templates, expose as job outputs
- extract baked LOG_LEVEL_*/LOG_COLOR/LOG_JSON/LOG_IS_PROD from
Dockerfile.tee with privacy gate (hard-fails build if
LOG_LEVEL_APP=debug or any required LOG_LEVEL_* missing)
- manifest now publishes measurements.amd_sev_snp.per_template (×5) and
baked_env.LOG_* fields alongside intel_tdx.rtmr3
- proxy-router/.gitignore + .dockerignore: ignore Python __pycache__/
- .ai-docs/TEE_Attestation_Architecture.md + TEE_CICD_Supply_Chain_Hardening.md:
document v0.0.27-alpha.1 pin, SEV per-template asymmetry, baked log
levels, updated manifest schema
Auto-deploy + RTMR3-poll (Deploy-SecretVM-Test) remains TDX-only for this
PR; SEV auto-deploy is deferred (manual verifier flow works today via the
SEVPerTemplate map).
Validation
- python3 -m py_compile compute-sev-measurement.py: clean
- TestComputeSevMeasurementPythonParity: PASS (Go and Python produce
identical SHA-384 chains for all 5 templates)
- go vet ./internal/attestation/...: clean
- yaml.safe_load(build.yml): clean
- jq dry-run of manifest assembly: produces well-formed manifest with
amd_sev_snp.per_template and baked_env.LOG_* populated
Made-with: Cursor
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