# =============================================================================
# Ingress — ported from basic/aws/cloudformation/ingress.yaml
#
# ACM certificates for the rs/ds domains (public ACM + DNS validation by
# default; account Private CA when var.use_pca = true) and WAFv2 IPSet/WebACL
# pairs. Office CIDR lists are copied verbatim from the CloudFormation template.
# =============================================================================

locals {
  # RsIpSet addresses in ingress.yaml
  rs_office_cidrs = [
    "104.196.246.224/32",
    "44.234.235.72/32",
    "120.92.20.16/32",
    "54.81.145.46/32",
    "117.50.66.239/32",
    "45.251.23.184/29",
    "39.170.92.156/32",
    "44.232.56.92/32",
    "18.207.70.160/32",
    "120.92.20.26/32",
    "106.75.116.22/32",
    "54.185.150.209/32",
    "125.238.198.74/32",
    "103.85.175.128/29",
    "106.75.54.70/32",
    "54.148.240.60/32",
    "54.144.61.155/32",
    "180.167.192.138/32",
    "119.28.181.184/32",
    "119.28.138.220/32",
    "54.87.103.202/32",
    "106.75.21.237/32",
    "54.160.183.243/32",
    "173.248.249.128/27",
    "120.92.20.132/32",
    "54.156.132.78/32",
    "120.92.55.116/32",
    "54.156.147.26/32",
    "35.233.250.206/32",
    "119.28.189.132/32",
    "118.113.15.98/32",
    "45.251.23.189/32",
    "128.1.49.85/32",
    "107.22.53.149/32",
    "128.1.49.135/32",
    "211.95.24.8/29",
    "119.136.31.176/32",
    "34.237.193.137/32",
    "117.50.84.111/32",
    "35.170.28.53/32",
    "52.13.110.238/32",
    "45.64.247.112/32",
    "45.64.247.96/32",
    "152.104.28.129/32",
    "54.71.2.116/32",
    "58.94.102.181/32",
    "120.92.100.187/32",
    "54.166.186.135/32",
    "1.203.96.0/29",
    "106.75.104.17/32",
    "211.95.24.10/32",
    "106.75.96.68/32",
    "20.63.218.57/32",
    "35.155.73.60/32",
    "152.32.135.177/32",
    "45.251.23.186/32",
    "34.196.134.104/32",
    "52.41.43.61/32",
    "118.194.230.143/32",
    "101.207.139.187/32",
    "40.74.68.232/32",
    "52.53.225.210/32",
    "117.134.13.184/29",
    "45.64.247.96/27",
    "34.193.173.209/32",
    "106.75.52.157/32",
    "118.194.230.2/32",
    "54.91.191.4/32",
    "120.92.122.221/32",
    "120.92.102.252/32",
    "106.75.97.89/32",
    "183.129.144.200/29",
    "203.90.236.192/27",
    "106.75.64.135/32",
    "183.6.107.178/32",
    "34.208.168.149/32",
    "203.90.236.205/32",
    "34.193.189.203/32",
    "128.1.48.244/32",
    "35.83.225.251/32",
    "35.85.207.121/32",
    "52.11.60.187/32",
    "128.1.40.139/32",
    "104.250.53.216/32",
    "120.92.20.69/32",
    "124.155.208.205/32",
    "104.250.53.237/32",
    "152.32.204.171/32",
    "63.70.5.80/32",
  ]

  # OfficeIpSet (ds) addresses in ingress.yaml
  ds_office_cidrs = [
    "104.196.246.224/32",
    "120.92.20.16/32",
    "117.50.66.239/32",
    "45.251.23.184/29",
    "106.75.116.22/32",
    "54.185.150.209/32",
    "54.203.54.239/32",
    "103.85.175.128/29",
    "3.71.167.176/32",
    "106.75.54.70/32",
    "54.148.240.60/32",
    "54.144.61.155/32",
    "180.167.192.138/32",
    "119.28.181.184/32",
    "44.231.162.131/32",
    "119.28.138.220/32",
    "106.75.21.237/32",
    "129.226.181.138/32",
    "222.212.99.41/32",
    "120.92.20.132/32",
    "120.92.55.116/32",
    "119.28.189.132/32",
    "45.251.23.189/32",
    "35.85.207.121/32",
    "128.1.49.85/32",
    "34.237.193.137/32",
    "54.250.172.151/32",
    "117.50.84.111/32",
    "13.56.192.33/32",
    "54.71.2.116/32",
    "106.75.104.17/32",
    "34.208.189.148/32",
    "106.75.96.68/32",
    "18.232.214.42/32",
    "152.32.135.177/32",
    "54.188.27.23/32",
    "118.194.230.143/32",
    "101.207.139.187/32",
    "104.250.50.40/32",
    "52.53.225.210/32",
    "117.134.13.184/29",
    "34.193.173.209/32",
    "106.75.52.157/32",
    "54.148.161.241/32",
    "120.92.102.252/32",
    "203.90.236.192/27",
    "106.75.64.135/32",
    "183.6.107.178/32",
    "34.208.168.149/32",
    "63.70.2.110/32",
    "44.234.235.72/32",
    "120.92.55.209/32",
    "39.170.92.156/32",
    "44.232.56.92/32",
    "120.92.20.26/32",
    "13.214.108.29/32",
    "125.238.198.74/32",
    "44.236.31.184/32",
    "100.20.198.224/32",
    "35.83.225.251/32",
    "54.87.103.202/32",
    "52.79.124.61/32",
    "34.209.53.107/32",
    "119.28.24.16/32",
    "173.248.249.128/27",
    "54.156.132.78/32",
    "35.233.250.206/32",
    "118.113.15.98/32",
    "128.1.49.135/32",
    "211.95.24.8/29",
    "119.136.31.176/32",
    "54.160.88.7/32",
    "52.13.110.238/32",
    "43.154.73.240/32",
    "45.64.247.112/32",
    "45.64.247.96/32",
    "152.104.28.129/32",
    "58.94.102.181/32",
    "120.92.100.187/32",
    "1.203.96.0/29",
    "104.250.50.243/32",
    "44.239.25.171/32",
    "211.95.24.10/32",
    "20.63.218.57/32",
    "35.155.73.60/32",
    "45.251.23.186/32",
    "34.196.134.104/32",
    "35.86.46.244/32",
    "52.11.60.187/32",
    "52.41.43.61/32",
    "120.92.72.28/32",
    "40.74.68.232/32",
    "18.204.147.39/32",
    "45.64.247.96/27",
    "118.194.230.2/32",
    "52.72.84.40/32",
    "52.38.19.119/32",
    "165.154.134.148/32",
    "43.155.60.35/32",
    "120.92.122.221/32",
    "106.75.97.89/32",
    "183.129.144.200/29",
    "203.90.236.205/32",
    "128.1.48.244/32",
    "183.129.144.202/32",
    "104.250.53.216/32",
    "120.92.20.69/32",
    "124.155.208.205/32",
    "104.250.53.237/32",
    "152.32.204.171/32",
    "63.70.5.80/32",
  ]
}

data "aws_route53_zone" "this" {
  name = local.hosted_zone_name
}

# =============================================================================
# ACM certificates (public, DNS validated) — used when use_pca = false
# =============================================================================

resource "aws_acm_certificate" "rs" {
  count = var.use_pca ? 0 : 1

  domain_name       = local.rs_domain_name
  validation_method = "DNS"

  tags = merge(local.common_tags, {
    Environment = var.env
  })
}

resource "aws_acm_certificate" "ds" {
  count = var.use_pca ? 0 : 1

  domain_name       = local.ds_domain_name
  validation_method = "DNS"

  tags = merge(local.common_tags, {
    Environment = var.env
  })
}

resource "aws_route53_record" "rs_cert_validation" {
  count = var.use_pca ? 0 : 1

  zone_id = data.aws_route53_zone.this.zone_id
  name    = tolist(aws_acm_certificate.rs[0].domain_validation_options)[0].resource_record_name
  type    = tolist(aws_acm_certificate.rs[0].domain_validation_options)[0].resource_record_type
  records = [tolist(aws_acm_certificate.rs[0].domain_validation_options)[0].resource_record_value]
  ttl     = 300
}

resource "aws_route53_record" "ds_cert_validation" {
  count = var.use_pca ? 0 : 1

  zone_id = data.aws_route53_zone.this.zone_id
  name    = tolist(aws_acm_certificate.ds[0].domain_validation_options)[0].resource_record_name
  type    = tolist(aws_acm_certificate.ds[0].domain_validation_options)[0].resource_record_type
  records = [tolist(aws_acm_certificate.ds[0].domain_validation_options)[0].resource_record_value]
  ttl     = 300
}

resource "aws_acm_certificate_validation" "rs" {
  count = var.use_pca ? 0 : 1

  certificate_arn         = aws_acm_certificate.rs[0].arn
  validation_record_fqdns = [aws_route53_record.rs_cert_validation[0].fqdn]
}

resource "aws_acm_certificate_validation" "ds" {
  count = var.use_pca ? 0 : 1

  certificate_arn         = aws_acm_certificate.ds[0].arn
  validation_record_fqdns = [aws_route53_record.ds_cert_validation[0].fqdn]
}

# =============================================================================
# ACM private certificates (PCA issued) — used when use_pca = true
# =============================================================================

resource "aws_acm_certificate" "rs_pca" {
  count = var.use_pca ? 1 : 0

  domain_name               = local.rs_domain_name
  certificate_authority_arn = local.pca_arn

  tags = merge(local.common_tags, {
    Environment = var.env
  })
}

resource "aws_acm_certificate" "ds_pca" {
  count = var.use_pca ? 1 : 0

  domain_name               = local.ds_domain_name
  certificate_authority_arn = local.pca_arn

  tags = merge(local.common_tags, {
    Environment = var.env
  })
}

locals {
  rs_certificate_arn = var.use_pca ? aws_acm_certificate.rs_pca[0].arn : aws_acm_certificate_validation.rs[0].certificate_arn
  ds_certificate_arn = var.use_pca ? aws_acm_certificate.ds_pca[0].arn : aws_acm_certificate_validation.ds[0].certificate_arn
}

# =============================================================================
# WAFv2 IP sets
# =============================================================================

resource "aws_wafv2_ip_set" "rs" {
  name               = "${local.cluster_name}-rs-office"
  description        = "Office IP set"
  scope              = "REGIONAL"
  ip_address_version = "IPV4"
  addresses          = local.rs_office_cidrs

  tags = local.common_tags
}

resource "aws_wafv2_ip_set" "ds" {
  name               = "${local.cluster_name}-ds-office"
  description        = "Office IP set"
  scope              = "REGIONAL"
  ip_address_version = "IPV4"
  addresses          = local.ds_office_cidrs

  tags = local.common_tags
}

# =============================================================================
# WAFv2 Web ACLs
# =============================================================================

resource "aws_wafv2_web_acl" "rs" {
  name        = "${local.cluster_name}-rs-api"
  description = "O11Y Regional Server API Web ACL."
  scope       = "REGIONAL"

  default_action {
    block {}
  }

  rule {
    name     = "regional-server-api"
    priority = 2

    action {
      allow {}
    }

    statement {
      and_statement {
        statement {
          byte_match_statement {
            positional_constraint = "STARTS_WITH"
            search_string         = "/"
            field_to_match {
              uri_path {}
            }
            text_transformation {
              priority = 0
              type     = "NONE"
            }
          }
        }
        statement {
          ip_set_reference_statement {
            arn = aws_wafv2_ip_set.rs.arn
          }
        }
      }
    }

    visibility_config {
      metric_name                = "o11y-regional-server-api"
      cloudwatch_metrics_enabled = true
      sampled_requests_enabled   = true
    }
  }

  visibility_config {
    metric_name                = "o11y-regional-server-api"
    cloudwatch_metrics_enabled = true
    sampled_requests_enabled   = true
  }

  tags = local.common_tags
}

resource "aws_wafv2_web_acl" "ds" {
  name        = "${local.cluster_name}-ds-api"
  description = "O11Y Web ACL."
  scope       = "REGIONAL"

  default_action {
    block {}
  }

  rule {
    name     = "external"
    priority = 0

    action {
      allow {}
    }

    statement {
      byte_match_statement {
        positional_constraint = "STARTS_WITH"
        search_string         = "/external/"
        field_to_match {
          uri_path {}
        }
        text_transformation {
          priority = 0
          type     = "NONE"
        }
      }
    }

    visibility_config {
      metric_name                = "o11y-prometheus-api-external"
      cloudwatch_metrics_enabled = true
      sampled_requests_enabled   = true
    }
  }

  rule {
    name     = "internal"
    priority = 5

    action {
      allow {}
    }

    statement {
      ip_set_reference_statement {
        arn = aws_wafv2_ip_set.ds.arn
      }
    }

    visibility_config {
      metric_name                = "o11y-api-internal"
      cloudwatch_metrics_enabled = true
      sampled_requests_enabled   = true
    }
  }

  visibility_config {
    metric_name                = "o11y-prometheus-api"
    cloudwatch_metrics_enabled = true
    sampled_requests_enabled   = true
  }

  tags = local.common_tags
}
