From fc2a7ee941f63f3b1f1f55242afe49d392adcf60 Mon Sep 17 00:00:00 2001 From: Nitin Bhadauria Date: Fri, 23 Jun 2023 12:18:18 +1000 Subject: [PATCH 1/8] add option to allow request from AWS IP Range --- _variables.tf | 10 ++++++++++ alb.tf | 6 ++++-- sg-aws-iprange.tf | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 sg-aws-iprange.tf diff --git a/_variables.tf b/_variables.tf index 87aa19f..ed24b71 100644 --- a/_variables.tf +++ b/_variables.tf @@ -90,6 +90,16 @@ variable "alb_sg_allow_test_listener" { description = "Whether to allow world access to the test listeners" } +variable "alb_sg_allow_cloudfront" { + default = true + description = "Whether to allow Cloudfront IP range to access" +} + +variable "alb_sg_allow_api_gateway" { + default = true + description = "Whether to allow API Gateway IP range to access" +} + variable "alb_sg_allow_egress_https_world" { default = true description = "Whether to allow ALB to access HTTPS endpoints - needed when using OIDC authentication" diff --git a/alb.tf b/alb.tf index 54f353c..58187a4 100644 --- a/alb.tf +++ b/alb.tf @@ -8,9 +8,11 @@ resource "aws_lb" "ecs" { drop_invalid_header_fields = var.alb_drop_invalid_header_fields enable_deletion_protection = var.alb_enable_deletion_protection - security_groups = [ + security_groups = compact([ aws_security_group.alb[0].id, - ] + try(aws_security_group.from_cloudfront[0].id, ""), + try(aws_security_group.from_api_gateway[0].id, "") + ]) idle_timeout = 400 diff --git a/sg-aws-iprange.tf b/sg-aws-iprange.tf new file mode 100644 index 0000000..ec12d77 --- /dev/null +++ b/sg-aws-iprange.tf @@ -0,0 +1,47 @@ +data "aws_ip_ranges" "cloudfront" { + services = ["cloudfront"] +} + +data "aws_ip_ranges" "api_gateway" { + services = ["api_gateway"] +} + +resource "aws_security_group" "from_cloudfront" { + count = var.alb && var.alb_sg_allow_cloudfront ? 1 : 0 + name = "from-cloudfront-${var.name}" + description = "SG for Request from Cloudfront" + vpc_id = var.vpc_id + + ingress { + from_port = "443" + to_port = "443" + protocol = "tcp" + cidr_blocks = data.aws_ip_ranges.cloudfront.cidr_blocks + } + + tags = { + Name = "from-cloudfront-${var.name}" + CreateDate = data.aws_ip_ranges.cloudfront.create_date + SyncToken = data.aws_ip_ranges.cloudfront.sync_token + } +} + +resource "aws_security_group" "from_api_gateway" { + count = var.alb && var.alb_sg_allow_api_gateway ? 1 : 0 + name = "from-api-gateway-${var.name}" + description = "SG for Request from API Gateway" + vpc_id = var.vpc_id + + ingress { + from_port = "443" + to_port = "443" + protocol = "tcp" + cidr_blocks = data.aws_ip_ranges.api_gateway.cidr_blocks + } + + tags = { + Name = "from-api-gateway-${var.name}" + CreateDate = data.aws_ip_ranges.api_gateway.create_date + SyncToken = data.aws_ip_ranges.api_gateway.sync_token + } +} \ No newline at end of file From 43a75c837ca21799c91cc95cf59a5b02cec9baff Mon Sep 17 00:00:00 2001 From: Nitin Bhadauria Date: Fri, 23 Jun 2023 13:46:21 +1000 Subject: [PATCH 2/8] update lookup to specific regions --- _variables.tf | 5 +++++ alb.tf | 6 +++--- sg-aws-iprange.tf | 26 ++++++++++++++++++-------- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/_variables.tf b/_variables.tf index ed24b71..d27f622 100644 --- a/_variables.tf +++ b/_variables.tf @@ -100,6 +100,11 @@ variable "alb_sg_allow_api_gateway" { description = "Whether to allow API Gateway IP range to access" } +variable "alb_sg_allow_api_gateway_region" { + default = "" + description = "Use this region to allow API Gateway IP range" +} + variable "alb_sg_allow_egress_https_world" { default = true description = "Whether to allow ALB to access HTTPS endpoints - needed when using OIDC authentication" diff --git a/alb.tf b/alb.tf index 58187a4..434c402 100644 --- a/alb.tf +++ b/alb.tf @@ -8,11 +8,11 @@ resource "aws_lb" "ecs" { drop_invalid_header_fields = var.alb_drop_invalid_header_fields enable_deletion_protection = var.alb_enable_deletion_protection - security_groups = compact([ + security_groups = compact( + concat(try(aws_security_group.from_cloudfront.*.id, []), [ aws_security_group.alb[0].id, - try(aws_security_group.from_cloudfront[0].id, ""), try(aws_security_group.from_api_gateway[0].id, "") - ]) + ])) idle_timeout = 400 diff --git a/sg-aws-iprange.tf b/sg-aws-iprange.tf index ec12d77..1dd50fb 100644 --- a/sg-aws-iprange.tf +++ b/sg-aws-iprange.tf @@ -1,26 +1,36 @@ data "aws_ip_ranges" "cloudfront" { + regions = ["global"] services = ["cloudfront"] } data "aws_ip_ranges" "api_gateway" { + regions = compact([data.aws_region.current.name,try(var.alb_sg_allow_api_gateway_region, "")]) services = ["api_gateway"] } +locals { + ip_chunks = chunklist(data.aws_ip_ranges.cloudfront.cidr_blocks, 50) +} + resource "aws_security_group" "from_cloudfront" { - count = var.alb && var.alb_sg_allow_cloudfront ? 1 : 0 - name = "from-cloudfront-${var.name}" + count = var.alb && var.alb_sg_allow_cloudfront ? length(local.ip_chunks) : 0 + name = "from-cloudfront-${var.name}-${count.index}" description = "SG for Request from Cloudfront" vpc_id = var.vpc_id - ingress { - from_port = "443" - to_port = "443" - protocol = "tcp" - cidr_blocks = data.aws_ip_ranges.cloudfront.cidr_blocks + dynamic "ingress" { + for_each = local.ip_chunks[count.index] + + content { + from_port = 443 + to_port = 443 + protocol = "tcp" + cidr_blocks = [ingress.value] + } } tags = { - Name = "from-cloudfront-${var.name}" + Name = "from-cloudfront-${var.name}-${count.index}" CreateDate = data.aws_ip_ranges.cloudfront.create_date SyncToken = data.aws_ip_ranges.cloudfront.sync_token } From 2531cc505e23119af483dc7e16512e6939395800 Mon Sep 17 00:00:00 2001 From: Nitin Bhadauria Date: Fri, 23 Jun 2023 13:52:45 +1000 Subject: [PATCH 3/8] add option to pass additional sg for alb --- _variables.tf | 5 +++++ alb.tf | 1 + 2 files changed, 6 insertions(+) diff --git a/_variables.tf b/_variables.tf index d27f622..2ccb7c6 100644 --- a/_variables.tf +++ b/_variables.tf @@ -90,6 +90,11 @@ variable "alb_sg_allow_test_listener" { description = "Whether to allow world access to the test listeners" } +variable "alb_additional_sg" { + default = [] + description = "pass addition list of security groups to add to ALB" +} + variable "alb_sg_allow_cloudfront" { default = true description = "Whether to allow Cloudfront IP range to access" diff --git a/alb.tf b/alb.tf index 434c402..107a2c8 100644 --- a/alb.tf +++ b/alb.tf @@ -9,6 +9,7 @@ resource "aws_lb" "ecs" { enable_deletion_protection = var.alb_enable_deletion_protection security_groups = compact( + try(var.alb_additional_sg,[]), concat(try(aws_security_group.from_cloudfront.*.id, []), [ aws_security_group.alb[0].id, try(aws_security_group.from_api_gateway[0].id, "") From 57e022d05df8d46c00d1b31d7b9a05566b14d16b Mon Sep 17 00:00:00 2001 From: Nitin Bhadauria Date: Fri, 23 Jun 2023 16:03:40 +1000 Subject: [PATCH 4/8] Update defaults and lifecycle to modify LB first --- _variables.tf | 4 ++-- alb.tf | 4 ++-- sg-aws-iprange.tf | 12 ++++++++---- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/_variables.tf b/_variables.tf index 2ccb7c6..5670ca3 100644 --- a/_variables.tf +++ b/_variables.tf @@ -96,12 +96,12 @@ variable "alb_additional_sg" { } variable "alb_sg_allow_cloudfront" { - default = true + default = false description = "Whether to allow Cloudfront IP range to access" } variable "alb_sg_allow_api_gateway" { - default = true + default = false description = "Whether to allow API Gateway IP range to access" } diff --git a/alb.tf b/alb.tf index 107a2c8..29067f1 100644 --- a/alb.tf +++ b/alb.tf @@ -9,9 +9,9 @@ resource "aws_lb" "ecs" { enable_deletion_protection = var.alb_enable_deletion_protection security_groups = compact( + concat(try(aws_security_group.from_cloudfront.*.id, []), try(var.alb_additional_sg,[]), - concat(try(aws_security_group.from_cloudfront.*.id, []), [ - aws_security_group.alb[0].id, + [ aws_security_group.alb[0].id, try(aws_security_group.from_api_gateway[0].id, "") ])) diff --git a/sg-aws-iprange.tf b/sg-aws-iprange.tf index 1dd50fb..74665f6 100644 --- a/sg-aws-iprange.tf +++ b/sg-aws-iprange.tf @@ -31,8 +31,10 @@ resource "aws_security_group" "from_cloudfront" { tags = { Name = "from-cloudfront-${var.name}-${count.index}" - CreateDate = data.aws_ip_ranges.cloudfront.create_date - SyncToken = data.aws_ip_ranges.cloudfront.sync_token + } + + lifecycle { + create_before_destroy = true } } @@ -51,7 +53,9 @@ resource "aws_security_group" "from_api_gateway" { tags = { Name = "from-api-gateway-${var.name}" - CreateDate = data.aws_ip_ranges.api_gateway.create_date - SyncToken = data.aws_ip_ranges.api_gateway.sync_token + } + + lifecycle { + create_before_destroy = true } } \ No newline at end of file From bbcdd2522bbc42e7836b74dab6740f234c6ff9ac Mon Sep 17 00:00:00 2001 From: Nitin Bhadauria Date: Fri, 23 Jun 2023 16:25:10 +1000 Subject: [PATCH 5/8] block public access --- _variables.tf | 5 +++++ sg-alb.tf | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/_variables.tf b/_variables.tf index 5670ca3..0a04f83 100644 --- a/_variables.tf +++ b/_variables.tf @@ -90,6 +90,11 @@ variable "alb_sg_allow_test_listener" { description = "Whether to allow world access to the test listeners" } +variable "alb_sg_custom_cidr_blocks" { + default = ["0.0.0.0/0"] + description = "Block public access to ALB and stick to these CIDR blocks only" +} + variable "alb_additional_sg" { default = [] description = "pass addition list of security groups to add to ALB" diff --git a/sg-alb.tf b/sg-alb.tf index b24554c..4e9828b 100644 --- a/sg-alb.tf +++ b/sg-alb.tf @@ -31,7 +31,7 @@ resource "aws_security_group_rule" "https_from_world_to_alb" { to_port = 443 protocol = "tcp" security_group_id = aws_security_group.alb[0].id - cidr_blocks = ["0.0.0.0/0"] + cidr_blocks = var.alb_sg_custom_cidr_blocks } resource "aws_security_group_rule" "https_test_listener_from_world_to_alb" { @@ -43,7 +43,7 @@ resource "aws_security_group_rule" "https_test_listener_from_world_to_alb" { to_port = 8443 protocol = "tcp" security_group_id = aws_security_group.alb[0].id - cidr_blocks = ["0.0.0.0/0"] + cidr_blocks = var.alb_sg_custom_cidr_blocks } From 612b53326ffad30402d1d1d9ab879feaae217c2a Mon Sep 17 00:00:00 2001 From: Nitin Bhadauria Date: Tue, 10 Oct 2023 13:21:20 +1000 Subject: [PATCH 6/8] Update userdata.tpl --- userdata.tpl | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/userdata.tpl b/userdata.tpl index 7cf538f..67461c8 100644 --- a/userdata.tpl +++ b/userdata.tpl @@ -12,6 +12,20 @@ echo "vm.max_map_count=262144" >> /etc/sysctl.conf echo "fs.file-max=65536" >> /etc/sysctl.conf /sbin/sysctl -p /etc/sysctl.conf +function checkECSregistration { + logger -s "ecs Check if there are any running Docker containers" + # Check if there are any running Docker containers + sleep 1200 + docker_container_count=$(docker ps -q | wc -l) + ecs_registration=$(curl -s http://localhost:51678/v1/metadata | grep ${tf_cluster_name} | wc -l) + # If there are no running Docker containers and ECS agent is still not registered, terminate the instance + if [ "$docker_container_count" -eq "1" ] && [ $ecs_registration -eq "0" ]; then + logger -s "No running Docker containers found and ECS agent is not registered. Terminating the instance..." + shutdown -h now + fi +} + +checkECSregistration & echo "### INSTALL PACKAGES" yum update -y From b87c3a9c10207b427298807b384b7f2fe5cca4a1 Mon Sep 17 00:00:00 2001 From: nitin-bhadauria <106134393+nitin-bhadauria@users.noreply.github.com> Date: Wed, 19 Jun 2024 13:51:27 +1000 Subject: [PATCH 7/8] Update userdata.tpl --- userdata.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/userdata.tpl b/userdata.tpl index 67461c8..1c831a2 100644 --- a/userdata.tpl +++ b/userdata.tpl @@ -19,7 +19,7 @@ function checkECSregistration { docker_container_count=$(docker ps -q | wc -l) ecs_registration=$(curl -s http://localhost:51678/v1/metadata | grep ${tf_cluster_name} | wc -l) # If there are no running Docker containers and ECS agent is still not registered, terminate the instance - if [ "$docker_container_count" -eq "1" ] && [ $ecs_registration -eq "0" ]; then + if [ "$docker_container_count" -le "1" ] && [ $ecs_registration -eq "0" ]; then logger -s "No running Docker containers found and ECS agent is not registered. Terminating the instance..." shutdown -h now fi From d6cc5d3fb954cdd82b6426afbee30f8d99e2985e Mon Sep 17 00:00:00 2001 From: Nitin Bhadauria Date: Thu, 18 Jul 2024 12:17:56 +1000 Subject: [PATCH 8/8] update asg to allow managed_draining --- _variables.tf | 12 ++++++++++++ asg.tf | 15 +++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/_variables.tf b/_variables.tf index 0a04f83..9162a7a 100644 --- a/_variables.tf +++ b/_variables.tf @@ -391,4 +391,16 @@ variable "container_insights" { type = bool default = false description = "Enables CloudWatch Container Insights for a cluster." +} + +variable "enable_managed_draining" { + description = "Enable managed draining for ECS instances and add AmazonECSManaged tag" + type = bool + default = true +} + +variable "enable_managed_termination_protection" { + description = "Enable managed draining for ECS instances and add AmazonECSManaged tag" + type = bool + default = false } \ No newline at end of file diff --git a/asg.tf b/asg.tf index 787fbd9..759e5db 100644 --- a/asg.tf +++ b/asg.tf @@ -39,9 +39,19 @@ resource "aws_autoscaling_group" "ecs" { propagate_at_launch = true } + dynamic "tag" { + for_each = var.enable_managed_draining ? [1] : [] + content { + key = "AmazonECSManaged" + value = "" + propagate_at_launch = true + } + } + target_group_arns = var.target_group_arns health_check_grace_period = var.autoscaling_health_check_grace_period default_cooldown = var.autoscaling_default_cooldown + lifecycle { create_before_destroy = true } @@ -53,7 +63,8 @@ resource "aws_ecs_capacity_provider" "ecs_capacity_provider" { auto_scaling_group_provider { auto_scaling_group_arn = aws_autoscaling_group.ecs[0].arn - managed_termination_protection = "DISABLED" + managed_termination_protection = var.enable_managed_termination_protection ? "ENABLED" : "DISABLED" + managed_draining = var.enable_managed_draining ? "ENABLED" : "DISABLED" managed_scaling { maximum_scaling_step_size = 10 @@ -62,4 +73,4 @@ resource "aws_ecs_capacity_provider" "ecs_capacity_provider" { target_capacity = var.asg_target_capacity } } -} +} \ No newline at end of file