SQS queues should be encrypted with KMS CMK
SQS queues default to SSE-SQS encryption using AWS-owned keys, which means AWS controls the entire key lifecycle. A KMS CMK lets you define your own rotation schedule, restrict access through key policies, and audit every encrypt/decrypt call via CloudTrail. That distinction matters when your data classification requires customer-controlled key material or when regulations mandate that encryption keys stay under your organizational control.
Without a CMK, you cannot revoke access to queue data by disabling or deleting the key, and you lose the ability to enforce separation of duties between the team managing queues and the team managing encryption keys.
Retrofit consideration
Changing an existing SQS queue from SSE-SQS to KMS CMK is an in-place update. Producers and consumers must have kms:GenerateDataKey and kms:Decrypt on the new CMK before the change lands, or they will start throwing AccessDeniedException immediately.
Implementation
Choose the approach that matches how you manage Terraform.
Use the compliance.tf module to enforce this control by default. See get started with compliance.tf.
module "sqs" {
source = "nistcsf.compliance.tf/terraform-aws-modules/sqs/aws"
version = ">=5.0.0"
fifo_queue = false
name = "abc123"
}
If you use terraform-aws-modules/sqs/aws, set the right module inputs for this control. You can later migrate to the compliance.tf module with minimal changes because it is compatible by design.
module "sqs" {
source = "terraform-aws-modules/sqs/aws"
version = ">=5.0.0"
fifo_queue = false
name = "abc123"
}
Use AWS provider resources directly. See docs for the resources involved: aws_sqs_queue.
resource "aws_sqs_queue" "this" {
name = "pofix-abc123"
redrive_policy = jsonencode({ deadLetterTargetArn = "arn:aws:sqs:us-east-1:123456789012:example-queue", maxReceiveCount = 5 })
kms_master_key_id = "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012"
}
What this control checks
The aws_sqs_queue resource must have kms_master_key_id set to the ARN or alias of a customer-managed KMS key. A queue passes when kms_master_key_id references a valid CMK (not the AWS-managed alias/aws/sqs key). It fails if kms_master_key_id is omitted, empty, or points to the AWS-managed SQS key. Setting sqs_managed_sse_enabled = true without kms_master_key_id also fails: that enables SSE-SQS, not KMS CMK encryption. Define the CMK as a separate aws_kms_key resource and reference its ARN. Optionally, set kms_data_key_reuse_period_seconds (default 300, max 86400) to control how long SQS reuses a data key before calling KMS again, which directly affects KMS API costs.
Common pitfalls
AWS-managed key does not satisfy CMK requirement
Setting
kms_master_key_idtoalias/aws/sqsuses the AWS-managed key. You cannot disable it, attach a custom key policy, or control its rotation schedule. Most CMK controls treat this as a failure. Use anaws_kms_keyresource you own.SSE-SQS is not KMS CMK encryption
SQS queues encrypt by default with SSE-SQS. Setting
sqs_managed_sse_enabled = trueopts into that mode explicitly but does not satisfy a CMK requirement. The two arguments are mutually exclusive: setting bothsqs_managed_sse_enabledandkms_master_key_idcauses a conflict error.Missing KMS permissions on producers and consumers
Grant permissions before you apply the CMK change. Every IAM principal calling
sqs:SendMessageneedskms:GenerateDataKeyon the key; every principal callingsqs:ReceiveMessageneedskms:Decrypt. Lambda triggers, SNS subscriptions, and S3 event notifications are common offenders that fail withAccessDeniedExceptionif you miss them.KMS key account and Region constraints
The CMK must be in the same account and Region as the queue.
SetQueueAttributescan succeed even when key policy or IAM permissions are incomplete, so verify message operations work after the change, not just the Terraform apply.Low kms_data_key_reuse_period_seconds increases cost
Get
kms_data_key_reuse_period_secondswrong on a high-throughput queue and the bill will surprise you. The default is 300 seconds; drop it below 60 and you can generate thousands of KMS API calls per minute at $0.03 per 10,000 requests.
Audit evidence
Auditors expect AWS Config rule results (such as sqs-queue-encrypted or a custom Config rule) showing all queues as compliant, with each queue's KmsMasterKeyId attribute populated with a customer-managed key ARN. Console screenshots of the SQS encryption settings page showing the key ID and key type are supporting evidence. CloudTrail logs for sqs:SetQueueAttributes confirm when encryption was enabled or changed; kms:Decrypt and kms:GenerateDataKey events tied to the SQS service principal demonstrate active CMK usage.
For continuous compliance, a Security Hub or third-party scanner report showing the control passing across all accounts and regions fills out the evidence package. The auditor may also ask for the KMS key policy to verify access is appropriately scoped.
Framework-specific interpretation
NIST Cybersecurity Framework v2.0: PR.DS-01 asks for data-at-rest protection; PR.DS controls broadly cover encryption and key management. A customer-managed KMS key on SQS queues keeps cryptographic control inside your organization rather than delegating it to AWS, which is what the Govern function's requirement to align encryption policy with organizational risk appetite is getting at.
Related controls
Tool mappings
Use these identifiers to cross-reference this control across tools, reports, and evidence.
Compliance.tf Control:
sqs_queue_encrypted_with_kms_cmkCheckov Check:
CKV2_AWS_73Powerpipe Control:
aws_compliance.control.sqs_queue_encrypted_with_kms_cmkProwler Check:
sqs_queues_server_side_encryption_enabledAWS Security Hub Control:
SQS.1Trivy Checks:
AWS-0096,AWS-0135
Last reviewed: 2026-03-09