# Task 191


Create one public subnet and two private subnets.The public subnet will run a webserver, the private subnets will have  a application server and relational databse.

## Intent

## Reference Terraform solution

terraform {
  required_version = ">= 1.15.0"

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

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

# Create a Virtual Private Cloud (VPC)
resource "aws_vpc" "my_vpc" {
  cidr_block = "10.0.0.0/16"
}

data "aws_availability_zones" "available" {
  state = "available"
}

# Create Public Subnet
resource "aws_subnet" "public_subnet" {
  vpc_id                  = aws_vpc.my_vpc.id
  cidr_block              = "10.0.1.0/24"
  availability_zone       = data.aws_availability_zones.available.names[0]
  map_public_ip_on_launch = true
}

# Create Private Subnet 1
resource "aws_subnet" "private_subnet_1" {
  vpc_id            = aws_vpc.my_vpc.id
  cidr_block        = "10.0.2.0/24"
  availability_zone = data.aws_availability_zones.available.names[1]
}

# Create Private Subnet 2
resource "aws_subnet" "private_subnet_2" {
  vpc_id            = aws_vpc.my_vpc.id
  cidr_block        = "10.0.3.0/24"
  availability_zone = data.aws_availability_zones.available.names[2]
}

# Create Security Group for EC2 instances
resource "aws_security_group" "web_sg" {
  vpc_id = aws_vpc.my_vpc.id
  name   = "web_sg"

  # Define inbound and outbound rules as needed
}

data "aws_ami" "latest_amazon_linux_2" {
  most_recent = true
  owners      = ["amazon"]

  filter {
    name   = "name"
    values = ["*ubuntu-noble-24.04-amd64-server-*"]
  }
}

# Create EC2 instance in the Public Subnet (Web Server)
resource "aws_instance" "web_instance" {
  ami             =  data.aws_ami.latest_amazon_linux_2.id
  instance_type   = "t2.micro"
  subnet_id       = aws_subnet.public_subnet.id
  security_groups = [aws_security_group.web_sg.id]

  # Additional configurations can be added as needed
}

# Create EC2 instance in Private Subnet 1 (Application Server)
resource "aws_instance" "app_instance" {
  ami           = data.aws_ami.latest_amazon_linux_2.id
  instance_type = "t2.micro"
  subnet_id     = aws_subnet.private_subnet_1.id

  # Additional configurations can be added as needed
}

resource "aws_db_subnet_group" "main" {
  name       = "mydb-subnet-group"
  subnet_ids = [aws_subnet.private_subnet_1.id, aws_subnet.private_subnet_2.id]
}

# Create RDS instance in Private Subnet 2 (Database)
resource "aws_db_instance" "db_instance" {
  identifier           = "mydb"
  engine               = "mysql"
  instance_class       = "db.t3.micro"
  allocated_storage    = 20
  username             = "admin"
  password             = "your-password" # Replace with your desired password
  skip_final_snapshot  = true
  db_subnet_group_name = aws_db_subnet_group.main.name
}


## OPA Rego validation policy

package terraform.policy

import rego.v1

default allow = false

allow if {
    public_subnet_exists(input.resource_changes)
    count(private_subnet_exists) == 2
    count(aws_instances) == 2
    rds_exist(input.resource_changes)
}

public_subnet_exists(resources) if {
    some resource in resources
    resource.type == "aws_subnet"
    resource.change.after.map_public_ip_on_launch == true
}

private_subnet_exists contains resource if {
    resource := input.resource_changes[_]
    resource.type == "aws_subnet"
    resource.change.after.map_public_ip_on_launch == false
}

rds_exist(resources) if {
    some resource in resources
    resource.type == "aws_db_instance"
}

aws_instances contains resource if {
    resource := input.resource_changes[_]
    resource.type == "aws_instance"
}

main if {
    allow
}