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
Implementation
Choose the approach that matches how you manage Terraform.
Use the compliance.tf module to enforce this control by default. See get started with compliance.tf.
module "opensearch" {
source = "registry.compliance.tf/terraform-aws-modules/opensearch/aws"
version = ">=2.0.0,<3.0.0"
advanced_security_options = {
enabled = true
internal_user_database_enabled = true
master_user_options = {
master_user_name = "admin"
master_user_password = "P0fix-Test-2026!"
}
}
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"
}This control is enforced automatically with Compliance.tf modules. Start free trial
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.
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_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