Skip to main content

EBS Volume Has At Least One Snapshot

Overview

This check verifies that each Amazon EBS (Elastic Block Store) volume has at least one snapshot. Snapshots are point-in-time backups of your EBS volumes stored in Amazon S3, enabling you to recover data if something goes wrong.

Risk

Severity: High

EBS volumes without snapshots have no backup protection. If the volume is accidentally deleted, becomes corrupted, or is affected by ransomware, you could experience:

  • Permanent data loss with no way to recover
  • Extended service outages while rebuilding systems from scratch
  • Compliance violations for regulations requiring data backup (HIPAA, SOC 2, etc.)

Creating at least one snapshot ensures you have a recovery point available when you need it.

Remediation Steps

Prerequisites

  • AWS Console access with permissions to create EBS snapshots
  • The Volume ID of the EBS volume that needs a snapshot (looks like vol-0123456789abcdef0)

AWS Console Method

  1. Open the Amazon EC2 console
  2. In the left navigation, click Volumes (under Elastic Block Store)
  3. Select the checkbox next to the volume that needs a snapshot
  4. Click the Actions dropdown menu
  5. Select Create snapshot
  6. Enter a Description (e.g., "Initial backup snapshot")
  7. (Optional) Add tags to help organize your snapshots
  8. Click Create snapshot

The snapshot will appear in the Snapshots section with a status of "pending" until it completes.

AWS CLI (optional)

Create a snapshot for a single volume

aws ec2 create-snapshot \
--region us-east-1 \
--volume-id vol-0123456789abcdef0 \
--description "Initial backup snapshot"

Create a snapshot with tags

aws ec2 create-snapshot \
--region us-east-1 \
--volume-id vol-0123456789abcdef0 \
--description "Production database backup" \
--tag-specifications 'ResourceType=snapshot,Tags=[{Key=Name,Value=prod-db-snapshot},{Key=Environment,Value=production}]'

Find all volumes without snapshots

This command identifies volumes that have never been backed up:

# Get all volume IDs
ALL_VOLUMES=$(aws ec2 describe-volumes \
--region us-east-1 \
--query 'Volumes[*].VolumeId' \
--output text)

# Get volumes that have snapshots
VOLUMES_WITH_SNAPSHOTS=$(aws ec2 describe-snapshots \
--region us-east-1 \
--owner-ids self \
--query 'Snapshots[*].VolumeId' \
--output text | tr '\t' '\n' | sort -u)

# Compare to find volumes without snapshots
for vol in $ALL_VOLUMES; do
if ! echo "$VOLUMES_WITH_SNAPSHOTS" | grep -q "$vol"; then
echo "Volume without snapshot: $vol"
fi
done

Create snapshots for all unprotected volumes

for vol in $ALL_VOLUMES; do
if ! echo "$VOLUMES_WITH_SNAPSHOTS" | grep -q "$vol"; then
echo "Creating snapshot for: $vol"
aws ec2 create-snapshot \
--region us-east-1 \
--volume-id "$vol" \
--description "Initial backup snapshot" \
--tag-specifications "ResourceType=snapshot,Tags=[{Key=Name,Value=${vol}-snapshot},{Key=CreatedBy,Value=remediation-script}]"
fi
done
CloudFormation (optional)

CloudFormation can create a one-time snapshot. For ongoing automated snapshots, see the Automated Snapshot Scheduling section below.

AWSTemplateFormatVersion: '2010-09-09'
Description: EBS Snapshot for backup and recovery

Parameters:
VolumeId:
Type: String
Description: The ID of the EBS volume to snapshot
SnapshotDescription:
Type: String
Default: "Automated EBS snapshot for backup"
Description: Description for the snapshot

Resources:
EBSSnapshot:
Type: AWS::EC2::Snapshot
Properties:
VolumeId: !Ref VolumeId
Description: !Ref SnapshotDescription
Tags:
- Key: Name
Value: !Sub "${VolumeId}-snapshot"
- Key: CreatedBy
Value: CloudFormation

Outputs:
SnapshotId:
Description: The ID of the created snapshot
Value: !Ref EBSSnapshot

Deploy the template:

aws cloudformation create-stack \
--region us-east-1 \
--stack-name ebs-snapshot-remediation \
--template-body file://template.yaml \
--parameters ParameterKey=VolumeId,ParameterValue=vol-0123456789abcdef0
Terraform (optional)

Single snapshot

variable "volume_id" {
description = "The ID of the EBS volume to snapshot"
type = string
}

variable "description" {
description = "Description for the snapshot"
type = string
default = "Automated EBS snapshot for backup"
}

variable "tags" {
description = "Tags to apply to the snapshot"
type = map(string)
default = {}
}

resource "aws_ebs_snapshot" "this" {
volume_id = var.volume_id
description = var.description

tags = merge(
{
"Name" = "${var.volume_id}-snapshot"
},
var.tags
)
}

output "snapshot_id" {
description = "The ID of the created snapshot"
value = aws_ebs_snapshot.this.id
}

Apply the configuration:

terraform init
terraform apply -var="volume_id=vol-0123456789abcdef0"

Multiple volumes

variable "volume_ids" {
description = "List of EBS volume IDs to snapshot"
type = list(string)
}

resource "aws_ebs_snapshot" "volumes" {
for_each = toset(var.volume_ids)

volume_id = each.value
description = "Automated backup snapshot"

tags = {
Name = "${each.value}-snapshot"
ManagedBy = "Terraform"
}
}

output "snapshot_ids" {
description = "Map of volume IDs to snapshot IDs"
value = { for k, v in aws_ebs_snapshot.volumes : k => v.id }
}
Automated Snapshot Scheduling (recommended)

Creating a single snapshot addresses the immediate finding, but you should set up automated snapshots to maintain ongoing protection.

Using Amazon Data Lifecycle Manager (DLM)

DLM automates snapshot creation on a schedule. Here is a CloudFormation template:

AWSTemplateFormatVersion: '2010-09-09'
Description: Automated EBS snapshot lifecycle policy

Parameters:
TargetTagKey:
Type: String
Default: "Backup"
Description: Tag key to identify volumes for backup
TargetTagValue:
Type: String
Default: "true"
Description: Tag value to identify volumes for backup
RetentionCount:
Type: Number
Default: 7
Description: Number of snapshots to retain

Resources:
SnapshotLifecyclePolicy:
Type: AWS::DLM::LifecyclePolicy
Properties:
Description: Daily EBS snapshots with 7-day retention
State: ENABLED
ExecutionRoleArn: !GetAtt DLMRole.Arn
PolicyDetails:
ResourceTypes:
- VOLUME
TargetTags:
- Key: !Ref TargetTagKey
Value: !Ref TargetTagValue
Schedules:
- Name: DailySnapshots
CreateRule:
Interval: 24
IntervalUnit: HOURS
Times:
- "03:00"
RetainRule:
Count: !Ref RetentionCount
CopyTags: true

DLMRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: dlm.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSDataLifecycleManagerServiceRole

After deploying this policy, tag your EBS volumes with Backup=true to include them in automated snapshots.

Using Terraform with DLM

resource "aws_dlm_lifecycle_policy" "ebs_backup" {
description = "Daily EBS snapshot policy"
execution_role_arn = aws_iam_role.dlm_role.arn
state = "ENABLED"

policy_details {
resource_types = ["VOLUME"]

target_tags = {
Backup = "true"
}

schedule {
name = "Daily snapshots"

create_rule {
interval = 24
interval_unit = "HOURS"
times = ["03:00"]
}

retain_rule {
count = 7
}

copy_tags = true
}
}
}

resource "aws_iam_role" "dlm_role" {
name = "dlm-lifecycle-role"

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

resource "aws_iam_role_policy_attachment" "dlm_policy" {
role = aws_iam_role.dlm_role.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSDataLifecycleManagerServiceRole"
}

Verification

After creating a snapshot, verify it exists:

  1. In the EC2 console, go to Snapshots (under Elastic Block Store)
  2. Search for your volume ID in the search bar
  3. Confirm the snapshot shows a status of completed
CLI verification
# Check if a specific volume has snapshots
aws ec2 describe-snapshots \
--region us-east-1 \
--owner-ids self \
--filters "Name=volume-id,Values=vol-0123456789abcdef0" \
--query 'Snapshots[*].[SnapshotId,StartTime,State]' \
--output table

Expected output shows at least one snapshot with state completed:

------------------------------------------------------------
| DescribeSnapshots |
+---------------------------+---------------------+---------+
| snap-0123456789abcdef0 | 2024-01-15T10:30:00|completed|
+---------------------------+---------------------+---------+

Additional Resources

Notes

  • Snapshot costs: You pay for the storage used by snapshots. The first snapshot of a volume copies all data; subsequent snapshots are incremental and only store changed blocks.

  • Encryption: Snapshots of encrypted volumes are automatically encrypted. Snapshots of unencrypted volumes are unencrypted by default but can be copied with encryption enabled.

  • Cross-region copies: For disaster recovery, consider copying critical snapshots to another AWS region.

  • Snapshot completion time: Large volumes may take hours to complete their first snapshot. The volume remains usable during this time.

  • Application consistency: For databases and applications that write to disk, consider stopping writes or using application-consistent snapshot methods (like VSS for Windows or database-specific backup commands) before creating snapshots.