Skip to content

ES domain encryption at rest should be enabled

Elasticsearch domains frequently ingest and index sensitive data: application logs containing PII, financial transaction records, authentication events. Without encryption at rest, that data sits unencrypted on the EBS volumes and instance storage backing the domain. A compromised storage device or unauthorized snapshot access exposes all indexed content.

Encryption at rest uses AES-256 via KMS and has negligible performance impact for most workloads. It eliminates an entire class of storage-layer exposure without touching query latency or indexing throughput.

Retrofit consideration

Domains running Elasticsearch before version 6.7, or using unsupported instance types like t2.*, cannot enable encryption at rest without recreating the domain entirely. For supported versions, enabling encryption triggers a blue/green deployment that can run for several hours on large domains.

Implementation

Choose the approach that matches how you manage Terraform.

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

resource "aws_elasticsearch_domain" "this" {
  advanced_security_options {
    enabled                        = true
    internal_user_database_enabled = true

    master_user_options {
      master_user_name     = "admin"
      master_user_password = "ChangeMe123!"
    }
  }

  cluster_config {
    dedicated_master_count   = 3
    dedicated_master_enabled = true
    dedicated_master_type    = "m5.large.elasticsearch"
    instance_count           = 3
    instance_type            = "m5.large.elasticsearch"

    zone_awareness_config {
      availability_zone_count = 3
    }

    zone_awareness_enabled = true
  }

  cognito_options {
    enabled          = true
    identity_pool_id = "us-east-1:12345678-1234-1234-1234-123456789012"
    role_arn         = "arn:aws:iam::123456789012:role/example-role"
    user_pool_id     = "us-east-1_AbCdEfGhI"
  }

  domain_endpoint_options {
    enforce_https       = true
    tls_security_policy = "Policy-Min-TLS-1-2-2019-07"
  }

  domain_name = "pofix-abc123"

  ebs_options {
    ebs_enabled = true
    volume_size = 10
    volume_type = "gp3"
  }

  elasticsearch_version = "7.10"

  log_publishing_options {
    cloudwatch_log_group_arn = local.es_log_group_arn
    log_type                 = "AUDIT_LOGS"
  }
  log_publishing_options {
    cloudwatch_log_group_arn = local.es_log_group_arn
    log_type                 = "ES_APPLICATION_LOGS"
  }
  log_publishing_options {
    cloudwatch_log_group_arn = local.es_log_group_arn
    log_type                 = "SEARCH_SLOW_LOGS"
  }
  log_publishing_options {
    cloudwatch_log_group_arn = local.es_log_group_arn
    log_type                 = "INDEX_SLOW_LOGS"
  }

  node_to_node_encryption {
    enabled = true
  }

  vpc_options {
    security_group_ids = ["sg-12345678"]
    subnet_ids         = ["subnet-12345678", "subnet-12345678", "subnet-12345678"]
  }

  encrypt_at_rest {
    enabled = true
  }
}

What this control checks

The policy checks for an encrypt_at_rest block inside aws_elasticsearch_domain or aws_opensearch_domain with enabled = true. It fails when enabled is false, explicitly omitted, or the block is absent entirely. The optional kms_key_id argument specifies a customer-managed KMS key ARN; without it, the domain uses the AWS-managed aws/es service key. Either key type satisfies the control, but enabled must be explicitly true. The aws_opensearch_domain resource, recommended for new deployments, uses the same block name and behavior.

Common pitfalls

  • Unsupported instance types silently prevent encryption

    t2.* instance types do not support encryption at rest. Terraform will accept the configuration without complaint, but the AWS API returns an error at apply time. Use t3.* or a larger instance family in the instance_type argument of the cluster_config block.

  • Resource selection can cause migration complexity

    Use aws_opensearch_domain for new deployments; aws_elasticsearch_domain is legacy. Both support the encrypt_at_rest block identically, but switching between them requires a state move (terraform state mv) or import. Mixing both resource types in the same codebase creates audit confusion when reviewers expect consistency.

  • AWS-managed key limits cross-account snapshot access

    Omit kms_key_id and the domain defaults to the AWS-managed aws/es key. Snapshots encrypted with that key cannot be shared to another account, which breaks cross-account disaster recovery setups. If you need cross-account snapshot restores, specify a customer-managed KMS key with an explicit key policy.

  • Blue/green deployment during retrofit causes extended unavailability window

    Enabling encryption on a running domain via UpdateDomainConfig triggers a blue/green replacement. On large domains (hundreds of GB or more) this runs for several hours. Schedule the change in a maintenance window and track progress via DescribeDomainConfig or the DomainProcessingStatus field rather than assuming completion.

Audit evidence

AWS Config rule elasticsearch-encrypted-at-rest evaluation results showing all domains as COMPLIANT are the primary evidence. Console screenshots of each domain's security configuration tab, confirming encryption at rest is enabled and showing the KMS key ARN in use, establish current state. CloudTrail logs with CreateDomain or UpdateDomainConfig calls where EncryptionAtRestOptions.Enabled is true show when the control was applied at provisioning time.

For environments with multiple domains, a Config aggregator report or Security Hub findings export filtered to this check provides consolidated coverage across accounts and regions.

Framework-specific interpretation

SOC 2: C1.2 under the SOC 2 Confidentiality criteria calls for protecting confidential information during storage. Encryption at rest on ES domains addresses that directly, and auditors reviewing the Security criteria commonly check this control as well.

PCI DSS v4.0: If cardholder data ends up in Elasticsearch indices, Requirement 3.5 applies: PANs must be unreadable wherever stored. Encryption at rest with strong cryptographic keys is the required technical control, and the KMS key ARN is what examiners ask to see.

HIPAA Omnibus Rule 2013: 45 CFR 164.312(a)(2)(iv) treats encryption of ePHI at rest as an addressable safeguard under the HIPAA Omnibus Rule. Elasticsearch domains indexing health records or application logs containing ePHI need this enabled to satisfy that requirement.

GDPR: Article 32 requires appropriate technical measures including encryption for personal data. For data flowing through Elasticsearch, this control satisfies that requirement. It also matters for breach notification: Article 34(3)(a) allows skipping notification to affected individuals when the exposed data was encrypted.

NIST SP 800-53 Rev 5: SC-28 requires cryptographic mechanisms to protect information stored on digital media from unauthorized disclosure. KMS encryption on an ES domain is exactly that mechanism for any search or analytics data the domain holds.

FedRAMP Moderate Baseline Rev 4: At the FedRAMP Moderate baseline, SC-28 applies to federal data at rest. Domains processing government data in a FedRAMP-authorized environment need encryption enabled. Customer-managed KMS keys are preferred over the AWS-managed aws/es key to retain control over key rotation.

Tool mappings

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

  • Compliance.tf Control: es_domain_encryption_at_rest_enabled

  • AWS Config Managed Rule: ELASTICSEARCH_ENCRYPTED_AT_REST

  • Checkov Check: CKV_AWS_5

  • Powerpipe Controls: aws_compliance.control.es_domain_encryption_at_rest_enabled, aws_compliance.control.opensearch_domain_encryption_at_rest_enabled

  • Prowler Check: opensearch_service_domains_encryption_at_rest_enabled

  • AWS Security Hub Control: ES.1

  • KICS Query: 24e16922-4330-4e9d-be8a-caa90299466a

  • Trivy Check: AWS-0048

Last reviewed: 2026-03-09