mirror of
https://github.com/empayre/fleet.git
synced 2024-11-06 08:55:24 +00:00
create vuln processing addon (#10526)
two things here: 1. create addon for use in new modular terraform 2. create vuln processing terraform for legacy terraform, but by default its disabled
This commit is contained in:
parent
0e2c9bb873
commit
4161ee5679
151
infrastructure/dogfood/terraform/aws/vuln_processing.tf
Normal file
151
infrastructure/dogfood/terraform/aws/vuln_processing.tf
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
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
|
||||||
|
}
|
@ -26,7 +26,7 @@ module "aurora_mysql" { #tfsec:ignore:aws-rds-enable-performance-insights-encryp
|
|||||||
|
|
||||||
name = "${local.name}-mysql"
|
name = "${local.name}-mysql"
|
||||||
engine = "aurora-mysql"
|
engine = "aurora-mysql"
|
||||||
engine_version = "5.7.mysql_aurora.2.10.2"
|
engine_version = "5.7.mysql_aurora.2.10.3"
|
||||||
instance_type = var.db_instance_type
|
instance_type = var.db_instance_type
|
||||||
instance_type_replica = var.db_instance_type
|
instance_type_replica = var.db_instance_type
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ resource "aws_elasticache_replication_group" "default" {
|
|||||||
security_group_ids = [aws_security_group.redis.id, aws_security_group.backend.id]
|
security_group_ids = [aws_security_group.redis.id, aws_security_group.backend.id]
|
||||||
replication_group_id = "${local.prefix}-redis"
|
replication_group_id = "${local.prefix}-redis"
|
||||||
number_cache_clusters = 3
|
number_cache_clusters = 3
|
||||||
node_type = "cache.m6g.large"
|
node_type = var.redis_instance_type
|
||||||
engine_version = "5.0.6"
|
engine_version = "5.0.6"
|
||||||
port = "6379"
|
port = "6379"
|
||||||
snapshot_retention_limit = 0
|
snapshot_retention_limit = 0
|
||||||
|
3
infrastructure/loadtesting/terraform/terraform.tfvars
Normal file
3
infrastructure/loadtesting/terraform/terraform.tfvars
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
tag = "6f8abe3"
|
||||||
|
db_instance_type = "db.t4g.medium"
|
||||||
|
redis_instance_type = "cache.t4g.small"
|
@ -25,3 +25,9 @@ variable "db_instance_type" {
|
|||||||
type = string
|
type = string
|
||||||
default = "db.r6g.4xlarge"
|
default = "db.r6g.4xlarge"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable "redis_instance_type" {
|
||||||
|
description = "the redis instance type to use in loadtesting. default is cache.m6g.large"
|
||||||
|
type = string
|
||||||
|
default = "cache.m6g.large"
|
||||||
|
}
|
79
terraform/addons/vuln-processing/README.md
Normal file
79
terraform/addons/vuln-processing/README.md
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
# vulnerability processing addon
|
||||||
|
This addon adds [external vulnerability processing](https://fleetdm.com/docs/using-fleet/vulnerability-processing#advanced-configuration) to the Fleet deployment.
|
||||||
|
|
||||||
|
Be sure to set `FLEET_VULNERABILITIES_DISABLE_SCHEDULE = "true"` or use this modules' `fleet_extra_environment_variables` output to configure
|
||||||
|
your Fleet server deployment.
|
||||||
|
|
||||||
|
Below is an example implementation of the module:
|
||||||
|
|
||||||
|
```
|
||||||
|
module "vulnerability_processing" {
|
||||||
|
source = "github.com/fleetdm/fleet//terraform/addons/vuln-processing?ref=main"
|
||||||
|
customer_prefix = "fleet"
|
||||||
|
ecs_cluster = module.main.byo-vpc.byo-db.byo-ecs.cluster.cluster_arn
|
||||||
|
vpc_id = module.main.vpc.vpc_id
|
||||||
|
fleet_config = {
|
||||||
|
image = "fleetdm/fleet:v4.28.1"
|
||||||
|
database = {
|
||||||
|
password_secret_arn = module.main.byo-vpc.secrets.secret_arns["${var.rds_config.name}-database-password"]
|
||||||
|
user = module.main.byo-vpc.rds.db_instance_username
|
||||||
|
address = "${module.main.byo-vpc.rds.db_instance_endpoint}:${module.main.byo-vpc.rds.db_instance_port}"
|
||||||
|
database = module.main.byo-vpc.rds.db_instance_name
|
||||||
|
}
|
||||||
|
extra_environment_variables = {
|
||||||
|
FLEET_LOGGING_DEBUG = "true"
|
||||||
|
FLEET_LOGGING_JSON = "true"
|
||||||
|
}
|
||||||
|
extra_secrets = {
|
||||||
|
// FLEET_LICENSE_KEY: "secret_manager_license_key_arn" // note needed for some feature of vuln processing
|
||||||
|
}
|
||||||
|
networking = {
|
||||||
|
subnets = module.main.byo-vpc.byo-db.byo-ecs.service.network_configuration[0].subnets
|
||||||
|
security_groups = module.main.byo-vpc.byo-db.byo-ecs.service.network_configuration[0].security_groups
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
[VPC DNS Hostnames](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-dns.html#vpc-dns-hostnames) must be enabled for proper communication to EFS mounted volumes.
|
||||||
|
|
||||||
|
## Providers
|
||||||
|
|
||||||
|
| Name | Version |
|
||||||
|
|---------------------------------------------------|---------|
|
||||||
|
| <a name="provider_aws"></a> [aws](#provider\_aws) | n/a |
|
||||||
|
|
||||||
|
## Modules
|
||||||
|
|
||||||
|
No modules.
|
||||||
|
|
||||||
|
## Resources
|
||||||
|
|
||||||
|
| Name | Type |
|
||||||
|
|----------------------------------------------------------------------------------------------------------------------------------------------------|----------|
|
||||||
|
| [aws_ecs_task_definition.vuln-data-stream](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_task_definition) | resource |
|
||||||
|
| [aws_ecs_task_definition.vuln-processing](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_task_definition) | resource |
|
||||||
|
| [aws_efs_file_system.vuln](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/efs_file_system) | resource |
|
||||||
|
| [aws_efs_mount_target.vuln](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/efs_mount_target) | resource |
|
||||||
|
| [aws_cloudwatch_event_rule.vuln_processing](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_rule) | resource |
|
||||||
|
| [aws_cloudwatch_event_target.vuln_processing](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_target) | resource |
|
||||||
|
| [aws_security_group.efs_security_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource |
|
||||||
|
| [aws_iam_role.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
|
||||||
|
| [aws_iam_role_policy_attachment.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy_attachment) | resource |
|
||||||
|
| [aws_iam_role.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
|
||||||
|
|
||||||
|
|
||||||
|
## Inputs
|
||||||
|
|
||||||
|
| Name | Description | Type | Default | Required |
|
||||||
|
|-----------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------|----------|-----------|:--------:|
|
||||||
|
| <a name="input_customer_prefix"></a> [customer\_prefix](#input\_customer\_prefix) | customer prefix to use to namespace all resources | `string` | `"fleet"` | no |
|
||||||
|
| <a name="input_ecs_cluster"></a> [ecs\_cluster](#input\_ecs\_cluster) | ECS cluster ARN | `string` | n/a | yes |
|
||||||
|
| <a name="input_vpc_id"></a> [vpc\_id](#input\_vpc\_id) | n/a | `string` | n/a | yes |
|
||||||
|
| <a name="input_fleet_config"></a> [fleet\_config](#input\_fleet\_config) | The configuration object for Fleet itself. Fields that default to null will have their respective resources created if not specified. | `object` | no | yes |
|
||||||
|
|
||||||
|
## Outputs
|
||||||
|
|
||||||
|
No outputs.
|
20
terraform/addons/vuln-processing/efs.tf
Normal file
20
terraform/addons/vuln-processing/efs.tf
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
resource "aws_efs_file_system" "vuln" {}
|
||||||
|
|
||||||
|
resource "aws_security_group" "efs_security_group" {
|
||||||
|
name_prefix = "${var.customer_prefix}-efs-mount-sg"
|
||||||
|
vpc_id = var.vpc_id
|
||||||
|
|
||||||
|
// NFS
|
||||||
|
ingress {
|
||||||
|
from_port = 2049
|
||||||
|
to_port = 2049
|
||||||
|
protocol = "tcp"
|
||||||
|
security_groups = var.fleet_config.networking.security_groups # Allow traffic from the ECS task security group
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_efs_mount_target" "vuln" {
|
||||||
|
for_each = var.fleet_config.networking.subnets
|
||||||
|
file_system_id = aws_efs_file_system.vuln.id
|
||||||
|
subnet_id = each.value
|
||||||
|
}
|
132
terraform/addons/vuln-processing/iam.tf
Normal file
132
terraform/addons/vuln-processing/iam.tf
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
data "aws_iam_policy_document" "fleet-execution" {
|
||||||
|
// allow fleet application to obtain the database password from secrets manager
|
||||||
|
statement {
|
||||||
|
effect = "Allow"
|
||||||
|
actions = ["secretsmanager:GetSecretValue"]
|
||||||
|
resources = concat(var.fleet_config.database.password_secret_arn, values(var.fleet_config.extra_secrets))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data "aws_iam_policy_document" "fleet" {
|
||||||
|
statement {
|
||||||
|
effect = "Allow"
|
||||||
|
actions = ["cloudwatch:PutMetricData"]
|
||||||
|
resources = ["*"]
|
||||||
|
}
|
||||||
|
|
||||||
|
statement {
|
||||||
|
effect = "Allow"
|
||||||
|
actions = [
|
||||||
|
"elasticfilesystem:ClientMount",
|
||||||
|
"elasticfilesystem:ClientWrite",
|
||||||
|
"elasticfilesystem:ClientRead",
|
||||||
|
]
|
||||||
|
resources = [aws_efs_file_system.vuln.arn]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
data "aws_iam_policy_document" "assume_events" {
|
||||||
|
statement {
|
||||||
|
effect = "Allow"
|
||||||
|
actions = ["sts:AssumeRole"]
|
||||||
|
|
||||||
|
principals {
|
||||||
|
type = "Service"
|
||||||
|
identifiers = ["events.amazonaws.com", "ecs-tasks.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 = [var.ecs_cluster]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_iam_role" "main" {
|
||||||
|
count = var.fleet_config.iam_role_arn == null ? 1 : 0
|
||||||
|
name = var.fleet_config.iam.role.name
|
||||||
|
description = "IAM role that Fleet application assumes when running in ECS"
|
||||||
|
assume_role_policy = data.aws_iam_policy_document.assume_events.json
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_iam_policy" "main" {
|
||||||
|
count = var.fleet_config.iam_role_arn == null ? 1 : 0
|
||||||
|
name = var.fleet_config.iam.role.policy_name
|
||||||
|
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" "main" {
|
||||||
|
count = var.fleet_config.iam_role_arn == null ? 1 : 0
|
||||||
|
policy_arn = aws_iam_policy.main[0].arn
|
||||||
|
role = aws_iam_role.main[0].name
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_iam_role_policy_attachment" "extras" {
|
||||||
|
for_each = toset(var.fleet_config.extra_iam_policies)
|
||||||
|
policy_arn = each.value
|
||||||
|
role = aws_iam_role.main[0].name
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_iam_role_policy_attachment" "execution_extras" {
|
||||||
|
for_each = toset(var.fleet_config.extra_execution_iam_policies)
|
||||||
|
policy_arn = each.value
|
||||||
|
role = aws_iam_role.execution.name
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_iam_policy" "execution" {
|
||||||
|
name = var.fleet_config.iam.execution.policy_name
|
||||||
|
description = "IAM policy that Fleet application uses to define access to AWS resources"
|
||||||
|
policy = data.aws_iam_policy_document.fleet-execution.json
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_iam_role_policy_attachment" "execution" {
|
||||||
|
policy_arn = aws_iam_policy.execution.arn
|
||||||
|
role = aws_iam_role.execution.name
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_iam_role" "run_cloudwatch" {
|
||||||
|
name_prefix = "${var.customer_prefix}-cloudwatch-run"
|
||||||
|
assume_role_policy = data.aws_iam_policy_document.assume_events.json
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_iam_policy" "run_cloudwatch" {
|
||||||
|
name_prefix = "${var.customer_prefix}-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.execution.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.execution.name
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_iam_role" "execution" {
|
||||||
|
name = var.fleet_config.iam.execution.name
|
||||||
|
description = "The execution role for Fleet in ECS"
|
||||||
|
assume_role_policy = data.aws_iam_policy_document.assume_events.json
|
||||||
|
}
|
181
terraform/addons/vuln-processing/main.tf
Normal file
181
terraform/addons/vuln-processing/main.tf
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
locals {
|
||||||
|
environment = [for k, v in var.fleet_config.extra_environment_variables : {
|
||||||
|
name = k
|
||||||
|
value = v
|
||||||
|
}]
|
||||||
|
secrets = [for k, v in var.fleet_config.extra_secrets : {
|
||||||
|
name = k
|
||||||
|
valueFrom = v
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
|
||||||
|
data "aws_region" "current" {}
|
||||||
|
|
||||||
|
resource "aws_cloudwatch_log_group" "main" { #tfsec:ignore:aws-cloudwatch-log-group-customer-key:exp:2022-07-01
|
||||||
|
count = var.fleet_config.awslogs.create == true ? 1 : 0
|
||||||
|
name = var.fleet_config.awslogs.name
|
||||||
|
retention_in_days = var.fleet_config.awslogs.retention
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_ecs_task_definition" "vuln-data-stream" {
|
||||||
|
family = var.fleet_config.family
|
||||||
|
cpu = var.fleet_config.vuln_data_stream_cpu
|
||||||
|
memory = var.fleet_config.vuln_data_stream_mem
|
||||||
|
execution_role_arn = aws_iam_role.execution.arn
|
||||||
|
task_role_arn = aws_iam_role.main.arn
|
||||||
|
network_mode = "awsvpc"
|
||||||
|
requires_compatibilities = ["FARGATE"]
|
||||||
|
|
||||||
|
container_definitions = jsonencode([
|
||||||
|
{
|
||||||
|
name = "fleet-vuln-provisioner"
|
||||||
|
image = var.fleet_config.image
|
||||||
|
essential = true
|
||||||
|
user = "root"
|
||||||
|
command = ["fleetctl", "vulnerability-data-stream", "--dir=${var.fleet_config.vuln_database_path}"]
|
||||||
|
networkMode = "awsvpc"
|
||||||
|
mountPoints = [
|
||||||
|
{
|
||||||
|
sourceVolume = "efs-mount"
|
||||||
|
containerPath = var.fleet_config.vuln_database_path
|
||||||
|
readOnly = false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
logConfiguration = {
|
||||||
|
logDriver = "awslogs"
|
||||||
|
options = {
|
||||||
|
awslogs-group = var.fleet_config.awslogs.create == true ? aws_cloudwatch_log_group.main[0].name : var.fleet_config.awslogs.name
|
||||||
|
awslogs-region = var.fleet_config.awslogs.create == true ? data.aws_region.current.name : var.fleet_config.awslogs.region
|
||||||
|
awslogs-stream-prefix = "${var.fleet_config.awslogs.prefix}-data-stream"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
volume {
|
||||||
|
name = "efs-mount"
|
||||||
|
efs_volume_configuration {
|
||||||
|
file_system_id = aws_efs_file_system.vuln.id
|
||||||
|
root_directory = var.efs_root_directory
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
resource "aws_ecs_task_definition" "vuln-processing" {
|
||||||
|
family = var.fleet_config.family
|
||||||
|
cpu = var.fleet_config.vuln_processing_cpu
|
||||||
|
memory = var.fleet_config.vuln_processing_mem
|
||||||
|
execution_role_arn = aws_iam_role.execution.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_config.image
|
||||||
|
essential = true
|
||||||
|
command = ["fleet", "vuln_processing"]
|
||||||
|
user = "root"
|
||||||
|
networkMode = "awsvpc"
|
||||||
|
mountPoints = [
|
||||||
|
{
|
||||||
|
sourceVolume = "efs-mount"
|
||||||
|
containerPath = var.fleet_config.vuln_database_path
|
||||||
|
readOnly = false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
secrets = concat(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
name = "FLEET_MYSQL_PASSWORD"
|
||||||
|
valueFrom = var.fleet_config.database.password_secret_arn
|
||||||
|
}
|
||||||
|
], local.secrets),
|
||||||
|
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_VULNERABILITIES_DISABLE_DATA_SYNC"
|
||||||
|
value = "true"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name = "FLEET_VULNERABILITIES_DATABASES_PATH"
|
||||||
|
value = var.fleet_config.vuln_database_path
|
||||||
|
}
|
||||||
|
], local.environment),
|
||||||
|
logConfiguration = {
|
||||||
|
logDriver = "awslogs"
|
||||||
|
options = {
|
||||||
|
awslogs-group = var.fleet_config.awslogs.create == true ? aws_cloudwatch_log_group.main[0].name : var.fleet_config.awslogs.name
|
||||||
|
awslogs-region = var.fleet_config.awslogs.create == true ? data.aws_region.current.name : var.fleet_config.awslogs.region
|
||||||
|
awslogs-stream-prefix = "${var.fleet_config.awslogs.prefix}-procssing"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
volume {
|
||||||
|
name = "efs-mount"
|
||||||
|
efs_volume_configuration {
|
||||||
|
file_system_id = aws_efs_file_system.vuln.id
|
||||||
|
root_directory = var.efs_root_directory
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_cloudwatch_event_rule" "vuln_processing" {
|
||||||
|
name_prefix = "${var.customer_prefix}-vuln-processing"
|
||||||
|
schedule_expression = var.fleet_config.vuln_processing_schedule_expression
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_cloudwatch_event_target" "vuln_processing" {
|
||||||
|
arn = var.ecs_cluster
|
||||||
|
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 = var.fleet_config.networking.subnets
|
||||||
|
security_groups = var.fleet_config.networking.security_groups
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_cloudwatch_event_rule" "vuln_data_stream" {
|
||||||
|
name_prefix = "${var.customer_prefix}-vuln-data-stream"
|
||||||
|
schedule_expression = var.fleet_config.vuln_data_stream_schedule_expression
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_cloudwatch_event_target" "vuln_data_stream" {
|
||||||
|
arn = var.ecs_cluster
|
||||||
|
rule = aws_cloudwatch_event_rule.vuln_data_stream.name
|
||||||
|
role_arn = aws_iam_role.run_cloudwatch.arn
|
||||||
|
ecs_target {
|
||||||
|
task_definition_arn = aws_ecs_task_definition.vuln-data-stream.arn
|
||||||
|
task_count = 1
|
||||||
|
launch_type = "FARGATE"
|
||||||
|
network_configuration {
|
||||||
|
assign_public_ip = false
|
||||||
|
subnets = var.fleet_config.networking.subnets
|
||||||
|
security_groups = var.fleet_config.networking.security_groups
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
9
terraform/addons/vuln-processing/outputs.tf
Normal file
9
terraform/addons/vuln-processing/outputs.tf
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
output "fleet_extra_environment_variables" {
|
||||||
|
value = {
|
||||||
|
FLEET_VULNERABILITIES_DISABLE_SCHEDULE = "true"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
output "enable_dns_hostnames" {
|
||||||
|
value = true
|
||||||
|
}
|
128
terraform/addons/vuln-processing/variables.tf
Normal file
128
terraform/addons/vuln-processing/variables.tf
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
variable "customer_prefix" {
|
||||||
|
type = string
|
||||||
|
description = "customer prefix to use to namespace all resources"
|
||||||
|
default = "fleet"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "ecs_cluster" {
|
||||||
|
type = string
|
||||||
|
description = "The ARN of the ECS cluster to use"
|
||||||
|
nullable = false
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "vpc_id" {
|
||||||
|
type = string
|
||||||
|
default = null
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "fleet_config" {
|
||||||
|
type = object({
|
||||||
|
vuln_processing_schedule_expression = optional(string, "rate(1 hour)")
|
||||||
|
vuln_data_stream_schedule_expression = optional(string, "rate(24 hours)")
|
||||||
|
vuln_database_path = optional(string, "/home/fleet/vuln_data")
|
||||||
|
vuln_processing_mem = optional(number, 4096)
|
||||||
|
vuln_processing_cpu = optional(number, 2048)
|
||||||
|
vuln_data_stream_mem = optional(number, 1024)
|
||||||
|
vuln_data_stream_cpu = optinal(number, 512)
|
||||||
|
image = optional(string, "fleetdm/fleet:v4.28.1")
|
||||||
|
family = optional(string, "fleet-vuln-processing")
|
||||||
|
sidecars = optional(list(any), [])
|
||||||
|
extra_environment_variables = optional(map(string), {})
|
||||||
|
extra_iam_policies = optional(list(string), [])
|
||||||
|
extra_execution_iam_policies = optional(list(string), [])
|
||||||
|
extra_secrets = optional(map(string), {})
|
||||||
|
iam_role_arn = optional(string, null)
|
||||||
|
database = object({
|
||||||
|
password_secret_arn = string
|
||||||
|
user = string
|
||||||
|
database = string
|
||||||
|
address = string
|
||||||
|
rr_address = optional(string, null)
|
||||||
|
})
|
||||||
|
awslogs = optional(object({
|
||||||
|
name = optional(string, null)
|
||||||
|
region = optional(string, null)
|
||||||
|
create = optional(bool, true)
|
||||||
|
prefix = optional(string, "fleet-vuln")
|
||||||
|
retention = optional(number, 5)
|
||||||
|
}), {
|
||||||
|
name = null
|
||||||
|
region = null
|
||||||
|
prefix = "fleet"
|
||||||
|
retention = 5
|
||||||
|
})
|
||||||
|
networking = object({
|
||||||
|
subnets = list(string)
|
||||||
|
security_groups = optional(list(string), null)
|
||||||
|
})
|
||||||
|
iam = optional(object({
|
||||||
|
role = optional(object({
|
||||||
|
name = optional(string, "fleet-vuln-processing-role")
|
||||||
|
policy_name = optional(string, "fleet-vuln-processing-iam-policy")
|
||||||
|
}), {
|
||||||
|
name = "fleet-vuln-processing-role"
|
||||||
|
policy_name = "fleet-vuln-processing-iam-policy"
|
||||||
|
})
|
||||||
|
execution = optional(object({
|
||||||
|
name = optional(string, "fleet-vuln-processing-execution-role")
|
||||||
|
policy_name = optional(string, "fleet-vuln-processing-execution-role")
|
||||||
|
}), {
|
||||||
|
name = "fleet-vuln-processing-execution-role"
|
||||||
|
policy_name = "fleet-vuln-processing-iam-policy-execution"
|
||||||
|
})
|
||||||
|
}), {
|
||||||
|
name = "fleet-vuln-processing-execution-role"
|
||||||
|
})
|
||||||
|
})
|
||||||
|
default = {
|
||||||
|
vuln_processing_schedule_expression = "rate(1 hour)"
|
||||||
|
vuln_data_stream_schedule_expression = "rate(24 hours)"
|
||||||
|
vuln_database_path = "/home/fleet/vuln_data"
|
||||||
|
vuln_processing_mem = 4096
|
||||||
|
vuln_processing_cpu = 2048
|
||||||
|
vuln_data_stream_mem = 1024
|
||||||
|
vuln_data_stream_cpu = 512
|
||||||
|
image = "fleetdm/fleet:v4.28.1"
|
||||||
|
family = "fleet-vuln-processing"
|
||||||
|
sidecars = []
|
||||||
|
extra_environment_variables = {}
|
||||||
|
extra_iam_policies = []
|
||||||
|
extra_execution_iam_policies = []
|
||||||
|
extra_secrets = {}
|
||||||
|
iam_role_arn = null
|
||||||
|
database = {
|
||||||
|
password_secret_arn = null
|
||||||
|
user = null
|
||||||
|
database = null
|
||||||
|
address = null
|
||||||
|
rr_address = null
|
||||||
|
}
|
||||||
|
awslogs = {
|
||||||
|
name = null
|
||||||
|
region = null
|
||||||
|
create = true
|
||||||
|
prefix = "fleet-vuln"
|
||||||
|
retention = 5
|
||||||
|
}
|
||||||
|
networking = {
|
||||||
|
subnets = null
|
||||||
|
security_groups = null
|
||||||
|
}
|
||||||
|
iam = {
|
||||||
|
role = {
|
||||||
|
name = "fleet-vuln-processing-role"
|
||||||
|
policy_name = "fleet-vuln-processing-iam-policy"
|
||||||
|
}
|
||||||
|
execution = {
|
||||||
|
name = "fleet-vuln-processing-execution-role"
|
||||||
|
policy_name = "fleet-vuln-processing-iam-policy-execution"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
description = "The configuration object for Fleet itself. Fields that default to null will have their respective resources created if not specified."
|
||||||
|
nullable = false
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "efs_root_directory" {
|
||||||
|
default = "/"
|
||||||
|
}
|
@ -2,6 +2,10 @@ output "byo-ecs" {
|
|||||||
value = module.ecs
|
value = module.ecs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
output "cluster" {
|
||||||
|
value = module.cluster
|
||||||
|
}
|
||||||
|
|
||||||
output "alb" {
|
output "alb" {
|
||||||
value = module.alb
|
value = module.alb
|
||||||
}
|
}
|
||||||
|
@ -9,3 +9,7 @@ output "rds" {
|
|||||||
output "redis" {
|
output "redis" {
|
||||||
value = module.redis
|
value = module.redis
|
||||||
}
|
}
|
||||||
|
|
||||||
|
output "secrets" {
|
||||||
|
value = module.secrets-manager-1
|
||||||
|
}
|
||||||
|
@ -22,9 +22,10 @@ module "main" {
|
|||||||
certificate_arn = module.acm.acm_certificate_arn
|
certificate_arn = module.acm.acm_certificate_arn
|
||||||
vpc = {
|
vpc = {
|
||||||
name = random_pet.main.id
|
name = random_pet.main.id
|
||||||
|
enable_dns_hostnames = module.vulnprocessing.enable_dns_hostnames
|
||||||
}
|
}
|
||||||
fleet_config = {
|
fleet_config = {
|
||||||
extra_environment_variables = module.firehose-logging.fleet_extra_environment_variables
|
extra_environment_variables = concat(module.firehose-logging.fleet_extra_environment_variables, module.vulnprocessing.fleet_extra_environment_variables)
|
||||||
extra_iam_policies = module.firehose-logging.fleet_extra_iam_policies
|
extra_iam_policies = module.firehose-logging.fleet_extra_iam_policies
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -65,3 +66,30 @@ module "firehose-logging" {
|
|||||||
name = "${random_pet.main.id}-status"
|
name = "${random_pet.main.id}-status"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module "vulnprocessing" {
|
||||||
|
source = "../addons/vuln-processing"
|
||||||
|
customer_prefix = "fleet"
|
||||||
|
ecs_cluster = module.main.byo-vpc.byo-db.byo-ecs.cluster.cluster_arn
|
||||||
|
vpc_id = module.main.vpc.vpc_id
|
||||||
|
fleet_config = {
|
||||||
|
image = "fleetdm/fleet:v4.28.1"
|
||||||
|
database = {
|
||||||
|
password_secret_arn = module.main.byo-vpc.secrets.secret_arns["${var.rds_config.name}-database-password"]
|
||||||
|
user = module.main.byo-vpc.rds.db_instance_username
|
||||||
|
address = "${module.main.byo-vpc.rds.db_instance_endpoint}:${module.main.byo-vpc.rds.db_instance_port}"
|
||||||
|
database = module.main.byo-vpc.rds.db_instance_name
|
||||||
|
}
|
||||||
|
extra_environment_variables = {
|
||||||
|
FLEET_LOGGING_DEBUG = "true"
|
||||||
|
FLEET_LOGGING_JSON = "true"
|
||||||
|
}
|
||||||
|
extra_secrets = {
|
||||||
|
// FLEET_LICENSE_KEY: "secret_manager_license_key_arn" // note needed for some feature of vuln processing
|
||||||
|
}
|
||||||
|
networking = {
|
||||||
|
subnets = module.main.byo-vpc.byo-db.byo-ecs.service.network_configuration[0].subnets
|
||||||
|
security_groups = module.main.byo-vpc.byo-db.byo-ecs.service.network_configuration[0].security_groups
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -25,6 +25,8 @@ module "vpc" {
|
|||||||
flow_log_cloudwatch_log_group_name_prefix = var.vpc.flow_log_cloudwatch_log_group_name_prefix
|
flow_log_cloudwatch_log_group_name_prefix = var.vpc.flow_log_cloudwatch_log_group_name_prefix
|
||||||
flow_log_cloudwatch_log_group_name_suffix = var.vpc.flow_log_cloudwatch_log_group_name_suffix
|
flow_log_cloudwatch_log_group_name_suffix = var.vpc.flow_log_cloudwatch_log_group_name_suffix
|
||||||
vpc_flow_log_tags = var.vpc.vpc_flow_log_tags
|
vpc_flow_log_tags = var.vpc.vpc_flow_log_tags
|
||||||
|
enable_dns_hostnames = var.vpc.enable_dns_hostnames
|
||||||
|
enable_dns_support = var.vpc.enable_dns_support
|
||||||
}
|
}
|
||||||
|
|
||||||
module "byo-vpc" {
|
module "byo-vpc" {
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
output "byo-vpc" {
|
output "byo-vpc" {
|
||||||
value = module.byo-vpc
|
value = module.byo-vpc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
output "vpc" {
|
||||||
|
value = module.vpc
|
||||||
|
}
|
@ -16,7 +16,8 @@ variable "vpc" {
|
|||||||
one_nat_gateway_per_az = optional(bool, false)
|
one_nat_gateway_per_az = optional(bool, false)
|
||||||
single_nat_gateway = optional(bool, true)
|
single_nat_gateway = optional(bool, true)
|
||||||
enable_nat_gateway = optional(bool, true)
|
enable_nat_gateway = optional(bool, true)
|
||||||
|
enable_dns_hostnames = optional(bool, false)
|
||||||
|
enable_dns_support = optional(bool, true)
|
||||||
enable_flow_log = optional(bool, false)
|
enable_flow_log = optional(bool, false)
|
||||||
create_flow_log_cloudwatch_log_group = optional(bool, false)
|
create_flow_log_cloudwatch_log_group = optional(bool, false)
|
||||||
create_flow_log_cloudwatch_iam_role = optional(bool, false)
|
create_flow_log_cloudwatch_iam_role = optional(bool, false)
|
||||||
@ -42,7 +43,8 @@ variable "vpc" {
|
|||||||
one_nat_gateway_per_az = false
|
one_nat_gateway_per_az = false
|
||||||
single_nat_gateway = true
|
single_nat_gateway = true
|
||||||
enable_nat_gateway = true
|
enable_nat_gateway = true
|
||||||
|
enable_dns_hostnames = false
|
||||||
|
enable_dns_support = true
|
||||||
enable_flow_log = false
|
enable_flow_log = false
|
||||||
create_flow_log_cloudwatch_log_group = false
|
create_flow_log_cloudwatch_log_group = false
|
||||||
create_flow_log_cloudwatch_iam_role = false
|
create_flow_log_cloudwatch_iam_role = false
|
||||||
|
Loading…
Reference in New Issue
Block a user