Skip to content

RDS DB clusters should have IAM authentication configured

Native database credentials are static secrets that must be stored, distributed, and rotated manually. When IAM authentication is enabled, applications retrieve short-lived tokens via rds-db:connect permissions instead of long-lived passwords. This eliminates an entire class of credential leakage risk and lets you govern database access through the same IAM policies that control every other AWS resource.

Retrofit consideration

Enabling IAM authentication on an existing cluster requires updating all application connection logic to use aws rds generate-db-auth-token instead of static passwords. The cluster itself can be modified without downtime, but any application still using native credentials will break immediately.

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 "rds_aurora" {
  source  = "pcidss.compliance.tf/terraform-aws-modules/rds-aurora/aws"
  version = ">=10.0.0,<11.0.0"

  create_db_subnet_group = true
  create_security_group  = true
  engine                 = "aurora-mysql"
  engine_version         = "8.0.mysql_aurora.3.08.0"
  instances = {
    one = {
      instance_class = "db.t4g.medium"
    }
  }
  manage_master_user_password = true
  master_username             = "root"
  name                        = "abc123"
  skip_final_snapshot         = true
  subnets                     = ["subnet-12345678", "subnet-12345678"]
  vpc_id                      = "vpc-12345678"
}

module "rds_aurora" {
  source  = "nist800171.compliance.tf/terraform-aws-modules/rds-aurora/aws"
  version = ">=10.0.0,<11.0.0"

  create_db_subnet_group = true
  create_security_group  = true
  engine                 = "aurora-mysql"
  engine_version         = "8.0.mysql_aurora.3.08.0"
  instances = {
    one = {
      instance_class = "db.t4g.medium"
    }
  }
  manage_master_user_password = true
  master_username             = "root"
  name                        = "abc123"
  skip_final_snapshot         = true
  subnets                     = ["subnet-12345678", "subnet-12345678"]
  vpc_id                      = "vpc-12345678"
}

module "rds_aurora" {
  source  = "acscessentialeight.compliance.tf/terraform-aws-modules/rds-aurora/aws"
  version = ">=10.0.0,<11.0.0"

  create_db_subnet_group = true
  create_security_group  = true
  engine                 = "aurora-mysql"
  engine_version         = "8.0.mysql_aurora.3.08.0"
  instances = {
    one = {
      instance_class = "db.t4g.medium"
    }
  }
  manage_master_user_password = true
  master_username             = "root"
  name                        = "abc123"
  skip_final_snapshot         = true
  subnets                     = ["subnet-12345678", "subnet-12345678"]
  vpc_id                      = "vpc-12345678"
}

module "rds_aurora" {
  source  = "nistcsfv11.compliance.tf/terraform-aws-modules/rds-aurora/aws"
  version = ">=10.0.0,<11.0.0"

  create_db_subnet_group = true
  create_security_group  = true
  engine                 = "aurora-mysql"
  engine_version         = "8.0.mysql_aurora.3.08.0"
  instances = {
    one = {
      instance_class = "db.t4g.medium"
    }
  }
  manage_master_user_password = true
  master_username             = "root"
  name                        = "abc123"
  skip_final_snapshot         = true
  subnets                     = ["subnet-12345678", "subnet-12345678"]
  vpc_id                      = "vpc-12345678"
}

If you use terraform-aws-modules/rds-aurora/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 "rds_aurora" {
  source  = "terraform-aws-modules/rds-aurora/aws"
  version = ">=10.0.0,<11.0.0"

  create_db_subnet_group = true
  create_security_group  = true
  engine                 = "aurora-mysql"
  engine_version         = "8.0.mysql_aurora.3.08.0"
  instances = {
    one = {
      instance_class = "db.t4g.medium"
    }
  }
  manage_master_user_password = true
  master_username             = "root"
  name                        = "abc123"
  skip_final_snapshot         = true
  subnets                     = ["subnet-12345678", "subnet-12345678"]
  vpc_id                      = "vpc-12345678"

  iam_database_authentication_enabled = true
}

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

resource "aws_rds_cluster" "this" {
  backtrack_window                = 72
  cluster_identifier              = "pofix-abc123"
  db_subnet_group_name            = "example-db-subnet-group"
  enabled_cloudwatch_logs_exports = ["audit"]
  engine                          = "aurora-mysql"
  engine_version                  = "8.0.mysql_aurora.3.08.0"
  manage_master_user_password     = true
  master_username                 = "dbadmin"
  skip_final_snapshot             = true
  vpc_security_group_ids          = ["sg-12345678"]

  iam_database_authentication_enabled = true
}

What this control checks

This control checks that aws_rds_cluster has iam_database_authentication_enabled set to true. The argument defaults to false, so any cluster that omits it or explicitly sets it to false will fail. For Aurora clusters, this argument lives directly on aws_rds_cluster. IAM authentication is only supported on Aurora MySQL and Aurora PostgreSQL engines; enabling it on an unsupported engine type produces an API error at apply time, not a policy failure.

Common pitfalls

  • Engine compatibility gaps

    IAM database authentication only works on Aurora MySQL and Aurora PostgreSQL, including their serverless variants. Apply this control broadly and RDS clusters on unsupported engines will fail the check even though enabling the feature is impossible for them. Scope your policy by engine to avoid flagging clusters that can't comply.

  • Connection limits with IAM auth

    IAM-authenticated connection attempts are subject to service-side throughput limits. Serverless functions that open many short-lived connections without pooling can hit this ceiling and start seeing authentication failures with no obvious cause. RDS Proxy or application-level connection pooling is the right fix.

  • Token expiration misunderstanding

    Tokens expire after 15 minutes, but an established connection stays open past that point. The token only needs to be valid at connection time. Refresh logic that generates a new token mid-session wastes API calls and adds latency without any security benefit.

  • Confusing cluster vs instance setting

    For Aurora, iam_database_authentication_enabled belongs on aws_rds_cluster, not aws_rds_cluster_instance. Setting it on the instance resource has no effect and won't satisfy this control. For non-Aurora RDS, the equivalent argument is on aws_db_instance.

Audit evidence

An auditor expects AWS Config rule evaluation results showing all RDS clusters as compliant under the managed rule rds-cluster-iam-authentication-enabled. Supporting that, aws rds describe-db-clusters output should show "IAMDatabaseAuthenticationEnabled": true for every cluster in scope.

An exported Config compliance report filtered to this rule and scoped across all relevant regions satisfies ongoing assurance requirements.

Framework-specific interpretation

PCI DSS v4.0: Requirement 8 calls for individual authentication to system components, not shared or static credentials. IAM auth tokens are scoped to an IAM principal, expire in 15 minutes, and route every connection attempt through IAM policy evaluation. That directly addresses the 8.2 and 8.3 expectations around unique authentication and strong credential management for database access.

Tool mappings

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

  • Compliance.tf Control: rds_db_cluster_iam_authentication_enabled

  • AWS Config Managed Rule: RDS_CLUSTER_IAM_AUTHENTICATION_ENABLED

  • Checkov Check: CKV_AWS_162

  • Powerpipe Control: aws_compliance.control.rds_db_cluster_iam_authentication_enabled

  • Prowler Checks: rds_cluster_iam_authentication_enabled, rds_instance_iam_authentication_enabled

  • AWS Security Hub Controls: RDS.10, RDS.12

  • KICS Query: 228497f6-414f-41c8-9113-f36a2b1b7975

  • Trivy Check: AWS-0176

Last reviewed: 2026-03-09