Skip to main content

At Least One AWS Backup Plan Exists

Overview

This check verifies that your AWS account has at least one AWS Backup plan configured. A backup plan defines when and how your resources are backed up, including schedules, retention policies, and which resources to protect.

Even if you have backup vaults, this check will fail if no backup plan is configured to actually create recovery points.

Risk

Without a backup plan, your AWS resources are not automatically protected. This creates several risks:

  • Data loss: Accidental deletions or data corruption cannot be recovered
  • Extended outages: No restore capability means longer recovery times during incidents
  • Compliance gaps: Many regulations require documented backup and recovery procedures
  • Operational risk: Manual backups are error-prone and easily forgotten

Remediation Steps

Prerequisites

You need permission to create AWS Backup plans. Typically this requires the AWSBackupFullAccess managed policy or equivalent permissions.

Required IAM permissions (technical detail)

At minimum, you need these permissions:

  • backup:CreateBackupPlan
  • backup:CreateBackupVault (if you need a new vault)
  • backup:CreateBackupSelection (to assign resources to the plan)
  • iam:PassRole (for the backup service role)

AWS Console Method

  1. Open the AWS Backup console

  2. In the left navigation, click Backup plans

  3. Click Create backup plan

  4. Choose how to create your plan:

    • Start with a template (recommended for beginners) - Uses AWS pre-built schedules
    • Build a new plan - Full customization
    • Define a plan using JSON - For advanced users
  5. If using a template:

    • Select a template (e.g., "Daily-35day-Retention" for daily backups kept 35 days)
    • Enter a Backup plan name (e.g., my-daily-backup-plan)
    • Click Create plan
  6. After creating the plan, you need to assign resources:

    • Click your new backup plan
    • Under Resource assignments, click Assign resources
    • Give the assignment a name (e.g., critical-resources)
    • Choose how to select resources:
      • Include all resource types - Backs up everything
      • Include specific resource types - Pick specific services (EC2, RDS, EFS, etc.)
    • Optionally filter by tags (e.g., only resources tagged Backup=true)
    • Select or create an IAM role for AWS Backup to use
    • Click Assign resources
  7. Your backup plan is now active and will run on the defined schedule

AWS CLI

Step 1: Create a backup plan

aws backup create-backup-plan \
--region us-east-1 \
--backup-plan '{
"BackupPlanName": "DailyBackupPlan",
"Rules": [
{
"RuleName": "DailyRule",
"TargetBackupVaultName": "Default",
"ScheduleExpression": "cron(0 5 ? * * *)",
"StartWindowMinutes": 480,
"CompletionWindowMinutes": 720,
"Lifecycle": {
"DeleteAfterDays": 35
}
}
]
}'

This creates a plan that:

  • Runs daily at 5:00 AM UTC
  • Stores backups in the "Default" vault
  • Retains backups for 35 days

Save the BackupPlanId from the output for the next step.

Step 2: Assign resources to the plan

aws backup create-backup-selection \
--region us-east-1 \
--backup-plan-id <your-backup-plan-id> \
--backup-selection '{
"SelectionName": "AllTaggedResources",
"IamRoleArn": "arn:aws:iam::<your-account-id>:role/service-role/AWSBackupDefaultServiceRole",
"Resources": ["*"],
"Conditions": {
"StringEquals": [
{
"ConditionKey": "aws:ResourceTag/Backup",
"ConditionValue": "true"
}
]
}
}'

Replace:

  • <your-backup-plan-id> with the ID from Step 1
  • <your-account-id> with your AWS account ID

This example backs up all resources tagged with Backup=true.

CloudFormation
AWSTemplateFormatVersion: '2010-09-09'
Description: AWS Backup Plan with daily backups and 35-day retention

Resources:
BackupVault:
Type: AWS::Backup::BackupVault
Properties:
BackupVaultName: MyBackupVault

BackupPlan:
Type: AWS::Backup::BackupPlan
Properties:
BackupPlan:
BackupPlanName: DailyBackupPlan
BackupPlanRule:
- RuleName: DailyBackupRule
TargetBackupVault: !Ref BackupVault
ScheduleExpression: cron(0 5 ? * * *)
StartWindowMinutes: 480
CompletionWindowMinutes: 720
Lifecycle:
DeleteAfterDays: 35

BackupRole:
Type: AWS::IAM::Role
Properties:
RoleName: AWSBackupServiceRole
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: backup.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForBackup
- arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForRestores

BackupSelection:
Type: AWS::Backup::BackupSelection
Properties:
BackupPlanId: !Ref BackupPlan
BackupSelection:
SelectionName: TaggedResources
IamRoleArn: !GetAtt BackupRole.Arn
ListOfTags:
- ConditionType: STRINGEQUALS
ConditionKey: Backup
ConditionValue: 'true'

Outputs:
BackupPlanId:
Description: The ID of the backup plan
Value: !Ref BackupPlan
BackupVaultArn:
Description: The ARN of the backup vault
Value: !GetAtt BackupVault.BackupVaultArn

Deploy with:

aws cloudformation deploy \
--region us-east-1 \
--template-file backup-plan.yaml \
--stack-name backup-plan-stack \
--capabilities CAPABILITY_NAMED_IAM
Terraform
# Backup vault to store recovery points
resource "aws_backup_vault" "main" {
name = "my-backup-vault"
}

# Backup plan with daily schedule
resource "aws_backup_plan" "daily" {
name = "daily-backup-plan"

rule {
rule_name = "daily-backup-rule"
target_vault_name = aws_backup_vault.main.name
schedule = "cron(0 5 ? * * *)"
start_window = 480
completion_window = 720

lifecycle {
delete_after = 35
}
}
}

# IAM role for AWS Backup
resource "aws_iam_role" "backup" {
name = "aws-backup-service-role"

assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "backup.amazonaws.com"
}
}
]
})
}

resource "aws_iam_role_policy_attachment" "backup" {
role = aws_iam_role.backup.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForBackup"
}

resource "aws_iam_role_policy_attachment" "restore" {
role = aws_iam_role.backup.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForRestores"
}

# Assign resources by tag
resource "aws_backup_selection" "tagged_resources" {
name = "tagged-resources"
plan_id = aws_backup_plan.daily.id
iam_role_arn = aws_iam_role.backup.arn

selection_tag {
type = "STRINGEQUALS"
key = "Backup"
value = "true"
}
}

output "backup_plan_id" {
value = aws_backup_plan.daily.id
}

Deploy with:

terraform init
terraform plan
terraform apply

Verification

After creating your backup plan, verify it exists:

  1. Go to AWS Backup console > Backup plans
  2. Confirm your backup plan appears in the list
  3. Click the plan and verify resources are assigned under Resource assignments
Verify with AWS CLI
# List all backup plans
aws backup list-backup-plans --region us-east-1

# Get details of a specific plan
aws backup get-backup-plan \
--region us-east-1 \
--backup-plan-id <your-backup-plan-id>

# Verify resources are assigned
aws backup list-backup-selections \
--region us-east-1 \
--backup-plan-id <your-backup-plan-id>

Re-run Prowler to confirm the check now passes:

prowler aws --check backup_plans_exist

Additional Resources

Notes

  • Cost considerations: AWS Backup charges for storage consumed by recovery points. Review pricing before enabling backups across many resources.

  • Default vault: AWS creates a "Default" backup vault in each region. You can use this or create custom vaults with specific encryption keys.

  • Cross-region and cross-account: For disaster recovery, consider enabling copy rules to replicate backups to another region or AWS account.

  • Resource tagging strategy: Using tags like Backup=true lets you control which resources are backed up without modifying the backup plan each time you add resources.

  • Testing restores: Having backups is only half the solution. Regularly test restore procedures to ensure backups are usable when needed.