mdmproxy terraform (#20009)

This commit is contained in:
Robert Fairburn 2024-06-28 14:40:05 -05:00 committed by GitHub
parent 196f761b6d
commit 2547277095
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 384 additions and 0 deletions

View file

@ -0,0 +1,56 @@
data "aws_iam_policy_document" "mdmproxy" {
statement {
effect = "Allow"
actions = ["cloudwatch:PutMetricData"]
resources = ["*"]
}
}
data "aws_iam_policy_document" "assume_role" {
statement {
effect = "Allow"
actions = ["sts:AssumeRole"]
principals {
identifiers = ["ecs.amazonaws.com", "ecs-tasks.amazonaws.com"]
type = "Service"
}
}
}
data "aws_iam_policy_document" "mdm_execution" {
// allow fleet application to obtain the database password from secrets manager
statement {
effect = "Allow"
actions = ["secretsmanager:GetSecretValue"]
resources = [aws_secretsmanager_secret.mdmproxy.arn]
}
}
resource "aws_iam_role_policy_attachment" "execution_extras" {
for_each = toset(var.config.extra_execution_iam_policies)
policy_arn = each.value
role = aws_iam_role.execution.name
}
resource "aws_iam_policy" "execution" {
name = var.config.iam.execution.policy_name
description = "IAM policy that Fleet mdmproxy uses to define access to AWS resources"
policy = data.aws_iam_policy_document.mdm_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" "execution" {
name = var.config.iam.execution.name
description = "The execution role for the mdmproxy 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.execution.name
}

View file

@ -0,0 +1,236 @@
data "aws_region" "current" {}
locals {
mdmproxy_secrets = {
MDMPROXY_AUTH_TOKEN = var.config.auth_token
MDMPROXY_MIGRATE_UDIDS = join(" ", var.config.migrate_udids)
}
}
resource "aws_security_group" "mdmproxy" {
count = var.config.networking.security_groups == null ? 1 : 0
name = var.config.networking.security_group_name
description = "Fleet ECS Service Security Group"
vpc_id = var.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"]
}
ingress {
description = "Ingress only on container port"
from_port = 8080
to_port = 8080
protocol = "TCP"
cidr_blocks = var.config.networking.ingress_sources.cidr_blocks
ipv6_cidr_blocks = var.config.networking.ingress_sources.ipv6_cidr_blocks
security_groups = concat(var.config.networking.ingress_sources.security_groups, [aws_security_group.alb.id])
prefix_list_ids = var.config.networking.ingress_sources.prefix_list_ids
}
}
module "alb" {
source = "terraform-aws-modules/alb/aws"
version = "8.3.0"
name = var.alb_config.name
load_balancer_type = "application"
vpc_id = var.vpc_id
subnets = var.alb_config.subnets
security_groups = concat(var.alb_config.security_groups, [aws_security_group.alb.id])
access_logs = var.alb_config.access_logs
idle_timeout = var.alb_config.idle_timeout
target_groups = concat([
{
name = var.alb_config.name
backend_protocol = "HTTP"
backend_port = 80
target_type = "ip"
health_check = {
path = "/healthz"
matcher = "200"
timeout = 10
interval = 15
healthy_threshold = 5
unhealthy_threshold = 5
}
}
], var.alb_config.extra_target_groups)
# Require TLS 1.2 as earlier versions are insecure
listener_ssl_policy_default = var.alb_config.tls_policy
https_listeners = [
{
port = 443
protocol = "HTTPS"
certificate_arn = var.alb_config.certificate_arn
target_group_index = 0
}
]
https_listener_rules = var.alb_config.https_listener_rules
http_tcp_listeners = [
{
port = 80
protocol = "HTTP"
action_type = "redirect"
redirect = {
port = "443"
protocol = "HTTPS"
status_code = "HTTP_301"
}
}
]
}
resource "aws_security_group" "alb" {
#checkov:skip=CKV2_AWS_5:False positive
vpc_id = var.vpc_id
description = "Fleet-mdmproxy ALB Security Group"
ingress {
description = "Ingress from all, its a public load balancer"
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = var.alb_config.allowed_cidrs
ipv6_cidr_blocks = var.alb_config.allowed_ipv6_cidrs
}
ingress {
description = "For http to https redirect"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = var.alb_config.allowed_cidrs
ipv6_cidr_blocks = var.alb_config.allowed_ipv6_cidrs
}
egress {
description = "Egress to all"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = var.alb_config.egress_cidrs
ipv6_cidr_blocks = var.alb_config.egress_ipv6_cidrs
}
}
resource "aws_secretsmanager_secret" "mdmproxy" {
name = "${var.customer_prefix}-mdmproxy"
}
resource "aws_secretsmanager_secret_version" "mdmproxy" {
secret_id = aws_secretsmanager_secret.mdmproxy.id
secret_string = jsonencode(local.mdmproxy_secrets)
}
resource "aws_ecs_service" "mdmproxy" {
name = "${var.customer_prefix}-mdmproxy"
launch_type = "FARGATE"
cluster = var.ecs_cluster
task_definition = aws_ecs_task_definition.mdmproxy.arn
desired_count = var.config.desired_count
deployment_minimum_healthy_percent = 100
deployment_maximum_percent = 200
load_balancer {
target_group_arn = module.alb.target_group_arns[0]
container_name = "mdmproxy"
container_port = 8080
}
lifecycle {
ignore_changes = [desired_count]
}
network_configuration {
subnets = var.config.networking.subnets
security_groups = var.config.networking.security_groups == null ? aws_security_group.mdmproxy.*.id : var.config.networking.security_groups
}
}
resource "aws_ecs_task_definition" "mdmproxy" {
family = "${var.customer_prefix}-mdmproxy"
cpu = var.config.cpu
memory = var.config.mem
execution_role_arn = aws_iam_role.execution.arn
network_mode = "awsvpc"
requires_compatibilities = ["FARGATE"]
container_definitions = jsonencode([
{
name = "mdmproxy"
image = var.config.image
cpu = var.config.cpu
memory = var.config.mem
essential = true
portMappings = [
{
# This port is the same that the contained application also uses
containerPort = 8080
protocol = "tcp"
}
]
networkMode = "awsvpc"
secrets = [
{
name = "MDMPROXY_AUTH_TOKEN"
valueFrom = "${aws_secretsmanager_secret.mdmproxy.arn}:MDMPROXY_AUTH_TOKEN::"
},
{
name = "MDMPROXY_MIGRATE_UDIDS"
valueFrom = "${aws_secretsmanager_secret.mdmproxy.arn}:MDMPROXY_MIGRATE_UDIDS::"
},
]
repositoryCredentials = var.config.repository_credentials
ulimits = [
{
name = "nofile"
softLimit = 999999
hardLimit = 999999
}
]
environment = [
{
name = "MDMPROXY_SERVER_ADDRESS"
value = ":8080"
},
{
name = "MDMPROXY_MIGRATE_PERCENTAGE"
value = tostring(var.config.migrate_percentage)
},
{
name = "MDMPROXY_EXISTING_HOSTNAME"
value = var.config.existing_hostname
},
{
name = "MDMPROXY_EXISTING_URL"
value = var.config.existing_url
},
{
name = "MDMPROXY_FLEET_URL"
value = var.config.fleet_url
},
]
logConfiguration = {
logDriver = "awslogs"
options = {
awslogs-group = var.awslogs_config.group
awslogs-region = var.awslogs_config.region == null ? data.aws_region.current.name : var.awslogs_config.region
awslogs-stream-prefix = "${var.awslogs_config.prefix}-mdmproxy"
}
}
}
])
}

View file

@ -0,0 +1,7 @@
output "alb" {
value = module.alb
}
output "ecs_service_name" {
value = aws_ecs_service.mdmproxy.name
}

View file

@ -0,0 +1,85 @@
variable "awslogs_config" {
type = object({
group = string
region = string
prefix = optional(string, "mdmproxy")
})
}
variable "ecs_cluster" {
type = string
}
variable "vpc_id" {
type = string
nullable = false
}
variable "customer_prefix" {
type = string
default = "fleet"
}
variable "config" {
type = object({
extra_execution_iam_policies = optional(list(string), [])
mem = optional(number, 2048)
cpu = optional(number, 1024)
image = string
desired_count = optional(number, 1)
repository_credentials = optional(string, null)
migrate_percentage = number
existing_hostname = string
existing_url = string
fleet_url = string
migrate_udids = optional(list(string), [])
auth_token = optional(string, "")
iam = optional(object({
execution = optional(object({
name = optional(string, "mdmproxy-execution-role")
policy_name = optional(string, "mdmproxy-iam-policy-execution")
}), {
name = "mdmproxy-execution-role"
policy_name = "mdmproxy-iam-policy-execution"
})
}), {
name = "mdmproxy-execution-role"
policy_name = "mdmproxy-iam-policy-execution"
})
networking = object({
subnets = list(string)
security_groups = optional(list(string), null)
security_group_name = optional(string, "fleet-mdmproxy")
ingress_sources = optional(object({
cidr_blocks = optional(list(string), [])
ipv6_cidr_blocks = optional(list(string), [])
security_groups = optional(list(string), [])
prefix_list_ids = optional(list(string), [])
}), {
cidr_blocks = []
ipv6_cidr_blocks = []
security_groups = []
prefix_list_ids = []
})
})
})
}
variable "alb_config" {
type = object({
name = optional(string, "fleet-mdmproxy")
subnets = list(string)
security_groups = optional(list(string), [])
access_logs = optional(map(string), {})
certificate_arn = string
allowed_cidrs = optional(list(string), ["0.0.0.0/0"])
allowed_ipv6_cidrs = optional(list(string), ["::/0"])
egress_cidrs = optional(list(string), ["0.0.0.0/0"])
egress_ipv6_cidrs = optional(list(string), ["::/0"])
extra_target_groups = optional(any, [])
https_listener_rules = optional(any, [])
tls_policy = optional(string, "ELBSecurityPolicy-TLS-1-2-2017-01")
idle_timeout = optional(number, 60)
})
}