From 004cc0d3cd32a347dc318e8064f719e49937b963 Mon Sep 17 00:00:00 2001
From: Zachary Winnerman <98712682+zwinnerman-fleetdm@users.noreply.github.com>
Date: Tue, 8 Aug 2023 14:38:20 -0400
Subject: [PATCH] Add external vuln scans addon (#13206)
# Checklist for submitter
If some of the following don't apply, delete the relevant line.
- [ ] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [ ] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- [ ] Documented any permissions changes
- [ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)
- [ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.
- [ ] Added/updated tests
- [ ] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [ ] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- [ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).
---
.../addons/external-vuln-scans/.header.md | 2 +
.../external-vuln-scans/.terraform-docs.yml | 1 +
.../external-vuln-scans/.terraform.lock.hcl | 24 +++++++
.../addons/external-vuln-scans/README.md | 42 ++++++++++++
terraform/addons/external-vuln-scans/main.tf | 65 +++++++++++++++++++
.../addons/external-vuln-scans/outputs.tf | 5 ++
.../addons/external-vuln-scans/variables.tf | 11 ++++
terraform/byo-vpc/main.tf | 7 +-
8 files changed, 154 insertions(+), 3 deletions(-)
create mode 100644 terraform/addons/external-vuln-scans/.header.md
create mode 100644 terraform/addons/external-vuln-scans/.terraform-docs.yml
create mode 100644 terraform/addons/external-vuln-scans/.terraform.lock.hcl
create mode 100644 terraform/addons/external-vuln-scans/README.md
create mode 100644 terraform/addons/external-vuln-scans/main.tf
create mode 100644 terraform/addons/external-vuln-scans/outputs.tf
create mode 100644 terraform/addons/external-vuln-scans/variables.tf
diff --git a/terraform/addons/external-vuln-scans/.header.md b/terraform/addons/external-vuln-scans/.header.md
new file mode 100644
index 0000000000..8a01da3747
--- /dev/null
+++ b/terraform/addons/external-vuln-scans/.header.md
@@ -0,0 +1,2 @@
+# External Vulnerability Scans addon
+This addon moves vulnerability scans off of serving nodes and onto a scheduled task in AWS Eventbridge.
diff --git a/terraform/addons/external-vuln-scans/.terraform-docs.yml b/terraform/addons/external-vuln-scans/.terraform-docs.yml
new file mode 100644
index 0000000000..1d139ddb40
--- /dev/null
+++ b/terraform/addons/external-vuln-scans/.terraform-docs.yml
@@ -0,0 +1 @@
+header-from: .header.md
diff --git a/terraform/addons/external-vuln-scans/.terraform.lock.hcl b/terraform/addons/external-vuln-scans/.terraform.lock.hcl
new file mode 100644
index 0000000000..99ef555634
--- /dev/null
+++ b/terraform/addons/external-vuln-scans/.terraform.lock.hcl
@@ -0,0 +1,24 @@
+# This file is maintained automatically by "terraform init".
+# Manual edits may be lost in future updates.
+
+provider "registry.terraform.io/hashicorp/aws" {
+ version = "5.11.0"
+ hashes = [
+ "h1:OyEBhYcTPChBb0gooSlLIcrxakh72qAN+Sd8Oo12uoc=",
+ "zh:2913af44f9b584f756e5548d5ddc5a251c6d68a7fcd7c41d1418a800a94ef113",
+ "zh:31d2bfa84608b74ff5896f41b09e5927d7c37d18875277a51dcd75a1fea3f909",
+ "zh:8538ff18e3b4822178e793f06764efdbb84c62227c1051af7d2409ab7be37bfc",
+ "zh:8a9295e623327613fc02a6994e73c61b9d0d195bf6fabdb31ee9fd0e6778f62b",
+ "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425",
+ "zh:a65877248951eadf0d16a3260e85f6b178645da7f1897bc7bda6f12fdbec8e47",
+ "zh:a70772851e2c87cc1e10c35389718a544746adc4acbbed129243c0972c367fc6",
+ "zh:b10ca631318f8d1d9a2baa318139bc9e545e51efaf677afece173badce75b44c",
+ "zh:ca2a5698c33158549fa084ad601610eae94498cba445458391b507da22355402",
+ "zh:cdbfc4d64161561bfbcaee5d9b078077ed986131a1eab32ff30e71be09037eec",
+ "zh:ce499f93835bf3d28c13ba98a0a220ff541a827fb400fa931601a375b907b56d",
+ "zh:da6af610e66e96280a299071a698568b505c2456bb15c906304d6f39578c72e3",
+ "zh:e42714e085126c10d8f29664143f97d771b6cc6887d27cdf6c4007ab12af4646",
+ "zh:e86dd0c561c73512acba69f55041adfc04d0467f592f52337a7ac600fbc93680",
+ "zh:f5da95bbd44809534c6678e9b1ae0b390331a5619f2ae353c6b88e96ae855cc0",
+ ]
+}
diff --git a/terraform/addons/external-vuln-scans/README.md b/terraform/addons/external-vuln-scans/README.md
new file mode 100644
index 0000000000..01bbe17d89
--- /dev/null
+++ b/terraform/addons/external-vuln-scans/README.md
@@ -0,0 +1,42 @@
+# External Vulnerability Scans addon
+This addon moves vulnerability scans off of serving nodes and onto a scheduled task in AWS Eventbridge.
+
+## Requirements
+
+No requirements.
+
+## Providers
+
+| Name | Version |
+|------|---------|
+| [aws](#provider\_aws) | 5.11.0 |
+
+## Modules
+
+No modules.
+
+## Resources
+
+| 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_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source |
+
+## Inputs
+
+| Name | Description | Type | Default | Required |
+|------|-------------|------|---------|:--------:|
+| [ecs\_cluster](#input\_ecs\_cluster) | The ecs cluster module that is created by the byo-db module | `any` | n/a | yes |
+| [ecs\_service](#input\_ecs\_service) | The ecs service resource that is created by the byo-ecs module | `any` | n/a | yes |
+| [task\_definition](#input\_task\_definition) | The task definition resource that is created by the byo-ecs module | `any` | n/a | yes |
+
+## Outputs
+
+| Name | Description |
+|------|-------------|
+| [extra\_environment\_variables](#output\_extra\_environment\_variables) | n/a |
diff --git a/terraform/addons/external-vuln-scans/main.tf b/terraform/addons/external-vuln-scans/main.tf
new file mode 100644
index 0000000000..d65877f4b7
--- /dev/null
+++ b/terraform/addons/external-vuln-scans/main.tf
@@ -0,0 +1,65 @@
+data "aws_region" "current" {}
+
+resource "aws_cloudwatch_event_rule" "main" {
+ schedule_expression = "rate(1h)"
+}
+
+data "aws_iam_policy_document" "assume_role" {
+ statement {
+ effect = "Allow"
+
+ principals {
+ type = "Service"
+ identifiers = ["events.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+$/", ":*")]
+ }
+}
+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
+ launch_type = "FARGATE"
+ network_configuration {
+ subnets = var.ecs_service.network_configuration[0].subnets
+ security_groups = var.ecs_service.network_configuration[0].security_groups
+ }
+ }
+
+ input = jsonencode({
+ containerOverrides = [
+ {
+ name = "fleet",
+ command = ["vuln_processing"]
+ }
+ ]
+ })
+}
diff --git a/terraform/addons/external-vuln-scans/outputs.tf b/terraform/addons/external-vuln-scans/outputs.tf
new file mode 100644
index 0000000000..be1bc6b3f6
--- /dev/null
+++ b/terraform/addons/external-vuln-scans/outputs.tf
@@ -0,0 +1,5 @@
+output "extra_environment_variables" {
+ value = {
+ FLEET_VULNERABILITIES_DISABLE_SCHEDULE = "true"
+ }
+}
diff --git a/terraform/addons/external-vuln-scans/variables.tf b/terraform/addons/external-vuln-scans/variables.tf
new file mode 100644
index 0000000000..b82855f5eb
--- /dev/null
+++ b/terraform/addons/external-vuln-scans/variables.tf
@@ -0,0 +1,11 @@
+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"
+}
diff --git a/terraform/byo-vpc/main.tf b/terraform/byo-vpc/main.tf
index 3355fa3107..67268e5b6b 100644
--- a/terraform/byo-vpc/main.tf
+++ b/terraform/byo-vpc/main.tf
@@ -47,9 +47,10 @@ module "rds" {
allowed_security_groups = concat(tolist(module.byo-db.byo-ecs.non_circular.security_groups), var.rds_config.allowed_security_groups)
allowed_cidr_blocks = var.rds_config.allowed_cidr_blocks
- storage_encrypted = true
- apply_immediately = var.rds_config.apply_immediately
- monitoring_interval = var.rds_config.monitoring_interval
+ performance_insights_enabled = true
+ storage_encrypted = true
+ apply_immediately = var.rds_config.apply_immediately
+ monitoring_interval = var.rds_config.monitoring_interval
db_parameter_group_name = var.rds_config.db_parameter_group_name == null ? aws_db_parameter_group.main[0].id : var.rds_config.db_parameter_group_name
db_cluster_parameter_group_name = var.rds_config.db_cluster_parameter_group_name == null ? aws_rds_cluster_parameter_group.main[0].id : var.rds_config.db_cluster_parameter_group_name