S3 Versioning + MFA Delete: Two-Layer Protection Against Accidental Data Loss

Ned
Ned Cloud Engineer
· Updated · 3 min read
S3 Versioning + MFA Delete: Two-Layer Protection Against Accidental Data Loss

The Problem

Your critical data lives in an S3 bucket. Requirements:

  • Protection against accidental deletion
  • Permanent deletions must require additional authentication

The Solution

Two layers:

  1. S3 Versioning — every write creates a new version; delete creates a delete marker instead of removing data
  2. MFA Delete — requires an MFA code to permanently delete any version or disable versioning

How It Works

Step 1: Enable Versioning

1
2
3
aws s3api put-bucket-versioning \
  --bucket critical-data \
  --versioning-configuration Status=Enabled

After this:

  • Overwriting an object creates a new version; old versions are retained
  • Deleting an object creates a delete marker — the current version becomes a marker but no data is lost
  • You can restore any previous version at any time

Step 2: Enable MFA Delete

This is only possible using the root account credentials via CLI (not the console):

1
2
3
4
aws s3api put-bucket-versioning \
  --bucket critical-data \
  --versioning-configuration 'Status=Enabled,MFADelete=Enabled' \
  --mfa "arn:aws:iam::123456789012:mfa/root-account-mfa-device 123456"

The --mfa parameter takes the MFA device ARN plus the current TOTP code.

What MFA Delete Requires

Once enabled, these operations need an MFA code:

  • Permanently deleting a specific object version
  • Suspending or re-enabling versioning
  • Turning off MFA Delete itself

Normal operations (uploading, reading, creating delete markers) do not need MFA.

The Interaction Model

1
2
3
4
5
Regular user (no MFA) → can PUT, GET, "delete" (creates marker)
                     → CANNOT permanently delete a version
                     → CANNOT change versioning state

Root user with MFA   → can do everything, including permanent version deletion

Even if a rogue IAM user has full S3 permissions, they cannot permanently destroy your data without physical access to the root account’s MFA device.

Recovering “Deleted” Objects

When a delete marker is created:

1
2
3
4
5
6
7
8
# List versions to see the delete marker
aws s3api list-object-versions --bucket critical-data --prefix report.pdf

# Remove the delete marker to restore
aws s3api delete-object \
  --bucket critical-data \
  --key report.pdf \
  --version-id <delete-marker-version-id>

Why Not the Alternatives?

Versioning alone — Protects against accidental overwrites but not intentional permanent deletion. Any admin can delete-object --version-id and destroy history.

Lifecycle policy denying deletion — Lifecycle policies expire objects based on age; they do not deny actions.

Bucket policy denying all DeleteObject — This blocks deletion for everyone, including authorized users. Meets “prevent deletion” but breaks legitimate workflows. MFA Delete allows deletion with extra authentication instead of blocking it entirely.

Key Takeaways

  • Versioning preserves every version; deletion creates a marker, not data loss
  • MFA Delete requires the root account’s MFA code for permanent deletions
  • MFA Delete can only be enabled by the root account via the CLI — not the console
  • Combining both provides two-layer protection against both accidents and malicious deletion
  • Consider also enabling Object Lock for regulatory scenarios requiring absolute WORM
Rating:
Share
Previous CloudFront Signed URLs vs Signed Cookies: When to Use Each for S3-Backed Content