When S3 buckets versioning is enabled it's possible to add an additional authentication factor before being allowed to delete versions of an object or changing the versioning state of a bucket. It prevents accidental object deletion by forcing the user sending the delete request to prove that he has a valid MFA device and a corresponding valid token.


== Ask Yourself Whether

* The S3 bucket stores sensitive information that is required to be preserved on the long term.
* The S3 bucket grants delete permission to many users.

There is a risk if you answered yes to any of those questions.


== Recommended Secure Coding Practices

It's recommended to enable S3 MFA delete, note that:

* MFA delete can only be enabled with the AWS CLI or API and with the root account.
* To delete an object version, the API should be used with the ``++x-amz-mfa++`` header.
* The API request, with the ``++x-amz-mfa++`` header, can only be used in HTTPS.


== Sensitive Code Example

A versioned S3 bucket does not have MFA delete enabled for AWS provider version 3 or below:

[source,terraform]
----
resource "aws_s3_bucket" "example" { # Sensitive
  bucket = "example"

  versioning {
    enabled = true
  }
}
----

A versioned S3 bucket does not have MFA delete enabled for AWS provider version 4 or above:

[source,terraform]
----
resource "aws_s3_bucket" "example" {
  bucket = "example"
}

resource "aws_s3_bucket_versioning" "example" { # Sensitive
  bucket = aws_s3_bucket.example.id
  versioning_configuration {
    status = "Enabled"
  }
}
----

== Compliant Solution

MFA delete is enabled for AWS provider version 3 or below:

[source,terraform]
----
resource "aws_s3_bucket" "example" {
  bucket = "example"

  versioning {
    enabled = true
    mfa_delete = true
  }
}
----

MFA delete is enabled for AWS provider version 4 or above:

[source,terraform]
----
resource "aws_s3_bucket" "example" {
  bucket = "example"
}

resource "aws_s3_bucket_versioning" "example" {
  bucket = aws_s3_bucket.example.id
  versioning_configuration {
    status = "Enabled"
    mfa_delete = "Enabled"
  }
  mfa = "${var.MFA}"
}
----

== See

* https://docs.aws.amazon.com/AmazonS3/latest/userguide/MultiFactorAuthenticationDelete.html[AWS documentation] - Configuring MFA delete
* CWE - https://cwe.mitre.org/data/definitions/308[CWE-308 - Use of Single-factor Authentication]

ifdef::env-github,rspecator-view[]

'''
== Implementation Specification
(visible only on this page)

=== Message

Make sure allowing object deletion without MFA is safe here.


endif::env-github,rspecator-view[]
