Back to Checks
RDS instance SSL/TLS certificate has more than 3 months of validity remaining
rds_instance_certificate_expiration
Service: rdsSeverity: high
OfficialBuilt-inVerified
Categories:encryption
Resource Type:AwsRdsDbInstance
RDS DB instances are evaluated for server certificate validity windows, including default and customer-managed certificates. Certificates expired or approaching expiration (e.g., <1 month, <3 months, 3-6 months, >6 months) are identified using the certificate valid_till date.
Risk
Without timely rotation:
- TLS failures block DB connections, impacting availability
- Bypassed or weak validation enables MITM, risking confidentiality and integrity
- Emergency changes increase operational risk and error rates
Run this check with Prowler
Run in Prowler CloudRun
prowler aws --checks rds_instance_certificate_expirationRecommendation
Establish a certificate lifecycle for RDS:
- Rotate server/CA certs well before expiry; avoid pinned or outdated CAs
- Keep client trust stores current and enforce TLS with validation
- Monitor expiry and automate alerts/rotation
- For custom certs, apply least privilege, separation of duties, and periodic key rotation; test changes
Remediation
CLI
aws rds modify-db-instance --db-instance-identifier <example_resource_id> --ca-certificate-identifier rds-ca-rsa2048-g1 --apply-immediatelyTerraform
# Set a current CA on the RDS instance
resource "aws_db_instance" "<example_resource_name>" {
identifier = "<example_resource_id>"
ca_cert_identifier = "rds-ca-rsa2048-g1" # CRITICAL: rotates to a valid CA to ensure certificate validity >3 months
}NativeIaC
# CloudFormation: update RDS instance CA to a current certificate
Resources:
<example_resource_name>:
Type: AWS::RDS::DBInstance
Properties:
CACertificateIdentifier: rds-ca-rsa2048-g1 # CRITICAL: rotates to a valid CA to restore >3 months certificate validityOther
1In the AWS Console, go to RDS > Databases and select the DB instance
2Click Modify
3In Connectivity (or Certificate authority), select rds-ca-rsa2048-g1
4Check Apply immediately
5Click Continue (if shown) and then Modify DB instance
Check Code
from datetime import datetime
from dateutil import relativedelta
from pytz import utc
from prowler.lib.check.models import Check, Check_Report_AWS, Severity
from prowler.providers.aws.services.rds.rds_client import rds_client
class rds_instance_certificate_expiration(Check):
# RDS Certificates with an expiration greater than 3 months the check will PASS with a severity of informational if greater than 6 months and a severity of low if between 3 and 6 months.
# RDS Certificates that expires in less than 3 months the check will FAIL with a severity of medium.
# RDS Certificates that expires in less than a month the check will FAIL with a severity of high.
# RDS Certificates that are expired the check will FAIL with a severity of critical.
def execute(self):
findings = []
for db_instance in rds_client.db_instances.values():
report = Check_Report_AWS(metadata=self.metadata(), resource=db_instance)
report.status = "FAIL"
report.check_metadata.Severity = Severity.critical
report.status_extended = (
f"RDS Instance {db_instance.id} certificate has expired."
)
# Check only RDS DB instances that support parameter group encryption
for cert in db_instance.cert:
if not cert.customer_override:
if cert.valid_till > datetime.now(
utc
) + relativedelta.relativedelta(months=6):
report.status = "PASS"
report.check_metadata.Severity = Severity.informational
report.status_extended = f"RDS Instance {db_instance.id} certificate has over 6 months of validity left."
elif cert.valid_till < datetime.now(
utc
) + relativedelta.relativedelta(
months=6
) and cert.valid_till > datetime.now(
utc
) + relativedelta.relativedelta(
months=3
):
report.status = "PASS"
report.check_metadata.Severity = Severity.low
report.status_extended = f"RDS Instance {db_instance.id} certificate has between 3 and 6 months of validity."
elif cert.valid_till < datetime.now(
utc
) + relativedelta.relativedelta(
months=3
) and cert.valid_till > datetime.now(
utc
) + relativedelta.relativedelta(
months=1
):
report.status = "FAIL"
report.check_metadata.Severity = Severity.medium
report.status_extended = f"RDS Instance {db_instance.id} certificate less than 3 months of validity."
elif cert.valid_till < datetime.now(
utc
) + relativedelta.relativedelta(
months=1
) and cert.valid_till > datetime.now(
utc
):
report.status = "FAIL"
report.check_metadata.Severity = Severity.high
report.status_extended = f"RDS Instance {db_instance.id} certificate less than 1 month of validity."
else:
report.status = "FAIL"
report.check_metadata.Severity = Severity.critical
report.status_extended = (
f"RDS Instance {db_instance.id} certificate has expired."
)
else:
if cert.valid_till > datetime.now(
utc
) + relativedelta.relativedelta(months=6):
report.status = "PASS"
report.check_metadata.Severity = Severity.informational
report.status_extended = f"RDS Instance {db_instance.id} custom certificate has over 6 months of validity left."
elif cert.valid_till < datetime.now(
utc
) + relativedelta.relativedelta(
months=6
) and cert.valid_till > datetime.now(
utc
) + relativedelta.relativedelta(
months=3
):
report.status = "PASS"
report.check_metadata.Severity = Severity.low
report.status_extended = f"RDS Instance {db_instance.id} custom certificate has between 3 and 6 months of validity."
elif cert.valid_till < datetime.now(
utc
) + relativedelta.relativedelta(
months=3
) and cert.valid_till > datetime.now(
utc
) + relativedelta.relativedelta(
months=1
):
report.status = "FAIL"
report.check_metadata.Severity = Severity.medium
report.status_extended = f"RDS Instance {db_instance.id} custom certificate less than 3 months of validity."
elif cert.valid_till < datetime.now(
utc
) + relativedelta.relativedelta(
months=1
) and cert.valid_till > datetime.now(
utc
):
report.status = "FAIL"
report.check_metadata.Severity = Severity.high
report.status_extended = f"RDS Instance {db_instance.id} custom certificate less than 1 month of validity."
else:
report.status = "FAIL"
report.check_metadata.Severity = Severity.critical
report.status_extended = f"RDS Instance {db_instance.id} custom certificate has expired."
findings.append(report)
return findings