Task: Configure Blue/Green deployment with Route53 resources to navigate traffic between Elastic Beanstalk Environments. Name the environments "blue" and "green" and implement a Weighted Routing Policy for the records

Specification:
Has one "aws_iam_role" resource
    with "name"
    with "assume_role_policy" and "Service" set to "ec2.amazonaws.com"

Has one "aws_iam_role_policy_attachment" resource
    with "role" referencing the "aws_iam_role"
    with "policy_arn" set to "arn:aws:iam::aws:policy/AWSElasticBeanstalkWebTier"

Has one "aws_iam_instance_profile" resource
    with "name"
    with "role" referencing the "aws_iam_role" resource

Has one "aws_elastic_beanstalk_application" resource
    with "name"

Has two "aws_elastic_beanstalk_environment" resources
    each are provisioned in different regions
    with "name"
    with "application" referencing the "aws_elastic_beanstalk_application" resource
    with "solution_stack_name"
    with one "setting" block which has a "value" that references the "aws_iam_instance_profile" resource

Has one "aws_route53_zone" resource
    with "name"

Has two "aws_route53_record" resources
    each are provisioned in different regions
    with "name"
    with "type"
    with "ttl"
    with "zone_id" referencing the "aws_route53_zone" resource
    with "set_identifier"
    with "weighted_routing_policy" block that contains "weight" as a non-zero number
    with "records" referencing one of the "aws_elastic_beanstalk_environment" resources

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_iam_role" "eb_ec2_role" {
  name = "elastic_beanstalk_ec2_role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17",
    Statement = [
      {
        Action = "sts:AssumeRole",
        Effect = "Allow",
        Principal = {
          Service = "ec2.amazonaws.com"
        },
      },
    ]
  })
}

# Attach the AWS managed policy for Elastic Beanstalk to the role
resource "aws_iam_role_policy_attachment" "eb_managed_policy" {
  role       = aws_iam_role.eb_ec2_role.name
  policy_arn = "arn:aws:iam::aws:policy/AWSElasticBeanstalkWebTier"
}


# Create an instance profile tied to the role
resource "aws_iam_instance_profile" "eb_ec2_profile" {
  name = "elastic_beanstalk_ec2_profile"
  role = aws_iam_role.eb_ec2_role.name
}

resource "aws_s3_bucket" "sample_bucket" {
  bucket_prefix = "sample-"
}

resource "aws_s3_object" "examplebucket_blue_object" {
  key    = "blue_app"
  bucket = aws_s3_bucket.sample_bucket.id
  source = "./supplement/app.zip"
}

resource "aws_s3_object" "examplebucket_green_object" {
  key    = "green_app"
  bucket = aws_s3_bucket.sample_bucket.id
  source = "./supplement/app.zip"
}

# Elastic Beanstalk application
resource "aws_elastic_beanstalk_application" "blue_app" {
  name        = "blue-app"
  description = "An application for Blue deployment."
}

resource "aws_elastic_beanstalk_application_version" "blue_version" {
  name        = "v1"
  application = aws_elastic_beanstalk_application.blue_app.name
  bucket = aws_s3_object.examplebucket_blue_object.bucket
  key    = aws_s3_object.examplebucket_blue_object.key
}

resource "aws_elastic_beanstalk_application" "green_app" {
  name        = "green-app"
  description = "An application for Green deployment."
}

resource "aws_elastic_beanstalk_application_version" "green_version" {
  name        = "v2"
  application = aws_elastic_beanstalk_application.green_app.name
  bucket = aws_s3_object.examplebucket_green_object.bucket
  key    = aws_s3_object.examplebucket_green_object.key
}

# Blue environment
resource "aws_elastic_beanstalk_environment" "blue" {
  name                = "${aws_elastic_beanstalk_application.blue_app.name}"
  application         = aws_elastic_beanstalk_application.blue_app.name
  solution_stack_name = "64bit Amazon Linux 2023 v4.3.0 running Python 3.9"
  version_label = aws_elastic_beanstalk_application_version.blue_version.name

  setting {
    namespace = "aws:autoscaling:launchconfiguration"
    name      = "IamInstanceProfile"
    value     = aws_iam_instance_profile.eb_ec2_profile.name
  }
}

# Green environment (New version)
resource "aws_elastic_beanstalk_environment" "green" {
  name                = "${aws_elastic_beanstalk_application.green_app.name}-green"
  application         = aws_elastic_beanstalk_application.green_app.name
  solution_stack_name = "64bit Amazon Linux 2023 v4.3.0 running Python 3.9"
  version_label = aws_elastic_beanstalk_application_version.green_version.name

  setting {
    namespace = "aws:autoscaling:launchconfiguration"
    name      = "IamInstanceProfile"
    value     = aws_iam_instance_profile.eb_ec2_profile.name
  }
}

# Route53 Hosted Zone
resource "aws_route53_zone" "main" {
  name = "example53.com"
}

# Weighted DNS records for Blue and Green environments
resource "aws_route53_record" "blue" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "app.example.com"
  type    = "CNAME"
  ttl     = "60"
  weighted_routing_policy {
    weight = 120
  }
  set_identifier = "BlueEnvironment"
  records = [
    aws_elastic_beanstalk_environment.blue.cname
  ]
}

resource "aws_route53_record" "green" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "app.example.com"
  type    = "CNAME"
  ttl     = "60"
  weighted_routing_policy {
    weight = 60
  }
  set_identifier = "GreenEnvironment"
  records = [
    aws_elastic_beanstalk_environment.green.cname
  ]
}

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

default is_configuration_valid = false

default is_valid_iam_instance_profile = false

default is_valid_iam_role = false

default is_valid_iam_role_policy_attachment = false

default is_valid_eb_app = false

default is_valid_eb_env = false

default is_valid_r53_zone = false

default is_valid_r53_record = false




# Validate aws_route53_zone resource
is_valid_r53_zone {
        some i
    resource := input.configuration.root_module.resources[i]
    resource.type == "aws_route53_zone"
    resource.name
}

# Validate aws_route53_record
is_valid_r53_record {
        some i, j
    resource := input.configuration.root_module.resources[i]
    resource.type == "aws_route53_record"
    resource.expressions.name
    resource.expressions.type
    resource.expressions.ttl
    resource.expressions.set_identifier
    resource.expressions.weighted_routing_policy
    resource.expressions.records.references[0] == "aws_elastic_beanstalk_environment.blue.cname"
    resource.expressions.zone_id.references[0]
    
    resource2 := input.configuration.root_module.resources[j]
    resource2.type == "aws_route53_record"
    resource2.expressions.name
    resource2.expressions.type
    resource2.expressions.ttl
    resource2.expressions.records.references[0] == "aws_elastic_beanstalk_environment.green.cname"
    resource2.expressions.zone_id.references[0]
    resource2.expressions.set_identifier
    resource2.expressions.weighted_routing_policy

}


is_valid_iam_role {
        some i
    resource := input.resource_changes[i]
    resource.type == "aws_iam_role"
    contains(resource.change.after.assume_role_policy,"ec2.amazonaws.com")
}

is_valid_iam_role_policy_attachment {
                 some i
    resource := input.configuration.root_module.resources[i]
    resource.type == "aws_iam_role_policy_attachment"
    resource.expressions.role.references[0]
    resource.expressions.policy_arn.constant_value == "arn:aws:iam::aws:policy/AWSElasticBeanstalkWebTier"
}

# Validate aws_iam_instance_profile resource
is_valid_iam_instance_profile {
                 some i
    resource := input.configuration.root_module.resources[i]
    resource.type == "aws_iam_instance_profile"
    resource.expressions.role.references[0]
}


# Validate aws_eb_app
is_valid_eb_app {
        some i
    resource := input.configuration.root_module.resources[i]
    resource.type == "aws_elastic_beanstalk_application"
    resource.expressions.name
}

# Validate aws_eb_env
is_valid_eb_env {
        some i, j
    resource := input.configuration.root_module.resources[i]
    resource.type == "aws_elastic_beanstalk_environment"
    resource.expressions.name
    resource.expressions.application.references[0]
    resource.expressions.solution_stack_name
        some a
    resource.expressions.setting[a].value.references[0]
    
    resource2 := input.configuration.root_module.resources[j]
    resource2.type == "aws_elastic_beanstalk_environment"
    resource2.expressions.name
    resource2.expressions.application.references[0]
    resource2.expressions.solution_stack_name
        some b
    resource2.expressions.setting[b].value.references[0]

}


# Combine all checks into a final rule
is_configuration_valid {
        is_valid_iam_role
    is_valid_iam_role_policy_attachment
    is_valid_iam_instance_profile
        is_valid_r53_zone
        is_valid_r53_record
    is_valid_eb_app
    is_valid_eb_env
}