Accidental deletion of Amazon S3 buckets can cause catastrophic data loss in production environments. Unlike objects within buckets, deleted buckets cannot be recovered through versioning or other AWS recovery mechanisms. This makes bucket deletion prevention a critical security consideration.
The most effective way to prevent bucket deletion is through a carefully crafted bucket policy that explicitly denies the s3:DeleteBucket
action. Here's a basic policy template:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Principal": "*",
"Action": "s3:DeleteBucket",
"Resource": "arn:aws:s3:::your-bucket-name"
}
]
}
For more granular control, you can add conditions to the policy. This example prevents all users except the root account from deleting the bucket:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Principal": "*",
"Action": "s3:DeleteBucket",
"Resource": "arn:aws:s3:::your-bucket-name",
"Condition": {
"StringNotLike": {
"aws:userId": "AROAEXAMPLEID:*"
}
}
}
]
}
For comprehensive protection, combine bucket policies with:
- S3 Object Lock (for compliance requirements)
- MFA delete requirements
- AWS Backup plans
- Service Control Policies (SCPs) at the organization level
Here's how to implement this protection in infrastructure-as-code:
resource "aws_s3_bucket" "protected_bucket" {
bucket = "my-protected-bucket"
}
resource "aws_s3_bucket_policy" "bucket_policy" {
bucket = aws_s3_bucket.protected_bucket.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Deny"
Principal = "*"
Action = "s3:DeleteBucket"
Resource = aws_s3_bucket.protected_bucket.arn
}
]
})
}
Always verify your protection works by attempting to delete the bucket through:
- AWS Management Console
- AWS CLI (
aws s3 rb s3://your-bucket-name --force
) - SDK calls
Accidental deletion of Amazon S3 buckets can cause catastrophic data loss. While AWS provides versioning and MFA delete options, these don't prevent bucket deletion itself. The most effective solution is implementing a bucket policy that explicitly denies delete actions.
Here's a basic bucket policy that prevents all users (including root) from deleting the bucket:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Principal": "*",
"Action": "s3:DeleteBucket",
"Resource": "arn:aws:s3:::your-bucket-name"
}
]
}
For production environments, consider these enhanced protections:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Principal": "*",
"Action": [
"s3:DeleteBucket",
"s3:DeleteBucketPolicy",
"s3:PutBucketPolicy"
],
"Resource": "arn:aws:s3:::your-bucket-name"
},
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:user/admin-user"
},
"Action": "*",
"Resource": "arn:aws:s3:::your-bucket-name"
}
]
}
1. Always test policies in a non-production environment first
2. Combine with S3 Object Lock for immutable data storage
3. Use AWS Backup for additional protection
4. Monitor policy changes with AWS Config
For infrastructure-as-code users:
resource "aws_s3_bucket_policy" "bucket_protection" {
bucket = aws_s3_bucket.important_data.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Deny"
Principal = "*"
Action = "s3:DeleteBucket"
Resource = aws_s3_bucket.important_data.arn
}
]
})
}
- Forgetting to include the bucket ARN in the Resource field
- Not specifying the correct action (s3:DeleteBucket vs s3:DeleteObject)
- Overly restrictive policies that block legitimate operations