data "aws_vpc" "this" {
  id = var.vpc_id
}

data "aws_prefix_list" "private_s3" {
  filter {
    name = "prefix-list-name"
    values = [ "com.amazonaws.*.s3" ]
  }
}

data "aws_prefix_list" "private_dynamodb" {
  filter {
    name = "prefix-list-name"
    values = [ "com.amazonaws.*.dynamodb" ]
  }
}

locals {
  vpc_name = lookup(data.aws_vpc.this.tags, "Name", data.aws_vpc.this.cidr_block)
}

resource "aws_security_group" "security_group" {
  name = "typical-host"
  description = "Required typical-host SG for VPC ${local.vpc_name} (${var.vpc_id})"
  vpc_id = var.vpc_id
  tags = merge(var.tags, { "Name" = "typical-host", "vpc_name" = local.vpc_name })
}

## Ingress
resource "aws_security_group_rule" "scanner_access" {
  security_group_id = aws_security_group.security_group.id
  type = "ingress"
  description = "Full Access from Security Scanners"
  from_port = 0
  to_port = 0
  protocol = -1
  cidr_blocks = var.cidr_map["scanners"]
  count = length(var.cidr_map["scanners"]) > 0 ? 1 : 0
}

resource "aws_security_group_rule" "teleport_ssh_access" {
  security_group_id = aws_security_group.security_group.id
  type = "ingress"
  description = "Teleport SSH Access"
  from_port = 3022
  to_port = 3022
  protocol = "tcp"
  # Convert to a set to remove duplicates
  cidr_blocks = var.cidr_map["vpc-access"]
  count = length(var.cidr_map["vpc-access"]) > 0 ? 1 : 0
}

resource "aws_security_group_rule" "ssh_access" {
  security_group_id = aws_security_group.security_group.id
  type = "ingress"
  description = "SSH Access"
  from_port = 22
  to_port = 22
  protocol = "tcp"
  # Convert to a set to remove duplicates
  cidr_blocks = toset(concat(var.cidr_map["bastions"], var.cidr_map["vpns"]))
  count = length(toset(concat(var.cidr_map["bastions"], var.cidr_map["vpns"]))) > 0 ? 1 : 0
}

resource "aws_security_group_rule" "ping_inbound" {
  security_group_id = aws_security_group.security_group.id
  type = "ingress"
  description = "Inbound Pings"
  from_port = -1
  to_port = -1
  protocol = "icmp"
  cidr_blocks = [ "10.0.0.0/8" ]
}

## Outbound:
resource "aws_security_group_rule" "ping_outbound" {
  security_group_id = aws_security_group.security_group.id
  type = "egress"
  description = "Outbound Pings"
  from_port = -1
  to_port = -1
  protocol = "icmp"
  cidr_blocks = [ "0.0.0.0/0" ]
}

resource "aws_security_group_rule" "github_access_ssh" {
  security_group_id = aws_security_group.security_group.id
  type = "egress"
  description = "Outbound GitHub"
  from_port = 22
  to_port = 22
  protocol = "tcp"
  cidr_blocks = var.cidr_map["vpc-public"]
  count = length(var.cidr_map["vpc-public"]) > 0 ? 1 : 0
}

resource "aws_security_group_rule" "github_access_http" {
  security_group_id = aws_security_group.security_group.id
  type = "egress"
  description = "Outbound GitHub"
  from_port = 80
  to_port = 80
  protocol = "tcp"
  cidr_blocks = var.cidr_map["vpc-public"]
  count = length(var.cidr_map["vpc-public"]) > 0 ? 1 : 0
}

resource "aws_security_group_rule" "github_access_https" {
  security_group_id = aws_security_group.security_group.id
  type = "egress"
  description = "Outbound GitHub"
  from_port = 443
  to_port = 443
  protocol = "tcp"
  cidr_blocks = var.cidr_map["vpc-public"]
  count = length(var.cidr_map["vpc-public"]) > 0 ? 1 : 0
}

resource "aws_security_group_rule" "dns_access_tcp" {
  security_group_id = aws_security_group.security_group.id
  type = "egress"
  description = "Outbound TCP DNS"
  from_port = 53
  to_port = 53
  protocol = "tcp"
  cidr_blocks = var.cidr_map["dns"]
  count = length(var.cidr_map["dns"]) > 0 ? 1 : 0
}

resource "aws_security_group_rule" "dns_access_udp" {
  security_group_id = aws_security_group.security_group.id
  type = "egress"
  description = "Outbound UDP DNS"
  from_port = 53
  to_port = 53
  protocol = "udp"
  cidr_blocks = var.cidr_map["dns"]
  count = length(var.cidr_map["dns"]) > 0 ? 1 : 0
}

resource "aws_security_group_rule" "outbound_to_teleport" {
  security_group_id = aws_security_group.security_group.id
  type = "egress"
  description = "Connect to Teleport"
  from_port = 3080
  to_port = 3080
  protocol = "tcp"
  cidr_blocks = var.cidr_map["vpc-access"]
  count = length(var.cidr_map["vpc-access"]) > 0 ? 1 : 0
}

resource "aws_security_group_rule" "outbound_to_teleport_30xx" {
  security_group_id = aws_security_group.security_group.id
  type = "egress"
 description = "Connect to Teleport"
  from_port = 3023
  to_port = 3026
  protocol = "tcp"
  cidr_blocks = var.cidr_map["vpc-access"]
  count = length(var.cidr_map["vpc-access"]) > 0 ? 1 : 0
}

resource "aws_security_group_rule" "outbound_to_salt_masters" {
  security_group_id = aws_security_group.security_group.id
  type = "egress"
  description = "Connect to Salt Masters"
  from_port = 4505
  to_port = 4506
  protocol = "tcp"
  cidr_blocks = var.cidr_map["salt"]
  count = length(var.cidr_map["salt"]) > 0 ? 1 : 0
}

resource "aws_security_group_rule" "outbound_to_web_servers_80" {
  security_group_id = aws_security_group.security_group.id
  type = "egress"
  description = "Connect to Repo Servers"
  from_port = 80
  to_port = 80
  protocol = "tcp"
  cidr_blocks = var.cidr_map["web"]
  count = length(var.cidr_map["web"]) > 0 ? 1 : 0
}

resource "aws_security_group_rule" "outbound_to_web_servers_443" {
  security_group_id = aws_security_group.security_group.id
  type = "egress"
  description = "Connect to Repo Servers"
  from_port = 443
  to_port = 443
  protocol = "tcp"
  cidr_blocks = var.cidr_map["web"]
  count = length(var.cidr_map["web"]) > 0 ? 1 : 0
}

# Systems need to be able to access vpc endpoints on 80/443
resource "aws_security_group_rule" "outbound_to_local_vpc_80" {
  security_group_id = aws_security_group.security_group.id
  type = "egress"
  description = "Connect to VPC Endpoints"
  from_port = 80
  to_port = 80
  protocol = "tcp"
  source_security_group_id = var.aws_endpoints_sg
}

resource "aws_security_group_rule" "outbound_to_local_vpc_443" {
  security_group_id = aws_security_group.security_group.id
  type = "egress"
  description = "Connect to VPC Endpoints"
  from_port = 443
  to_port = 443
  protocol = "tcp"
  source_security_group_id = var.aws_endpoints_sg
}

resource "aws_security_group_rule" "outbound_to_mailrelay_25" {
  security_group_id = aws_security_group.security_group.id
  type = "egress"
  description = "Outbound Email to mailrelay"
  from_port = 25
  to_port = 25
  protocol = "tcp"
  cidr_blocks = var.cidr_map["vpc-system-services"]
  count = length(var.cidr_map["vpc-system-services"]) > 0 ? 1 : 0
}

resource "aws_security_group_rule" "outbound_to_ec2_s3_endpoint" {
  security_group_id = aws_security_group.security_group.id
  type = "egress"
  description = "Outbound to S3 endpoint"
  from_port = 443
  to_port = 443
  protocol = "tcp"
  prefix_list_ids = [ data.aws_prefix_list.private_s3.id ]
  count = length([ data.aws_prefix_list.private_s3.id ]) > 0 ? 1 : 0 # todo: handle case of no s3 prefix list
}

resource "aws_security_group_rule" "outbound_to_ec2_dynamodb_endpoint" {
  security_group_id = aws_security_group.security_group.id
  type = "egress"
  description = "Outbound to dynamodb endpoint"
  from_port = 443
  to_port = 443
  protocol = "tcp"
  prefix_list_ids = [ data.aws_prefix_list.private_dynamodb.id ]
  count = length([ data.aws_prefix_list.private_dynamodb.id ]) > 0 ? 1 : 0 # todo: handle case of no s3 prefix list
}

resource "aws_security_group_rule" "outbound_to_sensu" {
  security_group_id = aws_security_group.security_group.id
  type = "egress"
  description = "Monitoring Outbound"
  from_port = 8081
  to_port   = 8081
  protocol  = "tcp"
  cidr_blocks = var.cidr_map["monitoring"]
  count = length(var.cidr_map["monitoring"]) > 0 ? 1 : 0
}

resource "aws_security_group_rule" "outbound_to_moose_s2s" {
  security_group_id = aws_security_group.security_group.id
  type = "egress"
  description              = "Splunk UF outbound to Moose Indexers"
  from_port = 9997
  to_port   = 9998
  protocol  = "tcp"
  cidr_blocks = var.cidr_map["moose"]
  count = length(var.cidr_map["moose"]) > 0 ? 1 : 0
}

resource "aws_security_group_rule" "outbound_to_moose_idxc" {
  security_group_id = aws_security_group.security_group.id
  type = "egress"
  description              = "Outbound IDXC Discovery to MOOSE"
  from_port = 8089
  to_port   = 8089
  protocol  = "tcp"
  cidr_blocks = var.cidr_map["moose"]
  count = length(var.cidr_map["moose"]) > 0 ? 1 : 0
}

resource "aws_security_group_rule" "outbound_to_moose_hec" {
  security_group_id = aws_security_group.security_group.id
  type = "egress"
  description = "Connect to HEC"
  from_port = 8088
  to_port = 8088
  protocol = "tcp"
  cidr_blocks = var.cidr_map["moose"]
  count = length(var.cidr_map["moose"]) > 0 ? 1 : 0
}
