Skip to content

ElastiCache for Redis replication groups should be encrypted at rest

Redis replication groups often hold session tokens, cached credentials, and PII. Without encryption at rest, anyone with access to the underlying storage volumes or snapshots can read that data directly. This includes AWS operators with physical access, compromised backup pipelines, or cross-account snapshot shares.

AES-256 encryption under an AWS-managed or customer-managed KMS key protects that data even if storage media is exfiltrated or improperly decommissioned.

Retrofit consideration

Encryption at rest cannot be toggled on an existing replication group. You must create a new replication group with at_rest_encryption_enabled = true, migrate data (e.g., via backup and restore), then destroy the old group. This can cause downtime unless you use a blue-green deployment pattern.

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 "elasticache" {
  source  = "pcidss.compliance.tf/terraform-aws-modules/elasticache/aws"
  version = ">=1.0.0,<2.0.0"

  description          = "Redis cluster"
  engine               = "redis"
  engine_version       = "7.1"
  node_type            = "cache.t3.micro"
  num_cache_clusters   = 2
  replication_group_id = "abc123"
  subnet_ids           = ["subnet-12345678", "subnet-12345678"]
  vpc_id               = "vpc-12345678"
}

If you use terraform-aws-modules/elasticache/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 "elasticache" {
  source  = "terraform-aws-modules/elasticache/aws"
  version = ">=1.0.0,<2.0.0"

  description          = "Redis cluster"
  engine               = "redis"
  engine_version       = "7.1"
  node_type            = "cache.t3.micro"
  num_cache_clusters   = 2
  replication_group_id = "abc123"
  subnet_ids           = ["subnet-12345678", "subnet-12345678"]
  vpc_id               = "vpc-12345678"

  at_rest_encryption_enabled = true
}

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

resource "aws_elasticache_replication_group" "this" {
  auth_token                 = "PofixExampleAuthToken32CharsLng"
  description                = "pofix example replication group"
  node_type                  = "cache.t3.micro"
  num_cache_clusters         = 2
  replication_group_id       = "pofix-abc123"
  snapshot_retention_limit   = 15
  subnet_group_name          = "example-subnet-group"
  transit_encryption_enabled = true

  at_rest_encryption_enabled = true
}

What this control checks

The aws_elasticache_replication_group resource must have at_rest_encryption_enabled = true. The argument defaults to false when omitted, which fails the control. You can optionally pair it with kms_key_id to use a customer-managed key instead of the default aws/elasticache AWS-managed key.

Common pitfalls

  • Cannot enable on existing clusters

    Terraform treats at_rest_encryption_enabled as ForceNew. Flip it to true on an existing replication group and Terraform will destroy and recreate the resource, taking your cached data with it. Plan a backup-restore or blue-green migration before applying the change.

  • Standalone cache clusters are not covered

    A standalone aws_elasticache_cluster resource isn't evaluated by this control. If your architecture doesn't use a replication group, this check never runs and you can be out of compliance without any policy signal. The aws_elasticache_replication_group resource is the recommended Redis pattern anyway.

  • Default KMS key limits cross-account snapshot sharing

    Omitting kms_key_id means ElastiCache uses the AWS-managed aws/elasticache key. That works for encryption, but AWS-managed keys can't be shared across accounts, so any snapshot export to another account will fail to decrypt. If cross-account snapshot access is part of your architecture, specify a customer-managed KMS key ARN in kms_key_id.

  • Encryption at rest does not imply in-transit encryption

    Setting at_rest_encryption_enabled = true doesn't touch transit_encryption_enabled. The two are independent arguments. PCI DSS, HIPAA, and most other data protection frameworks require both, so set them together in every replication group resource.

Audit evidence

Config rule evaluation results showing all AWS::ElastiCache::ReplicationGroup resources as COMPLIANT work as primary evidence, or a Security Hub findings export filtered to this control. The DescribeReplicationGroups API response includes AtRestEncryptionEnabled as a boolean; it should be true for every group. If a customer-managed KMS key is in use, expect to provide the KMS key policy showing appropriate access restrictions. ElastiCache console screenshots of the "Encryption at-rest" column set to "Yes" are acceptable supplementary evidence.

Framework-specific interpretation

PCI DSS v4.0: For environments storing cardholder data in Redis, Requirement 3.4 requires PAN to be rendered unreadable wherever it is stored, including caching layers. Encrypting the replication group at rest satisfies the strong cryptography requirement for that layer. Requirement 3.5 then applies to key management, which is where KMS key policies and rotation come in.

Tool mappings

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

  • Compliance.tf Control: elasticache_replication_group_encryption_at_rest_enabled

  • AWS Config Managed Rule: ELASTICACHE_REPL_GRP_ENCRYPTED_AT_REST

  • Checkov Check: CKV_AWS_29

  • Powerpipe Control: aws_compliance.control.elasticache_replication_group_encryption_at_rest_enabled

  • Prowler Check: elasticache_redis_cluster_rest_encryption_enabled

  • AWS Security Hub Control: ElastiCache.4

  • KICS Query: 76976de7-c7b1-4f64-a94f-90c1345914c2

  • Trivy Check: AWS-0045

Last reviewed: 2026-03-09