Skip to content

Elasticsearch domains should have audit logging enabled

Audit logs capture authentication attempts, index-level access, and query activity within Elasticsearch domains. Without them, there is no record of who accessed or modified data, making breach investigation and insider-threat detection nearly impossible.

Elasticsearch domains often store aggregated application logs, business analytics, or sensitive search indices. Enabling audit logging creates a persistent audit trail in CloudWatch Logs that security teams can query with Logs Insights or forward to a SIEM for correlation.

Retrofit consideration

Enabling audit logging requires fine-grained access control (advanced_security_options). On existing domains, enabling fine-grained access control is typically done through a blue/green deployment and may cause temporary performance impact; recreation or migration is not always required.

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

  node_to_node_encryption {
    enabled = true
  }

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

What this control checks

On aws_elasticsearch_domain (or aws_opensearch_domain), a log_publishing_options block must be present with log_type set to "AUDIT_LOGS" and cloudwatch_log_group_arn pointing to a CloudWatch Logs log group. advanced_security_options must have enabled = true, since audit logging is only available when fine-grained access control is active. It fails when the AUDIT_LOGS block is absent, when advanced_security_options is disabled, or when enabled inside log_publishing_options is explicitly set to false. A CloudWatch Logs log group and a resource policy granting es.amazonaws.com write access are also required.

Common pitfalls

  • Fine-grained access control prerequisite

    Audit logging requires advanced_security_options { enabled = true }. If this block is missing or enabled is false, the Elasticsearch API rejects the audit log configuration entirely. On existing domains where fine-grained access control was never enabled, turning it on may trigger a blue/green deployment with temporary performance impact.

  • CloudWatch log resource policy missing

    Even with log_publishing_options configured, Elasticsearch cannot write to CloudWatch Logs without an aws_cloudwatch_log_resource_policy granting es.amazonaws.com the logs:PutLogEvents and logs:CreateLogStream actions. Without it, log delivery silently fails, and the gap won't be obvious during terraform apply.

  • Deprecated inline log_publishing_options in older modules

    Older Terraform modules using aws_elasticsearch_domain may only include ES_APPLICATION_LOGS or INDEX_SLOW_LOGS in log_publishing_options, omitting AUDIT_LOGS entirely. Each log_type needs its own block, so add a separate log_publishing_options block for AUDIT_LOGS alongside the existing ones rather than modifying them.

  • Log group retention left at default

    CloudWatch log groups created without an explicit retention_in_days on aws_cloudwatch_log_group retain logs indefinitely. For audit logs, set a retention period that meets your compliance requirements (365 days for PCI DSS, for example) and avoid leaving it unbounded.

Audit evidence

An auditor expects the AWS Config rule evaluation to show compliant status across all in-scope Elasticsearch domains. Console evidence from the OpenSearch Service domain configuration page should show "Audit logs" enabled under the "Logs" tab, with a linked CloudWatch Logs log group containing recent entries for authentication events and index operations.

For deeper validation, CloudTrail logs showing UpdateElasticsearchDomainConfig or CreateElasticsearchDomain API calls confirm when audit logging was enabled and by whom. Security Hub finding status across accounts and regions provides a consolidated view of this control's coverage.

Framework-specific interpretation

NIST Cybersecurity Framework v2.0: DE.CM and DE.AE both call for continuous monitoring of data access and authentication events. Audit logs from Elasticsearch domains feed directly into that capability, covering search workloads that might otherwise be invisible to security tooling.

Tool mappings

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

  • Compliance.tf Control: es_domain_audit_logging_enabled

  • AWS Config Managed Rules: ELASTICSEARCH_LOGS_TO_CLOUDWATCH, OPENSEARCH_AUDIT_LOGGING_ENABLED

  • Checkov Check: CKV_AWS_317

  • Powerpipe Controls: aws_compliance.control.es_domain_audit_logging_enabled, aws_compliance.control.opensearch_domain_audit_logging_enabled

  • Prowler Check: opensearch_service_domains_audit_logging_enabled

  • AWS Security Hub Controls: ES.5, Opensearch.5

  • Trivy Check: AWS-0042

Last reviewed: 2026-03-09