feat(kmsCDHHelper): ecloud-platform stack integration - #122
Conversation
|
Claude finished @seanmcgary's task in 3m 11s —— View job Code Review — PR #122This is a well-engineered PR. The architecture is clearly thought through, the security rationale is documented at every key decision point, and the three prior rounds of feedback have been addressed cleanly. Below are the remaining items I found — one medium security concern that's genuinely new, and several lower-priority observations. [Medium, Security]
|
…MS error body, add tests
Round 1 — addressed in a59dd4fThanks for the review. Dispositions: [Medium] [Low] Uncapped body in [Low] [Low] [Nitpick] [Nitpick] [Nitpick] Re-parse/re-validation of base URL undocumented — Fixed. Added a comment noting the re-parse is intentional defense-in-depth so [Info] Escape test IDs are pre-rejected by [Nitpick] |
…k-path env check, stdin audit
Round 2 — addressed in 9592327[Low] Cache-path collision between valid stack IDs — Fixed. Dropped the [Low, pre-existing] Uncapped body in [Nitpick] Step-5 [Nitpick] Silent override of stdin All gates green on the touched packages (build, gofmt, lint 0 issues, |
…c env fields, query-strip test
Round 3 — addressed in 3778706 (final round, N=3 cap)[Low] Cache lookup races [Nitpick] RSA keypair generated before initdata check — Fixed by the same restructure: [Low] [Low] Query/fragment stripping untested — Fixed. Added [Nitpick] All gates green on the touched packages (build, gofmt, lint 0 issues, |
Bumps `VERSION` → `v0.4.2` to cut the first release containing **#122** (ecloud-platform stack-integration secrets path). ## Why No published `eigenx-kms` image has #122 — `v0.4.1` was tagged 2026-07-06, #122 (`ea89616`) merged 2026-07-09. The live preprod operators run `v0.3.3` (also pre-#122). The ecloud-platform confidential-app secrets path needs a post-#122 KMS (`RetrieveSecretsWithOptions` returns the app_private_key; the helper fetches ciphertext from the platform `/secrets` endpoint and IBE-decrypts in-guest). ## After merge Tag `v0.4.2` on master → CI (`build-container` + `build-create-release`) builds and publishes `public.ecr.aws/j0c8z4y5/eigenx-kms:v0.4.2`. Then the operator repo (Layr-Labs/eigenx-kms-operator#8) pins that tag and rolls the preprod operators. Just the VERSION bump — no code change (all the code is already on master via #122 and prior).
Summary
Converts
cmd/kmsCDHHelper(the SEV-SNP peer-pod secret-unseal helper) from the on-chainencrypted_envmodel to the ecloud-platform stack model introduced in #120.On the stack (
stack_id) path, the KMS/secretshandler returns only the recovered app-private-key — no env; the platform owns secrets. This PR teaches the helper to:stack_idas the single identity (replacesapp_id) — the KMS signsH(stackID)and secrets are IBE-sealed to identitystackIDby theec secrets setCLI, so the recovered keyS·H(stackID)decrypts them.stack_idplatform path (SecretsOptions.StackID).InternalSecretsServiceHTTP gateway (GET /internal/v1/stacks/{stack_id}/secrets,Authorization: Bearer <internal_api_key>) and IBE-decrypt each inside the TEE.stack_id+platform_secrets_url+platform_internal_api_keyfrom SNP-boundcc_init_data(never stdin).The on-chain
encrypted_env/public_envdecode + merge path is removed.What changed
pkg/clients/kmsClient:SecretsOptions.StackIDwired into the eigenx-snp request (was never set — the helper couldn't reach the platform path).cmd/kmsCDHHelper/platform_secrets.go(new):fetchStackSecrets—InternalSecretsServiceHTTP client (Bearer auth,url.PathEscaped path, capped/truncated bodies).cmd/kmsCDHHelper/main.go:stack_ididentity, SNP-bound platform config +validateStackID(path-injection guard),assembleEnvFromSecrets(per-secret IBE decrypt, fail-closed),resolveEnv(testable fetch seam; sentinel path skips fetch + cache);decodeEncryptedEnvremoved.cmd/kmsCDHHelper/env_cache.go:mergeEnvremoved; cache keyed bystack_id.main.goheader +docs/009_eigenxSnpAttestation.mdsynced to the stack model.Security posture
stack_idis content-validated (^[A-Za-z0-9._-]+$, rejects./..) ANDurl.PathEscaped into a single URL segment (url.JoinPathdeliberately avoided — it path-cleans rather than escapes).json:"-", sourced only from SNP-boundcc_init_data(same SSRF rationale as the KMS coords).__EIGENX_APP_PRIVATE_KEY__sentinel returns the raw key and never fetches or caches; no secrets/keys/plaintext logged.Testing
SecretsOptions.StackIDwiring;fetchStackSecrets(happy/non-200/malformed/path-escape/body-cap/empty);assembleEnvFromSecretsIBE round-trip + fail-closed;applyInitdataKMSConfig+validateStackID;resolveEnvsentinel/normal/error; cache keyed by stack_id.go build ./...clean,gofmtclean,make lint0 issues on touched packages,./scripts/goTest.sh ./cmd/kmsCDHHelper/... ./pkg/clients/kmsClient/...PASS.Design:
docs/superpowers/specs/2026-07-08-kmscdhhelper-stack-integration-design.mdPlan:
docs/superpowers/plans/2026-07-08-kmscdhhelper-stack-integration.mdStill a draft pending CI + your review.