From a14fd0d263ef3f8e157caa6bbc3f74a1bc979321 Mon Sep 17 00:00:00 2001 From: Noah Talerman <47070608+noahtalerman@users.noreply.github.com> Date: Mon, 24 Feb 2025 17:35:50 -0500 Subject: [PATCH] Terraform cleanup (#26379) - Remove `dogfood/aws/` folder - Update links in docs and guides --- articles/deploy-fleet-on-aws-ecs.md | 10 +- articles/log-destinations.md | 2 +- docs/Contributing/Releasing-Fleet.md | 2 +- .../dogfood/terraform/aws/.terraform-version | 1 - .../dogfood/terraform/aws/.terraform.lock.hcl | 80 ---- .../dogfood/terraform/aws/ecs-iam.tf | 97 ----- .../dogfood/terraform/aws/ecs-sgs.tf | 82 ---- infrastructure/dogfood/terraform/aws/ecs.tf | 373 ------------------ .../dogfood/terraform/aws/firehose.tf | 161 -------- infrastructure/dogfood/terraform/aws/main.tf | 21 - .../terraform/aws/monitoring/monitoring.tf | 363 ----------------- .../dogfood/terraform/aws/outputs.tf | 71 ---- .../dogfood/terraform/aws/percona/network.tf | 30 -- .../dogfood/terraform/aws/percona/percona.tf | 137 ------- .../terraform/aws/percona/security_groups.tf | 73 ---- .../terraform/aws/percona/variables.tf | 24 -- infrastructure/dogfood/terraform/aws/r53.tf | 46 --- infrastructure/dogfood/terraform/aws/rds.tf | 129 ------ .../dogfood/terraform/aws/readme.md | 76 ---- infrastructure/dogfood/terraform/aws/redis.tf | 63 --- .../terraform/aws/remote-state/main.tf | 69 ---- infrastructure/dogfood/terraform/aws/s3.tf | 35 -- infrastructure/dogfood/terraform/aws/vpc.tf | 24 -- .../dogfood/terraform/aws/vuln_processing.tf | 151 ------- 24 files changed, 7 insertions(+), 2113 deletions(-) delete mode 100644 infrastructure/dogfood/terraform/aws/.terraform-version delete mode 100644 infrastructure/dogfood/terraform/aws/.terraform.lock.hcl delete mode 100644 infrastructure/dogfood/terraform/aws/ecs-iam.tf delete mode 100644 infrastructure/dogfood/terraform/aws/ecs-sgs.tf delete mode 100644 infrastructure/dogfood/terraform/aws/ecs.tf delete mode 100644 infrastructure/dogfood/terraform/aws/firehose.tf delete mode 100644 infrastructure/dogfood/terraform/aws/main.tf delete mode 100644 infrastructure/dogfood/terraform/aws/monitoring/monitoring.tf delete mode 100644 infrastructure/dogfood/terraform/aws/outputs.tf delete mode 100644 infrastructure/dogfood/terraform/aws/percona/network.tf delete mode 100644 infrastructure/dogfood/terraform/aws/percona/percona.tf delete mode 100644 infrastructure/dogfood/terraform/aws/percona/security_groups.tf delete mode 100644 infrastructure/dogfood/terraform/aws/percona/variables.tf delete mode 100644 infrastructure/dogfood/terraform/aws/r53.tf delete mode 100644 infrastructure/dogfood/terraform/aws/rds.tf delete mode 100644 infrastructure/dogfood/terraform/aws/readme.md delete mode 100644 infrastructure/dogfood/terraform/aws/redis.tf delete mode 100644 infrastructure/dogfood/terraform/aws/remote-state/main.tf delete mode 100644 infrastructure/dogfood/terraform/aws/s3.tf delete mode 100644 infrastructure/dogfood/terraform/aws/vpc.tf delete mode 100644 infrastructure/dogfood/terraform/aws/vuln_processing.tf diff --git a/articles/deploy-fleet-on-aws-ecs.md b/articles/deploy-fleet-on-aws-ecs.md index 6d292aa58c..c61304b7a1 100644 --- a/articles/deploy-fleet-on-aws-ecs.md +++ b/articles/deploy-fleet-on-aws-ecs.md @@ -5,25 +5,25 @@ ![Deploy Fleet on AWS ECS](../website/assets/images/articles/deploy-fleet-on-aws-ecs-800x450@2x.png) -Terraform reference architecture can be found [here](https://github.com/fleetdm/fleet/tree/main/infrastructure/dogfood/terraform/aws) +Terraform reference architecture can be found [here](https://github.com/fleetdm/fleet-terraform) ### Infrastructure dependencies #### MySQL -In AWS we recommend running Aurora with MySQL Engine, see [here for terraform details](https://github.com/fleetdm/fleet/blob/main/infrastructure/dogfood/terraform/aws/rds.tf#L64). +In AWS we recommend running Aurora with MySQL Engine. #### Redis -In AWS we recommend running ElastiCache (Redis Engine) see [here for terraform details](https://github.com/fleetdm/fleet/blob/main/infrastructure/dogfood/terraform/aws/redis.tf#L13) +In AWS we recommend running ElastiCache (Redis Engine). #### Fleet server -Running Fleet in ECS consists of two main components the [ECS Service](https://github.com/fleetdm/fleet/blob/main/infrastructure/dogfood/terraform/aws/ecs.tf#L84) & [Load Balancer](https://github.com/fleetdm/fleet/blob/main/infrastructure/dogfood/terraform/aws/ecs.tf#L59). In our example the ALB is [handling TLS termination](https://github.com/fleetdm/fleet/blob/main/infrastructure/dogfood/terraform/aws/ecs.tf#L46) +Running Fleet in ECS consists of two main components the ECS service & load balancer. #### Fleet migrations -Migrations in ECS can be achieved by running [dedicated ECS tasks](https://github.com/fleetdm/fleet/tree/main/infrastructure/dogfood/terraform/aws#migrating-the-db) that run the `fleet prepare --no-prompt=true db` command. See [terraform for more details](https://github.com/fleetdm/fleet/blob/main/infrastructure/dogfood/terraform/aws/ecs.tf#L261) +Migrations in ECS can be achieved by running dedicated ECS tasks that run the `fleet prepare --no-prompt=true db` command. Alternatively you can bake the prepare command into the same task definition see [here for a discussion](https://github.com/fleetdm/fleet/pull/1761#discussion_r697599457), but this is not recommended for production environments. diff --git a/articles/log-destinations.md b/articles/log-destinations.md index c92eff5234..dcf95717a8 100644 --- a/articles/log-destinations.md +++ b/articles/log-destinations.md @@ -45,7 +45,7 @@ Note that Firehose logging has limits [discussed in the documentation](https://d To send logs to Snowflake, you must first configure Fleet to send logs to [Amazon Kinesis Data Firehose (Firehose)](#amazon-kinesis-data-firehose). This is because you'll use the Snowflake Snowpipe integration to direct logs to Snowflake. -If you're using Fleet's [terraform reference architecture](https://github.com/fleetdm/fleet/blob/main/infrastructure/dogfood/terraform/aws/firehose.tf), Firehose is already configured as your log destination. +If you're using Fleet's [best practice Terraform](https://github.com/fleetdm/fleet-terraform), Firehose is already configured as your log destination. With Fleet configured to send logs to Firehose, you then want to load the data from Firehose into a Snowflake database. AWS provides instructions on how to direct logs to a Snowflake database [here in the AWS documentation](https://docs.aws.amazon.com/prescriptive-guidance/latest/patterns/automate-data-stream-ingestion-into-a-snowflake-database-by-using-snowflake-snowpipe-amazon-s3-amazon-sns-and-amazon-kinesis-data-firehose.html) diff --git a/docs/Contributing/Releasing-Fleet.md b/docs/Contributing/Releasing-Fleet.md index 21b75ca781..a6c8b9b3b2 100644 --- a/docs/Contributing/Releasing-Fleet.md +++ b/docs/Contributing/Releasing-Fleet.md @@ -20,7 +20,7 @@ Note: Please prefix versions with `fleet-v` (e.g., `fleet-v4.0.0`) in git tags, - [fleetctl package.json](https://github.com/fleetdm/fleet/blob/main/tools/fleetctl-npm/package.json) (do not yet `npm publish`) - [Helm chart.yaml](https://github.com/fleetdm/fleet/blob/main/charts/fleet/Chart.yaml) and [values file](https://github.com/fleetdm/fleet/blob/main/charts/fleet/values.yaml) -- Terraform variables ([AWS](https://github.com/fleetdm/fleet/blob/main/infrastructure/dogfood/terraform/aws/variables.tf)/[GCP](https://github.com/fleetdm/fleet/blob/main/infrastructure/dogfood/terraform/gcp/variables.tf)) +- GCP Terraform [variables](https://github.com/fleetdm/fleet/blob/main/infrastructure/dogfood/terraform/gcp/variables.tf) - [Kubernetes `fleet-deployment.yml` file](https://github.com/fleetdm/fleet/blob/main/docs/Deploy/kubernetes/fleet-deployment.yml) - All Terraform (*.tf) files referencing the previous version of Fleet. - The full list can be found by using git grep: diff --git a/infrastructure/dogfood/terraform/aws/.terraform-version b/infrastructure/dogfood/terraform/aws/.terraform-version deleted file mode 100644 index a6a3a43c3a..0000000000 --- a/infrastructure/dogfood/terraform/aws/.terraform-version +++ /dev/null @@ -1 +0,0 @@ -1.0.4 \ No newline at end of file diff --git a/infrastructure/dogfood/terraform/aws/.terraform.lock.hcl b/infrastructure/dogfood/terraform/aws/.terraform.lock.hcl deleted file mode 100644 index d852f12a67..0000000000 --- a/infrastructure/dogfood/terraform/aws/.terraform.lock.hcl +++ /dev/null @@ -1,80 +0,0 @@ -# This file is maintained automatically by "terraform init". -# Manual edits may be lost in future updates. - -provider "registry.terraform.io/hashicorp/aws" { - version = "4.32.0" - constraints = ">= 3.30.0, >= 3.73.0, 4.32.0" - hashes = [ - "h1:8AKJChT1Sgqjfdn16BayH5DonF3B9g7qQ6N+IKPulP4=", - "zh:062c30cd8bcf29f8ee34c2b2509e4e8695c2bcac8b7a8145e1c72e83d4e68b13", - "zh:1503fabaace96a7eea4d73ced36a02a75ec587760850e58162e7eff419dcbb31", - "zh:39a1fa36f8cb999f048bf0000d9dab40b8b0c77df35584fb08aa8bd6c5052dee", - "zh:471a755d43b51cd7be3e386cebc151ad8d548c5dea798343620476887e721882", - "zh:61ed56fab811e62b8286e606d003f7eeb7e940ef99bb49c1d283d91c0b748cc7", - "zh:80607dfe5f7770d136d5c451308b9861084ffad08139de8014e48672ec43ea3f", - "zh:863bf0a6576f7a969a89631525250d947fbb207d3d13e7ca4f74d86bd97cdda3", - "zh:9a8f2e77e4f99dbb618eb8ad17218a4698833754b50d46da5727323a2050a400", - "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", - "zh:9b74ff6e638c2a470b3599d57c2081e0095976da0a54b6590884d571f930b53b", - "zh:da4fc553d50ae833d860ec95120e271c29b4cb636917ab5991327362b7486bb7", - "zh:f4b86e7df4e846a38774e8e648b41c5ebaddcefa913cfa1864568086b7735575", - ] -} - -provider "registry.terraform.io/hashicorp/null" { - version = "3.2.1" - hashes = [ - "h1:FbGfc+muBsC17Ohy5g806iuI1hQc4SIexpYCrQHQd8w=", - "zh:58ed64389620cc7b82f01332e27723856422820cfd302e304b5f6c3436fb9840", - "zh:62a5cc82c3b2ddef7ef3a6f2fedb7b9b3deff4ab7b414938b08e51d6e8be87cb", - "zh:63cff4de03af983175a7e37e52d4bd89d990be256b16b5c7f919aff5ad485aa5", - "zh:74cb22c6700e48486b7cabefa10b33b801dfcab56f1a6ac9b6624531f3d36ea3", - "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:79e553aff77f1cfa9012a2218b8238dd672ea5e1b2924775ac9ac24d2a75c238", - "zh:a1e06ddda0b5ac48f7e7c7d59e1ab5a4073bbcf876c73c0299e4610ed53859dc", - "zh:c37a97090f1a82222925d45d84483b2aa702ef7ab66532af6cbcfb567818b970", - "zh:e4453fbebf90c53ca3323a92e7ca0f9961427d2f0ce0d2b65523cc04d5d999c2", - "zh:e80a746921946d8b6761e77305b752ad188da60688cfd2059322875d363be5f5", - "zh:fbdb892d9822ed0e4cb60f2fedbdbb556e4da0d88d3b942ae963ed6ff091e48f", - "zh:fca01a623d90d0cad0843102f9b8b9fe0d3ff8244593bd817f126582b52dd694", - ] -} - -provider "registry.terraform.io/hashicorp/random" { - version = "3.4.3" - constraints = ">= 2.2.0" - hashes = [ - "h1:xZGZf18JjMS06pFa4NErzANI98qi59SEcBsOcS2P2yQ=", - "zh:41c53ba47085d8261590990f8633c8906696fa0a3c4b384ff6a7ecbf84339752", - "zh:59d98081c4475f2ad77d881c4412c5129c56214892f490adf11c7e7a5a47de9b", - "zh:686ad1ee40b812b9e016317e7f34c0d63ef837e084dea4a1f578f64a6314ad53", - "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:84103eae7251384c0d995f5a257c72b0096605048f757b749b7b62107a5dccb3", - "zh:8ee974b110adb78c7cd18aae82b2729e5124d8f115d484215fd5199451053de5", - "zh:9dd4561e3c847e45de603f17fa0c01ae14cae8c4b7b4e6423c9ef3904b308dda", - "zh:bb07bb3c2c0296beba0beec629ebc6474c70732387477a65966483b5efabdbc6", - "zh:e891339e96c9e5a888727b45b2e1bb3fcbdfe0fd7c5b4396e4695459b38c8cb1", - "zh:ea4739860c24dfeaac6c100b2a2e357106a89d18751f7693f3c31ecf6a996f8d", - "zh:f0c76ac303fd0ab59146c39bc121c5d7d86f878e9a69294e29444d4c653786f8", - "zh:f143a9a5af42b38fed328a161279906759ff39ac428ebcfe55606e05e1518b93", - ] -} - -provider "registry.terraform.io/hashicorp/tls" { - version = "4.0.4" - hashes = [ - "h1:pe9vq86dZZKCm+8k1RhzARwENslF3SXb9ErHbQfgjXU=", - "zh:23671ed83e1fcf79745534841e10291bbf34046b27d6e68a5d0aab77206f4a55", - "zh:45292421211ffd9e8e3eb3655677700e3c5047f71d8f7650d2ce30242335f848", - "zh:59fedb519f4433c0fdb1d58b27c210b27415fddd0cd73c5312530b4309c088be", - "zh:5a8eec2409a9ff7cd0758a9d818c74bcba92a240e6c5e54b99df68fff312bbd5", - "zh:5e6a4b39f3171f53292ab88058a59e64825f2b842760a4869e64dc1dc093d1fe", - "zh:810547d0bf9311d21c81cc306126d3547e7bd3f194fc295836acf164b9f8424e", - "zh:824a5f3617624243bed0259d7dd37d76017097dc3193dac669be342b90b2ab48", - "zh:9361ccc7048be5dcbc2fafe2d8216939765b3160bd52734f7a9fd917a39ecbd8", - "zh:aa02ea625aaf672e649296bce7580f62d724268189fe9ad7c1b36bb0fa12fa60", - "zh:c71b4cd40d6ec7815dfeefd57d88bc592c0c42f5e5858dcc88245d371b4b8b1e", - "zh:dabcd52f36b43d250a3d71ad7abfa07b5622c69068d989e60b79b2bb4f220316", - "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", - ] -} diff --git a/infrastructure/dogfood/terraform/aws/ecs-iam.tf b/infrastructure/dogfood/terraform/aws/ecs-iam.tf deleted file mode 100644 index e23ba7bc88..0000000000 --- a/infrastructure/dogfood/terraform/aws/ecs-iam.tf +++ /dev/null @@ -1,97 +0,0 @@ -data "aws_iam_policy_document" "fleet" { - statement { - effect = "Allow" - actions = ["cloudwatch:PutMetricData"] - resources = ["*"] - } - - // allow fleet application to obtain the database password from secrets manager - statement { - effect = "Allow" - actions = ["secretsmanager:GetSecretValue"] - resources = [aws_secretsmanager_secret.database_password_secret.arn] - } - - // useful when there is a static number of mysql cluster members - dynamic "statement" { - for_each = module.aurora_mysql.rds_cluster_instance_dbi_resource_ids - content { - effect = "Allow" - actions = ["rds-db:connect"] - resources = ["arn:aws:rds-db:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:dbuser:${statement.value}/${var.database_user}"] - } - } - - // allow access to any database via IAM that has the var.database_user user - // useful when you are autoscaling mysql read replicas dynamically - statement { - effect = "Allow" - actions = ["rds-db:connect"] - resources = ["arn:aws:rds-db:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:dbuser:*/${var.database_user}"] - } - - // allow fleet application to write to kinesis firehose for osquery log destination configuration - statement { - effect = "Allow" - actions = [ - "firehose:DescribeDeliveryStream", - "firehose:PutRecord", - "firehose:PutRecordBatch", - ] - resources = [aws_kinesis_firehose_delivery_stream.osquery_results.arn, aws_kinesis_firehose_delivery_stream.osquery_status.arn] - } - - // These actions are required for osquery file carving APIs - // We use wildcards on these actions for buckets that are single-use. - statement { #tfsec:ignore:aws-iam-no-policy-wildcards - effect = "Allow" - actions = [ - "s3:GetObject*", - "s3:PutObject*", - "s3:ListBucket*", - "s3:ListMultipartUploadParts*", - "s3:DeleteObject", - "s3:CreateMultipartUpload", - "s3:AbortMultipartUpload", - "s3:ListMultipartUploadParts", - "s3:GetBucketLocation" - ] - resources = [ - aws_s3_bucket.osquery-carve.arn, - "${aws_s3_bucket.osquery-carve.arn}/*" - ] - } -} - -data "aws_iam_policy_document" "assume_role" { - statement { - effect = "Allow" - actions = ["sts:AssumeRole"] - principals { - identifiers = ["ecs.amazonaws.com", "ecs-tasks.amazonaws.com"] - type = "Service" - } - } -} - -resource "aws_iam_role" "main" { - name = "fleetdm-role" - description = "IAM role that Fleet application assumes when running in ECS" - assume_role_policy = data.aws_iam_policy_document.assume_role.json -} - -resource "aws_iam_role_policy_attachment" "role_attachment" { - policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy" - role = aws_iam_role.main.name -} - -resource "aws_iam_policy" "main" { - name = "fleet-iam-policy" - description = "IAM policy that Fleet application uses to define access to AWS resources" - policy = data.aws_iam_policy_document.fleet.json -} - -resource "aws_iam_role_policy_attachment" "attachment" { - policy_arn = aws_iam_policy.main.arn - role = aws_iam_role.main.name -} \ No newline at end of file diff --git a/infrastructure/dogfood/terraform/aws/ecs-sgs.tf b/infrastructure/dogfood/terraform/aws/ecs-sgs.tf deleted file mode 100644 index 8e361ceb3a..0000000000 --- a/infrastructure/dogfood/terraform/aws/ecs-sgs.tf +++ /dev/null @@ -1,82 +0,0 @@ -# Security group for the public internet facing load balancer -resource "aws_security_group" "lb" { - name = "${var.prefix} load balancer" - description = "${var.prefix} Load balancer security group" - vpc_id = module.vpc.vpc_id -} - -# Allow traffic from public internet -resource "aws_security_group_rule" "lb-ingress" { - description = "${var.prefix}: allow traffic from public internet" - type = "ingress" - - from_port = "443" - to_port = "443" - protocol = "tcp" - // Internet connectivity here is by design - cidr_blocks = ["0.0.0.0/0"] #tfsec:ignore:aws-vpc-no-public-ingress-sgr - - security_group_id = aws_security_group.lb.id -} - -resource "aws_security_group_rule" "lb-http-ingress" { - description = "${var.prefix}: allow traffic from public internet" - type = "ingress" - - from_port = "80" - to_port = "80" - protocol = "tcp" - // Internet connectivity here is by design - cidr_blocks = ["0.0.0.0/0"] #tfsec:ignore:aws-vpc-no-public-ingress-sgr - - security_group_id = aws_security_group.lb.id -} - -# Allow outbound traffic -resource "aws_security_group_rule" "lb-egress" { - description = "${var.prefix}: allow all outbound traffic" - type = "egress" - - from_port = 0 - to_port = 0 - protocol = "-1" - // Egress filtering is not currently provided by our Terraform templates. - cidr_blocks = ["0.0.0.0/0"] #tfsec:ignore:aws-vpc-no-public-egress-sgr:exp:2022-10-01 - - security_group_id = aws_security_group.lb.id -} - -# Security group for the backends that run the application. -# Allows traffic from the load balancer -resource "aws_security_group" "backend" { - name = "${var.prefix} backend" - description = "${var.prefix} Backend security group" - vpc_id = module.vpc.vpc_id - -} - -# Allow traffic from the load balancer to the backends -resource "aws_security_group_rule" "backend-ingress" { - description = "${var.prefix}: allow traffic from load balancer" - type = "ingress" - - from_port = "8080" - to_port = "8080" - protocol = "tcp" - source_security_group_id = aws_security_group.lb.id - security_group_id = aws_security_group.backend.id -} - -# Allow outbound traffic from the backends -resource "aws_security_group_rule" "backend-egress" { - description = "${var.prefix}: allow all outbound traffic" - type = "egress" - - from_port = 0 - to_port = 0 - protocol = "-1" - // Egress filtering is not currently provided by our Terraform templates. - cidr_blocks = ["0.0.0.0/0"] #tfsec:ignore:aws-vpc-no-public-egress-sgr:exp:2022-10-01 - - security_group_id = aws_security_group.backend.id -} \ No newline at end of file diff --git a/infrastructure/dogfood/terraform/aws/ecs.tf b/infrastructure/dogfood/terraform/aws/ecs.tf deleted file mode 100644 index f0ee8af37a..0000000000 --- a/infrastructure/dogfood/terraform/aws/ecs.tf +++ /dev/null @@ -1,373 +0,0 @@ -data "aws_region" "current" {} - -resource "aws_route53_record" "record" { - name = "fleet-alb-${terraform.workspace}" - type = "A" - zone_id = aws_route53_zone.dogfood_fleetdm_com.zone_id - alias { - evaluate_target_health = false - name = aws_alb.main.dns_name - zone_id = aws_alb.main.zone_id - } -} - -resource "aws_alb" "main" { - // Exposed to the Internet by design - internal = false #tfsec:ignore:aws-elb-alb-not-public - security_groups = [aws_security_group.lb.id, aws_security_group.backend.id] - subnets = module.vpc.public_subnets - idle_timeout = 905 - name = "fleetdm" - drop_invalid_header_fields = true -} - -resource "aws_alb_target_group" "main" { - name = "fleetdm" - protocol = "HTTP" - target_type = "ip" - port = "8080" - vpc_id = module.vpc.vpc_id - deregistration_delay = 30 - - load_balancing_algorithm_type = "least_outstanding_requests" - - health_check { - path = "/healthz" - matcher = "200" - timeout = 10 - interval = 15 - healthy_threshold = 5 - unhealthy_threshold = 5 - } - - depends_on = [aws_alb.main] -} - -resource "aws_alb_listener" "https-fleetdm" { - load_balancer_arn = aws_alb.main.arn - port = 443 - protocol = "HTTPS" - ssl_policy = "ELBSecurityPolicy-FS-1-2-Res-2019-08" - certificate_arn = aws_acm_certificate_validation.dogfood_fleetdm_com.certificate_arn - - default_action { - target_group_arn = aws_alb_target_group.main.arn - type = "forward" - } -} - -resource "aws_alb_listener" "http" { - load_balancer_arn = aws_alb.main.arn - port = "80" - protocol = "HTTP" - - default_action { - type = "redirect" - - redirect { - port = "443" - protocol = "HTTPS" - status_code = "HTTP_301" - } - } -} - -resource "aws_ecs_cluster" "fleet" { - name = "${var.prefix}-backend" - - setting { - name = "containerInsights" - value = "enabled" - } -} - -resource "aws_ecs_service" "fleet" { - name = "fleet" - launch_type = "FARGATE" - cluster = aws_ecs_cluster.fleet.id - task_definition = aws_ecs_task_definition.backend.arn - desired_count = 5 - deployment_minimum_healthy_percent = 100 - deployment_maximum_percent = 200 - health_check_grace_period_seconds = 30 - - load_balancer { - target_group_arn = aws_alb_target_group.main.arn - container_name = "fleet" - container_port = 8080 - } - - // https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_service#ignoring-changes-to-desired-count - lifecycle { - ignore_changes = [desired_count] - } - - network_configuration { - subnets = module.vpc.private_subnets - security_groups = [aws_security_group.backend.id] - } - - depends_on = [aws_alb_listener.http, aws_alb_listener.https-fleetdm] -} -// Customer keys are not supported in our Fleet Terraforms at the moment. We will evaluate the -// possibility of providing this capability in the future. -resource "aws_cloudwatch_log_group" "backend" { #tfsec:ignore:aws-cloudwatch-log-group-customer-key:exp:2022-07-01 - name = "fleetdm" - retention_in_days = var.cloudwatch_log_retention -} - -resource "aws_ecs_task_definition" "backend" { - family = "fleet" - network_mode = "awsvpc" - requires_compatibilities = ["FARGATE"] - execution_role_arn = aws_iam_role.main.arn - task_role_arn = aws_iam_role.main.arn - cpu = var.fleet_backend_cpu - memory = var.fleet_backend_mem - container_definitions = jsonencode( - [ - { - name = "fleet" - image = var.fleet_image - cpu = var.fleet_backend_cpu - memory = var.fleet_backend_mem - mountPoints = [] - volumesFrom = [] - essential = true - portMappings = [ - { - # This port is the same that the contained application also uses - containerPort = 8080 - protocol = "tcp" - } - ] - networkMode = "awsvpc" - logConfiguration = { - logDriver = "awslogs" - options = { - awslogs-group = aws_cloudwatch_log_group.backend.name - awslogs-region = data.aws_region.current.name - awslogs-stream-prefix = "fleet" - } - }, - ulimits = [ - { - name = "nofile" - softLimit = 999999 - hardLimit = 999999 - } - ], - secrets = [ - { - name = "FLEET_MYSQL_PASSWORD" - valueFrom = aws_secretsmanager_secret.database_password_secret.arn - }, - { - name = "FLEET_MYSQL_READ_REPLICA_PASSWORD" - valueFrom = aws_secretsmanager_secret.database_password_secret.arn - } - ] - environment = [ - { - name = "FLEET_MYSQL_USERNAME" - value = var.database_user - }, - { - name = "FLEET_MYSQL_DATABASE" - value = var.database_name - }, - { - name = "FLEET_MYSQL_ADDRESS" - value = "${module.aurora_mysql.rds_cluster_endpoint}:3306" - }, - { - name = "FLEET_MYSQL_READ_REPLICA_USERNAME" - value = var.database_user - }, - { - name = "FLEET_MYSQL_READ_REPLICA_DATABASE" - value = var.database_name - }, - { - name = "FLEET_MYSQL_READ_REPLICA_ADDRESS" - value = "${module.aurora_mysql.rds_cluster_reader_endpoint}:3306" - }, - { - name = "FLEET_REDIS_ADDRESS" - value = "${aws_elasticache_replication_group.default.primary_endpoint_address}:6379" - }, - { - name = "FLEET_REDIS_USE_TLS" - value = "true" - }, - { - name = "FLEET_FIREHOSE_STATUS_STREAM" - value = aws_kinesis_firehose_delivery_stream.osquery_status.name - }, - { - name = "FLEET_FIREHOSE_RESULT_STREAM" - value = aws_kinesis_firehose_delivery_stream.osquery_results.name - }, - { - name = "FLEET_FIREHOSE_REGION" - value = data.aws_region.current.name - }, - { - name = "FLEET_OSQUERY_STATUS_LOG_PLUGIN" - value = "firehose" - }, - { - name = "FLEET_OSQUERY_RESULT_LOG_PLUGIN" - value = "firehose" - }, - { - name = "FLEET_SERVER_TLS" - value = "false" - }, - { - name = "FLEET_VULNERABILITIES_DATABASES_PATH" - value = var.vuln_db_path - }, - { - name = "FLEET_OSQUERY_ENABLE_ASYNC_HOST_PROCESSING" - value = var.async_host_processing - }, - { - name = "FLEET_LOGGING_DEBUG" - value = var.logging_debug - }, - { - name = "FLEET_LOGGING_JSON" - value = var.logging_json - }, - { - name = "FLEET_S3_BUCKET" - value = aws_s3_bucket.osquery-carve.bucket - }, - { - name = "FLEET_S3_PREFIX" - value = "carve_results/" - }, - { - name = "FLEET_LICENSE_KEY" - value = var.fleet_license - } - ] - } - ]) -} - - -resource "aws_ecs_task_definition" "migration" { - family = "fleet-migrate" - network_mode = "awsvpc" - requires_compatibilities = ["FARGATE"] - execution_role_arn = aws_iam_role.main.arn - task_role_arn = aws_iam_role.main.arn - cpu = var.cpu_migrate - memory = var.mem_migrate - container_definitions = jsonencode( - [ - { - name = "fleet-prepare-db" - image = var.fleet_image - cpu = var.cpu_migrate - memory = var.mem_migrate - mountPoints = [] - volumesFrom = [] - essential = true - portMappings = [ - { - # This port is the same that the contained application also uses - containerPort = 8080 - protocol = "tcp" - } - ] - networkMode = "awsvpc" - logConfiguration = { - logDriver = "awslogs" - options = { - awslogs-group = aws_cloudwatch_log_group.backend.name - awslogs-region = data.aws_region.current.name - awslogs-stream-prefix = "fleet" - } - }, - command = ["fleet", "prepare", "--no-prompt=true", "db"] - secrets = [ - { - name = "FLEET_MYSQL_PASSWORD" - valueFrom = aws_secretsmanager_secret.database_password_secret.arn - } - ] - environment = [ - { - name = "FLEET_MYSQL_USERNAME" - value = var.database_user - }, - { - name = "FLEET_MYSQL_DATABASE" - value = var.database_name - }, - { - name = "FLEET_MYSQL_ADDRESS" - value = "${module.aurora_mysql.rds_cluster_endpoint}:3306" - }, - { - name = "FLEET_REDIS_ADDRESS" - value = "${aws_elasticache_replication_group.default.primary_endpoint_address}:6379" - }, - { - name = "FLEET_REDIS_USE_TLS" - value = "true" - } - ] - } - ]) -} - -resource "aws_appautoscaling_target" "ecs_target" { - max_capacity = var.fleet_max_capacity - min_capacity = var.fleet_min_capacity - resource_id = "service/${aws_ecs_cluster.fleet.name}/${aws_ecs_service.fleet.name}" - scalable_dimension = "ecs:service:DesiredCount" - service_namespace = "ecs" -} - -resource "aws_appautoscaling_policy" "ecs_policy_memory" { - name = "fleet-memory-autoscaling" - policy_type = "TargetTrackingScaling" - resource_id = aws_appautoscaling_target.ecs_target.resource_id - scalable_dimension = aws_appautoscaling_target.ecs_target.scalable_dimension - service_namespace = aws_appautoscaling_target.ecs_target.service_namespace - - target_tracking_scaling_policy_configuration { - predefined_metric_specification { - predefined_metric_type = "ECSServiceAverageMemoryUtilization" - } - target_value = var.memory_tracking_target_value - } -} - -resource "aws_appautoscaling_policy" "ecs_policy_cpu" { - name = "fleet-cpu-autoscaling" - policy_type = "TargetTrackingScaling" - resource_id = aws_appautoscaling_target.ecs_target.resource_id - scalable_dimension = aws_appautoscaling_target.ecs_target.scalable_dimension - service_namespace = aws_appautoscaling_target.ecs_target.service_namespace - - target_tracking_scaling_policy_configuration { - predefined_metric_specification { - predefined_metric_type = "ECSServiceAverageCPUUtilization" - } - - target_value = var.cpu_tracking_target_value - } -} - -output "fleet_ecs_cluster_arn" { - value = aws_ecs_cluster.fleet.arn -} - -output "fleet_ecs_cluster_id" { - value = aws_ecs_cluster.fleet.id -} diff --git a/infrastructure/dogfood/terraform/aws/firehose.tf b/infrastructure/dogfood/terraform/aws/firehose.tf deleted file mode 100644 index 6875c6ab46..0000000000 --- a/infrastructure/dogfood/terraform/aws/firehose.tf +++ /dev/null @@ -1,161 +0,0 @@ -// Customer keys are not supported in our Fleet Terraforms at the moment. We will evaluate the -// possibility of providing this capability in the future. -// No versioning on this bucket is by design. -// Bucket logging is not supported in our Fleet Terraforms at the moment. It can be enabled by the -// organizations deploying Fleet, and we will evaluate the possibility of providing this capability -// in the future. -resource "aws_s3_bucket" "osquery-results" { #tfsec:ignore:aws-s3-encryption-customer-key:exp:2022-07-01 #tfsec:ignore:aws-s3-enable-versioning #tfsec:ignore:aws-s3-enable-bucket-logging:exp:2022-06-15 - bucket = var.osquery_results_s3_bucket - acl = "private" - - lifecycle_rule { - enabled = true - expiration { - days = 1 - } - } - - server_side_encryption_configuration { - rule { - apply_server_side_encryption_by_default { - sse_algorithm = "aws:kms" - } - } - } -} - -resource "aws_s3_bucket_public_access_block" "osquery-results" { - bucket = aws_s3_bucket.osquery-results.id - block_public_acls = true - block_public_policy = true - ignore_public_acls = true - restrict_public_buckets = true -} - -// Customer keys are not supported in our Fleet Terraforms at the moment. We will evaluate the -// possibility of providing this capability in the future. -// No versioning on this bucket is by design. -// Bucket logging is not supported in our Fleet Terraforms at the moment. It can be enabled by the -// organizations deploying Fleet, and we will evaluate the possibility of providing this capability -// in the future. -resource "aws_s3_bucket" "osquery-status" { #tfsec:ignore:aws-s3-encryption-customer-key:exp:2022-07-01 #tfsec:ignore:aws-s3-enable-versioning #tfsec:ignore:aws-s3-enable-bucket-logging:exp:2022-06-15 - bucket = var.osquery_status_s3_bucket - acl = "private" - - server_side_encryption_configuration { - rule { - apply_server_side_encryption_by_default { - sse_algorithm = "aws:kms" - } - } - } -} - -resource "aws_s3_bucket_lifecycle_configuration" "osquery-status" { - bucket = aws_s3_bucket.osquery-status.id - - rule { - id = "rule-1" - status = "Enabled" - expiration { - days = 1 - } - } -} - -resource "aws_s3_bucket_public_access_block" "osquery-status" { - bucket = aws_s3_bucket.osquery-status.id - block_public_acls = true - block_public_policy = true - ignore_public_acls = true - restrict_public_buckets = true -} - -data "aws_iam_policy_document" "osquery_results_policy_doc" { - statement { - effect = "Allow" - actions = [ - "s3:AbortMultipartUpload", - "s3:GetBucketLocation", - "s3:ListBucket", - "s3:ListBucketMultipartUploads", - "s3:PutObject" - ] - // This bucket is single-purpose and using a wildcard is not problematic - resources = [aws_s3_bucket.osquery-results.arn, "${aws_s3_bucket.osquery-results.arn}/*"] #tfsec:ignore:aws-iam-no-policy-wildcards - } -} - -data "aws_iam_policy_document" "osquery_status_policy_doc" { - statement { - effect = "Allow" - actions = [ - "s3:AbortMultipartUpload", - "s3:GetBucketLocation", - "s3:ListBucket", - "s3:ListBucketMultipartUploads", - "s3:PutObject" - ] - // This bucket is single-purpose and using a wildcard is not problematic - resources = [aws_s3_bucket.osquery-status.arn, "${aws_s3_bucket.osquery-status.arn}/*"] #tfsec:ignore:aws-iam-no-policy-wildcards - } -} - -resource "aws_iam_policy" "firehose-results" { - name = "osquery_results_firehose_policy" - policy = data.aws_iam_policy_document.osquery_results_policy_doc.json -} - -resource "aws_iam_policy" "firehose-status" { - name = "osquery_status_firehose_policy" - policy = data.aws_iam_policy_document.osquery_status_policy_doc.json -} - -resource "aws_iam_role" "firehose-results" { - assume_role_policy = data.aws_iam_policy_document.osquery_firehose_assume_role.json -} - -resource "aws_iam_role" "firehose-status" { - assume_role_policy = data.aws_iam_policy_document.osquery_firehose_assume_role.json -} - -resource "aws_iam_role_policy_attachment" "firehose-results" { - policy_arn = aws_iam_policy.firehose-results.arn - role = aws_iam_role.firehose-results.name -} - -resource "aws_iam_role_policy_attachment" "firehose-status" { - policy_arn = aws_iam_policy.firehose-status.arn - role = aws_iam_role.firehose-status.name -} - -data "aws_iam_policy_document" "osquery_firehose_assume_role" { - statement { - effect = "Allow" - actions = ["sts:AssumeRole"] - principals { - identifiers = ["firehose.amazonaws.com"] - type = "Service" - } - } -} - -resource "aws_kinesis_firehose_delivery_stream" "osquery_results" { - name = "osquery_results" - destination = "s3" - - s3_configuration { - role_arn = aws_iam_role.firehose-results.arn - bucket_arn = aws_s3_bucket.osquery-results.arn - } -} - -resource "aws_kinesis_firehose_delivery_stream" "osquery_status" { - name = "osquery_status" - destination = "s3" - - s3_configuration { - role_arn = aws_iam_role.firehose-status.arn - bucket_arn = aws_s3_bucket.osquery-status.arn - } -} diff --git a/infrastructure/dogfood/terraform/aws/main.tf b/infrastructure/dogfood/terraform/aws/main.tf deleted file mode 100644 index 173c4104e9..0000000000 --- a/infrastructure/dogfood/terraform/aws/main.tf +++ /dev/null @@ -1,21 +0,0 @@ -provider "aws" { - region = var.region -} - -terraform { - // these values should match what is bootstrapped in ./remote-state - backend "s3" { - bucket = "fleet-terraform-remote-state" - region = "us-east-2" - key = "fleet" - dynamodb_table = "fleet-terraform-state-lock" - } - required_providers { - aws = { - source = "hashicorp/aws" - version = "4.32.0" - } - } -} - -data "aws_caller_identity" "current" {} diff --git a/infrastructure/dogfood/terraform/aws/monitoring/monitoring.tf b/infrastructure/dogfood/terraform/aws/monitoring/monitoring.tf deleted file mode 100644 index b72280e78d..0000000000 --- a/infrastructure/dogfood/terraform/aws/monitoring/monitoring.tf +++ /dev/null @@ -1,363 +0,0 @@ -terraform { - // these values should match what is bootstrapped in ./remote-state - backend "s3" { - bucket = "fleet-terraform-remote-state" - region = "us-east-2" - key = "fleet-monitoring/" - dynamodb_table = "fleet-terraform-state-lock" - } - required_providers { - aws = { - source = "hashicorp/aws" - version = "3.57.0" - } - } -} - -provider "aws" { - region = "us-east-2" -} - -data "aws_caller_identity" "current" {} -data "aws_region" "current" {} - -data "terraform_remote_state" "fleet" { - backend = "s3" - config = { - bucket = "fleet-terraform-remote-state" - region = "us-east-2" - key = "env:/${terraform.workspace}/fleet" - } -} - -locals { - fleet_ecs_service_name = data.terraform_remote_state.fleet.outputs.fleet_ecs_service_name - alb_target_group_name = data.terraform_remote_state.fleet.outputs.aws_alb_target_group_name - alb_name = data.terraform_remote_state.fleet.outputs.aws_alb_name -} - -// sns topic to send cloudwatch alarms to -// sns topic encryption is not currently supported but is something we will investigate providing in -// the future -resource "aws_sns_topic" "cloudwatch_alarm_topic" { #tfsec:ignore:aws-sns-enable-topic-encryption:exp:2022-08-01 - name = "cloudwatch-alarm-${terraform.workspace}" -} - -resource "aws_sns_topic_policy" "default" { - arn = aws_sns_topic.cloudwatch_alarm_topic.arn - policy = data.aws_iam_policy_document.sns_topic_policy.json -} - -data "aws_iam_policy_document" "sns_topic_policy" { - statement { - sid = "AllowManageSNS" - - actions = [ - "sns:Subscribe", - "sns:SetTopicAttributes", - "sns:RemovePermission", - "sns:Receive", - "sns:Publish", - "sns:ListSubscriptionsByTopic", - "sns:GetTopicAttributes", - "sns:DeleteTopic", - "sns:AddPermission", - ] - - effect = "Allow" - resources = [aws_sns_topic.cloudwatch_alarm_topic.arn] - - principals { - type = "AWS" - identifiers = ["*"] - } - - condition { - test = "StringEquals" - variable = "AWS:SourceOwner" - - values = [data.aws_caller_identity.current.account_id] - - } - } - - statement { - sid = "Allow CloudwatchEvents" - actions = ["sns:Publish"] - resources = [aws_sns_topic.cloudwatch_alarm_topic.arn] - - principals { - type = "Service" - identifiers = ["events.amazonaws.com"] - } - } - - statement { - sid = "Allow RDS Event Notification" - actions = ["sns:Publish"] - resources = [aws_sns_topic.cloudwatch_alarm_topic.arn] - - principals { - type = "Service" - identifiers = ["rds.amazonaws.com"] - } - } -} - - -// Database alarms -resource "aws_cloudwatch_metric_alarm" "cpu_utilization_too_high" { - for_each = data.terraform_remote_state.fleet.outputs.mysql_cluster_members - alarm_name = "rds_cpu_utilization_too_high-${each.key}-${terraform.workspace}" - comparison_operator = "GreaterThanThreshold" - evaluation_periods = "1" - metric_name = "CPUUtilization" - namespace = "AWS/RDS" - period = "300" - statistic = "Average" - threshold = 80 - alarm_description = "Average database CPU utilization over last 5 minutes too high" - alarm_actions = [aws_sns_topic.cloudwatch_alarm_topic.arn] - ok_actions = [aws_sns_topic.cloudwatch_alarm_topic.arn] - dimensions = { - DBInstanceIdentifier = each.key - } -} - -resource "aws_db_event_subscription" "default" { - name = "rds-event-sub-${terraform.workspace}" - sns_topic = aws_sns_topic.cloudwatch_alarm_topic.arn - - source_type = "db-instance" - source_ids = data.terraform_remote_state.fleet.outputs.mysql_cluster_members - - event_categories = [ - "failover", - "failure", - "low storage", - "maintenance", - "notification", - "recovery", - ] - - depends_on = [ - aws_sns_topic_policy.default - ] -} - -// ECS Alarms -resource "aws_cloudwatch_metric_alarm" "alb_healthyhosts" { - alarm_name = "backend-healthyhosts-${terraform.workspace}" - comparison_operator = "LessThanThreshold" - evaluation_periods = "1" - metric_name = "HealthyHostCount" - namespace = "AWS/ApplicationELB" - period = "60" - statistic = "Minimum" - threshold = data.terraform_remote_state.fleet.outputs.fleet_min_capacity - alarm_description = "This alarm indicates the number of Healthy Fleet hosts is lower than expected. Please investigate the load balancer \"${local.alb_name}\" or the target group \"${local.alb_target_group_name}\" and the fleet backend service \"${local.fleet_ecs_service_name}\"" - actions_enabled = "true" - alarm_actions = [aws_sns_topic.cloudwatch_alarm_topic.arn] - ok_actions = [aws_sns_topic.cloudwatch_alarm_topic.arn] - dimensions = { - TargetGroup = data.terraform_remote_state.fleet.outputs.target_group_arn_suffix - LoadBalancer = data.terraform_remote_state.fleet.outputs.load_balancer_arn_suffix - } -} - -// alarm for target response time (anomaly detection) -resource "aws_cloudwatch_metric_alarm" "target_response_time" { - alarm_name = "backend-target-response-time-${terraform.workspace}" - comparison_operator = "GreaterThanUpperThreshold" - evaluation_periods = "2" - threshold_metric_id = "e1" - alarm_description = "This alarm indicates the Fleet server response time is greater than it usually is. Please investigate the ecs service \"${local.fleet_ecs_service_name}\" because the backend might need to be scaled up." - alarm_actions = [aws_sns_topic.cloudwatch_alarm_topic.arn] - ok_actions = [aws_sns_topic.cloudwatch_alarm_topic.arn] - insufficient_data_actions = [] - - metric_query { - id = "e1" - expression = "ANOMALY_DETECTION_BAND(m1)" - label = "TargetResponseTime (Expected)" - return_data = "true" - } - - metric_query { - id = "m1" - return_data = "true" - metric { - metric_name = "TargetResponseTime" - namespace = "AWS/ApplicationELB" - period = "120" - stat = "p99" - unit = "Count" - - dimensions = { - TargetGroup = data.terraform_remote_state.fleet.outputs.target_group_arn_suffix - LoadBalancer = data.terraform_remote_state.fleet.outputs.load_balancer_arn_suffix - } - } - } -} - -resource "aws_cloudwatch_metric_alarm" "httpcode_elb_5xx_count" { - alarm_name = "backend-load-balancer-5XX-${terraform.workspace}" - comparison_operator = "GreaterThanThreshold" - evaluation_periods = "2" - metric_name = "HTTPCode_ELB_5XX_Count" - namespace = "AWS/ApplicationELB" - period = "60" - statistic = "Sum" - threshold = "25" - alarm_description = "This alarm indicates there are an abnormal amount of load balancer 5XX responses i.e it cannot talk with the Fleet backend target" - treat_missing_data = "notBreaching" - alarm_actions = [aws_sns_topic.cloudwatch_alarm_topic.arn] - ok_actions = [aws_sns_topic.cloudwatch_alarm_topic.arn] - dimensions = { - LoadBalancer = data.terraform_remote_state.fleet.outputs.load_balancer_arn_suffix - } -} - -// Elasticache (redis) alerts https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/CacheMetrics.WhichShouldIMonitor.html -resource "aws_cloudwatch_metric_alarm" "redis_cpu" { - for_each = data.terraform_remote_state.fleet.outputs.redis_cluster_members - alarm_name = "redis-cpu-utilization-${each.key}-${terraform.workspace}" - alarm_description = "Redis cluster CPU utilization node ${each.key}" - comparison_operator = "GreaterThanThreshold" - evaluation_periods = "1" - metric_name = "CPUUtilization" - namespace = "AWS/ElastiCache" - period = "300" - statistic = "Average" - alarm_actions = [aws_sns_topic.cloudwatch_alarm_topic.arn] - ok_actions = [aws_sns_topic.cloudwatch_alarm_topic.arn] - - threshold = "70" - - dimensions = { - CacheClusterId = each.key - } - -} - -resource "aws_cloudwatch_metric_alarm" "redis_cpu_engine_utilization" { - for_each = data.terraform_remote_state.fleet.outputs.redis_cluster_members - alarm_name = "redis-cpu-engine-utilization-${each.key}-${terraform.workspace}" - alarm_description = "Redis cluster CPU Engine utilization node ${each.key}" - comparison_operator = "GreaterThanThreshold" - evaluation_periods = "1" - metric_name = "EngineCPUUtilization" - namespace = "AWS/ElastiCache" - period = "300" - statistic = "Average" - alarm_actions = [aws_sns_topic.cloudwatch_alarm_topic.arn] - ok_actions = [aws_sns_topic.cloudwatch_alarm_topic.arn] - - threshold = "25" - - dimensions = { - CacheClusterId = each.key - } - -} - -resource "aws_cloudwatch_metric_alarm" "redis-database-memory-percentage" { - alarm_name = "redis-database-memory-percentage-${terraform.workspace}" - alarm_description = "Percentage of the memory available for the cluster that is in use. This is calculated using used_memory/maxmemory." - comparison_operator = "GreaterThanThreshold" - evaluation_periods = "1" - metric_name = "DatabaseMemoryUsagePercentage" - namespace = "AWS/ElastiCache" - period = "300" - statistic = "Average" - alarm_actions = [aws_sns_topic.cloudwatch_alarm_topic.arn] - ok_actions = [aws_sns_topic.cloudwatch_alarm_topic.arn] - - threshold = "80" - -} - -resource "aws_cloudwatch_metric_alarm" "redis-current-connections" { - for_each = data.terraform_remote_state.fleet.outputs.redis_cluster_members - alarm_name = "redis-current-connections-${each.key}-${terraform.workspace}" - alarm_description = "Redis current connections for node ${each.key}" - comparison_operator = "LessThanLowerOrGreaterThanUpperThreshold" - evaluation_periods = "5" - threshold_metric_id = "e1" - alarm_actions = [aws_sns_topic.cloudwatch_alarm_topic.arn] - ok_actions = [aws_sns_topic.cloudwatch_alarm_topic.arn] - insufficient_data_actions = [] - - metric_query { - id = "e1" - expression = "ANOMALY_DETECTION_BAND(m1,20)" - label = "Current Connections (Expected)" - return_data = "true" - } - - metric_query { - id = "m1" - return_data = "true" - metric { - metric_name = "CurrConnections" - namespace = "AWS/ElastiCache" - period = "600" - stat = "Average" - unit = "Count" - - dimensions = { - CacheClusterId = each.key - } - } - } -} - -resource "aws_cloudwatch_metric_alarm" "redis-replication-lag" { - alarm_name = "redis-replication-lag-${terraform.workspace}" - alarm_description = "This metric is only applicable for a node running as a read replica. It represents how far behind, in seconds, the replica is in applying changes from the primary node. For Redis engine version 5.0.6 onwards, the lag can be measured in milliseconds." - comparison_operator = "GreaterThanUpperThreshold" - evaluation_periods = "3" - threshold_metric_id = "e1" - alarm_actions = [aws_sns_topic.cloudwatch_alarm_topic.arn] - ok_actions = [aws_sns_topic.cloudwatch_alarm_topic.arn] - insufficient_data_actions = [] - - metric_query { - id = "e1" - expression = "ANOMALY_DETECTION_BAND(m1)" - label = "ReplicationLag (expected)" - return_data = "true" - } - - metric_query { - id = "m1" - return_data = "true" - metric { - metric_name = "ReplicationLag" - namespace = "AWS/ElastiCache" - period = "300" - stat = "p90" - } - } -} - -// ACM Certificate Manager -resource "aws_cloudwatch_metric_alarm" "acm_certificate_expired" { - alarm_name = "acm-cert-expiry-${terraform.workspace}" - comparison_operator = "LessThanThreshold" - evaluation_periods = "1" - period = "86400" // 1 day in seconds - threshold = 30 // days - statistic = "Average" - namespace = "AWS/CertificateManager" - metric_name = "DaysToExpiry" - actions_enabled = "true" - alarm_description = "ACM Certificate will expire soon" - alarm_actions = [aws_sns_topic.cloudwatch_alarm_topic.arn] - ok_actions = [aws_sns_topic.cloudwatch_alarm_topic.arn] - - dimensions = { - CertificateArn = data.terraform_remote_state.fleet.outputs.acm_certificate_arn - } -} \ No newline at end of file diff --git a/infrastructure/dogfood/terraform/aws/outputs.tf b/infrastructure/dogfood/terraform/aws/outputs.tf deleted file mode 100644 index 6553387cbf..0000000000 --- a/infrastructure/dogfood/terraform/aws/outputs.tf +++ /dev/null @@ -1,71 +0,0 @@ -output "nameservers_fleetdm" { - value = aws_route53_zone.dogfood_fleetdm_com.name_servers -} - -output "backend_security_group" { - value = aws_security_group.backend.arn -} - -output "private_subnets" { - value = module.vpc.private_subnets -} - -output "fleet-backend-task-revision" { - value = aws_ecs_task_definition.backend.revision -} - -output "fleet-migration-task-revision" { - value = aws_ecs_task_definition.migration.revision -} - -output "redis_cluster_members" { - value = toset(aws_elasticache_replication_group.default.member_clusters) -} - -output "mysql_cluster_members" { - value = toset(module.aurora_mysql.rds_cluster_instance_ids) -} - -output "acm_certificate_arn" { - value = aws_acm_certificate.dogfood_fleetdm_com.arn -} - -output "load_balancer_arn_suffix" { - value = aws_alb.main.arn_suffix -} - -output "target_group_arn_suffix" { - value = aws_alb_target_group.main.arn_suffix -} - -output "fleet_min_capacity" { - value = var.fleet_min_capacity -} - -output "fleet_ecs_service_name" { - value = aws_ecs_service.fleet.name -} - -output "aws_alb_target_group_name" { - value = aws_alb_target_group.main.name -} - -output "aws_alb_name" { - value = aws_alb.main.name -} - -output "backend_security_group_id" { - value = aws_security_group.backend.id -} - -output "private_subnet" { - value = module.vpc.private_subnets[0] -} - -output "ecs_cluster_name" { - value = aws_ecs_cluster.fleet.name -} - -output "migrate_task_definition_family" { - value = aws_ecs_task_definition.migration.family -} \ No newline at end of file diff --git a/infrastructure/dogfood/terraform/aws/percona/network.tf b/infrastructure/dogfood/terraform/aws/percona/network.tf deleted file mode 100644 index dbdce6985e..0000000000 --- a/infrastructure/dogfood/terraform/aws/percona/network.tf +++ /dev/null @@ -1,30 +0,0 @@ -resource "aws_acm_certificate" "certificate" { - domain_name = var.domain_name - validation_method = "DNS" - - lifecycle { - create_before_destroy = true - } -} - -resource "aws_route53_record" "record" { - for_each = { - for dvo in aws_acm_certificate.certificate.domain_validation_options : dvo.domain_name => { - name = dvo.resource_record_name - record = dvo.resource_record_value - type = dvo.resource_record_type - } - } - - allow_overwrite = true - name = each.value.name - records = [each.value.record] - ttl = 60 - type = each.value.type - zone_id = var.zone_id -} - -resource "aws_acm_certificate_validation" "percona" { - certificate_arn = aws_acm_certificate.certificate.arn - validation_record_fqdns = [for record in aws_route53_record.record : record.fqdn] -} diff --git a/infrastructure/dogfood/terraform/aws/percona/percona.tf b/infrastructure/dogfood/terraform/aws/percona/percona.tf deleted file mode 100644 index 1577429e02..0000000000 --- a/infrastructure/dogfood/terraform/aws/percona/percona.tf +++ /dev/null @@ -1,137 +0,0 @@ -data "aws_ami" "percona" { - most_recent = true - - filter { - name = "name" - values = ["PMM2 Server *"] - } - - owners = ["679593333241"] # Percona -} - - -resource "aws_route53_record" "record" { - name = "percona" - type = "A" - zone_id = var.zone_id - alias { - evaluate_target_health = false - name = aws_lb.main.dns_name - zone_id = aws_lb.main.zone_id - } -} - -resource "aws_lb" "main" { - name = "percona" - // Exposed to the Internet by design - internal = false #tfsec:ignore:aws-elb-alb-not-public - security_groups = [aws_security_group.lb.id, aws_security_group.backend.id] - subnets = var.public_subnets - idle_timeout = 905 - drop_invalid_header_fields = true -} - -resource "aws_lb_listener" "https" { - load_balancer_arn = aws_lb.main.arn - port = 443 - protocol = "HTTPS" - ssl_policy = "ELBSecurityPolicy-FS-1-2-Res-2019-08" - certificate_arn = aws_acm_certificate_validation.percona.certificate_arn - - default_action { - target_group_arn = aws_lb_target_group.percona.arn - type = "forward" - } -} - -resource "aws_lb_target_group" "percona" { - name = "percona" - protocol = "HTTP" - target_type = "instance" - port = "80" - vpc_id = var.vpc_id -} - -resource "aws_lb_target_group_attachment" "percona" { - target_group_arn = aws_lb_target_group.percona.arn - target_id = aws_instance.percona.id -} - -// No permanent EBS encrypted volume at the moment. -resource "aws_instance" "percona" { #tfsec:ignore:aws-ec2-enable-at-rest-encryption:exp:2022-07-15 - ami = data.aws_ami.percona.id - instance_type = "m5.large" - subnet_id = var.private_subnet - vpc_security_group_ids = [aws_security_group.backend.id] - iam_instance_profile = aws_iam_instance_profile.profile.name - metadata_options { - http_tokens = "required" - } -} - -resource "aws_iam_instance_profile" "profile" { - name = "percona-profile" - role = aws_iam_role.role.name -} - -resource "aws_iam_role" "role" { - name = "percona-role" - - assume_role_policy = < { - name = dvo.resource_record_name - record = dvo.resource_record_value - type = dvo.resource_record_type - } - } - - allow_overwrite = true - name = each.value.name - records = [each.value.record] - ttl = 60 - type = each.value.type - zone_id = aws_route53_zone.dogfood_fleetdm_com.zone_id -} - -resource "aws_acm_certificate_validation" "dogfood_fleetdm_com" { - certificate_arn = aws_acm_certificate.dogfood_fleetdm_com.arn - validation_record_fqdns = [for record in aws_route53_record.dogfood_fleetdm_com_validation : record.fqdn] -} diff --git a/infrastructure/dogfood/terraform/aws/rds.tf b/infrastructure/dogfood/terraform/aws/rds.tf deleted file mode 100644 index bd37ea9cf9..0000000000 --- a/infrastructure/dogfood/terraform/aws/rds.tf +++ /dev/null @@ -1,129 +0,0 @@ -resource "random_password" "database_password" { - length = 32 - special = false -} -// Customer keys are not supported in our Fleet Terraforms at the moment. We will evaluate the -// possibility of providing this capability in the future. -resource "aws_secretsmanager_secret" "database_password_secret" { #tfsec:ignore:aws-ssm-secret-use-customer-key:exp:2022-07-01 - name = "/fleet/database/password/master" - recovery_window_in_days = 0 -} - -resource "aws_secretsmanager_secret_version" "database_password_secret_version" { - secret_id = aws_secretsmanager_secret.database_password_secret.id - secret_string = random_password.database_password.result -} - -// if you want to use RDS Serverless option prefer the following commented block -//module "aurora_mysql_serverless" { -// source = "terraform-aws-modules/rds-aurora/aws" -// version = "5.2.0" -// -// name = "${local.name}-mysql" -// engine = "aurora-mysql" -// engine_mode = "serverless" -// storage_encrypted = true -// username = "fleet" -// password = random_password.database_password.result -// create_random_password = false -// database_name = "fleet" -// enable_http_endpoint = true -// -// vpc_id = module.vpc.vpc_id -// subnets = module.vpc.database_subnets -// create_security_group = true -// allowed_cidr_blocks = concat(module.vpc.private_subnets_cidr_blocks, var.extra_security_group_cidrs) -// -// replica_scale_enabled = false -// replica_count = 0 -// -// monitoring_interval = 60 -// -// apply_immediately = true -// skip_final_snapshot = true -// -// db_parameter_group_name = aws_db_parameter_group.example_mysql.id -// db_cluster_parameter_group_name = aws_rds_cluster_parameter_group.example_mysql.id -// -// scaling_configuration = { -// auto_pause = true -// min_capacity = 2 -// max_capacity = 16 -// seconds_until_auto_pause = 300 -// timeout_action = "ForceApplyCapacityChange" -// } -//} - -variable "db_instance_type_writer" { - default = "db.t4g.medium" -} -variable "db_instance_type_reader" { - default = "db.t4g.medium" -} - -module "aurora_mysql" { - source = "terraform-aws-modules/rds-aurora/aws" - version = "5.2.0" - - name = "${local.name}-mysql-iam" - engine = "aurora-mysql" - engine_version = "8.0.mysql_aurora.3.05.2" - instance_type = var.db_instance_type_writer - instance_type_replica = var.db_instance_type_reader - - iam_database_authentication_enabled = true - storage_encrypted = true - username = var.database_user - password = random_password.database_password.result - create_random_password = false - database_name = var.database_name - enable_http_endpoint = false - backup_retention_period = var.rds_backup_retention_period - snapshot_identifier = var.rds_initial_snapshot - #performance_insights_enabled = true - - vpc_id = module.vpc.vpc_id - subnets = module.vpc.database_subnets - create_security_group = true - allowed_cidr_blocks = concat(module.vpc.private_subnets_cidr_blocks, var.extra_security_group_cidrs) - - replica_count = 1 - replica_scale_enabled = true - replica_scale_min = 1 - replica_scale_max = 3 - - monitoring_interval = 60 - iam_role_name = "${local.name}-rds-enhanced-monitoring" - iam_role_use_name_prefix = true - iam_role_description = "${local.name} RDS enhanced monitoring IAM role" - iam_role_path = "/autoscaling/" - iam_role_max_session_duration = 7200 - - apply_immediately = true - skip_final_snapshot = true - - db_parameter_group_name = aws_db_parameter_group.example_mysql.id - db_cluster_parameter_group_name = aws_rds_cluster_parameter_group.example_mysql.id -} - -resource "aws_db_parameter_group" "example_mysql" { - name = "${local.name}-aurora-db-mysql-parameter-group" - family = "aurora-mysql8.0" - description = "${local.name}-aurora-db-mysql-parameter-group" -} - -resource "aws_rds_cluster_parameter_group" "example_mysql" { - name = "${local.name}-aurora-mysql-cluster-parameter-group" - family = "aurora-mysql8.0" - description = "${local.name}-aurora-mysql-cluster-parameter-group" -} - -resource "null_resource" "rds_guardian" { - triggers = { - rds_cluster = module.aurora_mysql.rds_cluster_endpoint - } - - lifecycle { - prevent_destroy = true - } -} diff --git a/infrastructure/dogfood/terraform/aws/readme.md b/infrastructure/dogfood/terraform/aws/readme.md deleted file mode 100644 index 1e2a6fb1c6..0000000000 --- a/infrastructure/dogfood/terraform/aws/readme.md +++ /dev/null @@ -1,76 +0,0 @@ -## Terraform - -### Bootstrapping remote state - -First we need to bootstrap our terraform remote state management. This lives outside the main project to avoid "chicken before the egg" -issues. We are going to create the remote state S3 bucket and DynamoDB state locking table and then use hardcoded values -in parent folder `main.tf`. -1. `cd remote-state` -2. `terraform init` -3. `terraform apply` - -### Creating the Fleet infrastructure - -Create a new `tfvars` file for example: - -```terraform -fleet_backend_cpu = 512 -fleet_backend_mem = 4096 // 4GB needed for vuln processing -redis_instance = "cache.t3.micro" -fleet_min_capacity = 2 -fleet_max_capacity = 5 -``` - -If you have a Fleet license key you can include it in the `tfvars` file which will enable the paid features. - -```terraform -fleet_license = "` -3. `terraform apply -var-file=` - -**To deploy cloudwatch alarms** (requires infrastruture to be deployed) -1. `cd monitoring` -2. `terraform init && terraform workspace new prod` (workspace is optional terraform defaults to the `default` workspace) -3. `terraform plan -var-file=` -4. `terraform apply -var-file=` - -Check out [AWS Chatbot](https://docs.aws.amazon.com/chatbot/latest/adminguide/setting-up.html) for a quick and easy way to hook up Cloudwatch Alarms into a Slack channel. - -**To deploy Percona PMM advanced MySQL monitoring** -1. See [Percona deployment](https://www.percona.com/doc/percona-monitoring-and-management/1.x/deploy/server/ami.html#running-pmm-server-using-aws-marketplace) scenario for details -2. Deploy infrastructure using `percona` directory - 1. Create tfvars file - 2. Add the required variables (vpc_id, subnets, etc.) - 3. run `terraform apply -var-file=default.tfvars` -3. Add RDS Aurora MySQL by following this [guide](https://www.percona.com/doc/percona-monitoring-and-management/1.x/amazon-rds.html) - -### Configuration - -Typical settings to override in an existing environment: - -`module.vpc.vpc_id` -- the VPC ID output from VPC module. If you are introducing fleet to an existing VPC, you could replace all instances with your VPC ID. - -In this reference architecture we are placing ECS, RDS MySQL, and Redis (ElastiCache) in separate subnets, each associated to a route table, allowing communication between. -This is not required, as long as Fleet can resolve the MySQL and Redis hosts, that should be adequate. - -#### HTTPS - -The ALB is in the public subnet with an ENI to bridge into the private subnet. SSL is terminated at the ALB and `fleet serve` is launched with `FLEET_SERVER_TLS=false` as an -environment variable. - -Replace `cert_arn` with the **certificate ARN** that applies to your environment. This is the **certificate ARN** used in the **ALB HTTPS Listener**. - -### Migrating the DB - -After applying terraform run the following to migrate the database(`` and `` can be obtained from the terraform output after applying, any value will suffice): -``` -aws ecs run-task --cluster fleet-backend --task-definition fleet-migrate: --launch-type FARGATE --network-configuration "awsvpcConfiguration={subnets=[],securityGroups=[]}" -``` - -### Conecting a host - -Use your Route53 entry as your `fleet-url` [following these details.](https://fleetdm.com/docs/using-fleet/adding-hosts) \ No newline at end of file diff --git a/infrastructure/dogfood/terraform/aws/redis.tf b/infrastructure/dogfood/terraform/aws/redis.tf deleted file mode 100644 index fccf314c33..0000000000 --- a/infrastructure/dogfood/terraform/aws/redis.tf +++ /dev/null @@ -1,63 +0,0 @@ -variable "maintenance_window" { - default = "" -} -variable "engine_version" { - default = "6.x" -} -variable "number_cache_clusters" { - default = 3 -} -variable "redis_instance" { - default = "cache.m5.large" -} -resource "aws_elasticache_replication_group" "default" { - availability_zones = var.redis_azs - engine = "redis" - parameter_group_name = "default.redis6.x" - subnet_group_name = module.vpc.elasticache_subnet_group_name - security_group_ids = [aws_security_group.redis.id] - replication_group_id = "fleetdm-redis" - number_cache_clusters = var.number_cache_clusters - node_type = var.redis_instance - engine_version = var.engine_version - port = "6379" - maintenance_window = var.maintenance_window - snapshot_retention_limit = 0 - automatic_failover_enabled = true - at_rest_encryption_enabled = true - transit_encryption_enabled = true - apply_immediately = true - replication_group_description = "fleetdm-redis" -} - -resource "aws_security_group" "redis" { #tfsec:ignore:aws-vpc-add-description-to-security-group - // description = "Security group for Redis" // cannot add description without recreation - name = local.security_group_name - vpc_id = module.vpc.vpc_id -} - -locals { - security_group_name = "${var.prefix}-elasticache-redis" -} - -resource "aws_security_group_rule" "ingress" { - description = "Redis from private VPC" - type = "ingress" - from_port = "6379" - to_port = "6379" - protocol = "tcp" - cidr_blocks = concat(module.vpc.private_subnets_cidr_blocks, var.extra_security_group_cidrs) - security_group_id = aws_security_group.redis.id -} - -resource "aws_security_group_rule" "egress" { - description = "Redis VPC egress" - type = "egress" - from_port = 0 - to_port = 0 - protocol = "-1" - // Egress filtering is not currently provided by our Terraform templates. - cidr_blocks = ["0.0.0.0/0"] #tfsec:ignore:aws-vpc-no-public-egress-sgr:exp:2022-10-01 - security_group_id = aws_security_group.redis.id -} - diff --git a/infrastructure/dogfood/terraform/aws/remote-state/main.tf b/infrastructure/dogfood/terraform/aws/remote-state/main.tf deleted file mode 100644 index e199ccaea4..0000000000 --- a/infrastructure/dogfood/terraform/aws/remote-state/main.tf +++ /dev/null @@ -1,69 +0,0 @@ -variable "prefix" { - default = "fleet" -} - -variable "region" { - default = "us-east-2" -} - -provider "aws" { - region = var.region -} -// Customer keys are not supported in our Fleet Terraforms at the moment. We will evaluate the -// possibility of providing this capability in the future. -// Bucket logging is not supported in our Fleet Terraforms at the moment. It can be enabled by the -// organizations deploying Fleet, and we will evaluate the possibility of providing this capability -// in the future. -resource "aws_s3_bucket" "remote_state" { #tfsec:ignore:aws-s3-encryption-customer-key:exp:2022-07-01 #tfsec:ignore:aws-s3-enable-bucket-logging:exp:2022-06-15 - bucket = "${var.prefix}-terraform-remote-state" - acl = "private" - versioning { - enabled = true - } - lifecycle { - prevent_destroy = true - } - server_side_encryption_configuration { - rule { - apply_server_side_encryption_by_default { - sse_algorithm = "aws:kms" - } - } - } - tags = { - Name = "S3 Remote Terraform State Store" - } -} - -resource "aws_s3_bucket_public_access_block" "fleet_terraform_state" { - bucket = aws_s3_bucket.remote_state.id - block_public_acls = true - block_public_policy = true - ignore_public_acls = true - restrict_public_buckets = true -} - - -resource "aws_dynamodb_table" "fleet_terraform_state_lock" { - name = "${var.prefix}-terraform-state-lock" - hash_key = "LockID" - billing_mode = "PAY_PER_REQUEST" - - attribute { - name = "LockID" - type = "S" - } - - tags = { - Name = "DynamoDB Terraform State Lock Table" - } - // Customer keys are not supported in our Fleet Terraforms at the moment. We will evaluate the - // possibility of providing this capability in the future. - server_side_encryption { #tfsec:ignore:aws-dynamodb-table-customer-key:exp:2022-07-01 - enabled = true // enabled server side encryption - } - - point_in_time_recovery { - enabled = true - } -} \ No newline at end of file diff --git a/infrastructure/dogfood/terraform/aws/s3.tf b/infrastructure/dogfood/terraform/aws/s3.tf deleted file mode 100644 index c0edb2db44..0000000000 --- a/infrastructure/dogfood/terraform/aws/s3.tf +++ /dev/null @@ -1,35 +0,0 @@ -// file carving destination with versioning disabled and lifecycle to ensure files get deleted and -// no version is ever kept - -// Customer keys are not supported in our Fleet Terraforms at the moment. We will evaluate the -// possibility of providing this capability in the future. -// Bucket logging is not supported in our Fleet Terraforms at the moment. It can be enabled by the -// organizations deploying Fleet, and we will evaluate the possibility of providing this capability -// in the future. -resource "aws_s3_bucket" "osquery-carve" { #tfsec:ignore:aws-s3-enable-versioning #tfsec:ignore:aws-s3-encryption-customer-key:exp:2022-07-01 #tfsec:ignore:aws-s3-enable-bucket-logging:exp:2022-06-15 - bucket = "osquery-carve-${terraform.workspace}" - acl = "private" - - lifecycle_rule { - enabled = true - expiration { - days = 7 - } - } - - server_side_encryption_configuration { - rule { - apply_server_side_encryption_by_default { - sse_algorithm = "aws:kms" - } - } - } -} - -resource "aws_s3_bucket_public_access_block" "osquery-carve" { - bucket = aws_s3_bucket.osquery-carve.id - block_public_acls = true - block_public_policy = true - ignore_public_acls = true - restrict_public_buckets = true -} \ No newline at end of file diff --git a/infrastructure/dogfood/terraform/aws/vpc.tf b/infrastructure/dogfood/terraform/aws/vpc.tf deleted file mode 100644 index 5563fad940..0000000000 --- a/infrastructure/dogfood/terraform/aws/vpc.tf +++ /dev/null @@ -1,24 +0,0 @@ -module "vpc" { - source = "terraform-aws-modules/vpc/aws" - - name = "fleet-vpc" - cidr = "10.10.0.0/16" - - azs = var.vpc_azs - private_subnets = ["10.10.1.0/24", "10.10.2.0/24", "10.10.3.0/24"] - public_subnets = ["10.10.11.0/24", "10.10.12.0/24", "10.10.13.0/24"] - database_subnets = ["10.10.21.0/24", "10.10.22.0/24", "10.10.23.0/24"] - elasticache_subnets = ["10.10.31.0/24", "10.10.32.0/24", "10.10.33.0/24"] - - create_database_subnet_group = true - create_database_subnet_route_table = true - - create_elasticache_subnet_group = true - create_elasticache_subnet_route_table = true - - enable_vpn_gateway = false - one_nat_gateway_per_az = false - - single_nat_gateway = true - enable_nat_gateway = true -} \ No newline at end of file diff --git a/infrastructure/dogfood/terraform/aws/vuln_processing.tf b/infrastructure/dogfood/terraform/aws/vuln_processing.tf deleted file mode 100644 index a8163b89f2..0000000000 --- a/infrastructure/dogfood/terraform/aws/vuln_processing.tf +++ /dev/null @@ -1,151 +0,0 @@ -resource "aws_ecs_task_definition" "vuln-processing" { - family = "fleet-vuln-processing" - cpu = 2048 - memory = 4096 - execution_role_arn = aws_iam_role.main.arn - task_role_arn = aws_iam_role.main.arn - network_mode = "awsvpc" - requires_compatibilities = ["FARGATE"] - - container_definitions = jsonencode([ - { - name = "fleet-vuln-processing" - image = var.fleet_image - essential = true - command = ["fleet", "vuln_processing"] - networkMode = "awsvpc" - secrets = [ - { - name = "FLEET_MYSQL_PASSWORD" - valueFrom = aws_secretsmanager_secret.database_password_secret.arn - } - ] - environment = [ - { - name = "FLEET_MYSQL_USERNAME" - value = module.aurora_mysql.rds_cluster_master_username - }, - { - name = "FLEET_MYSQL_DATABASE" - value = module.aurora_mysql.rds_cluster_database_name - }, - { - name = "FLEET_MYSQL_ADDRESS" - value = "${module.aurora_mysql.rds_cluster_endpoint}:3306" - }, - { - name = "FLEET_VULNERABILITIES_DATABASES_PATH" - value = "/home/fleet/vuln_data" - }, - { - name = "FLEET_LOGGING_DEBUG" - value = "true" - }, - { - name = "FLEET_LICENSE_KEY" - value = var.fleet_license - } - ], - logConfiguration = { - logDriver = "awslogs" - options = { - awslogs-group = aws_cloudwatch_log_group.backend.name - awslogs-region = data.aws_region.current.name - awslogs-stream-prefix = "fleet-vuln-processing" - } - } - } - ]) -} - -resource "aws_cloudwatch_event_rule" "vuln_processing" { - name_prefix = "${local.name}-vuln-processing" - schedule_expression = "rate(1 hour)" - is_enabled = false -} - -resource "aws_cloudwatch_event_target" "vuln_processing" { - arn = aws_ecs_cluster.fleet.arn - rule = aws_cloudwatch_event_rule.vuln_processing.name - role_arn = aws_iam_role.run_cloudwatch.arn - ecs_target { - task_definition_arn = aws_ecs_task_definition.vuln-processing.arn - task_count = 1 - launch_type = "FARGATE" - network_configuration { - assign_public_ip = false - subnets = module.vpc.private_subnets - security_groups = [aws_security_group.backend.id] - } - } -} - - -data "aws_iam_policy_document" "assume_events" { - statement { - effect = "Allow" - actions = ["sts:AssumeRole"] - - principals { - type = "Service" - identifiers = ["events.amazonaws.com"] - } - } -} - - - -data "aws_iam_policy_document" "cloudwatch_task" { - statement { - effect = "Allow" - actions = ["iam:PassRole"] - resources = ["*"] - } - - statement { - effect = "Allow" - actions = ["ecs:RunTask"] - resources = ["*"] - condition { - test = "ArnEquals" - variable = "ecs:cluster" - values = [aws_ecs_cluster.fleet.arn] - } - } -} - -data "aws_iam_policy_document" "assume_role_policy" { - statement { - effect = "Allow" - actions = ["sts:AssumeRole"] - - principals { - type = "Service" - identifiers = ["ecs-tasks.amazonaws.com"] - } - } -} - -resource "aws_iam_role" "run_cloudwatch" { - name = "${local.name}-cloudwatch-run" - assume_role_policy = data.aws_iam_policy_document.assume_events.json -} - -resource "aws_iam_policy" "run_cloudwatch" { - name = "${local.name}-cloudwatch-run" - policy = data.aws_iam_policy_document.cloudwatch_task.json -} -resource "aws_iam_role_policy_attachment" "run_cloudwatch" { - role = aws_iam_role.run_cloudwatch.name - policy_arn = aws_iam_policy.run_cloudwatch.arn -} - -resource "aws_iam_role_policy_attachment" "ecs_role_attachment" { - role = aws_iam_role.main.name - policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceRole" -} - -resource "aws_iam_role_policy_attachment" "ecs_task" { - policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceEventsRole" - role = aws_iam_role.main.name -} \ No newline at end of file