Skip to main content

Check if DynamoDB Tables Are Included in a Backup Plan

Overview

This check verifies that your Amazon DynamoDB tables are protected by an AWS Backup plan. A backup plan automatically creates recovery points (backups) on a schedule you define, ensuring your data can be restored if something goes wrong.

Risk

Without backup protection, your DynamoDB tables are vulnerable to:

  • Accidental deletion of tables or items with no way to recover
  • Data corruption from application bugs or malicious activity
  • Compliance failures for regulations requiring data retention
  • Extended downtime during incidents when no recovery option exists

AWS Backup provides governed, scheduled backups with defined retention policies, cross-region replication, and immutability options that manual exports cannot match.

Remediation Steps

Prerequisites

You need:

  • AWS Console access with permissions to manage AWS Backup
  • Or, IAM permissions for backup:* actions if using CLI/IaC
Required IAM permissions for CLI/IaC

For CLI or Infrastructure as Code approaches, your IAM user or role needs these permissions:

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"backup:CreateBackupPlan",
"backup:CreateBackupSelection",
"backup:CreateBackupVault",
"backup:ListBackupPlans",
"backup:ListBackupSelections",
"backup:DescribeBackupVault",
"backup:GetBackupPlan",
"backup:GetBackupSelection",
"iam:PassRole"
],
"Resource": "*"
}
]
}

AWS Console Method

  1. Enable DynamoDB in AWS Backup

    • Open the AWS Backup console
    • In the left navigation, click Settings
    • Under Service opt-in, click Configure resources
    • Find DynamoDB and toggle it to Enabled
    • Click Confirm
  2. Create a Backup Plan

    • In the left navigation, click Backup plans
    • Click Create backup plan
    • Choose Build a new plan
    • Enter a name (e.g., DynamoDBDailyBackup)
    • Click Create plan
  3. Add a Backup Rule

    • Under Backup rule configuration, click Add backup rule
    • Enter a rule name (e.g., DailyRule)
    • Select a backup vault (or use Default)
    • Set Backup frequency to Daily
    • Set Backup window to your preferred time
    • Under Lifecycle, set retention (e.g., 35 days)
    • Click Add backup rule
  4. Assign Your DynamoDB Tables

    • Click Assign resources
    • Enter a resource assignment name (e.g., DynamoDBTables)
    • For IAM role, select Default role
    • Under Resource selection, choose one of:
      • Include specific resource types and select DynamoDB to cover all tables
      • Include specific resources to select individual tables by ARN
    • Click Assign resources
AWS CLI (optional)

Step 1: Create a Backup Plan

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

Save the BackupPlanId from the output for the next step.

Step 2: Assign DynamoDB Tables to the Plan

Option A: Protect all DynamoDB tables

aws backup create-backup-selection \
--region us-east-1 \
--backup-plan-id <your-backup-plan-id> \
--backup-selection '{
"SelectionName": "AllDynamoDBTables",
"IamRoleArn": "arn:aws:iam::<your-account-id>:role/service-role/AWSBackupDefaultServiceRole",
"Resources": [
"arn:aws:dynamodb:*:*:table/*"
]
}'

Option B: Protect specific tables by ARN

aws backup create-backup-selection \
--region us-east-1 \
--backup-plan-id <your-backup-plan-id> \
--backup-selection '{
"SelectionName": "SpecificDynamoDBTables",
"IamRoleArn": "arn:aws:iam::<your-account-id>:role/service-role/AWSBackupDefaultServiceRole",
"Resources": [
"arn:aws:dynamodb:us-east-1:<your-account-id>:table/MyTable1",
"arn:aws:dynamodb:us-east-1:<your-account-id>:table/MyTable2"
]
}'

Option C: Protect tables by tag

aws backup create-backup-selection \
--region us-east-1 \
--backup-plan-id <your-backup-plan-id> \
--backup-selection '{
"SelectionName": "TaggedDynamoDBTables",
"IamRoleArn": "arn:aws:iam::<your-account-id>:role/service-role/AWSBackupDefaultServiceRole",
"ListOfTags": [
{
"ConditionType": "STRINGEQUALS",
"ConditionKey": "backup",
"ConditionValue": "daily"
}
]
}'

Replace <your-backup-plan-id> and <your-account-id> with your actual values.

CloudFormation (optional)
AWSTemplateFormatVersion: '2010-09-09'
Description: AWS Backup plan for DynamoDB tables

Parameters:
BackupPlanName:
Type: String
Default: DynamoDBBackupPlan
Description: Name of the backup plan

BackupVaultName:
Type: String
Default: Default
Description: Name of the backup vault

Resources:
BackupPlan:
Type: AWS::Backup::BackupPlan
Properties:
BackupPlan:
BackupPlanName: !Ref BackupPlanName
BackupPlanRule:
- RuleName: DailyBackupRule
TargetBackupVault: !Ref BackupVaultName
ScheduleExpression: cron(0 5 ? * * *)
StartWindowMinutes: 60
CompletionWindowMinutes: 180
Lifecycle:
DeleteAfterDays: 35

BackupSelection:
Type: AWS::Backup::BackupSelection
Properties:
BackupPlanId: !Ref BackupPlan
BackupSelection:
SelectionName: DynamoDBTablesSelection
IamRoleArn: !Sub arn:aws:iam::${AWS::AccountId}:role/service-role/AWSBackupDefaultServiceRole
Resources:
- arn:aws:dynamodb:*:*:table/*

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

Deploy the stack:

aws cloudformation deploy \
--region us-east-1 \
--template-file backup-plan.yaml \
--stack-name dynamodb-backup-plan \
--capabilities CAPABILITY_IAM
Terraform (optional)
terraform {
required_version = ">= 1.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}

provider "aws" {
region = "us-east-1"
}

variable "backup_plan_name" {
description = "Name of the backup plan"
type = string
default = "dynamodb-backup-plan"
}

variable "backup_vault_name" {
description = "Name of the backup vault"
type = string
default = "Default"
}

variable "dynamodb_table_arns" {
description = "List of DynamoDB table ARNs to include in the backup plan. Leave empty to include all tables."
type = list(string)
default = []
}

resource "aws_backup_plan" "dynamodb" {
name = var.backup_plan_name

rule {
rule_name = "daily-backup"
target_vault_name = var.backup_vault_name
schedule = "cron(0 5 ? * * *)"
start_window = 60
completion_window = 180

lifecycle {
delete_after = 35
}
}

tags = {
Purpose = "DynamoDB backup"
}
}

data "aws_iam_role" "backup" {
name = "AWSBackupDefaultServiceRole"
}

resource "aws_backup_selection" "dynamodb_tables" {
name = "dynamodb-tables-selection"
plan_id = aws_backup_plan.dynamodb.id
iam_role_arn = data.aws_iam_role.backup.arn

resources = length(var.dynamodb_table_arns) > 0 ? var.dynamodb_table_arns : ["arn:aws:dynamodb:*:*:table/*"]
}

output "backup_plan_id" {
description = "The ID of the backup plan"
value = aws_backup_plan.dynamodb.id
}

output "backup_plan_arn" {
description = "The ARN of the backup plan"
value = aws_backup_plan.dynamodb.arn
}

Apply the configuration:

terraform init
terraform plan
terraform apply

To protect specific tables, provide their ARNs:

terraform apply -var='dynamodb_table_arns=["arn:aws:dynamodb:us-east-1:123456789012:table/MyTable1"]'

Verification

After completing the remediation:

  1. In the AWS Console:

    • Go to AWS Backup > Backup plans
    • Click on your backup plan
    • Under Resource assignments, verify your DynamoDB tables are listed
  2. Check backup jobs are running:

    • Go to AWS Backup > Jobs
    • Look for completed backup jobs for your DynamoDB tables
CLI verification commands

List backup plans:

aws backup list-backup-plans --region us-east-1

View backup selections for a plan:

aws backup list-backup-selections \
--region us-east-1 \
--backup-plan-id <your-backup-plan-id>

List recent backup jobs:

aws backup list-backup-jobs \
--region us-east-1 \
--by-resource-type DynamoDB \
--by-state COMPLETED

Re-run the Prowler check:

prowler aws --checks dynamodb_table_protected_by_backup_plan

Additional Resources

Notes

  • Default service role: AWS Backup requires an IAM role to perform backups. The AWSBackupDefaultServiceRole is created automatically when you first use AWS Backup through the console. If using CLI/IaC without prior console use, you may need to create this role first.

  • DynamoDB opt-in: DynamoDB must be enabled as a supported service in AWS Backup settings before it can be included in backup plans. The console method includes this step.

  • Backup vault lock: For additional protection against accidental or malicious deletion of backups, consider enabling AWS Backup Vault Lock to make backups immutable.

  • Cross-region backups: For disaster recovery, you can configure backup rules to copy recovery points to a different region. Add a copy_action block in Terraform or CopyActions in CloudFormation.

  • Cost considerations: AWS Backup charges for backup storage. DynamoDB backups are charged at standard DynamoDB backup storage rates. Review AWS Backup pricing before enabling for large tables.