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
-
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
-
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
-
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
-
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:
-
In the AWS Console:
- Go to AWS Backup > Backup plans
- Click on your backup plan
- Under Resource assignments, verify your DynamoDB tables are listed
-
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
- AWS Backup User Guide
- Backing up DynamoDB with AWS Backup
- AWS Backup best practices
- Creating a backup plan with the AWS CLI
Notes
-
Default service role: AWS Backup requires an IAM role to perform backups. The
AWSBackupDefaultServiceRoleis 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_actionblock in Terraform orCopyActionsin 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.