Review IAM access controls for an Elasticsearch domain

Review Elasticsearch domain policies, authentication and network restrictions together, and allow only required data access.

Description

Domain access policies define which principals and operations are allowed on Elasticsearch/OpenSearch indexes and APIs. When access is restricted to IAM principals, clients must sign requests with SigV4.

Principal: "*" does not necessarily mean unrestricted public access: IP conditions, VPC security groups or fine-grained access control may restrict access. Review actual authentication, permissions and networking alongside the domain policy.

Potential impact

  • Insufficient restrictions may let unauthorized clients read, change or delete documents.
  • Excessive permissions for approved clients can increase the damage from compromised accounts or mistakes.

Remediation

  • Where IAM authentication is required, restrict Principal to approved roles or users and configure request signing.
  • Limit actions and indexes, and allow only required connection paths. Use security groups for IP restrictions on VPC domains.
  • Review all applicable policies and fine-grained access controls, then verify the handling of authorized and unauthorized requests.

Examples

These excerpts compare policies for a public-endpoint domain. Set allowed_client_cidr to the clients' actual outbound IP range. A loopback address is not a remote client's source address. Verify support for the example engine version and configure the remaining domain settings separately.

Before

hcl
resource "aws_elasticsearch_domain" "example" {
  domain_name           = "tf-test"
  elasticsearch_version = "2.3"
}

resource "aws_elasticsearch_domain_policy" "example" {
  domain_name = aws_elasticsearch_domain.example.domain_name

  access_policies = <<POLICIES
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "es:*",
      "Principal": "*",
      "Effect": "Allow",
      "Condition": {
        "IpAddress": {"aws:SourceIp": "${var.allowed_client_cidr}"}
      },
      "Resource": "${aws_elasticsearch_domain.example.arn}/*"
    }
  ]
}
POLICIES
}

The principal is unrestricted, but the IP condition still applies. Assess the actual exposure together with the address range permitted by that condition.

After

hcl
resource "aws_elasticsearch_domain" "example" {
  domain_name           = "tf-test"
  elasticsearch_version = "2.3"
}

resource "aws_elasticsearch_domain_policy" "example" {
  domain_name = aws_elasticsearch_domain.example.domain_name

  access_policies = <<POLICIES
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "es:*",
      "Principal": {
        "AWS": [
          "arn:aws:iam::123456789012:root",
          "arn:aws:iam::555555555555:root"
        ]
      },
      "Effect": "Allow",
      "Condition": {
        "IpAddress": {"aws:SourceIp": "${var.allowed_client_cidr}"}
      },
      "Resource": "${aws_elasticsearch_domain.example.arn}/*"
    }
  ]
}
POLICIES
}

This narrows the principals to specified AWS accounts in addition to the IP condition. An account's root ARN delegates authority to that account, not only its root user. Replace the accounts with approved ones and further restrict access to roles and required actions where possible. The policy's es:* still grants broad HTTP operations on domain subresources.

References