Skip to content

OpenSearch domains internal user database should be disabled

The OpenSearch internal user database stores credentials directly inside the cluster, completely outside your centralized identity provider. That means separate rotation schedules, no automatic deprovisioning when someone leaves, and MFA enforcement that only applies to your IdP, not to anyone authenticating with local credentials.

Disabling it forces all authentication through IAM roles or SAML federation. Access reviews cover a single system, offboarding is automatic, and MFA enforcement is consistent across the board.

Retrofit consideration

Migrating an existing domain from internal user authentication to IAM or SAML means auditing and migrating all internal users, updating every application connection string, and rebuilding fine-grained access control role mappings. Test in a non-production environment before applying to live domains; a misconfigured master ARN or broken role mapping will lock all users out.

Implementation

Choose the approach that matches how you manage Terraform.

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

  auto_tune_options = {
    desired_state = "DISABLED"
  }
  cluster_config = {
    dedicated_master_enabled = false
    instance_count           = 1
    instance_type            = "t3.small.search"
    zone_awareness_enabled   = false
  }
  domain_endpoint_options = {
    enforce_https       = true
    tls_security_policy = "Policy-Min-TLS-1-2-2019-07"
  }
  domain_name = "abc123"
  ebs_options = {
    ebs_enabled = true
    volume_size = 20
    volume_type = "gp3"
  }
  engine_version = "OpenSearch_2.11"

  advanced_security_options = {
    internal_user_database_enabled = false
  }
}

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

resource "aws_opensearch_domain" "this" {
  auto_tune_options {
    desired_state = "DISABLED"
  }

  cluster_config {
    instance_count         = 1
    instance_type          = "t3.small.search"
    zone_awareness_enabled = false
  }

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

  encrypt_at_rest {
    enabled = true
  }

  engine_version = "OpenSearch_2.11"

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

  advanced_security_options {
    enabled                        = true
    internal_user_database_enabled = false

    master_user_options {
      master_user_arn = "arn:aws:iam::123456789012:role/example-role"
    }
  }
}

What this control checks

In the aws_opensearch_domain resource, the advanced_security_options block must have enabled = true and internal_user_database_enabled = false. With the internal database disabled, master_user_options must use master_user_arn (an IAM role or user ARN) rather than master_user_name and master_user_password. A domain passes if internal_user_database_enabled is explicitly false. It fails if set to true or if advanced_security_options is absent entirely. SAML-based authentication also requires a saml_options block, but the primary check is the internal_user_database_enabled argument.

Common pitfalls

  • master_user_options conflict when toggling off internal DB

    Terraform will error if you set internal_user_database_enabled = false while master_user_name and master_user_password are still present in master_user_options. The two modes are mutually exclusive: swap those arguments for master_user_arn before applying.

  • Fine-grained access control must be enabled first

    internal_user_database_enabled has no effect unless enabled = true is set in the same advanced_security_options block. Fine-grained access control has to be on first; without it, the argument is silently ignored and the domain will still fail the check.

  • Existing role mappings reference internal users

    Before disabling the internal database, audit your fine-grained access control role mappings. Roles like all_access and security_manager that reference internal usernames stop working immediately. Remap them to IAM ARNs or SAML groups via the OpenSearch Dashboards security plugin or the _plugins/_security/api/rolesmapping API before you flip the switch.

  • Cognito authentication is separate from this control

    cognito_options gives you Cognito-based access to OpenSearch Dashboards but leaves the internal user database untouched. Set internal_user_database_enabled = false in advanced_security_options explicitly; Cognito configuration doesn't do it for you.

Audit evidence

Auditors expect Config rule evaluation results confirming all OpenSearch domains have the internal user database disabled. In the AWS Console, the domain's security configuration should show fine-grained access control enabled, the internal user database toggled off, and a master IAM ARN in place of a username/password pair.

Supporting evidence includes SAML identity provider configuration in the domain settings, CloudTrail UpdateDomainConfig events with InternalUserDatabaseEnabled set to false, and IAM policies granting appropriate es:ESHttp* permissions to federated roles.

Framework-specific interpretation

Tool mappings

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

  • Compliance.tf Control: opensearch_domain_internal_user_database_disabled

  • Powerpipe Control: aws_compliance.control.opensearch_domain_internal_user_database_disabled

  • Prowler Check: opensearch_service_domains_internal_user_database_enabled

Last reviewed: 2026-03-09