Skip to content

Aurora MySQL DB clusters should have audit logging enabled

Aurora MySQL audit logs capture database activity including connections, disconnections, queries, and schema or data changes. Without them, you have no visibility into who accessed the database, what queries they ran, or whether unauthorized changes occurred. That blind spot makes breach investigation and access pattern analysis nearly impossible.

The Advanced Auditing feature publishes logs to CloudWatch Logs, where you can set alarms, query with CloudWatch Logs Insights, and feed events into a SIEM. Enabling it costs nothing beyond CloudWatch Logs storage and ingestion, so there is no valid cost reason to leave it off in production.

Retrofit consideration

Changing the DB cluster parameter group on an existing cluster may require a reboot to apply static parameters. The audit logging parameters are dynamic, but verify against your specific Aurora MySQL version before assuming a reboot is unnecessary. Also confirm CloudWatch Logs export is enabled on the cluster.

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

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

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

What this control checks

Two Terraform resources are required. First, an aws_rds_cluster_parameter_group with family matching your Aurora MySQL version (e.g., aurora-mysql8.0). Within it, set server_audit_logging to 1 and server_audit_events to a comma-separated list of event types, such as CONNECT,QUERY,QUERY_DCL,QUERY_DDL,QUERY_DML,TABLE. Second, on the aws_rds_cluster resource, set db_cluster_parameter_group_name to reference this parameter group and include "audit" in enabled_cloudwatch_logs_exports so audit logs are published to CloudWatch. A cluster on the default parameter group (where server_audit_logging defaults to 0), or one that omits "audit" from enabled_cloudwatch_logs_exports, will fail.

Common pitfalls

  • Forgetting enabled_cloudwatch_logs_exports

    Setting server_audit_logging to 1 in the parameter group is necessary but not sufficient. If "audit" is not included in enabled_cloudwatch_logs_exports on the aws_rds_cluster resource, logs stay internal to the engine and never reach CloudWatch. The control checks both conditions.

  • Empty server_audit_events parameter

    With server_audit_logging set to 1 but server_audit_events empty or unset, the auditing engine has nothing to capture. Explicitly set this parameter to the event categories you need, such as CONNECT,QUERY_DDL,QUERY_DCL,QUERY_DML.

  • Parameter group family mismatch

    Get the family wrong on aws_rds_cluster_parameter_group and you will hit Terraform errors or silent parameter misapplication. The family must match the cluster's actual Aurora MySQL engine version: aurora-mysql5.7 and aurora-mysql8.0 are not interchangeable.

  • Using incorrect resource for parameter blocks

    Define parameter {} blocks on aws_rds_cluster_parameter_group, not on aws_rds_cluster. Use a dedicated aws_rds_cluster_parameter_group resource and reference it via db_cluster_parameter_group_name so audit parameters are applied and tracked in state.

Audit evidence

An auditor expects to see the AWS Config rule rds-aurora-mysql-audit-logging-enabled marked COMPLIANT for each Aurora MySQL cluster. Supporting evidence includes the RDS Console showing the cluster's parameter group with server_audit_logging set to 1 and server_audit_events populated, plus the "Logs & events" tab confirming that audit log export to CloudWatch Logs is active.

Auditors may also request a sample of actual log entries from the CloudWatch Logs group /aws/rds/cluster/<cluster-name>/audit to confirm events are flowing and include expected fields: timestamp, user, host, and query text. The retention policy on that log group should be documented.

Framework-specific interpretation

PCI DSS v4.0: Requirement 10 covers audit logging across all in-scope system components, including databases that store or process cardholder data. Aurora MySQL audit logging can help meet parts of Requirement 10.2: it records user connections, disconnections, and query activity when the right event classes are configured. Requirement 10.3 calls for sufficient log detail to support forensic analysis, and publishing to CloudWatch Logs with defined retention and access controls can support that objective.

Tool mappings

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

  • Compliance.tf Control: rds_db_cluster_aurora_mysql_audit_logging_enabled

  • AWS Config Managed Rules: AURORA_MYSQL_CLUSTER_AUDIT_LOGGING, RDS_AURORA_MYSQL_AUDIT_LOGGING_ENABLED

  • Checkov Check: CKV_AWS_325

  • Powerpipe Control: aws_compliance.control.rds_db_cluster_aurora_mysql_audit_logging_enabled

  • AWS Security Hub Control: RDS.45

Last reviewed: 2026-03-09