locals {
  proxy_suffix = "ext"
}

resource "aws_security_group" "proxy" {
  name        = "${var.environment}-${var.service_name}-${local.proxy_suffix}-lb"
  description = "Load balancer security group for ${var.environment}-${var.service_name}-${local.proxy_suffix}"
  vpc_id      = module.vpc_info.vpc_id
  ingress {
    description = "Allow inbound traffic from proxy IPs"
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = var.allowed_cidrs
  }

  egress {
    from_port       = var.container_port
    to_port         = var.container_port
    protocol        = "tcp"
    security_groups = [module.service_fargate_environment.fargate_security_group_id]
  }

  tags = {
    eiso-exception = "aws.08.30"
  }

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_security_group" "proxy_auth0" {
  name        = "${var.environment}-${var.service_name}-${local.proxy_suffix}-lb-auth0"
  description = "Load balancer auth0 security group for ${var.environment}-${var.service_name}-${local.proxy_suffix}"
  vpc_id      = module.vpc_info.vpc_id
  ingress {
    description = "Allow inbound traffic from proxy IPs"
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = var.auth0_cidrs
  }

  egress {
    from_port       = var.container_port
    to_port         = var.container_port
    protocol        = "tcp"
    security_groups = [module.service_fargate_environment.fargate_security_group_id]
  }

  tags = {
    eiso-exception = "aws.08.30"
  }

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_lb" "proxy" {
  # checkov:skip=CKV2_AWS_20:We do not use HTTP to HTTPS redirect
  name                       = "${var.environment}-${var.service_name}-${local.proxy_suffix}"
  internal                   = false
  load_balancer_type         = "application"
  idle_timeout               = "90"
  security_groups            = [aws_security_group.proxy.id, aws_security_group.proxy_auth0.id]
  subnets                    = module.vpc_info.default_public_subnet_ids
  enable_deletion_protection = true

  access_logs {
    bucket  = data.aws_s3_bucket.logs.id
    prefix  = "${var.environment}-${var.service_name}-proxy-lb"
    enabled = true
  }
}

resource "aws_lb_listener" "proxy_https_listener" {
  load_balancer_arn = aws_lb.proxy.arn
  port              = "443"
  protocol          = "HTTPS"
  ssl_policy        = "ELBSecurityPolicy-TLS13-1-2-2021-06"
  certificate_arn   = data.aws_acm_certificate.theorchard_io.arn

  default_action {
    type = "fixed-response"

    fixed_response {
      content_type = "text/plain"
      message_body = "Forbidden"
      status_code  = "403"
    }
  }

  depends_on = [aws_lb_target_group.proxy]
}

resource "aws_lb_target_group" "proxy" {
  name                 = "${var.environment}-${var.service_name}-${local.proxy_suffix}"
  port                 = var.container_port
  protocol             = "HTTP"
  target_type          = "ip"
  deregistration_delay = "60"
  vpc_id               = module.vpc_info.vpc_id

  # Values copied from terraform-fargate module to match main service settings
  health_check {
    enabled             = true
    healthy_threshold   = "3"
    interval            = "10"
    matcher             = "200"
    path                = "/hello/"
    port                = var.container_port
    protocol            = "HTTP"
    timeout             = "5"
    unhealthy_threshold = "3"
  }

  stickiness {
    type            = "lb_cookie"
    cookie_duration = "86400"
    enabled         = false
  }
  depends_on = [aws_lb.proxy]
}

resource "aws_lb_listener_rule" "proxy_rule" {
  listener_arn = aws_lb_listener.proxy_https_listener.arn
  priority     = 100

  action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.proxy.arn
  }

  condition {
    host_header {
      values = ["${var.environment}-${var.service_name}-${local.proxy_suffix}.${data.aws_route53_zone.theorchard_io.name}"]
    }
  }
}

resource "aws_security_group_rule" "allow_inbound_from_proxy" {
  type                     = "ingress"
  from_port                = var.container_port
  to_port                  = var.container_port
  protocol                 = "TCP"
  source_security_group_id = aws_security_group.proxy.id
  security_group_id        = module.service_fargate_environment.fargate_security_group_id
}

resource "aws_wafv2_web_acl_association" "waf_association" {
  resource_arn = aws_lb.proxy.arn
  web_acl_arn  = coalesce(module.custom_waf.waf_blocking_arn_output, data.aws_wafv2_web_acl.public_shared_waf.arn)
}

resource "aws_route53_record" "proxy" {
  zone_id = data.aws_route53_zone.theorchard_io.id
  name    = "${var.environment}-${var.service_name}-${local.proxy_suffix}"
  type    = "A"

  alias {
    name                   = aws_lb.proxy.dns_name
    zone_id                = aws_lb.proxy.zone_id
    evaluate_target_health = true
  }
}

resource "aws_route53_record" "proxy_networking" {
  provider = aws.networking

  zone_id = data.aws_route53_zone.theorchard_io_networking.id
  name    = "${var.environment}-${var.service_name}-${local.proxy_suffix}"
  type    = "A"

  alias {
    name                   = aws_lb.proxy.dns_name
    zone_id                = aws_lb.proxy.zone_id
    evaluate_target_health = true
  }
}
