# Task 110


Create an AWS S3 bucket named 'wellcomecollection-platform-infra' with preventive destruction measures. Set the bucket ACL to 'private' and configure a lifecycle policy for automatic deletion of objects with a 'tmp/' prefix after 30 days. Implement versioning and set up lifecycle rules to transition old versions to the 'STANDARD_IA' storage class after 30 days and delete noncurrent versions after 90 days.

## Intent

has one aws_s3_bucket resource
with bucket

has one aws_s3_bucket_acl resource
with bucket 
with acl

has one aws_s3_bucket_lifecycle_configuration resource
with bucket
with rule
     with id
     with status
     with action
     with transition
          with days
          with storage_class
with expiration
     with days

has one aws_s3_bucket_versioning resource
with bucket
with versioning_configuration
     with status (can be "Enabled" or "Suspended")

## Reference Terraform solution

terraform {
  required_version = ">= 1.15.0"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 6.0"
    }
  }
}

provider "aws" {
  region = "us-east-1"
}

resource "aws_s3_bucket" "platform_infra" {
  bucket_prefix = "wellcomecollection-platform-infra-"
}

resource "aws_s3_bucket_ownership_controls" "example" {
    bucket = aws_s3_bucket.platform_infra.id
    rule {
        object_ownership = "BucketOwnerPreferred"
    }
}

resource "aws_s3_bucket_acl" "platform_infra" {
  depends_on = [ aws_s3_bucket_ownership_controls.example ]

  bucket = aws_s3_bucket.platform_infra.id
  acl    = "private"
}

resource "aws_s3_bucket_lifecycle_configuration" "platform_infra" {
  bucket = aws_s3_bucket.platform_infra.id

  rule {
    id = "tmp"

    filter {
      prefix = "tmp/"
    }

    expiration {
      days = 30
    }

    status = "Enabled"
  }

  rule {
    id = "expire_old_versions"

    transition {
      days          = 30
      storage_class = "STANDARD_IA"
    }

    noncurrent_version_expiration {
      noncurrent_days = 90
    }

    status = "Enabled"
  }
}

resource "aws_s3_bucket_versioning" "platform_infra" {
  bucket = aws_s3_bucket.platform_infra.id

  versioning_configuration {
    status = "Enabled"
  }
}


## OPA Rego validation policy

package terraform.policy

import rego.v1

default has_s3_bucket = false

default has_s3_bucket_acl = false

default has_s3_bucket_lifecycle_configuration_one = false

default has_s3_bucket_lifecycle_configuration_two = false

default has_s3_bucket_versioning = false

default valid_configuration = false

has_s3_bucket if {
    bucket := input.planned_values.root_module.resources[_]
    bucket.type == "aws_s3_bucket"
}

has_s3_bucket_acl if {
        acl := input.planned_values.root_module.resources[_]
    acl.type == "aws_s3_bucket_acl"
        acl.values.acl == "private"
}

has_s3_bucket_lifecycle_configuration_one if {
        lifecycle := input.planned_values.root_module.resources[_]
    lifecycle.type == "aws_s3_bucket_lifecycle_configuration"
        rule1 := lifecycle.values.rule[_]
        rule1.id != null
        rule1.status == "Enabled"
        rule1.expiration[_].days == 30
}

has_s3_bucket_lifecycle_configuration_two if {
        lifecycle := input.planned_values.root_module.resources[_]
    lifecycle.type == "aws_s3_bucket_lifecycle_configuration"
        rule2 := lifecycle.values.rule[_]
        rule2.id != null
        rule2.status == "Enabled"
        rule2.noncurrent_version_expiration[_].noncurrent_days == 90
    rule2.transition[_].days == 30
    rule2.transition[_].storage_class == "STANDARD_IA"
}

has_s3_bucket_versioning if {
    versioning := input.planned_values.root_module.resources[_]
    versioning.type == "aws_s3_bucket_versioning"
    versioning.values.versioning_configuration[_].status == "Enabled"
}

valid_configuration if {
        has_s3_bucket
        has_s3_bucket_acl
        has_s3_bucket_lifecycle_configuration_one
    has_s3_bucket_lifecycle_configuration_two
        has_s3_bucket_versioning
}

main if {
    valid_configuration
}