Skip to content

SQS queues should have encryption at rest enabled

SQS queues often carry sensitive payloads: PII in order processing, credentials in deployment pipelines, health data in event-driven workflows. Without encryption at rest, anyone with access to the underlying storage infrastructure can read message contents in plaintext.

AWS now enables SSE-SQS by default for new queues, but older queues may still be unencrypted unless explicitly updated in Terraform. SSE-SQS costs nothing and requires a single argument. SSE-KMS adds key management overhead but gives you control over key rotation, cross-account policies, and CloudTrail logging of decryption events.

Retrofit consideration

Enabling encryption on an existing SQS queue does not require queue replacement. Switching between SSE-SQS and SSE-KMS is where the work is: you'll need to update IAM policies on all producers and consumers to include kms:Decrypt and kms:GenerateDataKey permissions before the change goes live.

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"

  sqs_managed_sse_enabled = true
}

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 })

  sqs_managed_sse_enabled = true
}

What this control checks

This control checks that the aws_sqs_queue resource has encryption at rest configured. Two approaches pass:

  1. SSE-SQS: Set sqs_managed_sse_enabled = true. This uses an AWS-managed AES-256 key at no additional cost.
  2. SSE-KMS: Set kms_master_key_id to the ARN or alias of a KMS key. When present, omit sqs_managed_sse_enabled or set it to false; the two are mutually exclusive.

A queue fails if neither sqs_managed_sse_enabled nor kms_master_key_id is set. The kms_data_key_reuse_period_seconds argument (default 300, max 86400) controls how long SQS caches the data key before calling KMS again, which affects KMS API costs but not pass/fail.

Common pitfalls

  • SSE-SQS and SSE-KMS are mutually exclusive

    Setting both sqs_managed_sse_enabled = true and kms_master_key_id on the same queue is an invalid configuration that will error at apply time. Pick one and omit the other.

  • Consumer and producer IAM policies must include KMS permissions

    Switching to SSE-KMS without updating IAM policies causes AccessDeniedException at runtime. The KMS key policy must allow Amazon SQS to use the key on behalf of authorized principals, and in cross-account or restrictive key policy designs, producers and consumers may also need direct kms:Decrypt and kms:GenerateDataKey permissions.

  • FIFO queues follow the same encryption arguments

    FIFO queues support the same sqs_managed_sse_enabled and kms_master_key_id arguments as standard queues. Teams often miss encryption on FIFO queues because the configuration focus tends to land on content_based_deduplication and ordering settings.

  • Default queue created by SNS subscription may be unencrypted

    Queues managed outside Terraform, including those backing an aws_sns_topic_subscription, often lack encryption. Import them with terraform import aws_sqs_queue.<name> <queue_url>, then add the appropriate encryption argument. Without the import, Terraform won't enforce encryption on queues it doesn't manage.

Audit evidence

Auditors expect Config rule evaluation results showing all SQS queues as compliant, typically via the managed rule sqs-queue-encrypted or an equivalent custom rule. Supplementary evidence is the output of aws sqs get-queue-attributes --attribute-names SqsManagedSseEnabled KmsMasterKeyId for each queue, confirming one encryption mechanism is active. For SSE-KMS queues, CloudTrail events for kms:Decrypt and kms:GenerateDataKey tied to the queue's KMS key ARN confirm the key is in active use.

Framework-specific interpretation

NIST Cybersecurity Framework v2.0: PR.DS under the Protect function is the primary mapping. SQS encryption at rest keeps message payloads confidential within async processing pipelines. When SSE-KMS is used, the control also touches PR.AA: decryption is gated by IAM-governed key policies, making access auditable via CloudTrail.

Tool mappings

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

  • Compliance.tf Control: sqs_queue_encrypted_at_rest

  • Checkov Check: CKV_AWS_27

  • Powerpipe Control: aws_compliance.control.sqs_queue_encrypted_at_rest

  • Prowler Check: sqs_queues_server_side_encryption_enabled

  • AWS Security Hub Control: SQS.1

  • KICS Query: 6e8849c1-3aa7-40e3-9063-b85ee300f29f

  • Trivy Checks: AWS-0096, AWS-0135

Last reviewed: 2026-03-09