Back to Checks
aws

EBS volume is protected by a backup plan

ec2_ebs_volume_protected_by_backup_plan
Service: ec2Severity: medium
OfficialBuilt-inVerified
Categories:resilience
Resource Type:AwsEc2Volume

EBS volumes are evaluated for coverage by an AWS Backup plan, whether explicitly targeted or included via broad resource selection, confirming scheduled, policy-driven backups exist for the volume.

Risk

Absent backup coverage, volumes face data loss, weakened integrity, and reduced availability. Deletion or corruption-whether accidental or malicious-can leave no recovery path, causing prolonged outages, failed point-in-time restoration, unmet retention needs, and harder incident response.

Run this check with Prowler

Run in Prowler Cloud
Run
prowler aws --checks ec2_ebs_volume_protected_by_backup_plan

Recommendation

Include all critical EBS volumes in standardized AWS Backup plans aligned to your RPO/RTO. Use tags for automatic assignment, enable cross-Region/account copies, apply Vault Lock for WORM retention, encrypt with KMS, enforce least-privilege access, and regularly test restores to verify integrity.

Remediation

CLI

aws backup create-backup-selection --backup-plan-id <BACKUP_PLAN_ID> --backup-selection '{"SelectionName":"<example_resource_name>","IamRoleArn":"arn:aws:iam::<example_account_id>:role/service-role/AWSBackupDefaultServiceRole","Resources":["arn:aws:ec2:*:*:volume/*"]}'

Terraform

# Minimal AWS Backup plan protecting all EBS volumes
resource "aws_backup_plan" "<example_resource_name>" {
  name = "<example_resource_name>"

  rule {
    rule_name         = "<example_rule_name>"
    target_vault_name = "Default"
  }
}

resource "aws_backup_selection" "<example_resource_name>" {
  name         = "<example_resource_name>"
  plan_id      = aws_backup_plan.<example_resource_name>.id
  iam_role_arn = "arn:aws:iam::<example_account_id>:role/service-role/AWSBackupDefaultServiceRole"

  resources = [
    "arn:aws:ec2:*:*:volume/*" # Critical: selects all EBS volumes to satisfy the check
  ]
}

NativeIaC

# CloudFormation: protect all EBS volumes by assigning them to a backup plan
Resources:
  <example_resource_name>BackupPlan:
    Type: AWS::Backup::BackupPlan
    Properties:
      BackupPlan:
        BackupPlanName: <example_resource_name>
        Rules:
          - RuleName: <example_rule_name>
            TargetBackupVault: Default

  <example_resource_name>BackupSelection:
    Type: AWS::Backup::BackupSelection
    Properties:
      BackupPlanId: !Ref <example_resource_name>BackupPlan
      BackupSelection:
        SelectionName: <example_resource_name>
        IamRoleArn: arn:aws:iam::<example_account_id>:role/service-role/AWSBackupDefaultServiceRole
        Resources:
          - arn:aws:ec2:*:*:volume/*  # Critical: wildcard includes all EBS volumes so they are covered by the plan

Other

1In the AWS Backup console, go to Backup plans and click Create backup plan
2Choose Start with a template (any), keep the Default vault, and create the plan
3Open the plan and click Assign resources
4Set Selection name and choose IAM role AWSBackupDefaultServiceRole
5Under Assign resources, choose Include specific resource types and select EBS
6For Resources, select all EBS volumes (or the specific volumes to protect) and click Assign resources

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.ec2.ec2_client import ec2_client


class ec2_ebs_volume_protected_by_backup_plan(Check):
    def execute(self):
        findings = []
        for volume in ec2_client.volumes:
            report = Check_Report_AWS(metadata=self.metadata(), resource=volume)
            report.status = "FAIL"
            report.status_extended = (
                f"EBS Volume {volume.id} is not protected by a backup plan."
            )
            if (
                volume.arn in backup_client.protected_resources
                or f"arn:{ec2_client.audited_partition}:ec2:*:*:volume/*"
                in backup_client.protected_resources
                or "*" in backup_client.protected_resources
            ):
                report.status = "PASS"
                report.status_extended = (
                    f"EBS Volume {volume.id} is protected by a backup plan."
                )

            findings.append(report)

        return findings