Skip to content

feat(kms+ecr): real AES-256-GCM layer encryption on KMS repos#732

Merged
vieiralucas merged 1 commit intomainfrom
worktree-scoped-out-batch3
Apr 24, 2026
Merged

feat(kms+ecr): real AES-256-GCM layer encryption on KMS repos#732
vieiralucas merged 1 commit intomainfrom
worktree-scoped-out-batch3

Conversation

@vieiralucas
Copy link
Copy Markdown
Member

@vieiralucas vieiralucas commented Apr 24, 2026

Summary

Batch 3. Real encryption on KMS-configured ECR repos.

  • fakecloud_kms::api::encrypt_blob / decrypt_blob — AES-256-GCM, per-call 12-byte IV, authenticated tag bound to key ARN. Self-describing envelope so decrypt doesn't need the key passed back.
  • fakecloud-ecr with_kms builder; wired in server. Both OCI v2 upload paths (single-POST + two-phase) and the SDK CompleteLayerUpload branch on encryption_type=KMS. Blob GET decrypts.
  • Layer gets encrypted_with_kms_key so old snapshots stay readable.
  • aes-gcm 0.10 added as a fakecloud-kms dep.

Test plan

  • 4 new KMS unit tests — roundtrip, distinct IVs, tamper detection, disabled-key rejection
  • 2 new ECR E2E tests — KMS encrypt roundtrip + default AES256 plaintext guard
  • cargo test -p fakecloud-e2e --test ecr --test ecr_oci --test ecr_lifecycle --test ecr_pull_through — no regressions
  • clippy + fmt clean
  • CI + Cubic

Summary by cubic

Adds real AES‑256‑GCM encryption for ECR layer blobs when repositories are configured with KMS, and decrypts on blob GET. Existing repositories and snapshots remain readable; non‑KMS repos still store plaintext.

  • New Features

    • fakecloud_kms::api::{encrypt_blob, decrypt_blob} using AES‑256‑GCM with per‑call 12‑byte IV and a self‑describing envelope (|arn_len:u16|arn|iv:12|ct+tag|).
    • ECR: optional KMS wiring via EcrService::with_kms; encrypts on upload (single‑POST, two‑phase, and SDK CompleteLayerUpload) and decrypts on GET; pull‑through cache stays plaintext.
    • Adds Layer.encrypted_with_kms_key to track encrypted blobs; defaults to None for backward compatibility.
    • Server now passes KMS state into ECR at startup to enable KMS repos by default.
  • Dependencies

    • Added aes-gcm@0.10 to fakecloud-kms.

Written for commit d67c40c. Summary will update on new commits.

Previously `EncryptionConfiguration.encryption_type=KMS` with a kms_key
ARN was stored but never consulted. Layer blobs sat plaintext on the
fakecloud disk regardless. Now they're actually encrypted under
AES-256-GCM via a new fakecloud-kms crate-level API, with a fresh
12-byte IV per call and an authenticated tag bound to the key ARN.

- New `fakecloud_kms::api` module exposes `encrypt_blob` / `decrypt_blob`.
  Self-describing envelope format (`|arn_len:u16|arn|iv:12|ct+tag|`)
  so decrypters don't need the key ARN passed separately.

- The AES-256 key is derived via SHA-256 over the KMS key's
  `private_key_seed` (or `imported_material_bytes` when set via
  `ImportKeyMaterial`). Each CreateKey populates its own seed, so
  keys produce distinct ciphertext.

- aes-gcm 0.10 added as a fakecloud-kms dep (not workspace-level —
  it's the only crate that needs the crypto primitives).

- fakecloud-ecr gets a new optional `with_kms` builder. When wired,
  blob uploads (both the OCI v2 single-POST and two-phase paths, plus
  the AWS SDK `CompleteLayerUpload`) encrypt before storage; blob
  GETs decrypt on the way out. Pull-through-cached blobs stay
  plaintext (their repo is auto-created without KMS config).

- `Layer` gains `encrypted_with_kms_key: Option<String>` so the
  decrypt path knows whether to skip. Existing snapshots deserialize
  with it defaulted to None — pre-encryption layers stay readable.

- Server wires `kms_state` into the ECR service at startup so the
  integration is live by default.

- 4 new KMS unit tests (roundtrip, distinct IVs, tamper detection,
  disabled-key rejection). 2 new ECR E2E tests: KMS repo round-trips
  the plaintext via blob GET; the default AES256 path keeps storing
  plaintext as a regression guard.
@vieiralucas vieiralucas merged commit 65f1f09 into main Apr 24, 2026
15 checks passed
@vieiralucas vieiralucas deleted the worktree-scoped-out-batch3 branch April 24, 2026 12:30
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 24, 2026

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