Skip to content

Kinesis streams should be encrypted with CMK

AWS-managed keys for Kinesis (alias/aws/kinesis) encrypt data at rest but give you zero control over key policy, key deletion scheduling, or cross-account access grants. A customer-managed CMK lets you restrict which IAM principals can decrypt stream data, audit every Decrypt and GenerateDataKey call in CloudTrail, and revoke access instantly by modifying the key policy or disabling the key.

Without CMK encryption, an attacker who compromises a broadly scoped IAM role can read stream records with no additional barrier. CMK-based encryption adds a second authorization gate: even with kinesis:GetRecords permission, the caller must also hold kms:Decrypt on the specific key.

Retrofit consideration

Enabling or changing encryption on a running Kinesis stream moves it into an UPDATING state. Producers and consumers may hit transient errors during that window. Test in a non-production environment first and give downstream consumers a heads-up before applying to anything in active use.

Implementation

Choose the approach that matches how you manage Terraform.

Use AWS provider resources directly. See docs for the resources involved: aws_kinesis_stream.

resource "aws_kinesis_stream" "this" {
  encryption_type  = "KMS"
  name             = "pofix-abc123"
  retention_period = 168
  shard_count      = 1

  kms_key_id = "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012"
}

What this control checks

The aws_kinesis_stream resource must have encryption_type set to "KMS" and kms_key_id set to the ARN or alias of a customer-managed KMS key (aws_kms_key resource you control). It fails if encryption_type is "NONE" or omitted, or if kms_key_id resolves to the AWS-managed key (alias/aws/kinesis). The referenced aws_kms_key should have is_enabled = true and a key policy granting the Kinesis service principal kms:GenerateDataKey and kms:Decrypt.

Example passing configuration: encryption_type = "KMS" and kms_key_id = aws_kms_key.kinesis.arn on the aws_kinesis_stream resource.

Common pitfalls

  • AWS-managed key does not satisfy this control

    Setting encryption_type = "KMS" without specifying kms_key_id, or pointing it at alias/aws/kinesis, hands key control back to AWS. The data is encrypted, but this control fails because you have no access to the key policy. Always supply an explicit aws_kms_key resource ARN in kms_key_id.

  • Missing KMS key policy grants

    Even with the correct kms_key_id, if the key policy does not grant kms:GenerateDataKey, kms:Decrypt, and kms:DescribeKey to the Kinesis service principal or the producing and consuming IAM roles, writes and reads will return AccessDeniedException. Get this wrong and the stream fails silently from an application perspective until you trace the error back to KMS.

  • Key deletion disables the stream

    Schedule the CMK for deletion or disable it via aws kms disable-key and every PutRecord and GetRecords call fails with KMSDisabledException. Set deletion_window_in_days to an appropriate value (7-30 days) and monitor for that error in CloudWatch before it becomes an incident.

  • Cross-region replication needs region-local keys

    A CMK in one region cannot decrypt data in another. If you replicate Kinesis data cross-region, provision a separate CMK in each destination region and wire up the key policies accordingly. Reusing the source region's key ARN across regions will not work.

Audit evidence

Config rule evaluation results for kinesis-stream-encrypted (with a custom parameter requiring CMK) should show all streams as COMPLIANT. Back that up with aws kinesis describe-stream --stream-name <name> output showing EncryptionType: KMS and a KeyId that resolves to a customer-managed key, confirmed by aws kms describe-key --key-id <id> returning KeyManager: CUSTOMER.

CloudTrail logs showing kms:GenerateDataKey and kms:Decrypt calls referencing the stream's key ARN demonstrate ongoing enforcement. Prowler or Steampipe scan reports flagging streams without CMK encryption round out the continuous monitoring picture.

Framework-specific interpretation

Tool mappings

Use these identifiers to cross-reference this control across tools, reports, and evidence.

  • Compliance.tf Control: kinesis_stream_encrypted_with_kms_cmk

  • AWS Config Managed Rule: KINESIS_STREAM_ENCRYPTED

  • Checkov Check: CKV_AWS_185

  • Powerpipe Control: aws_compliance.control.kinesis_stream_encrypted_with_kms_cmk

  • Prowler Check: kinesis_stream_encrypted_at_rest

  • AWS Security Hub Control: Kinesis.1

  • KICS Queries: 5c6dd5e7-1fe0-4cae-8f81-4c122717cef3, 862fe4bf-3eec-4767-a517-40f378886b88

  • Trivy Check: AWS-0064

Last reviewed: 2026-03-09