Task: Set up an AWS S3 bucket and DynamoDB table for Terraform state management. Ensure the S3 bucket has preventive measures against accidental deletion and is configured with versioning enabled, server-side encryption using AES256, and public access restrictions. Create a DynamoDB table with a hash key named 'LockID' using 'PAY_PER_REQUEST' billing mode for Terraform locking.

Specification:
has one aws_s3_bucket_versioning resource
with bucket    
with status

has one aws_dynamodb_table resource
with name
with hash_key

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

has one aws_s3_bucket_server_side_encryption_configuration resource
with bucket
with rule
    with apply_server_side_encryption_by_default
    with sse_algorithm

has one aws_s3_bucket_public_access_block resource
with bucket
with block_public_acls (boolean)
with block_public_policy (boolean)
with ignore_public_acls (boolean)
with restrict_public_buckets(boolean)

has one aws_dynamodb_table resource
with name  
with hash_key  
with attribute
    with name
    with type

Terraform configuration (main.tf):
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = ">= 5.75"
    }
  }

  required_version = ">= 1.9.0"
}

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

resource "aws_s3_bucket" "terraform_state" {
  bucket = "iac-misc-terraform-state"
}

resource "aws_s3_bucket_versioning" "enabled" {
  bucket = aws_s3_bucket.terraform_state.id
  versioning_configuration {
    status = "Enabled"
  }
}

resource "aws_s3_bucket_server_side_encryption_configuration" "default" {
  bucket = aws_s3_bucket.terraform_state.id

  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm = "AES256"
    }
  }
}

resource "aws_s3_bucket_public_access_block" "public_access" {
  bucket                  = aws_s3_bucket.terraform_state.id
  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

resource "aws_dynamodb_table" "terraform_locks" {
  name         = "iac-misc-terraform-locks"
  billing_mode = "PAY_PER_REQUEST"
  hash_key     = "LockID"

  attribute {
    name = "LockID"
    type = "S"
  }
}

Validation policy (checks.rego):
package terraform.validation

default has_s3_bucket_versioning = false
default has_dynamodb_table = false
default has_s3_bucket_server_side_encryption_configuration = false
default has_s3_bucket_public_access_block = false
default valid_configuration = false


# Check for aws_s3_bucket_versioning resource with 'bucket' and 'status'
has_s3_bucket_versioning {
    versioning := input.planned_values.root_module.resources[_]
    versioning.type == "aws_s3_bucket_versioning"
    versioning.values.versioning_configuration[_].status == "Enabled"
}

# Check for aws_dynamodb_table resource with 'name' and 'hash_key'
has_dynamodb_table {
    some i
    table := input.planned_values.root_module.resources[i]
    table.type == "aws_dynamodb_table"
    table.values.name != null
    table.values.hash_key != null
}

# Check for aws_s3_bucket_server_side_encryption_configuration resource with 'bucket', 'rule', and 'sse_algorithm'
has_s3_bucket_server_side_encryption_configuration {
    some i
    encryption := input.planned_values.root_module.resources[i]
    encryption.type == "aws_s3_bucket_server_side_encryption_configuration"
    encryption.values.rule != null
    encryption.values.rule[0].apply_server_side_encryption_by_default != null
    encryption.values.rule[0].apply_server_side_encryption_by_default[0].sse_algorithm != null
}

# Check for aws_s3_bucket_public_access_block resource with 'bucket' and boolean flags
has_s3_bucket_public_access_block {
    some i
    access_block := input.planned_values.root_module.resources[i]
    access_block.type == "aws_s3_bucket_public_access_block"
    access_block.values.block_public_acls == true
    access_block.values.block_public_policy == true
    access_block.values.ignore_public_acls == true
    access_block.values.restrict_public_buckets == true
}

# Combined validation rule
valid_configuration {
    has_s3_bucket_versioning
    has_dynamodb_table
    has_s3_bucket_server_side_encryption_configuration
    has_s3_bucket_public_access_block
}