Back to Checks
aws

RDS instance is protected by an AWS Backup plan

rds_instance_protected_by_backup_plan
Service: rdsSeverity: high
OfficialBuilt-inVerified
Categories:resilience
Resource Type:AwsRdsDbInstance

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 Cloud
Run
prowler aws --checks rds_instance_protected_by_backup_plan

Recommendation

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 plan

Other

1In the AWS Console, open AWS Backup
2Go to Settings > Service opt-in and enable Amazon RDS (if not already)
3Go to Backup plans and select an existing plan (or Create backup plan with defaults)
4Click Assign resources
5Enter a name, select an IAM role, and add the RDS instance (by ARN or resource picker)
6Click Assign resources to save

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