← Back to Tutorials
Tutorial 16 Beginner

How to Secure AWS EBS Volumes and Snapshots

Protect your instance storage with default encryption, snapshot security, lifecycle management, and continuous compliance monitoring to prevent data exposure.

25 min implementation
10 min read
Storage Security

Why EBS Security Is Mission-Critical

Amazon Elastic Block Store (EBS) volumes are the persistent storage backbone of your AWS infrastructure. Unlike ephemeral instance storage, EBS volumes persist beyond instance lifecycles, often containing your most sensitive data—database files, application logs with authentication tokens, proprietary source code, and system configurations with secrets.

Security researchers at DefCon 2019 discovered over 1,250 publicly exposed EBS snapshots across AWS regions, containing encryption keys, passwords, authentication tokens, and PII. These exposures typically result from simple misconfigurations—volumes left unencrypted or snapshots accidentally made public.

The Three Most Dangerous EBS Vulnerabilities

1

Unencrypted Data at Rest

Unencrypted EBS volumes expose raw data to anyone with access to the underlying storage infrastructure. AWS decommissioned hardware could theoretically expose your data in plain text if not encrypted.

2

Public Snapshot Exposure

EBS snapshots set to "public" are discoverable and downloadable by anyone on the internet. Attackers use AWS APIs to scan for publicly available snapshots containing valuable data.

3

Inadequate Lifecycle Management

Orphaned volumes and snapshots create security debt—forgotten storage that may contain sensitive data without proper access controls or encryption standards.

⚠️
Key Insight: EBS encryption is free and has negligible performance impact. There is no technical or financial reason to leave EBS volumes unencrypted in production environments.
1

Enable Default EBS Encryption

~5 minutes

The most effective EBS security measure is enabling default encryption. This ensures all new volumes are automatically encrypted without requiring manual configuration for each volume.

Console Steps

1.1 Navigate to EBS Encryption Settings

  • Sign in to AWS Console
  • Navigate to EC2 service
  • In the navigation pane, find "Account attributes"
  • Click on "Data protection and security"
  • Click "Manage" next to EBS encryption

1.2 Enable Default Encryption

  • Check "Enable" for "Always encrypt new EBS volumes"
  • Choose your encryption key:
    • AWS managed key (aws/ebs): Free, convenient, but cannot share encrypted volumes cross-account
    • Customer managed key: Better control, audit trails, cross-account sharing capability
  • Click "Update EBS encryption"
AWS CLI - Enable Default EBS Encryption
# Enable default EBS encryption with AWS managed key
aws ec2 enable-ebs-encryption-by-default

# Verify the setting
aws ec2 get-ebs-encryption-by-default

# Optional: Set a customer managed key as default
aws ec2 modify-ebs-default-kms-key-id \
    --kms-key-id arn:aws:kms:us-east-1:123456789012:key/your-key-id

# Verify the default key
aws ec2 get-ebs-default-kms-key-id

1.3 Apply to All Regions

Default encryption is a region-specific setting. Use the following script to enable across all regions:

Bash - Enable EBS Encryption in All Regions
#!/bin/bash
# Enable EBS encryption by default in all regions

for region in $(aws ec2 describe-regions --query 'Regions[].RegionName' --output text); do
    echo "Enabling EBS encryption in $region..."
    aws ec2 enable-ebs-encryption-by-default --region $region
    
    # Verify the setting
    status=$(aws ec2 get-ebs-encryption-by-default \
        --region $region \
        --query 'EbsEncryptionByDefault' \
        --output text)
    echo "  Status: $status"
done

echo "EBS encryption enabled in all regions!"
ℹ️
Important: Default encryption only applies to new volumes. Existing unencrypted volumes remain vulnerable and require separate remediation (covered in Step 2).
Security Achievement: All new EBS volumes in your account will now be automatically encrypted, providing encryption at rest without requiring manual configuration.
2

Encrypt Existing Unencrypted Volumes

~10 minutes per volume

Existing unencrypted volumes represent your biggest immediate risk. You cannot directly encrypt an existing volume—you must create a new encrypted volume from a snapshot and replace the original.

Phase 1: Identify Unencrypted Volumes

AWS CLI - Find Unencrypted Volumes
# List all unencrypted EBS volumes
aws ec2 describe-volumes \
    --filters Name=encrypted,Values=false \
    --query 'Volumes[*].[VolumeId,Size,State,Attachments[0].InstanceId,Attachments[0].Device]' \
    --output table

# Get detailed information including tags
aws ec2 describe-volumes \
    --filters Name=encrypted,Values=false \
    --query 'Volumes[*].[VolumeId,Size,VolumeType,State,Tags[?Key==`Name`].Value|[0]]' \
    --output table

Phase 2: Create Encrypted Copy (Non-Root Volumes)

2.1 Create Snapshot of Unencrypted Volume

  • In EC2 Console, go to Volumes
  • Select the unencrypted volume
  • Actions → Create snapshot
  • Add description: "Migration snapshot for encryption"
  • Wait for snapshot to complete
AWS CLI - Create Encrypted Volume from Snapshot
# Step 1: Create snapshot of unencrypted volume
aws ec2 create-snapshot \
    --volume-id vol-1234567890abcdef0 \
    --description "Encryption migration snapshot"

# Step 2: Wait for snapshot completion
aws ec2 wait snapshot-completed \
    --snapshot-ids snap-0123456789abcdef0

# Step 3: Create encrypted copy of the snapshot
aws ec2 copy-snapshot \
    --source-region us-east-1 \
    --source-snapshot-id snap-0123456789abcdef0 \
    --encrypted \
    --kms-key-id arn:aws:kms:us-east-1:123456789012:key/your-key-id \
    --description "Encrypted copy for migration"

# Step 4: Create new encrypted volume from encrypted snapshot
aws ec2 create-volume \
    --snapshot-id snap-encrypted123456 \
    --availability-zone us-east-1a \
    --volume-type gp3 \
    --encrypted

Phase 3: Replace the Original Volume

AWS CLI - Replace Unencrypted Volume
# Step 1: Stop the instance (required for root volumes, recommended for data volumes)
aws ec2 stop-instances --instance-ids i-1234567890abcdef0
aws ec2 wait instance-stopped --instance-ids i-1234567890abcdef0

# Step 2: Detach the old unencrypted volume
aws ec2 detach-volume --volume-id vol-unencrypted123

# Step 3: Attach new encrypted volume with same device name
aws ec2 attach-volume \
    --volume-id vol-encrypted456 \
    --instance-id i-1234567890abcdef0 \
    --device /dev/sdf

# Step 4: Start the instance
aws ec2 start-instances --instance-ids i-1234567890abcdef0

# Step 5: After verification, delete old unencrypted volume
aws ec2 delete-volume --volume-id vol-unencrypted123

Alternative: Use AWS Systems Manager Automation

AWS CLI - Automated Encryption with SSM
# Use AWS Systems Manager for automated encryption
aws ssm start-automation-execution \
    --document-name "AWSSupport-CopyEC2InstanceWithEncryption" \
    --parameters '{
        "InstanceId": "i-1234567890abcdef0",
        "CreateBackup": "true",
        "KmsKeyId": "arn:aws:kms:us-east-1:123456789012:key/your-key-id"
    }'
⚠️
Root Volume Warning: Replacing root volumes requires stopping the instance. Plan for downtime and ensure you have verified backups before proceeding.
Migration Complete: You now have a process to encrypt existing volumes. Track your progress until all volumes report encrypted status.
3

Secure EBS Snapshots

~5 minutes

EBS snapshots can be shared publicly, which is a major security risk. Publicly accessible snapshots have been the source of numerous data breaches. Always audit and secure your snapshot permissions.

Audit Snapshot Permissions

AWS CLI - Find Public Snapshots (CRITICAL)
# Check for publicly accessible snapshots - THIS IS CRITICAL
aws ec2 describe-snapshots \
    --owner-ids self \
    --query 'Snapshots[?Public==`true`].[SnapshotId,Description,VolumeSize,StartTime]' \
    --output table

# Check permissions for each snapshot
for snapshot in $(aws ec2 describe-snapshots \
    --owner-ids self \
    --query 'Snapshots[].SnapshotId' \
    --output text); do
    
    echo "Checking permissions for $snapshot:"
    aws ec2 describe-snapshot-attribute \
        --snapshot-id $snapshot \
        --attribute createVolumePermission \
        --output json
done

Remove Public Access

AWS CLI - Remove Public Access from Snapshots
# Remove public access from a specific snapshot
aws ec2 modify-snapshot-attribute \
    --snapshot-id snap-1234567890abcdef0 \
    --attribute createVolumePermission \
    --operation-type remove \
    --group-names all

# Verify the change
aws ec2 describe-snapshot-attribute \
    --snapshot-id snap-1234567890abcdef0 \
    --attribute createVolumePermission

Block Public Access Account-Wide

AWS CLI - Enable Snapshot Block Public Access
# Block public access for all EBS snapshots in the region
aws ec2 enable-snapshot-block-public-access --state block-all-sharing

# Verify the setting
aws ec2 get-snapshot-block-public-access-state

# Note: This is a regional setting - repeat for each region

Implement IAM Policy to Prevent Public Snapshots

IAM Policy - Prevent Public Snapshots
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PreventPublicSnapshots",
            "Effect": "Deny",
            "Action": "ec2:ModifySnapshotAttribute",
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "ec2:Add/group": "all"
                }
            }
        },
        {
            "Sid": "RequireSnapshotEncryption",
            "Effect": "Deny",
            "Action": [
                "ec2:CreateSnapshot",
                "ec2:CopySnapshot"
            ],
            "Resource": "*",
            "Condition": {
                "Bool": {
                    "ec2:Encrypted": "false"
                }
            }
        }
    ]
}
Best Practice: Encrypted snapshots cannot be made public. Enabling default encryption automatically prevents public snapshot exposure.
4

Implement Lifecycle Management and Monitoring

~5 minutes

Proper lifecycle management prevents security debt from accumulating through orphaned volumes and snapshots. AWS Config rules provide continuous compliance monitoring.

Identify Orphaned Resources

AWS CLI - Find Orphaned Volumes and Old Snapshots
# Find unattached volumes (potential orphans)
aws ec2 describe-volumes \
    --filters Name=status,Values=available \
    --query 'Volumes[*].[VolumeId,Size,CreateTime,Tags[?Key==`Name`].Value|[0]]' \
    --output table

# Find old snapshots (candidates for cleanup)
aws ec2 describe-snapshots \
    --owner-ids self \
    --query 'Snapshots[?StartTime<=`2024-01-01`].[SnapshotId,StartTime,Description,VolumeSize]' \
    --output table

Configure AWS Data Lifecycle Manager

AWS CLI - Create Automated Snapshot Lifecycle Policy
# Create lifecycle policy for automated encrypted snapshots
aws dlm create-lifecycle-policy \
    --execution-role-arn arn:aws:iam::123456789012:role/AWSDataLifecycleManagerDefaultRole \
    --description "Encrypted EBS snapshot lifecycle policy" \
    --state ENABLED \
    --policy-details '{
        "PolicyType": "EBS_SNAPSHOT_MANAGEMENT",
        "ResourceTypes": ["VOLUME"],
        "TargetTags": [{"Key": "Backup", "Value": "Required"}],
        "Schedules": [{
            "Name": "DailySnapshots",
            "CopyTags": true,
            "CreateRule": {
                "Interval": 24,
                "IntervalUnit": "HOURS",
                "Times": ["23:45"]
            },
            "RetainRule": {
                "Count": 7
            }
        }]
    }'

Enable AWS Config Rules for Compliance

AWS CLI - Deploy EBS Security Config Rules
# Rule 1: Check that all EBS volumes are encrypted
aws configservice put-config-rule \
    --config-rule '{
        "ConfigRuleName": "encrypted-volumes",
        "Description": "Checks whether EBS volumes are encrypted",
        "Source": {
            "Owner": "AWS",
            "SourceIdentifier": "ENCRYPTED_VOLUMES"
        },
        "Scope": {
            "ComplianceResourceTypes": ["AWS::EC2::Volume"]
        }
    }'

# Rule 2: Check that EBS snapshots are not publicly restorable
aws configservice put-config-rule \
    --config-rule '{
        "ConfigRuleName": "ebs-snapshot-public-read-prohibited",
        "Description": "Checks that EBS snapshots are not publicly readable",
        "Source": {
            "Owner": "AWS",
            "SourceIdentifier": "EBS_SNAPSHOT_PUBLIC_RESTORABLE_CHECK"
        }
    }'

Set Up CloudWatch Alarms

AWS CLI - Create Compliance Monitoring Alarms
# Create SNS topic for alerts
aws sns create-topic --name ebs-security-alerts

# Create CloudWatch alarm for Config rule compliance
aws cloudwatch put-metric-alarm \
    --alarm-name "EBS-Encryption-NonCompliant" \
    --alarm-description "Alert when unencrypted EBS volumes are detected" \
    --metric-name ComplianceByConfigRule \
    --namespace AWS/Config \
    --statistic Average \
    --period 3600 \
    --threshold 1 \
    --comparison-operator LessThanThreshold \
    --dimensions Name=ConfigRuleName,Value=encrypted-volumes \
    --evaluation-periods 1 \
    --alarm-actions arn:aws:sns:us-east-1:123456789012:ebs-security-alerts
Monitoring Active: You now have automated lifecycle management for snapshots and continuous compliance monitoring with alerts for any security drift.

Validate Your EBS Security Configuration

Use this checklist to ensure your EBS security implementation is complete:

Comprehensive Validation Script

Bash - EBS Security Validation Script
#!/bin/bash
# EBS Security Validation Script
echo "============================================"
echo "EBS Security Assessment Starting..."
echo "============================================"

# Check 1: Default encryption status
echo -e "\n[1/5] Checking default encryption settings..."
for region in us-east-1 us-west-2 eu-west-1; do
    status=$(aws ec2 get-ebs-encryption-by-default \
        --region $region \
        --query 'EbsEncryptionByDefault' \
        --output text 2>/dev/null)
    if [ "$status" = "True" ]; then
        echo "✓ $region: Default encryption ENABLED"
    else
        echo "✗ $region: Default encryption DISABLED"
    fi
done

# Check 2: Unencrypted volumes
echo -e "\n[2/5] Scanning for unencrypted volumes..."
UNENCRYPTED=$(aws ec2 describe-volumes \
    --filters Name=encrypted,Values=false \
    --query 'length(Volumes[])' \
    --output text 2>/dev/null)

if [ "$UNENCRYPTED" -gt 0 ]; then
    echo "✗ WARNING: Found $UNENCRYPTED unencrypted volumes!"
    aws ec2 describe-volumes \
        --filters Name=encrypted,Values=false \
        --query 'Volumes[*].[VolumeId,Size,State]' \
        --output table
else
    echo "✓ All volumes are encrypted"
fi

# Check 3: Public snapshots
echo -e "\n[3/5] Checking for public snapshots..."
PUBLIC_COUNT=$(aws ec2 describe-snapshots \
    --owner-ids self \
    --query 'length(Snapshots[?Public==`true`])' \
    --output text 2>/dev/null)

if [ "$PUBLIC_COUNT" -gt 0 ]; then
    echo "✗ CRITICAL: Found $PUBLIC_COUNT public snapshots!"
else
    echo "✓ No public snapshots found"
fi

# Check 4: Snapshot block public access
echo -e "\n[4/5] Checking snapshot block public access..."
BLOCK_STATE=$(aws ec2 get-snapshot-block-public-access-state \
    --query 'State' \
    --output text 2>/dev/null)

if [ "$BLOCK_STATE" = "block-all-sharing" ]; then
    echo "✓ Snapshot block public access is ENABLED"
else
    echo "✗ Snapshot block public access is NOT enabled (State: $BLOCK_STATE)"
fi

# Check 5: Orphaned volumes
echo -e "\n[5/5] Scanning for orphaned volumes..."
ORPHANED=$(aws ec2 describe-volumes \
    --filters Name=status,Values=available \
    --query 'length(Volumes[])' \
    --output text 2>/dev/null)

if [ "$ORPHANED" -gt 0 ]; then
    echo "⚠ Found $ORPHANED unattached volumes (review for cleanup)"
else
    echo "✓ No orphaned volumes found"
fi

echo -e "\n============================================"
echo "EBS Security Assessment Complete!"
echo "============================================"

Common EBS Security Mistakes to Avoid

Enabling encryption only in some regions. Attackers will find and exploit unencrypted volumes in any region. Enable default encryption in ALL regions, even those you don't actively use.

Not auditing snapshot permissions. Many breaches result from accidentally public snapshots. Regularly audit and enable snapshot block public access.

Ignoring orphaned volumes. Unattached volumes represent both security risks (potential sensitive data) and unnecessary costs. Implement regular cleanup processes.

Using AWS managed keys for all workloads. While convenient, AWS managed keys prevent cross-account sharing and provide less granular access control. Use customer managed keys for sensitive workloads.

Not implementing lifecycle management. Without automated policies, security debt accumulates through forgotten snapshots and volumes without proper controls.

Want Continuous EBS Security Monitoring?

Don't wait for auditors to find your unencrypted volumes. AWSight provides continuous monitoring of your EBS encryption status, snapshot permissions, and compliance posture—alerting you before misconfigurations become breaches.

References