locals {
  ingress-ecs = [
    { from_port = 80, to_port = 80, source_sg_id = module.sg-ecs.sg_id, description = "Allow inbound http from ECS" },
    { from_port = 80, to_port = 80, source_sg_id = module.sg-alb.sg_id, description = "Allow inbound http from ECS" },
    { from_port = 8000, to_port = 8002, source_sg_id = module.sg-alb.sg_id, description = "Allow inbound http from ALB" },
    { from_port = 8000, to_port = 8000, source_sg_id = module.sg-ecs.sg_id, description = "Allow inbound http from ECS" }
  ]
  ingress-alb = [
    { 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 containers" },
    { from_port = 80, to_port = 80, source_sg_id = module.sg-batch.sg_id, description = "Allow inbound connections from Batch" },
    { from_port = 80, to_port = 80, source_sg_id = module.sg-lambda.sg_id, description = "Allow inbound connections from Lambda" },
    { from_port = 443, to_port = 443, source_sg_id = module.sg-alb.sg_id, description = "Allow inbound https from ALBs" },
    { from_port = 443, to_port = 443, source_sg_id = module.sg-ecs.sg_id, description = "Allow inbound https from ECS containers" },
    { from_port = 443, to_port = 443, source_sg_id = module.sg-batch.sg_id, description = "Allow inbound connections from Batch" },
    { from_port = 443, to_port = 443, source_sg_id = module.sg-lambda.sg_id, description = "Allow inbound connections from Lambda" },
  ]
  ingress-aurora = [
    { from_port = 5432, to_port = 5432, source_sg_id = module.sg-aurora.sg_id, description = "Allow inbound connections to Aurora Postrgesql from EC2 with pgbouncer" },
    { from_port = 5432, to_port = 5432, source_sg_id = module.sg-ecs.sg_id, description = "Allow inbound connections to Aurora Postrgesql from ECS containers" },
    { from_port = 5432, to_port = 5432, source_sg_id = module.sg-lambda.sg_id, description = "Allow inbound connections to Aurora Postrgesql from Lambda functions inside VPC" },
    { from_port = 5432, to_port = 5432, source_sg_id = module.sg-batch.sg_id, description = "Allow inbound connections to Aurora Postrgesql from Batch compute environments" },
    { from_port = 5432, to_port = 5432, source_sg_id = module.sg-quicksight.sg_id, description = "Allow inbound connections to Aurora Postrgesql from Quicksight" },
  ]
  ingress-es = [
    { from_port = 443, to_port = 443, source_sg_id = module.sg-ecs.sg_id, description = "Allow inbound connections from ECS" },
    { from_port = 443, to_port = 443, source_sg_id = module.sg-lambda.sg_id, description = "Allow inbound connections from Lambda" },
    { from_port = 443, to_port = 443, source_sg_id = module.sg-batch.sg_id, description = "Allow inbound connections from Batch" },
  ]
  ingress-kinesis-endpoint = [
    { from_port = 443, to_port = 443, source_sg_id = module.sg-ecs.sg_id, description = "Allow inbound connections from ECS" },
    { from_port = 443, to_port = 443, source_sg_id = module.sg-lambda.sg_id, description = "Allow inbound connections from Lambda" },
    { from_port = 443, to_port = 443, source_sg_id = module.sg-batch.sg_id, description = "Allow inbound connections from Batch" },
  ]
  ingress-redis = [
    { from_port = 6379, to_port = 6379, source_sg_id = module.sg-ecs.sg_id, description = "Allow inbound connections from ECS" },
    { from_port = 6379, to_port = 6379, source_sg_id = module.sg-lambda.sg_id, description = "Allow inbound connections from Lambda" },
    { from_port = 6379, to_port = 6379, source_sg_id = module.sg-batch.sg_id, description = "Allow inbound connections from Batch" },
  ]
  ingress-lambda = []
  ingress-batch = [
    { from_port = 8126, to_port = 8126, source_sg_id = module.sg-batch.sg_id, description = "Allow inbound connections from Batch" },
  ]
  ingress-quicksight = [{ from_port = 0, to_port = 65535, source_sg_id = module.sg-aurora.sg_id, description = "Allow inbound connections from Aurora" }]
  ingress-mks = [
    { from_port = 9092, to_port = 9092, source_sg_id = module.sg-ecs.sg_id, description = "To communicate with brokers in plaintext, from ECS" },
    { from_port = 9094, to_port = 9094, source_sg_id = module.sg-ecs.sg_id, description = "To communicate with brokers by using TLS encryption, from ECS" },
    { from_port = 9096, to_port = 9096, source_sg_id = module.sg-ecs.sg_id, description = "To communicate with brokers by using SASL/SCRAM, from ECS" },
    { from_port = 9098, to_port = 9098, source_sg_id = module.sg-ecs.sg_id, description = "To communicate with brokers by using IAM access control, from ECS" },
    { from_port = 2181, to_port = 2182, source_sg_id = module.sg-ecs.sg_id, description = "To communicate with zookeeper, from ECS" },
    { from_port = 9092, to_port = 9092, source_sg_id = module.sg-lambda.sg_id, description = "To communicate with brokers in plaintext, from Lambda" },
    { from_port = 9094, to_port = 9094, source_sg_id = module.sg-lambda.sg_id, description = "To communicate with brokers by using TLS encryption, from Lambda" },
    { from_port = 9096, to_port = 9096, source_sg_id = module.sg-lambda.sg_id, description = "To communicate with brokers by using SASL/SCRAM, from Lambda" },
    { from_port = 9098, to_port = 9098, source_sg_id = module.sg-lambda.sg_id, description = "To communicate with brokers by using IAM access control, from Lambda" },
    { from_port = 2181, to_port = 2182, source_sg_id = module.sg-lambda.sg_id, description = "To communicate with zookeeper, from Lambda" },
    { from_port = 9092, to_port = 9092, source_sg_id = module.sg-batch.sg_id, description = "To communicate with brokers in plaintext, from Lambda" },
    { from_port = 9094, to_port = 9094, source_sg_id = module.sg-batch.sg_id, description = "To communicate with brokers by using TLS encryption, from Lambda" },
    { from_port = 9096, to_port = 9096, source_sg_id = module.sg-batch.sg_id, description = "To communicate with brokers by using SASL/SCRAM, from Lambda" },
    { from_port = 9098, to_port = 9098, source_sg_id = module.sg-batch.sg_id, description = "To communicate with brokers by using IAM access control, from Lambda" },
    { from_port = 2181, to_port = 2182, source_sg_id = module.sg-batch.sg_id, description = "To communicate with zookeeper, from Lambda" },
  ]
  ingress-zabbix = [
    { from_port = 80, to_port = 80, source_sg_id = module.sg-alb.sg_id, description = "Allow inbound http from ALBs" },
  ]

  vpn_cidrs             = [for cidr in var.vpn_masq_cidrs : { cidr = cidr, description = "Access for VPN users" }]
  internal_access_cidrs = concat(local.vpn_cidrs, var.internal_access_cidrs)
}

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

# Create security group for load balancers
module "sg-alb" {
  source           = "../../../modules/vpc/sg"
  sg_description   = "Allows HTTP 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)
    },
  )
}

# 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-lambda" {
  source           = "../../../modules/vpc/sg"
  sg_description   = "Allow inbound connections to Lambda functions inside VPC"
  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)
    },
  )
}

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

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

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

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

  sg_description   = "Allows access to Elastic Search"
  vpc_id           = var.vpc_id
  protocol         = "tcp"
  ingress_template = local.ingress-es

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

module "sg-kinesis-endpoint" {
  source = "../../../modules/vpc/sg"

  sg_description   = "Allows access to Kinesis Data streams"
  vpc_id           = var.vpc_id
  protocol         = "tcp"
  ingress_template = local.ingress-kinesis-endpoint

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

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

  sg_description   = "Allows access to Redis in Elasticache"
  vpc_id           = var.vpc_id
  protocol         = "tcp"
  ingress_template = local.ingress-redis
  name             = format("%v-sg-redis", var.name_prefix)

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

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

  sg_description   = "Allows access to Kafka"
  vpc_id           = var.vpc_id
  protocol         = "tcp"
  ingress_template = local.ingress-mks
  name             = format("%v-sg-kafka", var.name_prefix)

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

# Create security group for Zabbix
module "sg-zabbix" {
  count            = var.zabbix_enabled ? 1 : 0
  source           = "../../../modules/vpc/sg"
  sg_description   = "Allows HTTP connections to Zabbix"
  vpc_id           = var.vpc_id
  protocol         = "tcp"
  ingress_template = local.ingress-zabbix
  tags = merge(
    var.common_tags,
    {
      "Name" = format("%v-sg-zabbix", var.name_prefix)
    },
  )
}

resource "aws_security_group" "sg_sm_endpoint" {
  name        = "${var.name_prefix}-sg-sm-endpoint"
  description = "Allow connections via https to secrets manager endpoint"
  vpc_id      = var.vpc_id

  ingress {
    description = "Allow incoming https"
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = [data.aws_vpc.this.cidr_block]
  }

  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-sm-endpoint",
      "eiso-exception" = "aws.08.30",
    }
  )
}

resource "aws_security_group" "remote_management_access" {
  name_prefix = "${var.name_prefix}-sg-remote-access"
  description = "Allow connections via SSH"
  vpc_id      = var.vpc_id

  dynamic "ingress" {
    for_each = local.internal_access_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-remote-access",
      "eiso-exception" = "aws.08.30",
  })

  lifecycle {
    ignore_changes = [description, name_prefix]
  }
}

moved {
  from = aws_security_group.remote_management_access_rdp
  to   = aws_security_group.remote_management_access_rdp[0]
}

resource "aws_security_group" "remote_management_access_rdp" {
  count       = var.rdp_enabled ? 1 : 0
  name_prefix = "${var.name_prefix}-sg-remote-access-rdp"
  description = "Allow connections via RDP"
  vpc_id      = var.vpc_id

  dynamic "ingress" {
    for_each = local.internal_access_cidrs
    content {
      description = ingress.value["description"]
      from_port   = 3389
      to_port     = 3389
      protocol    = "tcp"
      cidr_blocks = [ingress.value["cidr"]]
    }
  }

  ingress {
    description     = "Access from transit gateway"
    from_port       = 3389
    to_port         = 3389
    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-remote-access-rdp",
      "eiso-exception" = "aws.08.30",
  })

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_security_group" "debug_access_http" {
  name_prefix = "${var.name_prefix}-sg-external-debug-http"
  description = "Allow HTTP connections from whitelisted addresses to external web resources"
  vpc_id      = var.vpc_id
  # http 80
  dynamic "ingress" {
    for_each = var.web_whitelist
    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
  }

  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-external-debug-http",
      "eiso-exception" = "aws.08.30",
  })

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_security_group" "debug_access_https" {
  name_prefix = "${var.name_prefix}-sg-external-debug-https"
  description = "Allow HTTPS connections from whitelisted addresses to external web resources"
  vpc_id      = var.vpc_id

  # https 443
  dynamic "ingress" {
    for_each = var.web_whitelist
    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
  }

  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-external-debug-https",
      "eiso-exception" = "aws.08.30",
  })

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_security_group" "internal_debug_access_http" {
  name_prefix = "${var.name_prefix}-sg-internal-debug-http"
  description = "Allow HTTP connections from vpn and peering addresses to internal web resources"
  vpc_id      = var.vpc_id
  # http 80
  dynamic "ingress" {
    for_each = local.internal_access_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
  }

  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-debug-http",
      "eiso-exception" = "aws.08.30",
  })

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_security_group" "internal_debug_access_https" {
  name_prefix = "${var.name_prefix}-sg-internal-debug-https"
  description = "Allow HTTPS connections from vpn and peering addresses to internal web resources"
  vpc_id      = var.vpc_id

  # https 443
  dynamic "ingress" {
    for_each = local.internal_access_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
  }

  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-internal-debug-https",
      "eiso-exception" = "aws.08.30",
  })

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_security_group" "db_debug_access" {
  name_prefix = "${var.name_prefix}-sg-dbdebug"
  description = "Allow connections to databases from specified addresses for debug purposes"
  vpc_id      = var.vpc_id
  # Postresql
  dynamic "ingress" {
    for_each = local.internal_access_cidrs
    content {
      description = ingress.value["description"]
      from_port   = 5432
      to_port     = 5432
      protocol    = "tcp"
      cidr_blocks = [ingress.value["cidr"]]
    }
  }

  ingress {
    description     = "Access from transit gateway"
    from_port       = 5432
    to_port         = 5432
    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-dbdebug",
      "eiso-exception" = "aws.08.30",
  })

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_security_group" "nat_web_sg" {
  name_prefix = "${var.name_prefix}-sg-nat-web"
  description = "HTTPS access for list of external NAT gateways"
  vpc_id      = var.vpc_id

  # https 443
  dynamic "ingress" {
    # In case VPN is enabled, add whitelisted IP addresses to the SG
    for_each = var.nat_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-nat-web",
      "eiso-exception" = "aws.08.30",
  })

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_security_group" "redis_debug_access" {
  description = "Allow connections to Redis from specified addresses for debug purposes"
  vpc_id      = var.vpc_id
  name_prefix = "${var.name_prefix}-sg-redis-debug"
  # Postresql
  dynamic "ingress" {
    for_each = local.internal_access_cidrs
    content {
      description = ingress.value["description"]
      from_port   = 6379
      to_port     = 6379
      protocol    = "tcp"
      cidr_blocks = [ingress.value["cidr"]]
    }
  }

  ingress {
    description     = "Access from transit gateway"
    from_port       = 6379
    to_port         = 6379
    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-redis-debug",
      "eiso-exception" = "aws.08.30",
  })

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_security_group" "kafka_debug_access" {
  description = "Allow connections to Kafka from specified addresses for debug purposes"
  vpc_id      = var.vpc_id
  name_prefix = "${var.name_prefix}-sg-kafka-debug"

  # To communicate with brokers in plaintext
  dynamic "ingress" {
    for_each = local.internal_access_cidrs
    content {
      description = ingress.value["description"]
      from_port   = 9092
      to_port     = 9096
      protocol    = "tcp"
      cidr_blocks = [ingress.value["cidr"]]
    }
  }

  # To communicate with Apache Zookeeper in plaintext
  dynamic "ingress" {
    for_each = local.internal_access_cidrs
    content {
      description = ingress.value["description"]
      from_port   = 2181
      to_port     = 2181
      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"           = "${var.name_prefix}-sg-kafka-debug",
      "eiso-exception" = "aws.08.30",
  })

  lifecycle {
    create_before_destroy = true
  }
}
