RDS instance is protected by an AWS Backup plan
RDS DB instances (non-Aurora) are included in an AWS Backup plan, indicating scheduled backups and retention are applied to the resource.
Aurora engines are evaluated separately.
Risk
Without an AWS Backup plan, databases lack assured recovery, degrading availability and integrity. Likely outcomes: accidental deletion, corruption, or malicious wipes with no recent restore point. Expect missed RPO/RTO, extended outages, and data inconsistency after incidents.
Run this check with Prowler
Run in Prowler Cloudprowler aws --checks rds_instance_protected_by_backup_planRecommendation
Assign all non-Aurora RDS to an AWS Backup plan aligned to business RPO/RTO. Use tags for automatic coverage, define retention and lifecycle, and store backups in immutable vaults where possible. Regularly perform restore tests. Enforce least privilege and separation of duties for backup administration.
Remediation
CLI
aws backup create-backup-selection --backup-plan-id <example_backup_plan_id> --backup-selection '{"SelectionName":"<selection_name>","IamRoleArn":"<example_role_arn>","Resources":["<rds-instance-arn>"]}'Terraform
# Assign an RDS instance to an AWS Backup plan
resource "aws_backup_selection" "<example_resource_name>" {
name = "<selection_name>"
plan_id = "<example_backup_plan_id>" # CRITICAL: attaches to the backup plan
iam_role_arn = "<example_role_arn>" # CRITICAL: role AWS Backup uses
resources = ["<rds-instance-arn>"] # CRITICAL: RDS instance protected by the plan
}NativeIaC
# CloudFormation: assign an RDS instance to an AWS Backup plan
Resources:
<example_resource_name>:
Type: AWS::Backup::BackupSelection
Properties:
BackupPlanId: <example_backup_plan_id> # CRITICAL: targets the backup plan to protect the instance
BackupSelection:
SelectionName: <selection_name>
IamRoleArn: <example_role_arn> # CRITICAL: role AWS Backup uses to back up the resource
Resources:
- <rds-instance-arn> # CRITICAL: assigns the RDS instance to the planOther
Check Code
from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.backup.backup_client import backup_client
from prowler.providers.aws.services.rds.rds_client import rds_client
class rds_instance_protected_by_backup_plan(Check):
def execute(self):
findings = []
for db_instance in rds_client.db_instances.values():
report = Check_Report_AWS(metadata=self.metadata(), resource=db_instance)
# Makes sure the instance is not running with an Aurora engine
# Aurora backup plans require enabling it separately from RDS
if db_instance.engine not in [
"aurora-mysql",
"aurora",
"aurora-postgresql",
]:
report.status = "FAIL"
report.status_extended = (
f"RDS Instance {db_instance.id} is not protected by a backup plan."
)
if (
db_instance.arn in backup_client.protected_resources
or f"arn:{rds_client.audited_partition}:rds:*:*:instance:*"
in backup_client.protected_resources
or "*" in backup_client.protected_resources
):
report.status = "PASS"
report.status_extended = (
f"RDS Instance {db_instance.id} is protected by a backup plan."
)
findings.append(report)
return findings