RDS for SQL Server DB instances should publish logs to CloudWatch Logs
SQL Server database logs contain error messages, agent job history, and optionally SQL Server Audit records. Without CloudWatch Logs integration, these logs exist only on the RDS instance's local storage, where they rotate and eventually disappear. You lose the ability to set CloudWatch alarms on error patterns, run Logs Insights queries across your fleet, or retain logs beyond the instance's lifecycle.
Forwarding logs to CloudWatch decouples log retention from instance operations. If someone deletes or resizes an instance, the logs survive independently. That matters during incident investigations where you need weeks or months of history.
Retrofit consideration
Enabling CloudWatch Logs exports on an existing RDS SQL Server instance triggers a modification that may cause a brief log delivery delay but does not require a reboot. If the instance lacks the required IAM service-linked role permissions or the target CloudWatch log group does not exist, the modification can fail silently.
Implementation
Choose the approach that matches how you manage Terraform.
If you use terraform-aws-modules/rds/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" {
source = "terraform-aws-modules/rds/aws"
version = ">=7.0.0"
allocated_storage = 20
db_name = "myapp"
db_subnet_group_name = "example-db-subnet-group"
engine = "mysql"
engine_version = "8.0.41"
family = "mysql8.0"
identifier = "abc123"
instance_class = "db.t3.micro"
major_engine_version = "8.0"
password_wo = "change-me-in-production"
skip_final_snapshot = true
username = "dbadmin"
vpc_security_group_ids = ["sg-12345678"]
}
Use AWS provider resources directly. See docs for the resources involved: aws_db_instance.
resource "aws_db_instance" "this" {
allocated_storage = 20
enabled_cloudwatch_logs_exports = ["agent", "error"]
engine = "sqlserver-ex"
identifier = "pofix-abc123"
instance_class = "db.t3.small"
license_model = "license-included"
monitoring_interval = 60
monitoring_role_arn = "arn:aws:iam::123456789012:role/example-role"
password = "ChangeMe123!"
skip_final_snapshot = true
username = "dbadmin"
}
What this control checks
This control validates that the aws_db_instance resource for a SQL Server engine family has enabled_cloudwatch_logs_exports set with at least one valid log type. For SQL Server engines (sqlserver-ee, sqlserver-se, sqlserver-ex, sqlserver-web), the accepted log types are "error" and "agent". An instance passes when enabled_cloudwatch_logs_exports contains one or both values. It fails when the argument is omitted entirely or set to an empty list. The control may optionally require specific log types depending on the parameter configuration. No additional IAM or CloudWatch resources need to be declared in Terraform; RDS automatically creates the /aws/rds/instance/<instance-id>/<log-type> log groups.
Common pitfalls
Empty list still fails
Terraform treats
enabled_cloudwatch_logs_exports = []the same as omitting the argument entirely. No log types are sent to the API, and the control reports a failure. You must include at least one valid value, for example["error"].SQL Server Audit logs require additional setup
If your organization needs SQL Server Audit, configure it through a custom option group with the
SQLSERVER_AUDIToption (viaaws_db_option_group) and the relevant SQL Server settings. Don't add"audit"toenabled_cloudwatch_logs_exportsfor RDS SQL Server. The only valid CloudWatch export types are"error"and"agent".CloudWatch log group retention defaults to never expire
RDS auto-creates CloudWatch log groups with no expiration policy. Left alone, logs accumulate indefinitely and CloudWatch Logs storage costs grow with them. Pre-create the log groups in Terraform using
aws_cloudwatch_log_groupwithretention_in_daysset before enabling exports.Engine filter matters
Get the engine check wrong in a conditional module and this control silently misapplies. All four SQL Server variants must be handled explicitly:
sqlserver-ee,sqlserver-se,sqlserver-ex, andsqlserver-web. A prefix match onsqlserveralone can collide with future engine names and produce unexpected behavior.
Audit evidence
Auditors expect AWS Config rule evaluation results showing each SQL Server RDS instance as COMPLIANT. Supporting evidence includes the RDS instance detail page in the AWS Console (under the "Logs & events" or "Configuration" tab) showing the published log types, or the output of aws rds describe-db-instances where the EnabledCloudwatchLogsExports array contains "error" and/or "agent".
CloudWatch Logs console screenshots showing active log groups under /aws/rds/instance/ with recent log streams confirm log delivery is working. Retention policy settings on those log groups show logs are preserved for the required period.
Framework-specific interpretation
Related controls
Tool mappings
Use these identifiers to cross-reference this control across tools, reports, and evidence.
Compliance.tf Control:
rds_db_instance_sql_server_logging_enabledAWS Config Managed Rule:
RDS_SQL_SERVER_LOGS_TO_CLOUDWATCHCheckov Check:
CKV_AWS_129Powerpipe Control:
aws_compliance.control.rds_db_instance_sql_server_logging_enabledProwler Check:
rds_instance_integration_cloudwatch_logsAWS Security Hub Controls:
RDS.40,RDS.9KICS Query:
8d7f7b8c-6c7c-40f8-baa6-62006c6c7b56
Last reviewed: 2026-03-09