fleetdm / fleet

Open-source platform for IT, security, and infrastructure teams. (Linux, macOS, Chrome, Windows, cloud, data center)
https://fleetdm.com
Other
3.11k stars 427 forks source link

Feature Request: ALB Listener Default Rule #17675

Open misterjulien opened 7 months ago

misterjulien commented 7 months ago

Problem

Currently in FleetDM Terraform, the default/last ALB listener rule is to allow access to the target. I would like to request the ability to change the default/last rule to either "fixed-response" or "redirect".

For my use case, in the ALB I'm allowing all osquery agents to talk to specific API endpoints, then I'm allowing only specific VPN IPs to talk to any API endpoint, and finally for any path I'm giving a fixed-response HTTP code of 403. This last condition essentially acts as a "deny all".

Potential solutions

noahtalerman commented 7 months ago

Hey @misterjulien! Thanks for filing this feature request.

in the ALB I'm allowing all osquery agents to talk to specific API endpoints, then I'm allowing only specific VPN IPs to talk to any API endpoint, and finally for any path I'm giving a fixed-response HTTP code of 403.

If I'm understanding correctly, you're specifying these rules in the ALB console (for example, somewhere in AWS console) and you'd like to instead specify these in terraform.

Is that right?

What would the changes to the alb.tf look like? Please feel free to open a pull request!

misterjulien commented 7 months ago

I was able to put ALB rules in alb_config in the "fleet" module, so that they're in Terraform code.

To be able to modify the default ALB rule I'm not entirely sure how the TF code should change (my TF foo is limited).

noahtalerman commented 7 months ago

@misterjulien got it. Sorry for the delayed response.

modify the default ALB rule I'm not entirely sure how the TF code should change

@rfairburn do you know what the TF code change would look like to default/last rule to either "fixed-response" or "redirect"?

rfairburn commented 7 months ago

I can provide an example that we used with a fixed-response previously in cloud for the ALB config. While the module doesn't currently allow changing the default rule, we created a rule with a wildcard match. I will provide a code snippet below.

rfairburn commented 7 months ago

So to start with, we use a locals section that automatically splits the allowlist into a grouping of 5 allowed CIDRs per https_listener_rule since that is a limitation per rule. That looks like this:

locals {
  allowlist_cidrs = [
    "127.0.0.1/32",
    "127.0.0.2/32",
    "127.0.0.3/32",
    "127.0.0.4/32",
    "127.0.0.5/32",
  ]
  https_listener_rules = [for i in range(0, length(local.allowlist_cidrs), 5) : {
    https_listener_index = 0
    priority             = i / 5 + 3
    actions = [{
      type               = "forward"
      target_group_index = 0
    }]
    conditions = [{
      source_ips = slice(local.allowlist_cidrs, i, min(i + 5, length(local.allowlist_cidrs)))
    }]
  }]
}

Then for the alb_config section of the module configuration we do the following to always allow orbit/osquery but to disallow everything else with a fixed 403 response:

  alb_config = {
    https_listener_rules = concat([{
      https_listener_index = 0
      priority             = 9000
      actions = [{
        type         = "fixed-response"
        content_type = "text/html"
        status_code  = "403"
        message_body = "<h1><center>Forbidden</center></h1>"
      }]
      conditions = [{
        path_patterns = ["*"]
      }]
      }, {
      https_listener_index = 0
      priority             = 1
      actions = [{
        type               = "forward"
        target_group_index = 0
      }]
      conditions = [{
        path_patterns = [
          "/api/osquery/*",
          "/api/*/osquery/*",
          "/api/*/orbit/*",
        ]
      }]
      }, {
      https_listener_index = 0
      priority             = 2
      actions = [{
        type               = "forward"
        target_group_index = 0
      }]
      conditions = [{
        path_patterns = [
          "/api/*/fleet/device/*"
        ]
      }]
    }], local.https_listener_rules)
  }

Just replace the allow_list_cidrs local with the list of cidrs you want to allow and this should "do the thing". You can also include any other custom alb_config variables you wish to set such as idle timeouts or logging configurations, etc. The rest of the settings should remain unaffected by this.

rfairburn commented 7 months ago

@misterjulien let me know if that at least lets you work around the default rule not being able to change. The ultra-low priority rule with a wildcard match effectively achieves the same thing.

@noahtalerman we can likely implement overriding the default listener rule as part of the module, but we need to ensure that the defaults still operate as-is. The above example is what we do internally today to work around the lack of this feature in the module, but it should be possible to hand it via the default rule as well if we updated the module.

noahtalerman commented 7 months ago

Thanks @rfairburn!

we can likely implement overriding the default listener rule as part of the module

I think up to @lukeheath to prioritize since this is an infra request.

Luke, what labels should I add (if any) to make sure that you see this infra request?

rfairburn commented 7 months ago

Thanks @rfairburn!

we can likely implement overriding the default listener rule as part of the module

I think up to @lukeheath to prioritize since this is an infra request.

Certainly. I wanted to first and foremost ensure we had a work around provided in the mean time and also say that it would be possible if prioritized to implement the requested solution as well.

lukeheath commented 7 months ago

I'm adding the engineering-initiated label so this is triaged later.