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

terraform {
  backend "s3" {
    bucket  = "dev-orcd-terraform-state"
    key     = "dev/us_east_1_vpc/terraform.tfstate"
    region  = "us-east-1"
    encrypt = "true"
  }
}

data "aws_s3_bucket" "flow_logs_bucket" {
  bucket = "${var.environment}-orcd-vpc-logs"
}

data "aws_vpcs" "vpc" {}

data "aws_vpc" "dev_vpc" {
  tags = {
    Name = var.environment
  }
}

data "aws_subnets" "public_subnets" {
  filter {
    name   = "vpc-id"
    values = [data.aws_vpc.dev_vpc.id]
  }

  tags = {
    tier = "public"
  }
}

data "aws_subnet" "public" {
  for_each = toset(data.aws_subnets.public_subnets.ids)
  id       = each.value
}

data "aws_subnets" "private_subnets" {
  filter {
    name   = "vpc-id"
    values = [data.aws_vpc.dev_vpc.id]
  }

  tags = {
    tier = "private"
  }
}

data "aws_subnet" "private" {
  for_each = toset(data.aws_subnets.private_subnets.ids)
  id       = each.value
}

data "aws_ec2_transit_gateway" "transit_gateway" {
  filter {
    name   = "options.amazon-side-asn"
    values = ["64513"]
  }
}

data "aws_ec2_managed_prefix_list" "vpn_ny" {
  filter {
    name   = "prefix-list-name"
    values = ["vpn-ny"]
  }
}

data "aws_ec2_managed_prefix_list" "sme_vpn" {
  filter {
    name   = "prefix-list-name"
    values = ["vpn-sme-internal-primary"]
  }
}

data "aws_ec2_managed_prefix_list" "shared_private_prefix_list" {
  filter {
    name   = "prefix-list-name"
    values = ["shared-orcd-private-subnet-prefix-list"]
  }
}

data "aws_route53_resolver_firewall_rule_group" "dns_firewall_rule_group" {
  firewall_rule_group_id = "rslvr-frg-1764658298884585" # sony_ioc_rule_group
}

resource "aws_flow_log" "gsirt" {
  for_each = toset(data.aws_vpcs.vpc.ids)

  vpc_id               = each.value
  log_destination      = data.aws_s3_bucket.flow_logs_bucket.arn
  log_destination_type = "s3"
  traffic_type         = "REJECT"

  tags = {
    Name         = "${var.environment}-gsirt"
    service_name = "vpc-flow-log"
    terraformed  = true
  }
}

resource "aws_ec2_transit_gateway_vpc_attachment" "transit_gateway_attachment" {
  vpc_id             = data.aws_vpc.dev_vpc.id
  subnet_ids         = data.aws_subnets.private_subnets.ids
  transit_gateway_id = data.aws_ec2_transit_gateway.transit_gateway.id
}

resource "aws_route_table" "public" {
  vpc_id = data.aws_vpc.dev_vpc.id

  tags = {
    Name        = "public"
    terraformed = true
  }
}

resource "aws_route" "ny" {
  for_each = toset([data.aws_vpc.dev_vpc.main_route_table_id, aws_route_table.public.id])

  route_table_id             = each.value
  destination_prefix_list_id = data.aws_ec2_managed_prefix_list.vpn_ny.id
  transit_gateway_id         = data.aws_ec2_transit_gateway.transit_gateway.id
}

resource "aws_route" "sme_vpn" {
  for_each = toset([data.aws_vpc.dev_vpc.main_route_table_id, aws_route_table.public.id])

  route_table_id             = each.value
  destination_prefix_list_id = data.aws_ec2_managed_prefix_list.sme_vpn.id
  transit_gateway_id         = data.aws_ec2_transit_gateway.transit_gateway.id
}

resource "aws_route" "shared" {
  for_each = toset([data.aws_vpc.dev_vpc.main_route_table_id])

  route_table_id             = each.value
  destination_prefix_list_id = data.aws_ec2_managed_prefix_list.shared_private_prefix_list.id
  transit_gateway_id         = data.aws_ec2_transit_gateway.transit_gateway.id
}

resource "aws_ec2_managed_prefix_list" "public" {
  address_family = "IPv4"
  max_entries    = length(data.aws_subnet.public)
  name           = "${var.environment}-${var.account_group}-public-subnet-prefix-list"

  dynamic "entry" {
    for_each = data.aws_subnet.public
    content {
      cidr        = entry.value["cidr_block"]
      description = "${var.environment} ${var.account_group}  public subnet ${entry.value["cidr_block"]} in ${entry.value["availability_zone"]}"
    }
  }

  tags = {
    account_group = var.account_group
    environment   = var.environment
    service_name  = "managed-prefix-list"
    subnet_group  = "all"
    subnet_type   = "public"
    tier          = "public"
    terraformed   = "true"
    vpc_id        = data.aws_vpc.dev_vpc.id
  }
}

resource "aws_ram_resource_share" "public_subnet" {
  name = "${var.environment}-${var.account_group}-public-subnet-managed-prefix-list-share"

  tags = {
    account_group = var.account_group
    environment   = var.environment
    service_name  = "managed-prefix-list"
    terraformed   = true
  }
}

resource "aws_ram_resource_association" "public_subnet_association" {
  resource_arn       = aws_ec2_managed_prefix_list.public.arn
  resource_share_arn = aws_ram_resource_share.public_subnet.arn
}

resource "aws_ram_principal_association" "public_subnet_principal_association" {
  principal          = var.org_ou_arn
  resource_share_arn = aws_ram_resource_share.public_subnet.arn
}

resource "aws_ec2_managed_prefix_list" "private" {
  address_family = "IPv4"
  max_entries    = length(data.aws_subnet.private)
  name           = "${var.environment}-${var.account_group}-private-subnet-prefix-list"

  dynamic "entry" {
    for_each = data.aws_subnet.private
    content {
      cidr        = entry.value["cidr_block"]
      description = "${var.environment} ${var.account_group} private subnet ${entry.value["cidr_block"]} in ${entry.value["availability_zone"]}"
    }
  }

  tags = {
    account_group = var.account_group
    environment   = var.environment
    service_name  = "managed-prefix-list"
    subnet_group  = "all"
    subnet_type   = "private"
    tier          = "private"
    terraformed   = true
    vpc_id        = data.aws_vpc.dev_vpc.id
  }
}

resource "aws_ram_resource_share" "private_subnet" {
  name = "${var.environment}-${var.account_group}-private-subnet-managed-prefix-list-share"

  tags = {
    account_group = var.account_group
    environment   = var.environment
    service_name  = "managed-prefix-list"
    terraformed   = true
  }
}

resource "aws_ram_resource_association" "private_subnet_association" {
  resource_arn       = aws_ec2_managed_prefix_list.private.arn
  resource_share_arn = aws_ram_resource_share.private_subnet.arn
}

resource "aws_ram_principal_association" "private_subnet_principal_association" {
  principal          = var.org_ou_arn
  resource_share_arn = aws_ram_resource_share.private_subnet.arn
}

# Prefix lists can't be looked up using tags, so store the IDs in SSM parameters so that they can be looked up by VPC ID
resource "aws_ssm_parameter" "private_subnet_prefix_list_id" {
  name           = "/vpc/${data.aws_vpc.dev_vpc.id}/private-subnet-prefix-list-id"
  type           = "String"
  insecure_value = aws_ec2_managed_prefix_list.private.id

  tags = {
    account_group = var.account_group
    environment   = var.environment
    terraformed   = true
  }
}

resource "aws_ssm_parameter" "public_subnet_prefix_list_id" {
  name           = "/vpc/${data.aws_vpc.dev_vpc.id}/public-subnet-prefix-list-id"
  type           = "String"
  insecure_value = aws_ec2_managed_prefix_list.public.id

  tags = {
    account_group = var.account_group
    environment   = var.environment
    terraformed   = true
  }
}

resource "aws_route53_resolver_firewall_rule_group_association" "vpc_association" {
  name                   = "${data.aws_vpc.dev_vpc.id}-dns-firewall-rule-group-association"
  firewall_rule_group_id = data.aws_route53_resolver_firewall_rule_group.dns_firewall_rule_group.id
  priority               = 101
  vpc_id                 = data.aws_vpc.dev_vpc.id
}
