Skip to content

Elasticsearch domain node-to-node encryption should be enabled

Without node-to-node encryption, traffic between Elasticsearch nodes travels in plaintext within the VPC. An attacker with network-level access (through a compromised instance, misconfigured security group, or VPC peering) can passively sniff index data, search queries, and cluster state flowing between nodes. This includes the actual document content stored in your indices.

Enabling node-to-node encryption has no meaningful performance penalty on modern instance types and eliminates an entire class of eavesdropping risk. AWS requires it for certain Elasticsearch versions (6.0+) when using fine-grained access control, so skipping it also limits your future access control options.

Retrofit consideration

Enabling node-to-node encryption on a running domain triggers a blue/green deployment. AWS builds a new cluster, migrates data, then cuts over the endpoint. Depending on cluster size, this can run for hours and may cause brief endpoint unavailability or elevated latency. Plan a maintenance window before applying the change.

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"

  encrypt_at_rest {
    enabled = true
  }

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

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

  node_to_node_encryption {
    enabled = true
  }
}

What this control checks

The control checks that the domain resource has node-to-node encryption enabled. For aws_opensearch_domain, the node_to_node_encryption block must be present with enabled = true. The legacy aws_elasticsearch_domain resource uses the same block and argument. A domain that omits the block entirely, or sets enabled = false, fails. No KMS key is required; node-to-node encryption uses AWS-managed TLS certificates.

Common pitfalls

  • Blue/green deployment on existing domains

    What Terraform shows as an in-place update is actually a blue/green deployment in AWS. The cluster rebuild can run for hours, and brief endpoint unavailability is possible. Test the change in a staging environment before touching production.

  • Version and feature compatibility

    Some older Elasticsearch engine versions don't support node-to-node encryption, and certain feature combinations (fine-grained access control, for instance) require it to be enabled. A Terraform apply against an incompatible configuration fails with an API error, not a plan-time warning, so check version support before applying.

  • Deprecated resource confusion

    If you're migrating from aws_elasticsearch_domain to aws_opensearch_domain, carry the node_to_node_encryption block across explicitly. The block name is the same, but the resource operates against the OpenSearch API and the setting won't be inferred from the old resource definition.

  • Encryption at rest prerequisite

    Node-to-node encryption and encryption at rest are independent settings, but certain engine versions and advanced security feature combinations require both to be enabled together. If they aren't, the AWS API rejects the configuration, sometimes with an error message that doesn't make the dependency obvious.

Audit evidence

An auditor expects AWS Config rule results for elasticsearch-node-to-node-encryption-check showing compliant evaluations across all in-scope domains. Console screenshots of the domain security configuration page with 'Node-to-node encryption' shown as Enabled work as supplementary evidence. For programmatic verification, aws es describe-elasticsearch-domain --domain-name <name> should return "NodeToNodeEncryptionOptions": {"Enabled": true}.

AWS Security Hub dashboards tracking this Config rule over time strengthen the audit trail by showing the control was not briefly disabled between reviews. Third-party CSPM platforms that ingest Config findings serve the same purpose.

Framework-specific interpretation

SOC 2: CC6.1 asks for encryption during transmission as part of logical access and data protection controls. Node-to-node encryption covers the intra-cluster leg, where search queries and index data move between nodes outside the reach of application-layer TLS. That gap is what this setting closes.

PCI DSS v4.0: Requirement 4 targets cardholder data on open, public networks, but most security programs extend equivalent protections to sensitive internal traffic. Node-to-node TLS helps protect indexed cardholder data moving between shards within the cluster, even though that traffic stays inside the VPC.

HIPAA Omnibus Rule 2013: 45 CFR 164.312(e)(1) requires transmission security for ePHI. Any ePHI indexed in Elasticsearch traverses inter-node channels during shard operations, replication, and search execution. Node-to-node encryption covers all of that traffic with TLS 1.2, directly satisfying the transmission security standard.

GDPR: Index data flowing between nodes during shard replication and query execution can include personal data. Article 32's requirement for appropriate technical safeguards applies to this layer, and encrypting it reduces exposure during processing operations where application-layer protections don't reach.

NIST SP 800-53 Rev 5: This addresses both SC-8 (Transmission Confidentiality and Integrity) and SC-23 (Session Authenticity). TLS 1.2 on inter-node channels handles both: authenticated sessions prevent man-in-the-middle attacks, and encryption prevents passive interception of index data and cluster state. Two controls, one setting.

FedRAMP Moderate Baseline Rev 4: SC-8 calls for confidentiality and integrity of transmitted information. At the Moderate baseline, TLS 1.2 between nodes is what gets you there for federal data processed through Elasticsearch, ensuring plaintext interception by network-level adversaries isn't possible within the cluster.

Tool mappings

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

  • Compliance.tf Control: es_domain_node_to_node_encryption_enabled

  • AWS Config Managed Rule: ELASTICSEARCH_NODE_TO_NODE_ENCRYPTION_CHECK

  • Checkov Check: CKV_AWS_6

  • Powerpipe Controls: aws_compliance.control.es_domain_node_to_node_encryption_enabled, aws_compliance.control.opensearch_domain_node_to_node_encryption_enabled

  • Prowler Check: opensearch_service_domains_node_to_node_encryption_enabled

  • AWS Security Hub Control: ES.3

  • KICS Query: 967eb3e6-26fc-497d-8895-6428beb6e8e2

  • Trivy Check: AWS-0043

Last reviewed: 2026-03-09