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 = falsewhilemaster_user_nameandmaster_user_passwordare still present inmaster_user_options. The two modes are mutually exclusive: swap those arguments formaster_user_arnbefore applying.Fine-grained access control must be enabled first
internal_user_database_enabledhas no effect unlessenabled = trueis set in the sameadvanced_security_optionsblock. 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_accessandsecurity_managerthat 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/rolesmappingAPI before you flip the switch.Cognito authentication is separate from this control
cognito_optionsgives you Cognito-based access to OpenSearch Dashboards but leaves the internal user database untouched. Setinternal_user_database_enabled = falseinadvanced_security_optionsexplicitly; 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
Related controls
Tool mappings
Use these identifiers to cross-reference this control across tools, reports, and evidence.
Compliance.tf Control:
opensearch_domain_internal_user_database_disabledPowerpipe Control:
aws_compliance.control.opensearch_domain_internal_user_database_disabledProwler Check:
opensearch_service_domains_internal_user_database_enabled
Last reviewed: 2026-03-09