Google Cloud KMS RMK provider

Copy Markdown View Source

KMS.RMK.GCP uses Google Cloud KMS as the RMK provider. It protects KMS database secrets with Google Cloud IAM, Cloud KMS audit logs, and Google-managed key-service boundaries.

Use it when GCP is your deployment boundary and DB-only compromise must not expose KMS secret material.

Configuration

config :kms, :rmk_provider, KMS.RMK.GCP

config :kms, KMS.RMK.GCP,
  project_id: "my-project",
  location: "europe-west3",
  key_ring: "kms-rmk",
  crypto_key: "root-master-key"

Environment:

  • KMS_RMK_GCP_PROJECT_ID or GOOGLE_CLOUD_PROJECT
  • KMS_RMK_GCP_LOCATION
  • KMS_RMK_GCP_KEY_RING
  • KMS_RMK_GCP_CRYPTO_KEY
  • KMS_RMK_GCP_ENDPOINT for custom endpoints/tests

Optional app config:

  • :endpoint
  • :additional_authenticated_data
  • :timeout_ms
  • :retry
  • :max_retries

Per-call :aad is sent as Cloud KMS additionalAuthenticatedData.

Credentials

Supported auth resolution order:

  1. explicit access token: :access_token, KMS_RMK_GCP_ACCESS_TOKEN, or GOOGLE_OAUTH_ACCESS_TOKEN
  2. GOOGLE_APPLICATION_CREDENTIALS service account JSON
  3. GOOGLE_APPLICATION_CREDENTIALS authorized user JSON
  4. GOOGLE_APPLICATION_CREDENTIALS external account JSON with file/url credential source and optional service account impersonation
  5. metadata server token for GCE/GKE workload identity

Prefer workload identity over long-lived service account JSON when possible.

Only the KMS authority process should receive GCP credentials. Do not configure GCP RMK credentials in remote-client-only apps.

Key reference and ciphertext

New ciphertexts are stored as:

kms-rmk:v1:gcp:<key_ref_b64url>:<ciphertext_b64url>

key_ref is the full Cloud KMS CryptoKey resource path:

projects/:project/locations/:location/keyRings/:ring/cryptoKeys/:key

Legacy raw ciphertext is still passed to the configured GCP provider for compatibility.

Imported/offline key material

For maximum provider migratability, use imported key versions or external key-management workflows when your GCP security policy supports them.

If you use Google-generated non-exportable key material, migration away from GCP requires the old Cloud KMS key to stay enabled and accessible until all RMK ciphertexts are re-encrypted under another provider.

Keep imported/offline key material outside KMS hosts and outside KMS database backups. Test restore before production.

Readiness

:ok = KMS.RMK.ensure_ready()

GCP readiness calls the Cloud KMS CryptoKey endpoint.

Common errors:

  • :unauthorized for bad IAM/credentials.
  • :not_found for missing key or path.
  • :rate_limited for quota/throttling.
  • :unavailable for network or provider outage.
  • :decryption_failed for invalid ciphertext or AAD mismatch.

Caching

Cloud KMS calls add latency and may cost money. Keep RMK decrypt caching enabled unless memory exposure is the stronger concern.

Default:

config :kms, :rmk_cache_ttl_ms, :timer.minutes(5)

Shorten per call:

KMS.decrypt_alias(encrypted, "alias", rmk_cache_ttl_ms: :timer.seconds(30))

Disable per call:

KMS.decrypt_alias(encrypted, "alias", rmk_cache_ttl_ms: 0)

Security notes

  • Do not log service account JSON, access tokens, plaintext, ciphertext, or request bodies.
  • Grant least privilege on the CryptoKey to the KMS authority identity.
  • Use AAD consistently; changing AAD can make old ciphertext undecryptable.
  • Monitor Cloud Audit Logs for unexpected decrypt volume.