locals {
  ingress-alb = [
    { from_port = 443, to_port = 443, source_sg_id = module.sg-alb.sg_id, description = "Allow inbound https from ALBs" },
    { from_port = 80, to_port = 80, source_sg_id = module.sg-nexus.sg_id, description = "Allow inbound http from Nexus" },
    { from_port = 443, to_port = 443, source_sg_id = module.sg-nexus.sg_id, description = "Allow inbound https from Nexus" },
    { from_port = 80, to_port = 80, source_sg_id = module.sg-grafana.sg_id, description = "Allow inbound https from Grafana" },
  ]
  ingress-influxdb = [
    { from_port = 8086, to_port = 8086, source_sg_id = module.sg-alb.sg_id, description = "Allow inbound influsdb from ALB" },
  ]
  ingress-grafana = [
    { from_port = 3000, to_port = 3000, source_sg_id = module.sg-alb.sg_id, description = "Allow inbound grafana from ALB" },
    { from_port = 8081, to_port = 8081, source_sg_id = module.sg-alb.sg_id, description = "Allow inbound grafana_renderer from ALB" },
  ]
  ingress-vpn = [
    { from_port = 943, to_port = 945, source_sg_id = module.sg-vpn.sg_id, description = "Allow communitaction in OpenVpn cluster" }
  ]
  ingress-mysql = [
    { from_port = 3306, to_port = 3306, source_sg_id = module.sg-vpn.sg_id, description = "Allow inbound connections from vpn EC2 instances" }
  ]
  ingress-squid = [
    { from_port = 3128, to_port = 3128, source_sg_id = module.sg-vpn.sg_id, description = "Allow connections from OpenVpn" },
    { from_port = 3128, to_port = 3128, source_sg_id = module.sg-squid.sg_id, description = "Allow connections from other Squid servers" }
  ]
  ingress-ecs = [
    { from_port = 80, to_port = 80, source_sg_id = module.sg-alb.sg_id, description = "Allow inbound http from ALBs" },
    { from_port = 80, to_port = 80, source_sg_id = module.sg-ecs.sg_id, description = "Allow inbound http from ECS" },
  ]

  ingress-efs = [
    { from_port = 2049, to_port = 2049, source_sg_id = module.sg-ecs.sg_id, description = "Allow inbound nfs from ECS" },
    { from_port = 2049, to_port = 2049, source_sg_id = module.sg-efs.sg_id, description = "Allow inbound nfs from EFS" },
  ]

  ingress-memcached = [
    { from_port = 11211, to_port = 11211, source_sg_id = module.sg-ecs.sg_id, description = "Allow inbound Memcached connections from ECS" },
  ]
  ingress-nexus = [
    { from_port = 8081, to_port = 8081, source_sg_id = module.sg-alb.sg_id, description = "Allow inbound http from ALBs" }
  ]
  ingress-lambda    = []
  whitelisted_cidrs = concat(module.ip_whitelist.whitelisted_cidrs, var.projectgroup_whitelist)
  vpn_cidrs         = [for cidr in var.vpn_masq_cidrs : { cidr = cidr, description = "Access for VPN users" }]
  access_list = var.external_access_mode == "whitelist" ? local.whitelisted_cidrs : (
    var.external_access_mode == "vpn" ? local.vpn_cidrs : concat(local.vpn_cidrs, local.whitelisted_cidrs)
  )
  whitelisted_ip_sets = [for item in concat(local.whitelisted_cidrs, var.external_https_access) : {
    type  = "IPV4"
    value = item["cidr"]
  }]

  whitelist_cidrs_list = [for item in concat(local.access_list, var.external_https_access) : item["cidr"]]
}

module "ip_whitelist" {
  source = "../../../modules/ip_whitelist"
}

# Create security group for load balancers
module "sg-alb" {
  source           = "../../../modules/vpc/sg"
  sg_description   = "Allows HTTP/HTTPS connections to ALB"
  vpc_id           = var.vpc_id
  protocol         = "tcp"
  ingress_template = local.ingress-alb
  tags = merge(
    var.common_tags,
    {
      "Name" = format("%v-sg-alb", var.name_prefix)
    },
  )
}

module "sg-efs" {
  source = "../../../modules/vpc/sg"

  sg_description   = "Allows NFS connections to EFS"
  vpc_id           = var.vpc_id
  protocol         = "tcp"
  ingress_template = local.ingress-efs

  tags = merge(
    var.common_tags,
    {
      "Name" = format("%v-sg-efs", var.name_prefix)
    },
  )
}

module "sg-memcached" {
  source = "../../../modules/vpc/sg"

  sg_description   = "Allows connections to Memcached"
  vpc_id           = var.vpc_id
  protocol         = "tcp"
  ingress_template = local.ingress-memcached

  tags = merge(
    var.common_tags,
    {
      "Name" = format("%v-sg-memcached", var.name_prefix)
    },
  )
}

# Create security group for containers in ECS
module "sg-ecs" {
  source = "../../../modules/vpc/sg"

  sg_description   = "Allows HTTP connections to ECS"
  vpc_id           = var.vpc_id
  protocol         = "tcp"
  ingress_template = local.ingress-ecs

  tags = merge(
    var.common_tags,
    {
      "Name" = format("%v-sg-ecs", var.name_prefix)
    },
  )
}

# Create security group for containers in ECS
module "sg-vpn" {
  source           = "../../../modules/vpc/sg"
  sg_description   = "Allows HTTP connections to ECS"
  vpc_id           = var.vpc_id
  protocol         = "tcp"
  ingress_template = local.ingress-vpn
  tags = merge(
    var.common_tags,
    {
      "Name" = format("%v-sg-vpn", var.name_prefix)
    },
  )
}

# Create security group for db access
module "sg-mysql" {
  source           = "../../../modules/vpc/sg"
  sg_description   = "Allows connections to mysql db"
  vpc_id           = var.vpc_id
  protocol         = "tcp"
  ingress_template = local.ingress-mysql
  tags = merge(
    var.common_tags,
    {
      "Name" = format("%v-sg-mysql", var.name_prefix)
    },
  )
}

# Create security group for influxdb access
module "sg-influxdb" {
  source           = "../../../modules/vpc/sg"
  sg_description   = "Allows connections to mysql db"
  vpc_id           = var.vpc_id
  protocol         = "tcp"
  ingress_template = local.ingress-influxdb
  tags = merge(
    var.common_tags,
    {
      "Name" = format("%v-sg-influxdb", var.name_prefix)
    },
  )
}
# Create security group for grafana access
module "sg-grafana" {
  source           = "../../../modules/vpc/sg"
  sg_description   = "Allows connections to mysql db"
  vpc_id           = var.vpc_id
  protocol         = "tcp"
  ingress_template = local.ingress-grafana
  tags = merge(
    var.common_tags,
    {
      "Name" = format("%v-sg-grafana", var.name_prefix)
    },
  )
}

# Squid
module "sg-squid" {
  source           = "../../../modules/vpc/sg"
  sg_description   = "Allows connections to Squid http/https proxy"
  vpc_id           = var.vpc_id
  protocol         = "tcp"
  ingress_template = local.ingress-squid
  tags = merge(
    var.common_tags,
    {
      "Name" = format("%v-sg-squid", var.name_prefix)
    },
  )
}

# Nexus3
module "sg-nexus" {
  source           = "../../../modules/vpc/sg"
  sg_description   = "Allows connections to Nexus"
  vpc_id           = var.vpc_id
  protocol         = "tcp"
  ingress_template = local.ingress-nexus
  tags = merge(
    var.common_tags,
    {
      "Name" = format("%v-sg-nexus", var.name_prefix)
    },
  )
}

module "sg-lambda" {
  source = "../../../modules/vpc/sg"

  sg_description   = "Allow AWS Lambda outgoing connections"
  vpc_id           = var.vpc_id
  protocol         = "tcp"
  ingress_template = local.ingress-lambda

  tags = merge(
    var.common_tags,
    {
      "Name" = format("%v-sg-lambda", var.name_prefix)
    },
  )
}

# Create security group for load balancers
resource "aws_security_group" "public_alb" {
  description = "Allow HTTP/HTTPS access from anywhere."
  vpc_id      = var.vpc_id

  ingress {
    from_port   = 80
    protocol    = "tcp"
    to_port     = 80
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 443
    protocol    = "tcp"
    to_port     = 443
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    description = "Allow all outbound traffic."
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = merge(
    var.common_tags,
    {
      "Name"           = format("%v-sg_public_web", var.name_prefix),
      "eiso-exception" = "aws.08.30",
    },
  )
}

resource "aws_security_group" "remote_management_ssh_access" {
  name        = "${var.name_prefix}-sg-remote-access-ssh"
  description = "Allow SSH connections from specified addresses"
  vpc_id      = var.vpc_id

  # SSH
  dynamic "ingress" {
    for_each = local.access_list
    content {
      description = ingress.value["description"]
      from_port   = 22
      to_port     = 22
      protocol    = "tcp"
      cidr_blocks = [ingress.value["cidr"]]
    }
  }

  ingress {
    description     = "Access from transit gateway"
    from_port       = 22
    to_port         = 22
    protocol        = "tcp"
    prefix_list_ids = var.managed_prefix_list_ids
  }

  egress {
    description = "Allow all outbound traffic."
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = merge(
    var.common_tags,
    {
      "Name"           = format("%v-sg-remote-access-ssh", var.name_prefix),
      "eiso-exception" = "aws.08.30",
    },
  )

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_security_group" "vpn_ssh" {
  description = "Allow SSH connections from whitelisted addresses to vpn server"
  vpc_id      = var.vpc_id
  # SSH
  dynamic "ingress" {
    for_each = local.whitelisted_cidrs
    content {
      description = ingress.value["description"]
      from_port   = 22
      to_port     = 22
      protocol    = "tcp"
      cidr_blocks = [ingress.value["cidr"]]
    }
  }

  ingress {
    description     = "Access from transit gateway"
    from_port       = 22
    to_port         = 22
    protocol        = "tcp"
    prefix_list_ids = var.managed_prefix_list_ids
  }

  egress {
    description = "Allow all outbound traffic."
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = merge(
    var.common_tags,
    {
      Name             = "${var.name_prefix}-sg-vpn-ssh",
      "eiso-exception" = "aws.08.30",
    },
  )
}

resource "aws_security_group" "db_debug_access" {
  description = "Allow connections custom db ports from specified addresses"
  vpc_id      = var.vpc_id

  # DB
  dynamic "ingress" {
    for_each = local.vpn_cidrs
    content {
      description = ingress.value["description"]
      from_port   = 3306
      to_port     = 3306
      protocol    = "tcp"
      cidr_blocks = [ingress.value["cidr"]]
    }
  }

  ingress {
    description     = "Access from transit gateway"
    from_port       = 3306
    to_port         = 3306
    protocol        = "tcp"
    prefix_list_ids = var.managed_prefix_list_ids
  }

  egress {
    description = "Allow all outbound traffic."
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = merge(
    var.common_tags,
    {
      "Name"           = format("%v-sg-db-debug", var.name_prefix),
      "eiso-exception" = "aws.08.30",
    },
  )
}

resource "aws_security_group" "vpn_access" {
  description = "Allow connections to VPN server"
  vpc_id      = var.vpc_id

  # OpenVPN UDP
  ingress {
    description = "Allow OpenVPN UDP inbound traffic."
    from_port   = 1194
    to_port     = 1194
    protocol    = "udp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  # web-ui
  dynamic "ingress" {
    for_each = concat(var.external_https_access, local.whitelisted_cidrs)
    content {
      description = ingress.value["description"]
      from_port   = 443
      to_port     = 443
      protocol    = "tcp"
      cidr_blocks = [ingress.value["cidr"]]
    }
  }

  /*
  # default web-ui
  dynamic "ingress" {
    for_each = local.whitelisted_cidrs
    content {
      description = ingress.value["description"]
      from_port   = 943
      to_port     = 943
      protocol    = "tcp"
      cidr_blocks = [ingress.value["cidr"]]
    }
  }
  */

  egress {
    description = "Allow all outbound traffic."
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = merge(
    var.common_tags,
    {
      "Name"           = format("%v-sg-vpn-access", var.name_prefix),
      "eiso-exception" = "aws.08.30",
    },
  )
}

resource "aws_security_group" "ext_web_sg" {
  description = "HTTPS access for list of external ip addresses"
  vpc_id      = var.vpc_id

  # https 443
  dynamic "ingress" {
    # In case VPN is enabled, add whitelisted IP addresses to the SG
    for_each = concat(var.external_https_access, local.whitelisted_cidrs)
    content {
      description = ingress.value["description"]
      from_port   = 443
      to_port     = 443
      protocol    = "tcp"
      cidr_blocks = [ingress.value["cidr"]]
    }
  }

  ingress {
    description     = "Access from transit gateway"
    from_port       = 443
    to_port         = 443
    protocol        = "tcp"
    prefix_list_ids = var.managed_prefix_list_ids
  }

  tags = merge(
    var.common_tags,
    {
      Name             = "${var.name_prefix}-sg-external-web",
      "eiso-exception" = "aws.08.30",
    },
  )
}

resource "aws_security_group" "ext_web_http_sg" {
  description = "HTTP access for list of external ip addresses"
  vpc_id      = var.vpc_id

  # http 80
  dynamic "ingress" {
    # In case VPN is enabled, add whitelisted IP addresses to the SG
    for_each = concat(var.external_https_access, local.whitelisted_cidrs)
    content {
      description = ingress.value["description"]
      from_port   = 80
      to_port     = 80
      protocol    = "tcp"
      cidr_blocks = [ingress.value["cidr"]]
    }
  }

  ingress {
    description     = "Access from transit gateway"
    from_port       = 80
    to_port         = 80
    protocol        = "tcp"
    prefix_list_ids = var.managed_prefix_list_ids
  }

  tags = merge(
    var.common_tags,
    {
      Name             = "${var.name_prefix}-sg-external-web-http",
      "eiso-exception" = "aws.08.30",
    },
  )
}

resource "aws_security_group" "internal_web_sg" {
  description = "HTTPS access for list of internal ip addresses"
  vpc_id      = var.vpc_id

  # https 443
  dynamic "ingress" {
    # In case VPN is enabled, add whitelisted IP addresses to the SG
    for_each = concat(var.internal_https_access, local.vpn_cidrs)
    content {
      description = ingress.value["description"]
      from_port   = 443
      to_port     = 443
      protocol    = "tcp"
      cidr_blocks = [ingress.value["cidr"]]
    }
  }

  ingress {
    description     = "Access from transit gateway"
    from_port       = 443
    to_port         = 443
    protocol        = "tcp"
    prefix_list_ids = var.managed_prefix_list_ids
  }

  tags = merge(
    var.common_tags,
    {
      Name             = "${var.name_prefix}-sg-internal-web",
      "eiso-exception" = "aws.08.30",
    },
  )
}

resource "aws_security_group" "internal_web_http_sg" {
  description = "HTTP access for list of internal ip addresses"
  vpc_id      = var.vpc_id

  # http 80
  dynamic "ingress" {
    # In case VPN is enabled, add whitelisted IP addresses to the SG
    for_each = concat(var.internal_https_access, local.vpn_cidrs)
    content {
      description = ingress.value["description"]
      from_port   = 80
      to_port     = 80
      protocol    = "tcp"
      cidr_blocks = [ingress.value["cidr"]]
    }
  }

  ingress {
    description     = "Access from transit gateway"
    from_port       = 80
    to_port         = 80
    protocol        = "tcp"
    prefix_list_ids = var.managed_prefix_list_ids
  }

  tags = merge(
    var.common_tags,
    {
      Name             = "${var.name_prefix}-sg-internal-web-http",
      "eiso-exception" = "aws.08.30",
    },
  )
}


resource "aws_security_group" "github_access" {
  //Creates dynamic list of security groups based on how many addresses has been provided in the list.
  //Due to the limitation of max rules per security group
  count       = ceil((length(var.github_ip_addr)) / var.max_sg_rules)
  description = "Connections from github ${count.index}"
  vpc_id      = var.vpc_id
  # https 443
  dynamic "ingress" {
    for_each = slice(
      var.github_ip_addr,
      var.max_sg_rules * count.index,
      length(var.github_ip_addr) > var.max_sg_rules * (count.index + 1) ? var.max_sg_rules * (count.index + 1) : length(var.github_ip_addr)
    )
    content {
      description = ingress.value["description"]
      from_port   = 443
      to_port     = 443
      protocol    = "tcp"
      cidr_blocks = [ingress.value["cidr"]]
    }
  }

  tags = merge(
    var.common_tags,
    {
      "Name"           = "${var.name_prefix}-sg-github",
      "eiso-exception" = "aws.08.30",
    },
  )
}

resource "aws_security_group" "sentry_access_from_nat" {
  description = "HTTPS access for list of external ip addresses"
  vpc_id      = var.vpc_id

  # https 443
  dynamic "ingress" {
    # In case VPN is enabled, add whitelisted IP addresses to the SG
    for_each = concat(var.nat_gateways)
    content {
      description = ingress.value["description"]
      from_port   = 443
      to_port     = 443
      protocol    = "tcp"
      cidr_blocks = [ingress.value["cidr"]]
    }
  }

  tags = merge(
    var.common_tags,
    {
      Name             = "${var.name_prefix}-sg-sentry-nat-web",
      "eiso-exception" = "aws.08.30",
    },
  )
}

resource "aws_security_group" "sentry_access_from_public_ip" {
  description = "HTTPS access for list of external ip addresses"
  vpc_id      = var.vpc_id

  # https 443
  dynamic "ingress" {
    # In case VPN is enabled, add whitelisted IP addresses to the SG
    for_each = concat(var.sentry_access)
    content {
      description = ingress.value["description"]
      from_port   = 443
      to_port     = 443
      protocol    = "tcp"
      cidr_blocks = [ingress.value["cidr"]]
    }
  }

  tags = merge(
    var.common_tags,
    {
      Name             = "${var.name_prefix}-sg-sentry-external-web",
      "eiso-exception" = "aws.08.30",
    },
  )
}
