Skip to content

feat(crypto): GCP / Azure / Vault KMS providers (Step 6.7c) - #157

Merged
officialCodeWork merged 1 commit into
mainfrom
build/phase-6/step-6.7c-cloud-kms-providers
Jun 8, 2026
Merged

feat(crypto): GCP / Azure / Vault KMS providers (Step 6.7c)#157
officialCodeWork merged 1 commit into
mainfrom
build/phase-6/step-6.7c-cloud-kms-providers

Conversation

@officialCodeWork

Copy link
Copy Markdown
Owner

Summary

Completes the four-provider BYOK KMS matrix. Each new provider subclasses EnvelopeKeyManager (inheriting the DEK + AES-256-GCM + tenant-AAD + envelope framing from 6.7a) and only wraps/unwraps the DEK via its KMS API:

  • GcpKmsKeyManager — google-cloud-kms encrypt/decrypt (shared async client).
  • AzureKeyVaultKeyManager — azure-keyvault-keys wrap_key/unwrap_key (RSA-OAEP-256); a CryptographyClient per key via a cached factory (Azure binds a client to one key).
  • VaultKeyManager — HashiCorp Vault Transit encrypt_data/decrypt_data (sync hvac run in a thread, configurable mount_point).

Each is behind a [kms-gcp] / [kms-azure] / [kms-vault] extra — the SDKs are lazy-imported, so the modules import without the SDK and selecting a provider without its extra raises a clear ImportError. An injectable client / client_factory seam makes every provider fully unit-testable with a fake KMS — no cloud creds / network. Connection uses each SDK's standard credential discovery (GCP ADC, Azure DefaultAzureCredential, Vault VAULT_ADDR/VAULT_TOKEN); per-tenant key resolution + sealing (KeyUnavailableError) are uniform with AWS.

KmsProvider enum + build_key_manager_from_config factory + KmsConfig.vault_mount extended; mypy overrides added for the three SDK module trees (absent at lint time).

Scope / deferred: providers only. 6.7d — zero-downtime key rotation (closes Step 6.7). Wiring EncryptingStorage into the ingest path stays deferred (tiered storage).

Tests & gates

  • ~18 new tests: each of GCP / Vault / Azure over an injected fake client (tests/kms/test_cloud_providers.py — round-trip, per-tenant key-bound cross-tenant block, sealing, SDK-error → KeyUnavailableError); factory cloud-provider-requires-extra contract.
  • Full tests/ packages/ 2362 passed, 1 skipped; gateway 290 passed (+1, no regression). Green: ruff, mypy --strict (309 files), RAG001, policy-coverage, log-schema; only the intended dist/rag.schema.* regen.

Documentation

Test plan

  • uv run pytest tests/ packages/ -m "not integration" — 2362 passed, 1 skipped
  • uv run pytest apps/gateway/tests — 290 passed
  • ruff + mypy --strict (309) + RAG001 + policy-coverage + log-schema; config schema-drift regenerated
  • Each provider's sealing / cross-tenant binding / SDK-error mapping verified via a fake client

🤖 Generated with Claude Code

Complete the four-provider BYOK KMS matrix. Each new provider subclasses
EnvelopeKeyManager (inheriting the DEK + AES-GCM + tenant-AAD + envelope framing)
and only wraps/unwraps the DEK via its KMS API:

- GcpKmsKeyManager — google-cloud-kms encrypt/decrypt, shared async client.
- AzureKeyVaultKeyManager — azure-keyvault-keys wrap_key/unwrap_key (RSA-OAEP-256);
  a CryptographyClient per key via a cached factory (Azure binds a client to one key).
- VaultKeyManager — HashiCorp Vault Transit encrypt_data/decrypt_data (sync hvac
  run in a thread, configurable mount_point).

Each is behind a [kms-gcp] / [kms-azure] / [kms-vault] extra (SDKs lazy-imported,
so the modules import without the SDK and selecting a provider without its extra
raises a clear ImportError). An injectable client / client_factory seam makes
every provider fully unit-testable with a fake KMS — no cloud creds/network.
Connection uses each SDK's standard credential discovery; per-tenant key
resolution + sealing (KeyUnavailableError) are uniform with AWS.

KmsProvider enum + build_key_manager_from_config factory + KmsConfig.vault_mount
extended; mypy overrides added for the three SDK module trees. Scope: providers
only — key rotation is 6.7d; wiring EncryptingStorage into the ingest path stays
deferred (tiered storage).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@officialCodeWork
officialCodeWork merged commit f444c77 into main Jun 8, 2026
12 of 17 checks passed
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