diff --git a/infrastructure/infrastructure/elastic-agent/.terraform.lock.hcl b/infrastructure/infrastructure/elastic-agent/.terraform.lock.hcl new file mode 100644 index 0000000000..ec59d9ece6 --- /dev/null +++ b/infrastructure/infrastructure/elastic-agent/.terraform.lock.hcl @@ -0,0 +1,25 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/aws" { + version = "4.59.0" + constraints = ">= 3.63.0, ~> 4.59.0" + hashes = [ + "h1:fuIdjl9f2JEH0TLoq5kc9NIPbJAAV7YBbZ8fvNp5XSg=", + "zh:0341a460210463a0bebd5c12ce13dc49bd8cae2399b215418c5efa607fed84e4", + "zh:0544e9bbdd31d3551e7273bed7326d26a28653fd9c26b5cd06ac8ed76f188798", + "zh:3d13acd0363f0a48d2725cae9d224481df38dddb90ef4a66eb82303f0aa45a99", + "zh:416f5b92d41dce1d7ee1a1acb06ba8b0f10679eecee2fcc134853adbb09d9757", + "zh:80c9c3b901151cd697caa58bfa196816d4622e4ce11aa789e36efc460695313b", + "zh:8fc3659ebdae1ac9de899f57e5a3a50274a2e96c46aa2cf74be51ffdac56300a", + "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", + "zh:a235b44ad074446a6138b3fb454dd0d234aacf7a1efea89d1eafac7284689d19", + "zh:a36a7f1cd7f9f6c45127d916a65b5441cc0430393535a5a3de4b646405c50c41", + "zh:c161c38727902271efa19020b95b69ebe0282989d575f31dff603a1d551bafd2", + "zh:d1562223347c49cbe3ff6e7295e25816a35dfef862d28cd8a7870e7be6ec8093", + "zh:e7a1d08bfe91d3789755ee587fc816907c3bea203342c717144c7459111ce20c", + "zh:e89d5a668c391669ed323d493c5ea131fe8833d562a6fe31f525bdcbe959056e", + "zh:f268ccd3e1a32ba7fd59bbf0c8d85611201c0c87462a2a5cddd02babde7b5fe8", + "zh:fe8c2eae8c367d2cb7cade250a8d5f6c411ac4a8214c46df0a1fd90d9eaf7152", + ] +} diff --git a/infrastructure/infrastructure/elastic-agent/main.tf b/infrastructure/infrastructure/elastic-agent/main.tf new file mode 100644 index 0000000000..ae7ef8d890 --- /dev/null +++ b/infrastructure/infrastructure/elastic-agent/main.tf @@ -0,0 +1,194 @@ +provider "aws" { + region = "us-east-2" + default_tags { + tags = { + environment = "elastic-agent" + terraform = "https://github.com/fleetdm/fleet/tree/main/infrastructure/infrastructure/elastic-agent" + state = "s3://fleet-terraform-state20220408141538466600000002/infrastructure/elastic-agent/terraform.tfstate" + } + } +} + +data "aws_caller_identity" "current" {} +data "aws_region" "current" {} + +variable "fleet_url" {} +variable "fleet_enroll_token" {} +variable "kibana_fleet_password" {} + +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 4.59.0" + } + } + backend "s3" { + bucket = "fleet-terraform-state20220408141538466600000002" + key = "infrastructure/elastic-agent/terraform.tfstate" # This should be set to account_alias/unique_key/terraform.tfstate + workspace_key_prefix = "infrastructure" # This should be set to the account alias + region = "us-east-2" + encrypt = true + kms_key_id = "9f98a443-ffd7-4dbe-a9c3-37df89b2e42a" + dynamodb_table = "tf-remote-state-lock" + } +} + +module "vpc" { + source = "terraform-aws-modules/vpc/aws" + version = "3.12.0" + + name = "elastic-agent" + cidr = "10.10.0.0/16" + + azs = ["us-east-2a", "us-east-2b", "us-east-2c"] + private_subnets = [ + "10.10.16.0/20", + "10.10.32.0/20", + "10.10.48.0/20", + ] + public_subnets = [ + "10.10.128.0/24", + "10.10.129.0/24", + "10.10.130.0/24", + ] + + create_database_subnet_group = false + create_database_subnet_route_table = false + + create_elasticache_subnet_group = false + create_elasticache_subnet_route_table = false + + enable_vpn_gateway = false + one_nat_gateway_per_az = false + + single_nat_gateway = true + enable_nat_gateway = true +} + +resource "aws_ecs_cluster" "main" { + name = "main" + + setting { + name = "containerInsights" + value = "enabled" + } +} + +output "ecs_cluster" { + value = aws_ecs_cluster.main +} + +resource "aws_ecs_service" "main" { + name = "elastic-agent" + launch_type = "FARGATE" + cluster = aws_ecs_cluster.main.id + task_definition = aws_ecs_task_definition.main.arn + desired_count = 1 + deployment_minimum_healthy_percent = 100 + deployment_maximum_percent = 200 + + lifecycle { + ignore_changes = [desired_count] + } + + network_configuration { + subnets = module.vpc.private_subnets + security_groups = [aws_security_group.main.id] + } +} + +resource "aws_ecs_task_definition" "main" { + family = "elastic-agent" + network_mode = "awsvpc" + requires_compatibilities = ["FARGATE"] + execution_role_arn = aws_iam_role.execution.arn + cpu = 256 + memory = 512 + container_definitions = jsonencode( + [ + { + name = "elastic-agent" + image = "docker.elastic.co/beats/elastic-agent:8.7.0" + cpu = 256 + memory = 512 + essential = true + networkMode = "awsvpc" + logConfiguration = { + logDriver = "awslogs" + options = { + awslogs-group = aws_cloudwatch_log_group.main.name + awslogs-region = data.aws_region.current.name + awslogs-stream-prefix = "elastic-agent" + } + }, + environment = [ + { + name = "FLEET_ENROLL" + value = "1" + }, + { + name = "FLEET_URL" + value = var.fleet_url + }, + { + name = "FLEET_ENROLLMENT_TOKEN" + value = var.fleet_enroll_token + }, + { + name = "KIBANA_HOST" + value = "http://kibana:5601" + }, + { + name = "KIBANA_FLEET_USERNAME" + value = "elastic" + }, + { + name = "KIBANA_FLEET_PASSWORD" + value = var.kibana_fleet_password + }, + ] + } + ]) +} + +resource "aws_cloudwatch_log_group" "main" { + name = "elastic-agent" + retention_in_days = 30 +} + +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" "execution" { + name = "elastic-agent" + description = "The execution role for Elastic Agent" + 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.execution.name +} + +resource "aws_security_group" "main" { + name = "elastic-agent" + description = "Elastic Agent Service Security Group" + vpc_id = module.vpc.vpc_id + egress { + description = "Egress to all" + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + ipv6_cidr_blocks = ["::/0"] + } +}