mirror of
https://github.com/empayre/fleet.git
synced 2024-11-06 08:55:24 +00:00
vuln processing as distinct service (#16544)
create a distinct service to managed vulnerability processing
This commit is contained in:
parent
5629b271d0
commit
9ba0dafa94
@ -1,2 +1,10 @@
|
||||
# External Vulnerability Scans addon
|
||||
This addon moves vulnerability scans off of serving nodes and onto a scheduled task in AWS Eventbridge.
|
||||
This addon creates an additional ECS service that only runs a single task, responsible for vuln processing. It receives
|
||||
no web traffic. We utilize [current instance checks](https://fleetdm.com/docs/configuration/fleet-server-configuration#current-instance-checks) to make this happen. The advantages of this mechanism:
|
||||
|
||||
1. dedicating processing power to vuln processing
|
||||
2. ensures task responsible for vuln processing isn't also trying to serve web traffic
|
||||
2. caching of vulnerability artifacts/dependencies
|
||||
|
||||
|
||||
Usage is simplified by using the output from the fleet byo-ecs module (../terraform/byo-vpc/byo-db/byo-ecs/README.md)
|
||||
|
@ -1,5 +1,12 @@
|
||||
# External Vulnerability Scans addon
|
||||
This addon moves vulnerability scans off of serving nodes and onto a scheduled task in AWS Eventbridge.
|
||||
This addon creates an additional ECS service that only runs a single task, responsible for vuln processing. It receives
|
||||
no web traffic. We utilize [current instance checks](https://fleetdm.com/docs/configuration/fleet-server-configuration#current-instance-checks) to make this happen. The advantages of this mechanism:
|
||||
|
||||
1. dedicating processing power to vuln processing
|
||||
2. ensures task responsible for vuln processing isn't also trying to serve web traffic
|
||||
2. caching of vulnerability artifacts/dependencies
|
||||
|
||||
Usage is simplified by using the output from the fleet byo-ecs module (../terraform/byo-vpc/byo-db/byo-ecs/README.md)
|
||||
|
||||
## Requirements
|
||||
|
||||
@ -19,21 +26,24 @@ No modules.
|
||||
|
||||
| Name | Type |
|
||||
|------|------|
|
||||
| [aws_cloudwatch_event_rule.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_rule) | resource |
|
||||
| [aws_cloudwatch_event_target.ecs_scheduled_task](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_target) | resource |
|
||||
| [aws_iam_role.ecs_events](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
|
||||
| [aws_iam_role_policy.ecs_events_run_task_with_any_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource |
|
||||
| [aws_iam_policy_document.assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
|
||||
| [aws_iam_policy_document.ecs_events_run_task_with_any_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
|
||||
| [aws_ecs_service.fleet](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_service) | resource |
|
||||
| [aws_ecs_task_definition.vuln-processing](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_task_definition) | resource |
|
||||
| [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source |
|
||||
|
||||
## Inputs
|
||||
|
||||
| Name | Description | Type | Default | Required |
|
||||
|------|-------------|------|---------|:--------:|
|
||||
| <a name="input_awslogs_config"></a> [awslogs\_config](#input\_awslogs\_config) | n/a | <pre>object({<br> group = string<br> region = string<br> prefix = string<br> })</pre> | n/a | yes |
|
||||
| <a name="input_customer_prefix"></a> [customer\_prefix](#input\_customer\_prefix) | n/a | `string` | `"fleet"` | no |
|
||||
| <a name="input_ecs_cluster"></a> [ecs\_cluster](#input\_ecs\_cluster) | The ecs cluster module that is created by the byo-db module | `any` | n/a | yes |
|
||||
| <a name="input_ecs_service"></a> [ecs\_service](#input\_ecs\_service) | The ecs service resource that is created by the byo-ecs module | `any` | n/a | yes |
|
||||
| <a name="input_task_definition"></a> [task\_definition](#input\_task\_definition) | The task definition resource that is created by the byo-ecs module | `any` | n/a | yes |
|
||||
| <a name="input_execution_iam_role_arn"></a> [execution\_iam\_role\_arn](#input\_execution\_iam\_role\_arn) | The ARN of the fleet execution role, this is necessary to pass role from ecs events | `any` | n/a | yes |
|
||||
| <a name="input_fleet_config"></a> [fleet\_config](#input\_fleet\_config) | The root Fleet config object | `any` | n/a | yes |
|
||||
| <a name="input_security_groups"></a> [security\_groups](#input\_security\_groups) | n/a | `list(string)` | n/a | yes |
|
||||
| <a name="input_subnets"></a> [subnets](#input\_subnets) | n/a | `list(string)` | n/a | yes |
|
||||
| <a name="input_task_role_arn"></a> [task\_role\_arn](#input\_task\_role\_arn) | The ARN of the fleet task role, this is necessary to pass role from ecs events | `any` | n/a | yes |
|
||||
| <a name="input_vuln_processing_cpu"></a> [vuln\_processing\_cpu](#input\_vuln\_processing\_cpu) | The amount of CPU to dedicate to the vuln processing command | `number` | `1024` | no |
|
||||
| <a name="input_vuln_processing_memory"></a> [vuln\_processing\_memory](#input\_vuln\_processing\_memory) | The amount of memory to dedicate to the vuln processing command | `number` | `4096` | no |
|
||||
|
||||
## Outputs
|
||||
|
||||
|
@ -1,82 +1,109 @@
|
||||
data "aws_region" "current" {}
|
||||
|
||||
resource "aws_cloudwatch_event_rule" "main" {
|
||||
schedule_expression = "rate(1 hour)"
|
||||
locals {
|
||||
environment = [
|
||||
// specifically overriding disable schedule here because the output of this module sets this to true
|
||||
// and then we pull in the output of fleet ecs module
|
||||
for k, v in merge(
|
||||
var.fleet_config.extra_environment_variables,
|
||||
{ FLEET_VULNERABILITIES_DISABLE_SCHEDULE = "false"}
|
||||
) : {
|
||||
name = k
|
||||
value = v
|
||||
}
|
||||
]
|
||||
secrets = [
|
||||
for k, v in var.fleet_config.extra_secrets : {
|
||||
name = k
|
||||
valueFrom = v
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
data "aws_iam_policy_document" "assume_role" {
|
||||
statement {
|
||||
effect = "Allow"
|
||||
|
||||
principals {
|
||||
type = "Service"
|
||||
identifiers = ["events.amazonaws.com", "ecs-tasks.amazonaws.com"]
|
||||
}
|
||||
|
||||
actions = ["sts:AssumeRole"]
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_iam_role" "ecs_events" {
|
||||
assume_role_policy = data.aws_iam_policy_document.assume_role.json
|
||||
}
|
||||
|
||||
data "aws_iam_policy_document" "ecs_events_run_task_with_any_role" {
|
||||
statement {
|
||||
effect = "Allow"
|
||||
actions = ["iam:PassRole"]
|
||||
resources = ["*"]
|
||||
}
|
||||
|
||||
statement {
|
||||
effect = "Allow"
|
||||
actions = ["ecs:RunTask"]
|
||||
resources = [replace(var.task_definition.arn, "/:\\d+$/", ":*")]
|
||||
condition {
|
||||
test = "ArnEquals"
|
||||
values = [var.ecs_cluster.cluster_arn]
|
||||
variable = "ecs:cluster"
|
||||
}
|
||||
}
|
||||
}
|
||||
resource "aws_iam_role_policy" "ecs_events_run_task_with_any_role" {
|
||||
role = aws_iam_role.ecs_events.id
|
||||
policy = data.aws_iam_policy_document.ecs_events_run_task_with_any_role.json
|
||||
}
|
||||
|
||||
resource "aws_cloudwatch_event_target" "ecs_scheduled_task" {
|
||||
arn = var.ecs_cluster.cluster_arn
|
||||
rule = aws_cloudwatch_event_rule.main.name
|
||||
role_arn = aws_iam_role.ecs_events.arn
|
||||
|
||||
ecs_target {
|
||||
task_count = 1
|
||||
task_definition_arn = var.task_definition.arn
|
||||
resource "aws_ecs_service" "fleet" {
|
||||
name = "${var.fleet_config.service.name}-vuln-processing"
|
||||
launch_type = "FARGATE"
|
||||
network_configuration {
|
||||
subnets = var.ecs_service.network_configuration[0].subnets
|
||||
security_groups = var.ecs_service.network_configuration[0].security_groups
|
||||
}
|
||||
cluster = var.ecs_cluster
|
||||
task_definition = aws_ecs_task_definition.vuln-processing.arn
|
||||
desired_count = 1
|
||||
deployment_minimum_healthy_percent = 100
|
||||
deployment_maximum_percent = 200
|
||||
|
||||
lifecycle {
|
||||
ignore_changes = [desired_count]
|
||||
}
|
||||
|
||||
input = jsonencode({
|
||||
containerOverrides = [
|
||||
{
|
||||
name = "fleet",
|
||||
command = ["fleet", "vuln_processing"]
|
||||
},
|
||||
{
|
||||
resourceRequirements = [
|
||||
{
|
||||
type = "VCPU",
|
||||
value = "1"
|
||||
},
|
||||
{
|
||||
type = "MEMORY",
|
||||
value = "4096"
|
||||
network_configuration {
|
||||
subnets = var.subnets
|
||||
security_groups = var.security_groups
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
|
||||
resource "aws_ecs_task_definition" "vuln-processing" {
|
||||
family = "${var.fleet_config.family}-vuln-processing"
|
||||
cpu = var.vuln_processing_cpu
|
||||
memory = var.vuln_processing_memory
|
||||
execution_role_arn = var.execution_iam_role_arn
|
||||
task_role_arn = var.task_role_arn
|
||||
network_mode = "awsvpc"
|
||||
requires_compatibilities = ["FARGATE"]
|
||||
|
||||
container_definitions = jsonencode(concat([
|
||||
{
|
||||
name = "fleet-vuln-processing"
|
||||
image = var.fleet_config.image
|
||||
essential = true
|
||||
networkMode = "awsvpc"
|
||||
secrets = [
|
||||
{
|
||||
name = "FLEET_MYSQL_PASSWORD"
|
||||
valueFrom = var.fleet_config.database.password_secret_arn
|
||||
}
|
||||
]
|
||||
ulimits = [
|
||||
{
|
||||
name = "nofile"
|
||||
softLimit = 999999
|
||||
hardLimit = 999999
|
||||
}
|
||||
],
|
||||
environment = concat([
|
||||
{
|
||||
name = "FLEET_MYSQL_USERNAME"
|
||||
value = var.fleet_config.database.user
|
||||
},
|
||||
{
|
||||
name = "FLEET_MYSQL_DATABASE"
|
||||
value = var.fleet_config.database.database
|
||||
},
|
||||
{
|
||||
name = "FLEET_MYSQL_ADDRESS"
|
||||
value = var.fleet_config.database.address
|
||||
},
|
||||
{
|
||||
name = "FLEET_REDIS_ADDRESS"
|
||||
value = var.fleet_config.redis.address
|
||||
},
|
||||
{
|
||||
name = "FLEET_REDIS_USE_TLS"
|
||||
value = tostring(var.fleet_config.redis.use_tls)
|
||||
},
|
||||
{
|
||||
name = "FLEET_SERVER_TLS"
|
||||
value = "false"
|
||||
},
|
||||
], local.environment),
|
||||
logConfiguration = {
|
||||
logDriver = "awslogs"
|
||||
options = {
|
||||
awslogs-group = var.awslogs_config.group
|
||||
awslogs-region = var.awslogs_config.region == null ? data.aws_region.current.name : var.awslogs_config.region
|
||||
awslogs-stream-prefix = "${var.awslogs_config.prefix}-vuln-processing"
|
||||
}
|
||||
}
|
||||
}]
|
||||
, var.fleet_config.sidecars))
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -1,11 +1,53 @@
|
||||
variable "task_definition" {
|
||||
description = "The task definition resource that is created by the byo-ecs module"
|
||||
}
|
||||
|
||||
variable "ecs_service" {
|
||||
description = "The ecs service resource that is created by the byo-ecs module"
|
||||
}
|
||||
|
||||
variable "ecs_cluster" {
|
||||
description = "The ecs cluster module that is created by the byo-db module"
|
||||
}
|
||||
|
||||
variable "fleet_config" {
|
||||
description = "The root Fleet config object"
|
||||
type = any
|
||||
}
|
||||
|
||||
variable "awslogs_config" {
|
||||
type = object({
|
||||
group = string
|
||||
region = string
|
||||
prefix = string
|
||||
})
|
||||
}
|
||||
|
||||
variable "subnets" {
|
||||
type = list(string)
|
||||
nullable = false
|
||||
}
|
||||
|
||||
variable "security_groups" {
|
||||
type = list(string)
|
||||
nullable = false
|
||||
}
|
||||
|
||||
|
||||
variable "customer_prefix" {
|
||||
type = string
|
||||
default = "fleet"
|
||||
}
|
||||
|
||||
variable "execution_iam_role_arn" {
|
||||
description = "The ARN of the fleet execution role, this is necessary to pass role from ecs events"
|
||||
}
|
||||
|
||||
variable "task_role_arn" {
|
||||
description = "The ARN of the fleet task role, this is necessary to pass role from ecs events"
|
||||
}
|
||||
|
||||
variable "vuln_processing_memory" {
|
||||
// note must conform to FARGATE breakpoints https://docs.aws.amazon.com/AmazonECS/latest/userguide/fargate-task-defs.html
|
||||
default = 4096
|
||||
description = "The amount of memory to dedicate to the vuln processing command"
|
||||
}
|
||||
|
||||
variable "vuln_processing_cpu" {
|
||||
// note must conform to FARGETE breakpoints https://docs.aws.amazon.com/AmazonECS/latest/userguide/fargate-task-defs.html
|
||||
default = 1024
|
||||
description = "The amount of CPU to dedicate to the vuln processing command"
|
||||
}
|
||||
|
||||
|
@ -34,3 +34,7 @@ output "non_circular" {
|
||||
"subnets" = var.fleet_config.networking.subnets,
|
||||
}
|
||||
}
|
||||
|
||||
output "fleet_config" {
|
||||
value = var.fleet_config
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user