Skip to main content
emnode / learn
Compliance Medium severity

AWS Security Hub · RDS

RDS.41: RDS SQL Server should be encrypted in transit

Written and reviewed by Emnode · Last reviewed

What does AWS Security Hub RDS.41 check?

RDS.41 inspects the parameter group on an RDS for SQL Server instance (AWS::RDS::DBInstance) and checks the rds.force_ssl parameter. It runs on a periodic schedule and reports FAILED when rds.force_ssl is 0 (off).

Why does RDS.41 matter?

RDS for SQL Server supports TLS out of the box but accepts unencrypted connections by default — if a client doesn't ask for TLS, the database happily exchanges logins, queries, and result sets in the clear. The failure mode is invisible in normal operation: applications keep working and dashboards stay green while the app-to-database connection is readable to anyone observing the network path (a misconfigured VPC peering, a compromised host in the same subnet, a mirroring port). Credentials, PII, and financial records stay exposed for as long as the flag is off.

How do I fix RDS.41?

  1. Confirm all clients can negotiate TLS.
  2. Set rds.force_ssl=1 in a custom DB parameter group attached to the instance.
  3. Reboot if the parameter requires it, then verify non-TLS connections are rejected.
  4. Standardise the parameter group across SQL Server instances.

Remediation script · bash

# Find the highest-impact plaintext-permitting stores across engines.
aws rds describe-db-instances \
  --query 'DBInstances[].DBInstanceIdentifier' --output text
aws elasticache describe-replication-groups \
  --query 'ReplicationGroups[?TransitEncryptionEnabled==`false`].ReplicationGroupId' \
  --output text

# RDS for PostgreSQL: require TLS via rds.force_ssl (static -> needs a reboot).
PG=$(aws rds describe-db-instances --db-instance-identifier prod-orders-pg \
  --query 'DBInstances[].DBParameterGroups[].DBParameterGroupName' --output text)
aws rds modify-db-parameter-group --db-parameter-group-name "$PG" \
  --parameters 'ParameterName=rds.force_ssl,ParameterValue=1,ApplyMethod=pending-reboot'
aws rds reboot-db-instance --db-instance-identifier prod-orders-pg

# Redshift: require_ssl on a custom cluster parameter group, then reboot.
aws redshift modify-cluster-parameter-group --parameter-group-name analytics-tls \
  --parameters ParameterName=require_ssl,ParameterValue=true
aws redshift reboot-cluster --cluster-identifier analytics-prod

Full walkthrough (console steps, edge cases and verification) in the lesson Enforce TLS on database and cache connections.

Is RDS.41 a false positive?

RDS.41 re-evaluates on a schedule rather than on change, so the finding will not clear instantly after you flip rds.force_ssl — the evaluator re-reads the effective parameter set on its own cadence.

Part of the learning path Encrypt everything
  • RDS.1 An RDS snapshot is shared publicly
  • RDS.2 An RDS instance is publicly accessible from the internet
  • RDS.3 RDS DB instances should be encrypted at rest
  • RDS.4 RDS snapshots should be encrypted at rest
  • RDS.5 RDS DB instances should use multiple AZs
  • RDS.6 RDS lacks enhanced monitoring
  • RDS.7 RDS clusters should have deletion protection
  • RDS.8 RDS DB instances should have deletion protection
  • RDS.9 RDS engine logs are not shipped to CloudWatch
  • RDS.10 RDS relies on long-lived database passwords
  • RDS.11 RDS instances should have automatic backups
  • RDS.12 IAM auth should be configured for RDS clusters