An Amazon S3 bucket without Multi-Factor Authentication (MFA) delete enabled is vulnerable to accidental or malicious deletion of objects, even if bucket versioning is turned on. MFA delete adds an extra layer of security by requiring a time-based one-time password from a hardware or virtual MFA device before allowing delete operations on objects or bucket versions. If this protection is not enabled, anyone with appropriate credentials can permanently delete data, increasing the risk of data loss due to stolen credentials or misconfigured permissions. Terraform does not currently support enabling mfa_delete in the versioning block of the aws_s3_bucket resource, so this must be configured manually using the AWS CLI after applying Terraform, as shown in the command: aws s3api put-bucket-versioning --versioning-configuration Status=Enabled,MFADelete=Enabled --bucket=<BUCKET_NAME> --mfa=<MFA_SERIAL_NUMBER>.
# On a fresh-create plan, both aws_s3_bucket_versioning.bucket and
# aws_s3_bucket_lifecycle_configuration.bucket are unresolved in
# planned_values (absent, not just null). The scanner's
# _dd_tfplan_meta.<type>.<name>.configuration_expressions mirrors
# configuration.*.expressions for each resource unmodified, so even though
# neither bucket value is resolvable, both references' target ("aws_s3_bucket
# b0") can still be compared -- see references_same_target in
# assets/libraries/terraform.rego. The rule uses this to confirm the
# versioning and lifecycle-configuration resources target the same bucket and
# correctly honors the exemption here despite the unresolved references (see
# negative10.json). The literal-linked case (bucket resolvable via a plain
# string) is covered separately by negative8.tf/json.
terraform{required_providers{aws={source="hashicorp/aws"version="4.2.0"}}}provider"aws"{ # Configuration options
}resource"aws_s3_bucket""b0"{bucket="my-tf-test-bucket"tags={Name="My bucket"Environment="Dev"}}resource"aws_s3_bucket_versioning""example"{bucket=aws_s3_bucket.b0.idversioning_configuration{status="Enabled"mfa_delete="Disabled"}}resource"aws_s3_bucket_lifecycle_configuration""example"{bucket=aws_s3_bucket.b0.idrule{id="tmp"status="Enabled"expiration{days=90}}}