OpenSearch domains should have fine-grained access control enabled
Fine-grained access control in OpenSearch lets you define index-level, document-level, and field-level permissions using roles mapped to IAM principals or an internal user database. Without it, any authenticated principal with domain-level access can read or modify all indices. This creates a flat access model where a compromised application credential exposes every index in the domain.
Enabling FGAC also activates the OpenSearch Dashboards security plugin, giving you audit logging of authentication events and a UI for managing roles. For domains holding PII, financial records, or log data from multiple tenants, the absence of FGAC makes least-privilege enforcement impossible at the data layer.
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.
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 = {
enabled = true
}
}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 = true
master_user_options {
master_user_name = "admin"
master_user_password = "ChangeMe123!"
}
}
}What this control checks
On the aws_opensearch_domain resource, advanced_security_options must be present with enabled = true. Inside that block, master_user_options must specify either master_user_arn for an IAM-based master user, or both master_user_name and master_user_password for the internal user database. When using the internal user database, also set internal_user_database_enabled = true. Fine-grained access control has prerequisites: encrypt_at_rest.enabled, node_to_node_encryption.enabled, and domain_endpoint_options.enforce_https must all be true. A domain missing any of these causes apply to fail with an API error. The control fails when advanced_security_options is omitted or enabled is false.
Common pitfalls
Prerequisites silently block enablement
Fine-grained access control requires encrypt_at_rest.enabled, node_to_node_encryption.enabled, and domain_endpoint_options.enforce_https all set to true. If any is missing, Terraform surfaces an API error, but the message often doesn't clearly identify which prerequisite failed. Configure all three before or alongside advanced_security_options to avoid iterating through apply failures.
Master user password in state file
Setting master_user_name and master_user_password directly in master_user_options puts the password in plaintext in Terraform state. Use master_user_arn pointing to an IAM principal instead, or generate a password with random_password, store it via aws_secretsmanager_secret_version, and mark it sensitive to at least limit exposure in logs and plan output.
Overly broad domain access policy
Enabling FGAC does not automatically restrict the domain access policy. A resource-based policy with "Principal": "*" and no conditions still lets any principal reach the endpoint; FGAC handles authorization from there, but you've left the front door open. Tighten the access policy to specific IAM principals or VPC-constrained sources.
Blue/green deployment on existing domains
Enabling advanced_security_options on a running domain triggers a blue/green deployment. Depending on cluster size, that can take anywhere from 15 minutes to several hours. Plan a maintenance window, notify dependent teams, and test client authentication patterns after the cutover before declaring it done.
Audit evidence
AWS Config rule evaluation results showing each OpenSearch domain as compliant satisfy the primary evidence requirement, or equivalent CSPM output. The DescribeDomain API response should show AdvancedSecurityOptions.Enabled: true and AdvancedSecurityOptions.InternalUserDatabaseEnabled reflecting the chosen authentication strategy. Supporting evidence includes the domain's access policy document and OpenSearch Dashboards screenshots showing configured roles with index-level or document-level restrictions.
CloudTrail UpdateDomainConfig events confirm when FGAC was enabled and by whom. If the internal user database is in use, evidence that the master user password is stored in Secrets Manager with automatic rotation is also expected.
Framework-specific interpretation
PCI DSS v4.0: PCI DSS v4.0 Requirement 7 calls for restricting access to cardholder data by business need to know. FGAC addresses this at the data layer: index-level and document-level permissions mean individual roles see only the data they need. Requirement 7.2.1 specifically expects access control models tied to business need, and FGAC's role mapping against IAM principals or internal users is how you meet it.
Related controls
Tool mappings
Use these identifiers to cross-reference this control across tools, reports, and evidence.
- Compliance.tf Control:
opensearch_domain_fine_grained_access_enabled - AWS Config Managed Rule:
OPENSEARCH_ACCESS_CONTROL_ENABLED - Checkov Check:
CKV2_AWS_52 - Powerpipe Control:
aws_compliance.control.opensearch_domain_fine_grained_access_enabled - Prowler Check:
opensearch_service_domains_access_control_enabled - AWS Security Hub Control:
Opensearch.7
Last reviewed: 2026-03-09