AWS KMS RMK provider

Copy Markdown View Source

KMS.RMK.AWS uses AWS KMS as the RMK provider. It protects KMS database secrets with AWS KMS key policy, IAM, CloudTrail, and AWS KMS availability boundaries.

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

Configuration

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

config :kms, KMS.RMK.AWS,
  region: "eu-central-1",
  key_id: "alias/kms-rmk-prod",
  encryption_context: %{"kms:purpose" => "rmk"}

Environment:

  • KMS_RMK_AWS_REGION or AWS_REGION / AWS_DEFAULT_REGION
  • KMS_RMK_AWS_KEY_ID
  • AWS_ENDPOINT_URL_KMS for LocalStack/custom endpoints

Optional app config:

  • :endpoint
  • :encryption_context or :context
  • :timeout_ms
  • :retry
  • :max_retries

Per-call :aad is added to the AWS encryption context as "kms:rmk:aad".

Credentials

Credential resolution order:

  1. explicit app config: :access_key_id, :secret_access_key, optional :session_token
  2. env: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, optional AWS_SESSION_TOKEN
  3. shared credentials file: AWS_SHARED_CREDENTIALS_FILE, AWS_PROFILE
  4. web identity: AWS_ROLE_ARN, AWS_WEB_IDENTITY_TOKEN_FILE
  5. ECS container credentials
  6. EC2 IMDSv2 instance profile credentials

Prefer workload identity / instance roles over static access keys.

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

Key reference and ciphertext

New ciphertexts are stored as:

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

key_ref is the configured AWS KMS key id or alias. AWS ciphertext blobs also carry AWS KMS metadata internally, but KMS keeps the key ref for audit and provider-switch safety.

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

Imported/offline key material

For maximum provider migratability, use AWS KMS key material that your organization controls offline when your security policy supports it, such as imported key material.

If you use AWS-generated non-exportable key material, migration away from AWS requires the old AWS KMS key to remain 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()

AWS readiness calls DescribeKey for the configured key.

Common errors:

  • :unauthorized for bad IAM/credentials.
  • :not_found for missing key.
  • :rate_limited for AWS throttling.
  • :unavailable for AWS KMS/network/transient key-state failures.
  • :decryption_failed for invalid ciphertext or context mismatch.

Caching

AWS 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 AWS signed headers, access keys, session tokens, plaintext, ciphertext, or request bodies.
  • Use least-privilege IAM: the KMS authority process needs encrypt/decrypt/describe on the RMK key.
  • Use encryption context consistently; changing context can make old ciphertext undecryptable.
  • Monitor CloudTrail/KMS events for unexpected decrypt volume.