bridgecrewio / checkov

Prevent cloud misconfigurations and find vulnerabilities during build-time in infrastructure as code, container images and open source packages with Checkov by Bridgecrew.
https://www.checkov.io/
Apache License 2.0
7.15k stars 1.12k forks source link

CKV_AWS_378 is triggering for SSL offloading of ECS services #6754

Open Shanjohn opened 1 month ago

Shanjohn commented 1 month ago

Describe the issue CKV_AWS_378 triggers on configurations which have HTTP targets. But in a lot of cases SSL is offloaded on the load balancer level, and further targets use HTTP protocol to interact. For example, if you use a certificate from AWS ACM, ALB and AWS ECS Fargate service (which in my case is the majority of all services), the usual approach is to set up the certificate on HTTPS listener and offload it for the fargate service itself. CKV_AWS_378 stand for Ensure AWS Load Balancer doesn’t use HTTP protocol and seems like this is a demand for the listeners. This check seems more like Prohibit SSL offloading in target groups. I want to verify that this is an expected behavior, because I suspect majority of the users will have to ignore this check as a result. cc @tsmithv11

Examples

resource "aws_lb_target_group" "fargate_target_group" {
  name                 = "example-target-group-name"
  port                 = "8080"
  protocol             = "HTTP"
  target_type          = "ip"
  deregistration_delay = "60"
  vpc_id               = "some-vpc-id

  health_check { ... }
}

Version (please complete the following information):

Additional context

tsmithv11 commented 1 week ago

Hey @Shanjohn thanks for reporting. I believe you're correct, but can you share a more full example? In your case, does it look like this:

resource "aws_lb_target_group" "fargate_target_group" {
  name                 = "example-target-group-name"
  port                 = "8080"
  protocol             = "HTTP"
  target_type          = "ip"
  deregistration_delay = "60"
  vpc_id               = "some-vpc-id

  health_check { ... }
}

resource "aws_lb_listener" "https_listener" {
  load_balancer_arn = aws_lb.example.arn
  port              = 443
  protocol          = "HTTPS"
  ssl_policy        = "ELBSecurityPolicy-2016-08"
  certificate_arn   = aws_acm_certificate.example.arn

  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.fargate_target_group.arn
  }
}

Where we could fix the check to also look for a a listener that has HTTPS or can you share more?

Shanjohn commented 1 week ago

Hi @tsmithv11 , yes, the code looks like this:

resource "aws_lb" "public_application_load_balancer" {
  name               = "${var.environment}-${var.service_name}-public-lb"
  internal           = false
  load_balancer_type = "application"
  idle_timeout       = "90"
  security_groups    = [aws_security_group.public_load_balancer_security_group.id]  
  subnets                    = values(local.subnet_ids)
  enable_deletion_protection = true

  access_logs {
    bucket  = var.load_balancer_access_logs_s3_bucket_name
    prefix  = "${var.environment}-${var.service_name}-public-lb"
    enabled = true
  }

  tags = {
    environment        = var.environment
    service_name       = var.service_name
    application_family = var.application_family
    terraformed        = true
  }
}

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

  default_action {
    target_group_arn = aws_lb_target_group.public_fargate_target_group.arn
    type             = "forward"
  }

  depends_on = [aws_lb_target_group.public_fargate_target_group]

  tags = {
    environment        = var.environment
    service_name       = var.service_name
    application_family = var.application_family
    terraformed        = true
  }
}

resource "aws_lb_target_group" "public_fargate_target_group" {
  name                 = "${var.environment}-${var.service_name}-public"
  port                 = "8080"
  protocol             = "HTTP"
  target_type          = "ip"
  deregistration_delay = "60"
  vpc_id               = data.aws_vpc.vpc.id

  health_check {
    enabled             = true
    healthy_threshold   = "3"
    interval            = "10"
    matcher             = "200"
    path                = "/hello/"
    port                = "8080"
    protocol            = "HTTP"
    timeout             = "5"
    unhealthy_threshold = "3"
  }

  stickiness {
    type            = "lb_cookie"
    cookie_duration = "86400"
    enabled         = false
  }

  tags = {
    environment        = var.environment
    service_name       = var.service_name
    application_family = var.application_family
    terraformed        = true
  }

  depends_on = [aws_lb.public_application_load_balancer]
}

So there is an HTTPS listener and forwarding requests to the IP Target group is the default action for it.