From 631431687decd445ea25a619ff915c6b7e80ed90 Mon Sep 17 00:00:00 2001 From: jakeasaurus Date: Tue, 17 Dec 2024 11:37:39 -0500 Subject: [PATCH 01/36] added module for nlb --- modules/aws/nlb/README.md | 41 +++++++ modules/aws/nlb/main.tf | 209 +++++++++++++++++++++++++++++++++++ modules/aws/nlb/outputs.tf | 49 ++++++++ modules/aws/nlb/variables.tf | 103 +++++++++++++++++ 4 files changed, 402 insertions(+) create mode 100644 modules/aws/nlb/README.md create mode 100644 modules/aws/nlb/main.tf create mode 100644 modules/aws/nlb/outputs.tf create mode 100644 modules/aws/nlb/variables.tf diff --git a/modules/aws/nlb/README.md b/modules/aws/nlb/README.md new file mode 100644 index 00000000..1446e71e --- /dev/null +++ b/modules/aws/nlb/README.md @@ -0,0 +1,41 @@ +NLB +```hcl +module "nlb" { + source = "./terraform-modules/modules/aws/nlb" + + name = "my-nlb" + internal = false + load_balancer_type = "network" + subnets = ["subnet-1234", "subnet-5678"] + + enable_cross_zone_load_balancing = true + + tags = { + Environment = "production" + } +} +``` + +For an ALB: + +```hcl +module "alb" { + source = "./terraform-modules/modules/aws/nlb" + + name = "my-alb" + internal = false + load_balancer_type = "application" + security_groups = ["sg-1234"] + subnets = ["subnet-1234", "subnet-5678"] + + access_logs = { + bucket = "my-alb-logs" + prefix = "my-alb" + enabled = true + } + + tags = { + Environment = "production" + } +} +``` diff --git a/modules/aws/nlb/main.tf b/modules/aws/nlb/main.tf new file mode 100644 index 00000000..07e6b5c7 --- /dev/null +++ b/modules/aws/nlb/main.tf @@ -0,0 +1,209 @@ +locals { + is_application = var.load_balancer_type == "application" + is_network = var.load_balancer_type == "network" +} + +# Load Balancer +resource "aws_lb" "this" { + name = var.name + internal = var.internal + load_balancer_type = var.load_balancer_type + security_groups = local.is_application ? var.security_groups : null + subnets = var.subnets + enable_deletion_protection = var.enable_deletion_protection + enable_cross_zone_load_balancing = local.is_network ? var.enable_cross_zone_load_balancing : null + customer_owned_ipv4_pool = var.customer_owned_ipv4_pool + ip_address_type = var.ip_address_type + desync_mitigation_mode = local.is_application ? var.desync_mitigation_mode : null + + dynamic "access_logs" { + for_each = var.access_logs != null ? [var.access_logs] : [] + content { + bucket = access_logs.value.bucket + prefix = access_logs.value.prefix + enabled = access_logs.value.enabled + } + } + + dynamic "subnet_mapping" { + for_each = var.subnet_mappings + content { + subnet_id = subnet_mapping.value.subnet_id + allocation_id = lookup(subnet_mapping.value, "allocation_id", null) + private_ipv4_address = lookup(subnet_mapping.value, "private_ipv4_address", null) + ipv6_address = lookup(subnet_mapping.value, "ipv6_address", null) + } + } + + tags = merge( + var.tags, + { + Name = var.name + }, + ) +} + +# Target Groups +resource "aws_lb_target_group" "this" { + for_each = var.target_groups + + name = lookup(each.value, "name", null) + name_prefix = lookup(each.value, "name_prefix", null) + port = each.value.port + protocol = each.value.protocol + vpc_id = each.value.vpc_id + target_type = lookup(each.value, "target_type", "instance") + deregistration_delay = lookup(each.value, "deregistration_delay", 300) + slow_start = lookup(each.value, "slow_start", 0) + proxy_protocol_v2 = lookup(each.value, "proxy_protocol_v2", false) + load_balancing_algorithm_type = lookup(each.value, "load_balancing_algorithm_type", null) + preserve_client_ip = lookup(each.value, "preserve_client_ip", null) + + dynamic "health_check" { + for_each = lookup(each.value, "health_check", null) != null ? [each.value.health_check] : [] + content { + enabled = lookup(health_check.value, "enabled", true) + healthy_threshold = lookup(health_check.value, "healthy_threshold", 3) + interval = lookup(health_check.value, "interval", 30) + matcher = lookup(health_check.value, "matcher", null) + path = lookup(health_check.value, "path", null) + port = lookup(health_check.value, "port", "traffic-port") + protocol = lookup(health_check.value, "protocol", "HTTP") + timeout = lookup(health_check.value, "timeout", 5) + unhealthy_threshold = lookup(health_check.value, "unhealthy_threshold", 3) + } + } + + dynamic "stickiness" { + for_each = lookup(each.value, "stickiness", null) != null ? [each.value.stickiness] : [] + content { + type = stickiness.value.type + cookie_duration = lookup(stickiness.value, "cookie_duration", null) + cookie_name = lookup(stickiness.value, "cookie_name", null) + } + } + + tags = merge( + var.tags, + lookup(each.value, "tags", {}), + ) +} + +# Listeners +resource "aws_lb_listener" "this" { + for_each = var.listeners + + load_balancer_arn = aws_lb.this.arn + port = each.value.port + protocol = each.value.protocol + ssl_policy = lookup(each.value, "ssl_policy", null) + certificate_arn = lookup(each.value, "certificate_arn", null) + + dynamic "default_action" { + for_each = [each.value.default_action] + content { + type = default_action.value.type + target_group_arn = lookup(default_action.value, "target_group_arn", null) + + dynamic "fixed_response" { + for_each = lookup(default_action.value, "fixed_response", null) != null ? [default_action.value.fixed_response] : [] + content { + content_type = fixed_response.value.content_type + message_body = lookup(fixed_response.value, "message_body", null) + status_code = lookup(fixed_response.value, "status_code", null) + } + } + + dynamic "redirect" { + for_each = lookup(default_action.value, "redirect", null) != null ? [default_action.value.redirect] : [] + content { + path = lookup(redirect.value, "path", null) + host = lookup(redirect.value, "host", null) + port = lookup(redirect.value, "port", null) + protocol = lookup(redirect.value, "protocol", null) + query = lookup(redirect.value, "query", null) + status_code = redirect.value.status_code + } + } + } + } +} + +# Listener Rules +resource "aws_lb_listener_rule" "this" { + for_each = var.listener_rules + + listener_arn = aws_lb_listener.this[each.value.listener_key].arn + priority = lookup(each.value, "priority", null) + + dynamic "action" { + for_each = [each.value.action] + content { + type = action.value.type + target_group_arn = lookup(action.value, "target_group_arn", null) + + dynamic "fixed_response" { + for_each = lookup(action.value, "fixed_response", null) != null ? [action.value.fixed_response] : [] + content { + content_type = fixed_response.value.content_type + message_body = lookup(fixed_response.value, "message_body", null) + status_code = lookup(fixed_response.value, "status_code", null) + } + } + + dynamic "redirect" { + for_each = lookup(action.value, "redirect", null) != null ? [action.value.redirect] : [] + content { + path = lookup(redirect.value, "path", null) + host = lookup(redirect.value, "host", null) + port = lookup(redirect.value, "port", null) + protocol = lookup(redirect.value, "protocol", null) + query = lookup(redirect.value, "query", null) + status_code = redirect.value.status_code + } + } + } + } + + dynamic "condition" { + for_each = each.value.conditions + content { + dynamic "host_header" { + for_each = lookup(condition.value, "host_header", null) != null ? [condition.value.host_header] : [] + content { + values = host_header.value.values + } + } + + dynamic "http_header" { + for_each = lookup(condition.value, "http_header", null) != null ? [condition.value.http_header] : [] + content { + http_header_name = http_header.value.http_header_name + values = http_header.value.values + } + } + + dynamic "path_pattern" { + for_each = lookup(condition.value, "path_pattern", null) != null ? [condition.value.path_pattern] : [] + content { + values = path_pattern.value.values + } + } + + dynamic "query_string" { + for_each = lookup(condition.value, "query_string", null) != null ? condition.value.query_string : [] + content { + key = lookup(query_string.value, "key", null) + value = query_string.value.value + } + } + + dynamic "source_ip" { + for_each = lookup(condition.value, "source_ip", null) != null ? [condition.value.source_ip] : [] + content { + values = source_ip.value.values + } + } + } + } +} diff --git a/modules/aws/nlb/outputs.tf b/modules/aws/nlb/outputs.tf new file mode 100644 index 00000000..894ef1b1 --- /dev/null +++ b/modules/aws/nlb/outputs.tf @@ -0,0 +1,49 @@ +output "id" { + description = "The ID of the load balancer" + value = aws_lb.this.id +} + +output "arn" { + description = "The ARN of the load balancer" + value = aws_lb.this.arn +} + +output "arn_suffix" { + description = "The ARN suffix for use with CloudWatch Metrics" + value = aws_lb.this.arn_suffix +} + +output "dns_name" { + description = "The DNS name of the load balancer" + value = aws_lb.this.dns_name +} + +output "zone_id" { + description = "The canonical hosted zone ID of the load balancer" + value = aws_lb.this.zone_id +} + +output "name" { + description = "The name of the load balancer" + value = aws_lb.this.name +} + +output "vpc_id" { + description = "The VPC ID of the load balancer" + value = aws_lb.this.vpc_id +} + +output "target_groups" { + description = "Map of target groups created and their attributes" + value = aws_lb_target_group.this +} + +output "listeners" { + description = "Map of listeners created and their attributes" + value = aws_lb_listener.this +} + +output "listener_rules" { + description = "Map of listener rules created and their attributes" + value = aws_lb_listener_rule.this +} diff --git a/modules/aws/nlb/variables.tf b/modules/aws/nlb/variables.tf new file mode 100644 index 00000000..7efbc55d --- /dev/null +++ b/modules/aws/nlb/variables.tf @@ -0,0 +1,103 @@ +variable "name" { + description = "Name of the load balancer" + type = string +} + +variable "internal" { + description = "If true, the LB will be internal" + type = bool + default = false +} + +variable "load_balancer_type" { + description = "Type of load balancer. Valid values are application or network" + type = string + default = "network" + + validation { + condition = contains(["application", "network"], var.load_balancer_type) + error_message = "Valid values for load_balancer_type are (application, network)." + } +} + +variable "security_groups" { + description = "List of security group IDs to assign to the LB" + type = list(string) + default = [] +} + +variable "subnets" { + description = "List of subnet IDs to attach to the LB" + type = list(string) + default = [] +} + +variable "subnet_mappings" { + description = "List of subnet mapping configurations" + type = list(map(string)) + default = [] +} + +variable "enable_deletion_protection" { + description = "If true, deletion of the load balancer will be disabled" + type = bool + default = false +} + +variable "enable_cross_zone_load_balancing" { + description = "If true, cross-zone load balancing of the load balancer will be enabled" + type = bool + default = false +} + +variable "customer_owned_ipv4_pool" { + description = "The ID of the customer owned ipv4 pool to use for this load balancer" + type = string + default = null +} + +variable "ip_address_type" { + description = "The type of IP addresses used by the subnets for your load balancer" + type = string + default = "ipv4" +} + +variable "desync_mitigation_mode" { + description = "Determines how the load balancer handles requests that might pose a security risk to your application" + type = string + default = "defensive" +} + +variable "access_logs" { + description = "Access logs configuration for the LB" + type = object({ + bucket = string + prefix = string + enabled = bool + }) + default = null +} + +variable "tags" { + description = "A map of tags to assign to the resource" + type = map(string) + default = {} +} + +variable "target_groups" { + description = "Map of target group configurations" + type = any + default = {} +} + +variable "listeners" { + description = "Map of listener configurations" + type = any + default = {} +} + +variable "listener_rules" { + description = "Map of listener rule configurations" + type = any + default = {} +} From a7601693582f4fa7c6a7e337c436137230528f4d Mon Sep 17 00:00:00 2001 From: jakeasaurus Date: Tue, 17 Dec 2024 11:38:37 -0500 Subject: [PATCH 02/36] renamed module folder to use lb rather than nlb --- modules/aws/{nlb => lb}/README.md | 0 modules/aws/{nlb => lb}/main.tf | 0 modules/aws/{nlb => lb}/outputs.tf | 0 modules/aws/{nlb => lb}/variables.tf | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename modules/aws/{nlb => lb}/README.md (100%) rename modules/aws/{nlb => lb}/main.tf (100%) rename modules/aws/{nlb => lb}/outputs.tf (100%) rename modules/aws/{nlb => lb}/variables.tf (100%) diff --git a/modules/aws/nlb/README.md b/modules/aws/lb/README.md similarity index 100% rename from modules/aws/nlb/README.md rename to modules/aws/lb/README.md diff --git a/modules/aws/nlb/main.tf b/modules/aws/lb/main.tf similarity index 100% rename from modules/aws/nlb/main.tf rename to modules/aws/lb/main.tf diff --git a/modules/aws/nlb/outputs.tf b/modules/aws/lb/outputs.tf similarity index 100% rename from modules/aws/nlb/outputs.tf rename to modules/aws/lb/outputs.tf diff --git a/modules/aws/nlb/variables.tf b/modules/aws/lb/variables.tf similarity index 100% rename from modules/aws/nlb/variables.tf rename to modules/aws/lb/variables.tf From 1da7b58dca44eb635da772893630644e88dfe286 Mon Sep 17 00:00:00 2001 From: jakeasaurus Date: Wed, 18 Dec 2024 13:47:49 -0500 Subject: [PATCH 03/36] updated the naming of outputs and resources --- modules/aws/lb/main.tf | 12 ++++++------ modules/aws/lb/outputs.tf | 20 ++++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/modules/aws/lb/main.tf b/modules/aws/lb/main.tf index 07e6b5c7..2bcf02f1 100644 --- a/modules/aws/lb/main.tf +++ b/modules/aws/lb/main.tf @@ -4,7 +4,7 @@ locals { } # Load Balancer -resource "aws_lb" "this" { +resource "aws_lb" "load_balancer" { name = var.name internal = var.internal load_balancer_type = var.load_balancer_type @@ -44,7 +44,7 @@ resource "aws_lb" "this" { } # Target Groups -resource "aws_lb_target_group" "this" { +resource "aws_lb_target_group" "target_group" { for_each = var.target_groups name = lookup(each.value, "name", null) @@ -90,10 +90,10 @@ resource "aws_lb_target_group" "this" { } # Listeners -resource "aws_lb_listener" "this" { +resource "aws_lb_listener" "listener" { for_each = var.listeners - load_balancer_arn = aws_lb.this.arn + load_balancer_arn = aws_lb.load_balancer.arn port = each.value.port protocol = each.value.protocol ssl_policy = lookup(each.value, "ssl_policy", null) @@ -130,10 +130,10 @@ resource "aws_lb_listener" "this" { } # Listener Rules -resource "aws_lb_listener_rule" "this" { +resource "aws_lb_listener_rule" "listener_rule" { for_each = var.listener_rules - listener_arn = aws_lb_listener.this[each.value.listener_key].arn + listener_arn = aws_lb_listener.listener[each.value.listener_key].arn priority = lookup(each.value, "priority", null) dynamic "action" { diff --git a/modules/aws/lb/outputs.tf b/modules/aws/lb/outputs.tf index 894ef1b1..cbb0c879 100644 --- a/modules/aws/lb/outputs.tf +++ b/modules/aws/lb/outputs.tf @@ -1,49 +1,49 @@ output "id" { description = "The ID of the load balancer" - value = aws_lb.this.id + value = aws_lb.load_balancer.id } output "arn" { description = "The ARN of the load balancer" - value = aws_lb.this.arn + value = aws_lb.load_balancer.arn } output "arn_suffix" { description = "The ARN suffix for use with CloudWatch Metrics" - value = aws_lb.this.arn_suffix + value = aws_lb.load_balancer.arn_suffix } output "dns_name" { description = "The DNS name of the load balancer" - value = aws_lb.this.dns_name + value = aws_lb.load_balancer.dns_name } output "zone_id" { description = "The canonical hosted zone ID of the load balancer" - value = aws_lb.this.zone_id + value = aws_lb.load_balancer.zone_id } output "name" { description = "The name of the load balancer" - value = aws_lb.this.name + value = aws_lb.load_balancer.name } output "vpc_id" { description = "The VPC ID of the load balancer" - value = aws_lb.this.vpc_id + value = aws_lb.load_balancer.vpc_id } output "target_groups" { description = "Map of target groups created and their attributes" - value = aws_lb_target_group.this + value = aws_lb_target_group.target_group } output "listeners" { description = "Map of listeners created and their attributes" - value = aws_lb_listener.this + value = aws_lb_listener.listener } output "listener_rules" { description = "Map of listener rules created and their attributes" - value = aws_lb_listener_rule.this + value = aws_lb_listener_rule.listener_rule } From 316c41ff34f87f251d7327b1beb8d213661125b9 Mon Sep 17 00:00:00 2001 From: jakeasaurus Date: Thu, 2 Jan 2025 12:04:15 -0500 Subject: [PATCH 04/36] fixed syntax to remove all instances of lookup --- modules/aws/lb/main.tf | 114 +++++++++++------------ modules/aws/lb/variables.tf | 178 ++++++++++++++++++++++++++++++++++-- 2 files changed, 226 insertions(+), 66 deletions(-) diff --git a/modules/aws/lb/main.tf b/modules/aws/lb/main.tf index 2bcf02f1..6a782588 100644 --- a/modules/aws/lb/main.tf +++ b/modules/aws/lb/main.tf @@ -29,9 +29,9 @@ resource "aws_lb" "load_balancer" { for_each = var.subnet_mappings content { subnet_id = subnet_mapping.value.subnet_id - allocation_id = lookup(subnet_mapping.value, "allocation_id", null) - private_ipv4_address = lookup(subnet_mapping.value, "private_ipv4_address", null) - ipv6_address = lookup(subnet_mapping.value, "ipv6_address", null) + allocation_id = subnet_mapping.value.allocation_id + private_ipv4_address = subnet_mapping.value.private_ipv4_address + ipv6_address = subnet_mapping.value.ipv6_address } } @@ -47,45 +47,45 @@ resource "aws_lb" "load_balancer" { resource "aws_lb_target_group" "target_group" { for_each = var.target_groups - name = lookup(each.value, "name", null) - name_prefix = lookup(each.value, "name_prefix", null) - port = each.value.port - protocol = each.value.protocol - vpc_id = each.value.vpc_id - target_type = lookup(each.value, "target_type", "instance") - deregistration_delay = lookup(each.value, "deregistration_delay", 300) - slow_start = lookup(each.value, "slow_start", 0) - proxy_protocol_v2 = lookup(each.value, "proxy_protocol_v2", false) - load_balancing_algorithm_type = lookup(each.value, "load_balancing_algorithm_type", null) - preserve_client_ip = lookup(each.value, "preserve_client_ip", null) + name = var.target_group_name + name_prefix = var.target_group_name_prefix + port = var.target_group_port + protocol = var.target_group_protocol + vpc_id = var.target_group_vpc_id + target_type = var.target_group_target_type + deregistration_delay = var.target_group_deregistration_delay + slow_start = var.target_group_slow_start + proxy_protocol_v2 = var.target_group_proxy_protocol_v2 + load_balancing_algorithm_type = var.target_group_load_balancing_algorithm_type + preserve_client_ip = var.target_group_preserve_client_ip dynamic "health_check" { - for_each = lookup(each.value, "health_check", null) != null ? [each.value.health_check] : [] + for_each = each.value.health_check != null ? [each.value.health_check] : [] content { - enabled = lookup(health_check.value, "enabled", true) - healthy_threshold = lookup(health_check.value, "healthy_threshold", 3) - interval = lookup(health_check.value, "interval", 30) - matcher = lookup(health_check.value, "matcher", null) - path = lookup(health_check.value, "path", null) - port = lookup(health_check.value, "port", "traffic-port") - protocol = lookup(health_check.value, "protocol", "HTTP") - timeout = lookup(health_check.value, "timeout", 5) - unhealthy_threshold = lookup(health_check.value, "unhealthy_threshold", 3) + enabled = health_check.value.enabled + healthy_threshold = health_check.value.healthy_threshold + interval = health_check.value.interval + matcher = health_check.value.matcher + path = health_check.value.path + port = health_check.value.port + protocol = health_check.value.protocol + timeout = health_check.value.timeout + unhealthy_threshold = health_check.value.unhealthy_threshold } } dynamic "stickiness" { - for_each = lookup(each.value, "stickiness", null) != null ? [each.value.stickiness] : [] + for_each = each.value.stickiness != null ? [each.value.stickiness] : [] content { type = stickiness.value.type - cookie_duration = lookup(stickiness.value, "cookie_duration", null) - cookie_name = lookup(stickiness.value, "cookie_name", null) + cookie_duration = stickiness.value.cookie_duration + cookie_name = stickiness.value.cookie_name } } tags = merge( var.tags, - lookup(each.value, "tags", {}), + each.value.tags ) } @@ -96,32 +96,32 @@ resource "aws_lb_listener" "listener" { load_balancer_arn = aws_lb.load_balancer.arn port = each.value.port protocol = each.value.protocol - ssl_policy = lookup(each.value, "ssl_policy", null) - certificate_arn = lookup(each.value, "certificate_arn", null) + ssl_policy = each.value.ssl_policy + certificate_arn = each.value dynamic "default_action" { for_each = [each.value.default_action] content { type = default_action.value.type - target_group_arn = lookup(default_action.value, "target_group_arn", null) + target_group_arn = default_action.value.target_group_arn dynamic "fixed_response" { - for_each = lookup(default_action.value, "fixed_response", null) != null ? [default_action.value.fixed_response] : [] + for_each = default_action.value.fixed_response != null ? [default_action.value.fixed_response] : [] content { content_type = fixed_response.value.content_type - message_body = lookup(fixed_response.value, "message_body", null) - status_code = lookup(fixed_response.value, "status_code", null) + message_body = fixed_response.value.message_body + status_code = fixed_response.value.status_code } } dynamic "redirect" { - for_each = lookup(default_action.value, "redirect", null) != null ? [default_action.value.redirect] : [] + for_each = default_action.value.redirect != null ? [default_action.value.redirect] : [] content { - path = lookup(redirect.value, "path", null) - host = lookup(redirect.value, "host", null) - port = lookup(redirect.value, "port", null) - protocol = lookup(redirect.value, "protocol", null) - query = lookup(redirect.value, "query", null) + path = redirect.value.path + host = redirect.value.host + port = redirect.value.port + protocol = redirect.value.protocol + query = redirect.value.query status_code = redirect.value.status_code } } @@ -134,31 +134,31 @@ resource "aws_lb_listener_rule" "listener_rule" { for_each = var.listener_rules listener_arn = aws_lb_listener.listener[each.value.listener_key].arn - priority = lookup(each.value, "priority", null) + priority = each.value.priority dynamic "action" { for_each = [each.value.action] content { type = action.value.type - target_group_arn = lookup(action.value, "target_group_arn", null) + target_group_arn = action.value.target_group_arn dynamic "fixed_response" { - for_each = lookup(action.value, "fixed_response", null) != null ? [action.value.fixed_response] : [] + for_each = action.value.fixed_response != null ? [action.value.fixed_response] : [] content { content_type = fixed_response.value.content_type - message_body = lookup(fixed_response.value, "message_body", null) - status_code = lookup(fixed_response.value, "status_code", null) + message_body = fixed_response.value.message_body + status_code = fixed_response.value.status_code } } dynamic "redirect" { - for_each = lookup(action.value, "redirect", null) != null ? [action.value.redirect] : [] + for_each = action.value.redirect != null ? [action.value.redirect] : [] content { - path = lookup(redirect.value, "path", null) - host = lookup(redirect.value, "host", null) - port = lookup(redirect.value, "port", null) - protocol = lookup(redirect.value, "protocol", null) - query = lookup(redirect.value, "query", null) + path = redirect.value.path + host = redirect.value.host + port = redirect.value.port + protocol = redirect.value.protocol + query = redirect.value.query status_code = redirect.value.status_code } } @@ -169,14 +169,14 @@ resource "aws_lb_listener_rule" "listener_rule" { for_each = each.value.conditions content { dynamic "host_header" { - for_each = lookup(condition.value, "host_header", null) != null ? [condition.value.host_header] : [] + for_each = condition.value.host_header != null ? [condition.value.host_header] : [] content { values = host_header.value.values } } dynamic "http_header" { - for_each = lookup(condition.value, "http_header", null) != null ? [condition.value.http_header] : [] + for_each = condition.value.http_header != null ? [condition.value.http_header] : [] content { http_header_name = http_header.value.http_header_name values = http_header.value.values @@ -184,22 +184,22 @@ resource "aws_lb_listener_rule" "listener_rule" { } dynamic "path_pattern" { - for_each = lookup(condition.value, "path_pattern", null) != null ? [condition.value.path_pattern] : [] + for_each = condition.value.path_pattern != null ? [condition.value.path_pattern] : [] content { values = path_pattern.value.values } } dynamic "query_string" { - for_each = lookup(condition.value, "query_string", null) != null ? condition.value.query_string : [] + for_each = condition.value.query_string != null ? [condition.value.query_string] : [] content { - key = lookup(query_string.value, "key", null) + key = query_string.value.key value = query_string.value.value } } dynamic "source_ip" { - for_each = lookup(condition.value, "source_ip", null) != null ? [condition.value.source_ip] : [] + for_each = condition.value.source_ip != null ? [condition.value.source_ip] : [] content { values = source_ip.value.values } diff --git a/modules/aws/lb/variables.tf b/modules/aws/lb/variables.tf index 7efbc55d..9b139b68 100644 --- a/modules/aws/lb/variables.tf +++ b/modules/aws/lb/variables.tf @@ -1,3 +1,4 @@ +# Load Balancer Variables variable "name" { description = "Name of the load balancer" type = string @@ -78,26 +79,185 @@ variable "access_logs" { default = null } -variable "tags" { - description = "A map of tags to assign to the resource" - type = map(string) - default = {} +# Target Group Variables +variable "target_group_name" { + description = "Name of the target group" + type = string + default = null +} + +variable "target_group_name_prefix" { + description = "Prefix for the target group name" + type = string + default = null +} + +variable "target_group_port" { + description = "Port on which targets receive traffic" + type = number +} + +variable "target_group_protocol" { + description = "Protocol to use for routing traffic to the targets" + type = string +} + +variable "target_group_vpc_id" { + description = "Identifier of the VPC in which to create the target group" + type = string +} + +variable "target_group_target_type" { + description = "Type of target that you must specify when registering targets with this target group" + type = string + default = "instance" +} + +variable "target_group_deregistration_delay" { + description = "Amount of time to wait for in-flight requests to complete before deregistering a target" + type = number + default = 300 +} + +variable "target_group_slow_start" { + description = "Amount of time for targets to warm up before the load balancer sends them a full share of requests" + type = number + default = 0 +} + +variable "target_group_proxy_protocol_v2" { + description = "Whether to enable support for proxy protocol v2" + type = bool + default = false } +variable "target_group_load_balancing_algorithm_type" { + description = "Determines how the load balancer selects targets when routing requests" + type = string + default = null +} + +variable "target_group_preserve_client_ip" { + description = "Whether client IP preservation is enabled" + type = bool + default = null +} + +# The target_groups variable should now only contain the nested objects variable "target_groups" { description = "Map of target group configurations" - type = any - default = {} + type = map(object({ + health_check = optional(object({ + enabled = optional(bool, true) + healthy_threshold = optional(number, 3) + interval = optional(number, 30) + matcher = optional(string) + path = optional(string) + port = optional(string, "traffic-port") + protocol = optional(string, "HTTP") + timeout = optional(number, 5) + unhealthy_threshold = optional(number, 3) + })) + + stickiness = optional(object({ + type = string + cookie_duration = optional(number) + cookie_name = optional(string) + })) + + tags = optional(map(string), {}) + })) + default = {} } +# Listener Variables variable "listeners" { description = "Map of listener configurations" - type = any - default = {} + type = map(object({ + port = number + protocol = string + ssl_policy = optional(string) + certificate_arn = optional(string) + + default_action = object({ + type = string + target_group_arn = optional(string) + + fixed_response = optional(object({ + content_type = string + message_body = optional(string) + status_code = optional(string) + })) + + redirect = optional(object({ + path = optional(string) + host = optional(string) + port = optional(string) + protocol = optional(string) + query = optional(string) + status_code = string + })) + }) + })) + default = {} } +# Listener Rule Variables variable "listener_rules" { description = "Map of listener rule configurations" - type = any + type = map(object({ + listener_key = string + priority = optional(number) + + action = object({ + type = string + target_group_arn = optional(string) + + fixed_response = optional(object({ + content_type = string + message_body = optional(string) + status_code = optional(string) + })) + + redirect = optional(object({ + path = optional(string) + host = optional(string) + port = optional(string) + protocol = optional(string) + query = optional(string) + status_code = string + })) + }) + + conditions = list(object({ + host_header = optional(object({ + values = list(string) + })) + + http_header = optional(object({ + http_header_name = string + values = list(string) + })) + + path_pattern = optional(object({ + values = list(string) + })) + + query_string = optional(list(object({ + key = optional(string) + value = string + }))) + + source_ip = optional(object({ + values = list(string) + })) + })) + })) + default = {} +} + +variable "tags" { + description = "A map of tags to assign to the resource" + type = map(string) default = {} } From f6a0c5fb0107ba3c12d7cd66f217217b28e8c0dc Mon Sep 17 00:00:00 2001 From: jakeasaurus Date: Thu, 2 Jan 2025 14:04:42 -0500 Subject: [PATCH 05/36] updated syntax for cert arn on listener --- modules/aws/lb/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/aws/lb/main.tf b/modules/aws/lb/main.tf index 6a782588..05b68634 100644 --- a/modules/aws/lb/main.tf +++ b/modules/aws/lb/main.tf @@ -97,7 +97,7 @@ resource "aws_lb_listener" "listener" { port = each.value.port protocol = each.value.protocol ssl_policy = each.value.ssl_policy - certificate_arn = each.value + certificate_arn = each.value.certificate_arn dynamic "default_action" { for_each = [each.value.default_action] From 700a1a6faf2081ac7514ab202a5f251753473f46 Mon Sep 17 00:00:00 2001 From: jakeasaurus Date: Thu, 2 Jan 2025 14:23:45 -0500 Subject: [PATCH 06/36] updated arn resource addressing --- modules/aws/lb/main.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/aws/lb/main.tf b/modules/aws/lb/main.tf index 05b68634..24c9e5db 100644 --- a/modules/aws/lb/main.tf +++ b/modules/aws/lb/main.tf @@ -103,7 +103,7 @@ resource "aws_lb_listener" "listener" { for_each = [each.value.default_action] content { type = default_action.value.type - target_group_arn = default_action.value.target_group_arn + target_group_arn = aws_lb_target_group.target_group.arn dynamic "fixed_response" { for_each = default_action.value.fixed_response != null ? [default_action.value.fixed_response] : [] @@ -140,7 +140,7 @@ resource "aws_lb_listener_rule" "listener_rule" { for_each = [each.value.action] content { type = action.value.type - target_group_arn = action.value.target_group_arn + target_group_arn = aws_lb_target_group.target_group.arn dynamic "fixed_response" { for_each = action.value.fixed_response != null ? [action.value.fixed_response] : [] From 3341e95ff7ea7e9ab6ec649e235c9bd9c0dd0558 Mon Sep 17 00:00:00 2001 From: jakeasaurus Date: Thu, 2 Jan 2025 15:16:27 -0500 Subject: [PATCH 07/36] squashed silly commits --- modules/aws/lb/main.tf | 4 ++-- modules/aws/lb/variables.tf | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/modules/aws/lb/main.tf b/modules/aws/lb/main.tf index 24c9e5db..3229b1dc 100644 --- a/modules/aws/lb/main.tf +++ b/modules/aws/lb/main.tf @@ -103,7 +103,7 @@ resource "aws_lb_listener" "listener" { for_each = [each.value.default_action] content { type = default_action.value.type - target_group_arn = aws_lb_target_group.target_group.arn + target_group_arn = aws_lb_target_group.target_group["main"].arn dynamic "fixed_response" { for_each = default_action.value.fixed_response != null ? [default_action.value.fixed_response] : [] @@ -140,7 +140,7 @@ resource "aws_lb_listener_rule" "listener_rule" { for_each = [each.value.action] content { type = action.value.type - target_group_arn = aws_lb_target_group.target_group.arn + target_group_arn = aws_lb_target_group.target_group["main"].arn dynamic "fixed_response" { for_each = action.value.fixed_response != null ? [action.value.fixed_response] : [] diff --git a/modules/aws/lb/variables.tf b/modules/aws/lb/variables.tf index 9b139b68..ed37ae1c 100644 --- a/modules/aws/lb/variables.tf +++ b/modules/aws/lb/variables.tf @@ -143,7 +143,6 @@ variable "target_group_preserve_client_ip" { default = null } -# The target_groups variable should now only contain the nested objects variable "target_groups" { description = "Map of target group configurations" type = map(object({ From 517d0762c236c2ce666a6691ddb6bbfe53af6b92 Mon Sep 17 00:00:00 2001 From: jakeasaurus Date: Fri, 3 Jan 2025 10:06:25 -0500 Subject: [PATCH 08/36] added a lot of comments and some additional arguements and associated vars --- modules/aws/lb/main.tf | 115 ++++++++++++++++++++++++++++-------- modules/aws/lb/variables.tf | 68 ++++++++++++++++++--- 2 files changed, 148 insertions(+), 35 deletions(-) diff --git a/modules/aws/lb/main.tf b/modules/aws/lb/main.tf index 3229b1dc..0bc229d7 100644 --- a/modules/aws/lb/main.tf +++ b/modules/aws/lb/main.tf @@ -5,16 +5,25 @@ locals { # Load Balancer resource "aws_lb" "load_balancer" { - name = var.name - internal = var.internal - load_balancer_type = var.load_balancer_type - security_groups = local.is_application ? var.security_groups : null - subnets = var.subnets - enable_deletion_protection = var.enable_deletion_protection + # Common settings + name = var.name + internal = var.internal + load_balancer_type = var.load_balancer_type + subnets = var.subnets + enable_deletion_protection = var.enable_deletion_protection + customer_owned_ipv4_pool = var.customer_owned_ipv4_pool + ip_address_type = var.ip_address_type + + # Application Load Balancer specific settings + security_groups = local.is_application ? var.security_groups : null + desync_mitigation_mode = local.is_application ? var.desync_mitigation_mode : null + idle_timeout = local.is_application ? var.idle_timeout : null + drop_invalid_header_fields = local.is_application ? var.drop_invalid_header_fields : null + enable_http2 = local.is_application ? var.enable_http2 : null + enable_waf_fail_open = local.is_application ? var.enable_waf_fail_open : null + + # Network Load Balancer specific settings enable_cross_zone_load_balancing = local.is_network ? var.enable_cross_zone_load_balancing : null - customer_owned_ipv4_pool = var.customer_owned_ipv4_pool - ip_address_type = var.ip_address_type - desync_mitigation_mode = local.is_application ? var.desync_mitigation_mode : null dynamic "access_logs" { for_each = var.access_logs != null ? [var.access_logs] : [] @@ -43,21 +52,25 @@ resource "aws_lb" "load_balancer" { ) } -# Target Groups resource "aws_lb_target_group" "target_group" { for_each = var.target_groups - name = var.target_group_name - name_prefix = var.target_group_name_prefix - port = var.target_group_port - protocol = var.target_group_protocol - vpc_id = var.target_group_vpc_id - target_type = var.target_group_target_type - deregistration_delay = var.target_group_deregistration_delay - slow_start = var.target_group_slow_start - proxy_protocol_v2 = var.target_group_proxy_protocol_v2 - load_balancing_algorithm_type = var.target_group_load_balancing_algorithm_type - preserve_client_ip = var.target_group_preserve_client_ip + # Common settings + name = var.target_group_name + name_prefix = var.target_group_name_prefix + port = var.target_group_port + protocol = var.target_group_protocol + vpc_id = var.target_group_vpc_id + target_type = var.target_group_target_type + deregistration_delay = var.target_group_deregistration_delay + + # Application Load Balancer specific settings + slow_start = local.is_application ? var.target_group_slow_start : null + load_balancing_algorithm_type = local.is_application ? var.target_group_load_balancing_algorithm_type : null + + # Network Load Balancer specific settings + proxy_protocol_v2 = local.is_network ? var.target_group_proxy_protocol_v2 : null + preserve_client_ip = local.is_network ? var.target_group_preserve_client_ip : null dynamic "health_check" { for_each = each.value.health_check != null ? [each.value.health_check] : [] @@ -93,18 +106,26 @@ resource "aws_lb_target_group" "target_group" { resource "aws_lb_listener" "listener" { for_each = var.listeners + # Common settings load_balancer_arn = aws_lb.load_balancer.arn port = each.value.port protocol = each.value.protocol - ssl_policy = each.value.ssl_policy - certificate_arn = each.value.certificate_arn + + # SSL/TLS settings + ssl_policy = each.value.ssl_policy + certificate_arn = each.value.certificate_arn + + # Application Load Balancer specific settings + alpn_policy = local.is_application ? each.value.alpn_policy : null dynamic "default_action" { for_each = [each.value.default_action] content { + # Common settings type = default_action.value.type target_group_arn = aws_lb_target_group.target_group["main"].arn + # Application Load Balancer specific fixed response action dynamic "fixed_response" { for_each = default_action.value.fixed_response != null ? [default_action.value.fixed_response] : [] content { @@ -114,6 +135,7 @@ resource "aws_lb_listener" "listener" { } } + # Application Load Balancer specific redirect action dynamic "redirect" { for_each = default_action.value.redirect != null ? [default_action.value.redirect] : [] content { @@ -125,23 +147,57 @@ resource "aws_lb_listener" "listener" { status_code = redirect.value.status_code } } + + # Application Load Balancer authentication settings + dynamic "authenticate_oidc" { + for_each = each.value.authenticate_oidc != null && local.is_application ? [each.value.authenticate_oidc] : [] + content { + authorization_endpoint = authenticate_oidc.value.authorization_endpoint + client_id = authenticate_oidc.value.client_id + client_secret = authenticate_oidc.value.client_secret + issuer = authenticate_oidc.value.issuer + token_endpoint = authenticate_oidc.value.token_endpoint + user_info_endpoint = authenticate_oidc.value.user_info_endpoint + } + } + + dynamic "authenticate_cognito" { + for_each = each.value.authenticate_cognito != null && local.is_application ? [each.value.authenticate_cognito] : [] + content { + user_pool_arn = authenticate_cognito.value.user_pool_arn + user_pool_client_id = authenticate_cognito.value.user_pool_client_id + user_pool_domain = authenticate_cognito.value.user_pool_domain + } + } + + # Network Load Balancer specific settings + dynamic "mutual_authentication" { + for_each = each.value.mutual_authentication != null && local.is_network ? [each.value.mutual_authentication] : [] + content { + mode = mutual_authentication.value.mode + trust_store_uri = mutual_authentication.value.trust_store_uri + } + } } } } -# Listener Rules -resource "aws_lb_listener_rule" "listener_rule" { - for_each = var.listener_rules +# Listener Rules (Application Load Balancer only) +resource "aws_lb_listener_rule" "listener_rule" { + # Common settings + for_each = var.listener_rules listener_arn = aws_lb_listener.listener[each.value.listener_key].arn priority = each.value.priority + # Application Load Balancer action settings dynamic "action" { for_each = [each.value.action] content { type = action.value.type target_group_arn = aws_lb_target_group.target_group["main"].arn + # ALB fixed response action dynamic "fixed_response" { for_each = action.value.fixed_response != null ? [action.value.fixed_response] : [] content { @@ -151,6 +207,7 @@ resource "aws_lb_listener_rule" "listener_rule" { } } + # ALB redirect action dynamic "redirect" { for_each = action.value.redirect != null ? [action.value.redirect] : [] content { @@ -165,9 +222,11 @@ resource "aws_lb_listener_rule" "listener_rule" { } } + # Application Load Balancer condition settings dynamic "condition" { for_each = each.value.conditions content { + # ALB host header condition dynamic "host_header" { for_each = condition.value.host_header != null ? [condition.value.host_header] : [] content { @@ -175,6 +234,7 @@ resource "aws_lb_listener_rule" "listener_rule" { } } + # ALB http header condition dynamic "http_header" { for_each = condition.value.http_header != null ? [condition.value.http_header] : [] content { @@ -183,6 +243,7 @@ resource "aws_lb_listener_rule" "listener_rule" { } } + # ALB path pattern condition dynamic "path_pattern" { for_each = condition.value.path_pattern != null ? [condition.value.path_pattern] : [] content { @@ -190,6 +251,7 @@ resource "aws_lb_listener_rule" "listener_rule" { } } + # ALB query string condition dynamic "query_string" { for_each = condition.value.query_string != null ? [condition.value.query_string] : [] content { @@ -198,6 +260,7 @@ resource "aws_lb_listener_rule" "listener_rule" { } } + # Common source IP condition (works for both ALB and NLB) dynamic "source_ip" { for_each = condition.value.source_ip != null ? [condition.value.source_ip] : [] content { diff --git a/modules/aws/lb/variables.tf b/modules/aws/lb/variables.tf index ed37ae1c..7ec7d973 100644 --- a/modules/aws/lb/variables.tf +++ b/modules/aws/lb/variables.tf @@ -79,6 +79,30 @@ variable "access_logs" { default = null } +variable "idle_timeout" { + description = "The time in seconds that the connection is allowed to be idle" + type = number + default = 60 +} + +variable "enable_http2" { + description = "Indicates whether HTTP/2 is enabled in application load balancers" + type = bool + default = true +} + +variable "enable_waf_fail_open" { + description = "Indicates whether to allow a WAF-enabled load balancer to route requests to targets if it is unable to forward the request to AWS WAF" + type = bool + default = false +} + +variable "drop_invalid_header_fields" { + description = "Indicates whether invalid header fields are dropped in application load balancers" + type = bool + default = false +} + # Target Group Variables variable "target_group_name" { description = "Name of the target group" @@ -146,16 +170,21 @@ variable "target_group_preserve_client_ip" { variable "target_groups" { description = "Map of target group configurations" type = map(object({ + protocol_version = optional(string) + connection_termination = optional(bool) + lambda_multi_value_headers_enabled = optional(bool) health_check = optional(object({ - enabled = optional(bool, true) - healthy_threshold = optional(number, 3) - interval = optional(number, 30) - matcher = optional(string) - path = optional(string) - port = optional(string, "traffic-port") - protocol = optional(string, "HTTP") - timeout = optional(number, 5) - unhealthy_threshold = optional(number, 3) + enabled = optional(bool, true) + healthy_threshold = optional(number, 3) + interval = optional(number, 30) + matcher = optional(string) + path = optional(string) + port = optional(string, "traffic-port") + protocol = optional(string, "HTTP") + timeout = optional(number, 5) + unhealthy_threshold = optional(number, 3) + success_codes = optional(string) + grace_period_seconds = optional(number) })) stickiness = optional(object({ @@ -177,6 +206,27 @@ variable "listeners" { protocol = string ssl_policy = optional(string) certificate_arn = optional(string) + alpn_policy = optional(string) + + authenticate_oidc = optional(object({ + authorization_endpoint = string + client_id = string + client_secret = string + issuer = string + token_endpoint = string + user_info_endpoint = string + })) + + authenticate_cognito = optional(object({ + user_pool_arn = string + user_pool_client_id = string + user_pool_domain = string + })) + + mutual_authentication = optional(object({ + mode = string + trust_store_uri = optional(string) + })) default_action = object({ type = string From 34bbe74283c45b14b824afb52ee1722ee511f0ff Mon Sep 17 00:00:00 2001 From: jakeasaurus Date: Fri, 3 Jan 2025 10:23:30 -0500 Subject: [PATCH 09/36] updated source to test new changes --- modules/aws/lb/main.tf | 18 +++++++++--------- modules/aws/lb/variables.tf | 3 +-- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/modules/aws/lb/main.tf b/modules/aws/lb/main.tf index 0bc229d7..a7c4beac 100644 --- a/modules/aws/lb/main.tf +++ b/modules/aws/lb/main.tf @@ -118,6 +118,15 @@ resource "aws_lb_listener" "listener" { # Application Load Balancer specific settings alpn_policy = local.is_application ? each.value.alpn_policy : null + dynamic "mutual_authentication" { + for_each = (local.is_network && each.value.mutual_authentication != null) ? [each.value.mutual_authentication] : [] + content { + mode = mutual_authentication.value.mode + } + } + + + dynamic "default_action" { for_each = [each.value.default_action] content { @@ -169,15 +178,6 @@ resource "aws_lb_listener" "listener" { user_pool_domain = authenticate_cognito.value.user_pool_domain } } - - # Network Load Balancer specific settings - dynamic "mutual_authentication" { - for_each = each.value.mutual_authentication != null && local.is_network ? [each.value.mutual_authentication] : [] - content { - mode = mutual_authentication.value.mode - trust_store_uri = mutual_authentication.value.trust_store_uri - } - } } } } diff --git a/modules/aws/lb/variables.tf b/modules/aws/lb/variables.tf index 7ec7d973..0cc5d017 100644 --- a/modules/aws/lb/variables.tf +++ b/modules/aws/lb/variables.tf @@ -224,8 +224,7 @@ variable "listeners" { })) mutual_authentication = optional(object({ - mode = string - trust_store_uri = optional(string) + mode = string # Only valid field, can be "verify" or "strict" })) default_action = object({ From 087d505fb9296e75bda166ef816144bb7b039a8e Mon Sep 17 00:00:00 2001 From: jakeasaurus Date: Mon, 6 Jan 2025 11:29:25 -0500 Subject: [PATCH 10/36] made various changes to use sets rather than lists --- modules/aws/lb/main.tf | 30 +++++++++++++++--------------- modules/aws/lb/variables.tf | 12 ++++++------ 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/modules/aws/lb/main.tf b/modules/aws/lb/main.tf index a7c4beac..1a48a9dd 100644 --- a/modules/aws/lb/main.tf +++ b/modules/aws/lb/main.tf @@ -26,7 +26,7 @@ resource "aws_lb" "load_balancer" { enable_cross_zone_load_balancing = local.is_network ? var.enable_cross_zone_load_balancing : null dynamic "access_logs" { - for_each = var.access_logs != null ? [var.access_logs] : [] + for_each = var.access_logs != null ? var.access_logs : {} content { bucket = access_logs.value.bucket prefix = access_logs.value.prefix @@ -73,7 +73,7 @@ resource "aws_lb_target_group" "target_group" { preserve_client_ip = local.is_network ? var.target_group_preserve_client_ip : null dynamic "health_check" { - for_each = each.value.health_check != null ? [each.value.health_check] : [] + for_each = each.value.health_check != null ? { "key" = each.value.health_check } : {} content { enabled = health_check.value.enabled healthy_threshold = health_check.value.healthy_threshold @@ -88,7 +88,7 @@ resource "aws_lb_target_group" "target_group" { } dynamic "stickiness" { - for_each = each.value.stickiness != null ? [each.value.stickiness] : [] + for_each = each.value.stickiness != null ? { "key" = each.value.stickiness } : {} content { type = stickiness.value.type cookie_duration = stickiness.value.cookie_duration @@ -119,7 +119,7 @@ resource "aws_lb_listener" "listener" { alpn_policy = local.is_application ? each.value.alpn_policy : null dynamic "mutual_authentication" { - for_each = (local.is_network && each.value.mutual_authentication != null) ? [each.value.mutual_authentication] : [] + for_each = local.is_network && each.value.mutual_authentication != null ? { "key" = each.value.mutual_authentication } : {} content { mode = mutual_authentication.value.mode } @@ -136,7 +136,7 @@ resource "aws_lb_listener" "listener" { # Application Load Balancer specific fixed response action dynamic "fixed_response" { - for_each = default_action.value.fixed_response != null ? [default_action.value.fixed_response] : [] + for_each = default_action.value.fixed_response != null ? { "key" = default_action.value.fixed_response } : {} content { content_type = fixed_response.value.content_type message_body = fixed_response.value.message_body @@ -146,7 +146,7 @@ resource "aws_lb_listener" "listener" { # Application Load Balancer specific redirect action dynamic "redirect" { - for_each = default_action.value.redirect != null ? [default_action.value.redirect] : [] + for_each = default_action.value.redirect != null ? { "key" = default_action.value.redirect } : {} content { path = redirect.value.path host = redirect.value.host @@ -159,7 +159,7 @@ resource "aws_lb_listener" "listener" { # Application Load Balancer authentication settings dynamic "authenticate_oidc" { - for_each = each.value.authenticate_oidc != null && local.is_application ? [each.value.authenticate_oidc] : [] + for_each = each.value.authenticate_oidc != null && local.is_application ? { "key" = each.value.authenticate_oidc } : {} content { authorization_endpoint = authenticate_oidc.value.authorization_endpoint client_id = authenticate_oidc.value.client_id @@ -171,7 +171,7 @@ resource "aws_lb_listener" "listener" { } dynamic "authenticate_cognito" { - for_each = each.value.authenticate_cognito != null && local.is_application ? [each.value.authenticate_cognito] : [] + for_each = each.value.authenticate_cognito != null && local.is_application ? { "key" = each.value.authenticate_cognito } : {} content { user_pool_arn = authenticate_cognito.value.user_pool_arn user_pool_client_id = authenticate_cognito.value.user_pool_client_id @@ -199,7 +199,7 @@ resource "aws_lb_listener_rule" "listener_rule" { # ALB fixed response action dynamic "fixed_response" { - for_each = action.value.fixed_response != null ? [action.value.fixed_response] : [] + for_each = action.value.fixed_response != null ? { "key" = action.value.fixed_response } : {} content { content_type = fixed_response.value.content_type message_body = fixed_response.value.message_body @@ -209,7 +209,7 @@ resource "aws_lb_listener_rule" "listener_rule" { # ALB redirect action dynamic "redirect" { - for_each = action.value.redirect != null ? [action.value.redirect] : [] + for_each = action.value.redirect != null ? { "key" = action.value.redirect } : {} content { path = redirect.value.path host = redirect.value.host @@ -228,7 +228,7 @@ resource "aws_lb_listener_rule" "listener_rule" { content { # ALB host header condition dynamic "host_header" { - for_each = condition.value.host_header != null ? [condition.value.host_header] : [] + for_each = condition.value.host_header != null ? { "key" = condition.value.host_header } : {} content { values = host_header.value.values } @@ -236,7 +236,7 @@ resource "aws_lb_listener_rule" "listener_rule" { # ALB http header condition dynamic "http_header" { - for_each = condition.value.http_header != null ? [condition.value.http_header] : [] + for_each = condition.value.http_header != null ? { "key" = condition.value.http_header } : {} content { http_header_name = http_header.value.http_header_name values = http_header.value.values @@ -245,7 +245,7 @@ resource "aws_lb_listener_rule" "listener_rule" { # ALB path pattern condition dynamic "path_pattern" { - for_each = condition.value.path_pattern != null ? [condition.value.path_pattern] : [] + for_each = condition.value.path_pattern != null ? { "key" = condition.value.path_pattern } : {} content { values = path_pattern.value.values } @@ -253,7 +253,7 @@ resource "aws_lb_listener_rule" "listener_rule" { # ALB query string condition dynamic "query_string" { - for_each = condition.value.query_string != null ? [condition.value.query_string] : [] + for_each = condition.value.query_string != null ? { "key" = condition.value.query_string } : {} content { key = query_string.value.key value = query_string.value.value @@ -262,7 +262,7 @@ resource "aws_lb_listener_rule" "listener_rule" { # Common source IP condition (works for both ALB and NLB) dynamic "source_ip" { - for_each = condition.value.source_ip != null ? [condition.value.source_ip] : [] + for_each = condition.value.source_ip != null ? { "key" = condition.value.source_ip } : {} content { values = source_ip.value.values } diff --git a/modules/aws/lb/variables.tf b/modules/aws/lb/variables.tf index 0cc5d017..4aec7dba 100644 --- a/modules/aws/lb/variables.tf +++ b/modules/aws/lb/variables.tf @@ -71,11 +71,11 @@ variable "desync_mitigation_mode" { variable "access_logs" { description = "Access logs configuration for the LB" - type = object({ + type = object(set({ bucket = string prefix = string enabled = bool - }) + })) default = null } @@ -173,7 +173,7 @@ variable "target_groups" { protocol_version = optional(string) connection_termination = optional(bool) lambda_multi_value_headers_enabled = optional(bool) - health_check = optional(object({ + health_check = map(object({ enabled = optional(bool, true) healthy_threshold = optional(number, 3) interval = optional(number, 30) @@ -187,7 +187,7 @@ variable "target_groups" { grace_period_seconds = optional(number) })) - stickiness = optional(object({ + stickiness = object(set({ type = string cookie_duration = optional(number) cookie_name = optional(string) @@ -277,9 +277,9 @@ variable "listener_rules" { })) }) - conditions = list(object({ + conditions = list(object({ #no set, order matters host_header = optional(object({ - values = list(string) + values = set(string) })) http_header = optional(object({ From d78b74ffdb1ddecd6175aa72360d41a11d02d829 Mon Sep 17 00:00:00 2001 From: jakeasaurus Date: Mon, 6 Jan 2025 13:07:34 -0500 Subject: [PATCH 11/36] syntax fixes --- modules/aws/lb/variables.tf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/aws/lb/variables.tf b/modules/aws/lb/variables.tf index 4aec7dba..9bb3832a 100644 --- a/modules/aws/lb/variables.tf +++ b/modules/aws/lb/variables.tf @@ -71,12 +71,12 @@ variable "desync_mitigation_mode" { variable "access_logs" { description = "Access logs configuration for the LB" - type = object(set({ + type = set(object({ bucket = string prefix = string enabled = bool })) - default = null + default = [] } variable "idle_timeout" { @@ -187,7 +187,7 @@ variable "target_groups" { grace_period_seconds = optional(number) })) - stickiness = object(set({ + stickiness = set(object({ type = string cookie_duration = optional(number) cookie_name = optional(string) From 9000eb6044c5bf709b1c7ba438a216420e9296b4 Mon Sep 17 00:00:00 2001 From: jakeasaurus Date: Mon, 6 Jan 2025 13:21:46 -0500 Subject: [PATCH 12/36] removed redundant vars --- modules/aws/lb/variables.tf | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/modules/aws/lb/variables.tf b/modules/aws/lb/variables.tf index 9bb3832a..d6ed8f6c 100644 --- a/modules/aws/lb/variables.tf +++ b/modules/aws/lb/variables.tf @@ -116,20 +116,20 @@ variable "target_group_name_prefix" { default = null } -variable "target_group_port" { - description = "Port on which targets receive traffic" - type = number -} - -variable "target_group_protocol" { - description = "Protocol to use for routing traffic to the targets" - type = string -} - -variable "target_group_vpc_id" { - description = "Identifier of the VPC in which to create the target group" - type = string -} +# variable "target_group_port" { +# description = "Port on which targets receive traffic" +# type = number +# } + +# variable "target_group_protocol" { +# description = "Protocol to use for routing traffic to the targets" +# type = string +# } + +# variable "target_group_vpc_id" { +# description = "Identifier of the VPC in which to create the target group" +# type = string +# } variable "target_group_target_type" { description = "Type of target that you must specify when registering targets with this target group" From ae35da6d5fd565b5fa7d07ebe6125a5e21f0f3ce Mon Sep 17 00:00:00 2001 From: jakeasaurus Date: Mon, 6 Jan 2025 13:38:43 -0500 Subject: [PATCH 13/36] fixes --- modules/aws/lb/variables.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/aws/lb/variables.tf b/modules/aws/lb/variables.tf index d6ed8f6c..a4ed060f 100644 --- a/modules/aws/lb/variables.tf +++ b/modules/aws/lb/variables.tf @@ -71,12 +71,12 @@ variable "desync_mitigation_mode" { variable "access_logs" { description = "Access logs configuration for the LB" - type = set(object({ + type = map(object({ bucket = string prefix = string enabled = bool })) - default = [] + default = null } variable "idle_timeout" { From 6f7313895a0beff987467a97cdf1af87f7986ebc Mon Sep 17 00:00:00 2001 From: jakeasaurus Date: Mon, 6 Jan 2025 14:00:07 -0500 Subject: [PATCH 14/36] removed old vars --- modules/aws/lb/variables.tf | 60 ++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/modules/aws/lb/variables.tf b/modules/aws/lb/variables.tf index a4ed060f..ab2d655e 100644 --- a/modules/aws/lb/variables.tf +++ b/modules/aws/lb/variables.tf @@ -131,41 +131,41 @@ variable "target_group_name_prefix" { # type = string # } -variable "target_group_target_type" { - description = "Type of target that you must specify when registering targets with this target group" - type = string - default = "instance" -} +# variable "target_group_target_type" { +# description = "Type of target that you must specify when registering targets with this target group" +# type = string +# default = "instance" +# } -variable "target_group_deregistration_delay" { - description = "Amount of time to wait for in-flight requests to complete before deregistering a target" - type = number - default = 300 -} +# variable "target_group_deregistration_delay" { +# description = "Amount of time to wait for in-flight requests to complete before deregistering a target" +# type = number +# default = 300 +# } -variable "target_group_slow_start" { - description = "Amount of time for targets to warm up before the load balancer sends them a full share of requests" - type = number - default = 0 -} +# variable "target_group_slow_start" { +# description = "Amount of time for targets to warm up before the load balancer sends them a full share of requests" +# type = number +# default = 0 +# } -variable "target_group_proxy_protocol_v2" { - description = "Whether to enable support for proxy protocol v2" - type = bool - default = false -} +# variable "target_group_proxy_protocol_v2" { +# description = "Whether to enable support for proxy protocol v2" +# type = bool +# default = false +# } -variable "target_group_load_balancing_algorithm_type" { - description = "Determines how the load balancer selects targets when routing requests" - type = string - default = null -} +# variable "target_group_load_balancing_algorithm_type" { +# description = "Determines how the load balancer selects targets when routing requests" +# type = string +# default = null +# } -variable "target_group_preserve_client_ip" { - description = "Whether client IP preservation is enabled" - type = bool - default = null -} +# variable "target_group_preserve_client_ip" { +# description = "Whether client IP preservation is enabled" +# type = bool +# default = null +# } variable "target_groups" { description = "Map of target group configurations" From 15aeec367b8bb80a49e999aa0002ed37512f3161 Mon Sep 17 00:00:00 2001 From: jakeasaurus Date: Mon, 6 Jan 2025 14:07:24 -0500 Subject: [PATCH 15/36] changed args --- modules/aws/lb/main.tf | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/modules/aws/lb/main.tf b/modules/aws/lb/main.tf index 1a48a9dd..3223a0e2 100644 --- a/modules/aws/lb/main.tf +++ b/modules/aws/lb/main.tf @@ -26,7 +26,7 @@ resource "aws_lb" "load_balancer" { enable_cross_zone_load_balancing = local.is_network ? var.enable_cross_zone_load_balancing : null dynamic "access_logs" { - for_each = var.access_logs != null ? var.access_logs : {} + for_each = var.access_logs content { bucket = access_logs.value.bucket prefix = access_logs.value.prefix @@ -56,21 +56,21 @@ resource "aws_lb_target_group" "target_group" { for_each = var.target_groups # Common settings - name = var.target_group_name - name_prefix = var.target_group_name_prefix - port = var.target_group_port - protocol = var.target_group_protocol - vpc_id = var.target_group_vpc_id - target_type = var.target_group_target_type - deregistration_delay = var.target_group_deregistration_delay + name = each.value.name + name_prefix = each.value.name_prefix + port = each.value.port + protocol = each.value.protocol + vpc_id = each.value.vpc_id + target_type = each.value.target_type + deregistration_delay = each.value.deregistration_delay # Application Load Balancer specific settings - slow_start = local.is_application ? var.target_group_slow_start : null - load_balancing_algorithm_type = local.is_application ? var.target_group_load_balancing_algorithm_type : null + slow_start = local.is_application ? each.value.slow_start : null + load_balancing_algorithm_type = local.is_application ? each.value.load_balancing_algorithm_type : null # Network Load Balancer specific settings - proxy_protocol_v2 = local.is_network ? var.target_group_proxy_protocol_v2 : null - preserve_client_ip = local.is_network ? var.target_group_preserve_client_ip : null + proxy_protocol_v2 = local.is_network ? each.value.target_group_proxy_protocol_v2 : null + preserve_client_ip = local.is_network ? each.value.target_group_preserve_client_ip : null dynamic "health_check" { for_each = each.value.health_check != null ? { "key" = each.value.health_check } : {} From 6bae0cc255549d7f7c72f231ef7334f2113d5258 Mon Sep 17 00:00:00 2001 From: jakeasaurus Date: Mon, 6 Jan 2025 14:45:30 -0500 Subject: [PATCH 16/36] removed keys --- modules/aws/lb/main.tf | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/modules/aws/lb/main.tf b/modules/aws/lb/main.tf index 3223a0e2..b80388f2 100644 --- a/modules/aws/lb/main.tf +++ b/modules/aws/lb/main.tf @@ -73,7 +73,7 @@ resource "aws_lb_target_group" "target_group" { preserve_client_ip = local.is_network ? each.value.target_group_preserve_client_ip : null dynamic "health_check" { - for_each = each.value.health_check != null ? { "key" = each.value.health_check } : {} + for_each = each.value.health_check != null ? { each.value.health_check } : {} content { enabled = health_check.value.enabled healthy_threshold = health_check.value.healthy_threshold @@ -88,7 +88,7 @@ resource "aws_lb_target_group" "target_group" { } dynamic "stickiness" { - for_each = each.value.stickiness != null ? { "key" = each.value.stickiness } : {} + for_each = each.value.stickiness != null ? { each.value.stickiness } : {} content { type = stickiness.value.type cookie_duration = stickiness.value.cookie_duration @@ -119,7 +119,7 @@ resource "aws_lb_listener" "listener" { alpn_policy = local.is_application ? each.value.alpn_policy : null dynamic "mutual_authentication" { - for_each = local.is_network && each.value.mutual_authentication != null ? { "key" = each.value.mutual_authentication } : {} + for_each = local.is_network && each.value.mutual_authentication != null ? { each.value.mutual_authentication } : {} content { mode = mutual_authentication.value.mode } @@ -136,7 +136,7 @@ resource "aws_lb_listener" "listener" { # Application Load Balancer specific fixed response action dynamic "fixed_response" { - for_each = default_action.value.fixed_response != null ? { "key" = default_action.value.fixed_response } : {} + for_each = default_action.value.fixed_response != null ? { default_action.value.fixed_response } : {} content { content_type = fixed_response.value.content_type message_body = fixed_response.value.message_body @@ -146,7 +146,7 @@ resource "aws_lb_listener" "listener" { # Application Load Balancer specific redirect action dynamic "redirect" { - for_each = default_action.value.redirect != null ? { "key" = default_action.value.redirect } : {} + for_each = default_action.value.redirect != null ? { default_action.value.redirect } : {} content { path = redirect.value.path host = redirect.value.host @@ -159,7 +159,7 @@ resource "aws_lb_listener" "listener" { # Application Load Balancer authentication settings dynamic "authenticate_oidc" { - for_each = each.value.authenticate_oidc != null && local.is_application ? { "key" = each.value.authenticate_oidc } : {} + for_each = each.value.authenticate_oidc != null && local.is_application ? { each.value.authenticate_oidc } : {} content { authorization_endpoint = authenticate_oidc.value.authorization_endpoint client_id = authenticate_oidc.value.client_id @@ -171,7 +171,7 @@ resource "aws_lb_listener" "listener" { } dynamic "authenticate_cognito" { - for_each = each.value.authenticate_cognito != null && local.is_application ? { "key" = each.value.authenticate_cognito } : {} + for_each = each.value.authenticate_cognito != null && local.is_application ? { each.value.authenticate_cognito } : {} content { user_pool_arn = authenticate_cognito.value.user_pool_arn user_pool_client_id = authenticate_cognito.value.user_pool_client_id @@ -199,7 +199,7 @@ resource "aws_lb_listener_rule" "listener_rule" { # ALB fixed response action dynamic "fixed_response" { - for_each = action.value.fixed_response != null ? { "key" = action.value.fixed_response } : {} + for_each = action.value.fixed_response != null ? { action.value.fixed_response } : {} content { content_type = fixed_response.value.content_type message_body = fixed_response.value.message_body @@ -209,7 +209,7 @@ resource "aws_lb_listener_rule" "listener_rule" { # ALB redirect action dynamic "redirect" { - for_each = action.value.redirect != null ? { "key" = action.value.redirect } : {} + for_each = action.value.redirect != null ? { action.value.redirect } : {} content { path = redirect.value.path host = redirect.value.host @@ -228,7 +228,7 @@ resource "aws_lb_listener_rule" "listener_rule" { content { # ALB host header condition dynamic "host_header" { - for_each = condition.value.host_header != null ? { "key" = condition.value.host_header } : {} + for_each = condition.value.host_header != null ? { condition.value.host_header } : {} content { values = host_header.value.values } @@ -236,7 +236,7 @@ resource "aws_lb_listener_rule" "listener_rule" { # ALB http header condition dynamic "http_header" { - for_each = condition.value.http_header != null ? { "key" = condition.value.http_header } : {} + for_each = condition.value.http_header != null ? { condition.value.http_header } : {} content { http_header_name = http_header.value.http_header_name values = http_header.value.values @@ -245,7 +245,7 @@ resource "aws_lb_listener_rule" "listener_rule" { # ALB path pattern condition dynamic "path_pattern" { - for_each = condition.value.path_pattern != null ? { "key" = condition.value.path_pattern } : {} + for_each = condition.value.path_pattern != null ? { condition.value.path_pattern } : {} content { values = path_pattern.value.values } @@ -253,7 +253,7 @@ resource "aws_lb_listener_rule" "listener_rule" { # ALB query string condition dynamic "query_string" { - for_each = condition.value.query_string != null ? { "key" = condition.value.query_string } : {} + for_each = condition.value.query_string != null ? { condition.value.query_string } : {} content { key = query_string.value.key value = query_string.value.value @@ -262,7 +262,7 @@ resource "aws_lb_listener_rule" "listener_rule" { # Common source IP condition (works for both ALB and NLB) dynamic "source_ip" { - for_each = condition.value.source_ip != null ? { "key" = condition.value.source_ip } : {} + for_each = condition.value.source_ip != null ? { condition.value.source_ip } : {} content { values = source_ip.value.values } From 1fb168e050cd3c33b68500012030bbd3d0614e91 Mon Sep 17 00:00:00 2001 From: jakeasaurus Date: Mon, 6 Jan 2025 14:54:46 -0500 Subject: [PATCH 17/36] removed curlys --- modules/aws/lb/main.tf | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/modules/aws/lb/main.tf b/modules/aws/lb/main.tf index b80388f2..97dc2e83 100644 --- a/modules/aws/lb/main.tf +++ b/modules/aws/lb/main.tf @@ -73,7 +73,7 @@ resource "aws_lb_target_group" "target_group" { preserve_client_ip = local.is_network ? each.value.target_group_preserve_client_ip : null dynamic "health_check" { - for_each = each.value.health_check != null ? { each.value.health_check } : {} + for_each = each.value.health_check != null ? each.value.health_check : {} content { enabled = health_check.value.enabled healthy_threshold = health_check.value.healthy_threshold @@ -88,7 +88,7 @@ resource "aws_lb_target_group" "target_group" { } dynamic "stickiness" { - for_each = each.value.stickiness != null ? { each.value.stickiness } : {} + for_each = each.value.stickiness != null ? each.value.stickiness : {} content { type = stickiness.value.type cookie_duration = stickiness.value.cookie_duration @@ -136,7 +136,7 @@ resource "aws_lb_listener" "listener" { # Application Load Balancer specific fixed response action dynamic "fixed_response" { - for_each = default_action.value.fixed_response != null ? { default_action.value.fixed_response } : {} + for_each = default_action.value.fixed_response != null ? default_action.value.fixed_response : {} content { content_type = fixed_response.value.content_type message_body = fixed_response.value.message_body @@ -146,7 +146,7 @@ resource "aws_lb_listener" "listener" { # Application Load Balancer specific redirect action dynamic "redirect" { - for_each = default_action.value.redirect != null ? { default_action.value.redirect } : {} + for_each = default_action.value.redirect != null ? default_action.value.redirect : {} content { path = redirect.value.path host = redirect.value.host @@ -159,7 +159,7 @@ resource "aws_lb_listener" "listener" { # Application Load Balancer authentication settings dynamic "authenticate_oidc" { - for_each = each.value.authenticate_oidc != null && local.is_application ? { each.value.authenticate_oidc } : {} + for_each = each.value.authenticate_oidc != null && local.is_application ? each.value.authenticate_oidc : {} content { authorization_endpoint = authenticate_oidc.value.authorization_endpoint client_id = authenticate_oidc.value.client_id @@ -171,7 +171,7 @@ resource "aws_lb_listener" "listener" { } dynamic "authenticate_cognito" { - for_each = each.value.authenticate_cognito != null && local.is_application ? { each.value.authenticate_cognito } : {} + for_each = each.value.authenticate_cognito != null && local.is_application ? each.value.authenticate_cognito : {} content { user_pool_arn = authenticate_cognito.value.user_pool_arn user_pool_client_id = authenticate_cognito.value.user_pool_client_id @@ -199,7 +199,7 @@ resource "aws_lb_listener_rule" "listener_rule" { # ALB fixed response action dynamic "fixed_response" { - for_each = action.value.fixed_response != null ? { action.value.fixed_response } : {} + for_each = action.value.fixed_response != null ? action.value.fixed_response : {} content { content_type = fixed_response.value.content_type message_body = fixed_response.value.message_body @@ -209,7 +209,7 @@ resource "aws_lb_listener_rule" "listener_rule" { # ALB redirect action dynamic "redirect" { - for_each = action.value.redirect != null ? { action.value.redirect } : {} + for_each = action.value.redirect != null ? action.value.redirect : {} content { path = redirect.value.path host = redirect.value.host @@ -228,7 +228,7 @@ resource "aws_lb_listener_rule" "listener_rule" { content { # ALB host header condition dynamic "host_header" { - for_each = condition.value.host_header != null ? { condition.value.host_header } : {} + for_each = condition.value.host_header != null ? condition.value.host_header : {} content { values = host_header.value.values } @@ -236,7 +236,7 @@ resource "aws_lb_listener_rule" "listener_rule" { # ALB http header condition dynamic "http_header" { - for_each = condition.value.http_header != null ? { condition.value.http_header } : {} + for_each = condition.value.http_header != null ? condition.value.http_header : {} content { http_header_name = http_header.value.http_header_name values = http_header.value.values @@ -245,7 +245,7 @@ resource "aws_lb_listener_rule" "listener_rule" { # ALB path pattern condition dynamic "path_pattern" { - for_each = condition.value.path_pattern != null ? { condition.value.path_pattern } : {} + for_each = condition.value.path_pattern != null ? condition.value.path_pattern : {} content { values = path_pattern.value.values } @@ -253,7 +253,7 @@ resource "aws_lb_listener_rule" "listener_rule" { # ALB query string condition dynamic "query_string" { - for_each = condition.value.query_string != null ? { condition.value.query_string } : {} + for_each = condition.value.query_string != null ? condition.value.query_string : {} content { key = query_string.value.key value = query_string.value.value @@ -262,7 +262,7 @@ resource "aws_lb_listener_rule" "listener_rule" { # Common source IP condition (works for both ALB and NLB) dynamic "source_ip" { - for_each = condition.value.source_ip != null ? { condition.value.source_ip } : {} + for_each = condition.value.source_ip != null ? condition.value.source_ip : {} content { values = source_ip.value.values } From ff58c87cdd4b61be558d3c89354aab845ac61d34 Mon Sep 17 00:00:00 2001 From: jakeasaurus Date: Mon, 6 Jan 2025 14:56:14 -0500 Subject: [PATCH 18/36] removed curlys --- modules/aws/lb/main.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/aws/lb/main.tf b/modules/aws/lb/main.tf index 97dc2e83..03a7a709 100644 --- a/modules/aws/lb/main.tf +++ b/modules/aws/lb/main.tf @@ -73,7 +73,7 @@ resource "aws_lb_target_group" "target_group" { preserve_client_ip = local.is_network ? each.value.target_group_preserve_client_ip : null dynamic "health_check" { - for_each = each.value.health_check != null ? each.value.health_check : {} + for_each = each.value.health_check != null ? each.value.health_check : {} content { enabled = health_check.value.enabled healthy_threshold = health_check.value.healthy_threshold @@ -119,7 +119,7 @@ resource "aws_lb_listener" "listener" { alpn_policy = local.is_application ? each.value.alpn_policy : null dynamic "mutual_authentication" { - for_each = local.is_network && each.value.mutual_authentication != null ? { each.value.mutual_authentication } : {} + for_each = local.is_network && each.value.mutual_authentication != null ? each.value.mutual_authentication : {} content { mode = mutual_authentication.value.mode } From 0bc22110bd504a614e697f5b6b2a012a8e1fd93e Mon Sep 17 00:00:00 2001 From: jakeasaurus Date: Thu, 9 Jan 2025 15:54:44 -0500 Subject: [PATCH 19/36] updated --- modules/aws/lb/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/aws/lb/main.tf b/modules/aws/lb/main.tf index 03a7a709..1078e233 100644 --- a/modules/aws/lb/main.tf +++ b/modules/aws/lb/main.tf @@ -56,7 +56,7 @@ resource "aws_lb_target_group" "target_group" { for_each = var.target_groups # Common settings - name = each.value.name + name = var.target_group_name name_prefix = each.value.name_prefix port = each.value.port protocol = each.value.protocol From 991d534f1c23bc4b54b5c986154597f67230b5bc Mon Sep 17 00:00:00 2001 From: jakeasaurus Date: Thu, 9 Jan 2025 16:21:56 -0500 Subject: [PATCH 20/36] updated --- modules/aws/lb/main.tf | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/modules/aws/lb/main.tf b/modules/aws/lb/main.tf index 1078e233..4c9e040d 100644 --- a/modules/aws/lb/main.tf +++ b/modules/aws/lb/main.tf @@ -26,7 +26,7 @@ resource "aws_lb" "load_balancer" { enable_cross_zone_load_balancing = local.is_network ? var.enable_cross_zone_load_balancing : null dynamic "access_logs" { - for_each = var.access_logs + for_each = var.access_logs != null ? { create = var.access_logs } : {} content { bucket = access_logs.value.bucket prefix = access_logs.value.prefix @@ -56,8 +56,7 @@ resource "aws_lb_target_group" "target_group" { for_each = var.target_groups # Common settings - name = var.target_group_name - name_prefix = each.value.name_prefix + name = xeach.value.name port = each.value.port protocol = each.value.protocol vpc_id = each.value.vpc_id From 82958cf12df7587fdd72b70347adc8e32fa1f8d6 Mon Sep 17 00:00:00 2001 From: jakeasaurus Date: Thu, 9 Jan 2025 16:23:48 -0500 Subject: [PATCH 21/36] updated --- modules/aws/lb/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/aws/lb/main.tf b/modules/aws/lb/main.tf index 4c9e040d..b7c029bd 100644 --- a/modules/aws/lb/main.tf +++ b/modules/aws/lb/main.tf @@ -56,7 +56,7 @@ resource "aws_lb_target_group" "target_group" { for_each = var.target_groups # Common settings - name = xeach.value.name + name = each.value.name port = each.value.port protocol = each.value.protocol vpc_id = each.value.vpc_id From f755ce1a27a305b11eddf662eb7870f58a54113d Mon Sep 17 00:00:00 2001 From: jakeasaurus Date: Thu, 9 Jan 2025 16:27:06 -0500 Subject: [PATCH 22/36] updated --- modules/aws/lb/main.tf | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/aws/lb/main.tf b/modules/aws/lb/main.tf index b7c029bd..f17ba96a 100644 --- a/modules/aws/lb/main.tf +++ b/modules/aws/lb/main.tf @@ -56,12 +56,12 @@ resource "aws_lb_target_group" "target_group" { for_each = var.target_groups # Common settings - name = each.value.name - port = each.value.port - protocol = each.value.protocol - vpc_id = each.value.vpc_id - target_type = each.value.target_type - deregistration_delay = each.value.deregistration_delay + name = target_group.value.name + port = target_group.value.port + protocol = target_group.value.protocol + vpc_id = target_group.value.vpc_id + target_type = target_group.value.target_type + deregistration_delay = target_group.value.deregistration_delay # Application Load Balancer specific settings slow_start = local.is_application ? each.value.slow_start : null From 103bd9a8d4fcf4ad890a2a759d59425505a887b6 Mon Sep 17 00:00:00 2001 From: jakeasaurus Date: Thu, 9 Jan 2025 16:31:27 -0500 Subject: [PATCH 23/36] updated --- modules/aws/lb/main.tf | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/aws/lb/main.tf b/modules/aws/lb/main.tf index f17ba96a..b7c029bd 100644 --- a/modules/aws/lb/main.tf +++ b/modules/aws/lb/main.tf @@ -56,12 +56,12 @@ resource "aws_lb_target_group" "target_group" { for_each = var.target_groups # Common settings - name = target_group.value.name - port = target_group.value.port - protocol = target_group.value.protocol - vpc_id = target_group.value.vpc_id - target_type = target_group.value.target_type - deregistration_delay = target_group.value.deregistration_delay + name = each.value.name + port = each.value.port + protocol = each.value.protocol + vpc_id = each.value.vpc_id + target_type = each.value.target_type + deregistration_delay = each.value.deregistration_delay # Application Load Balancer specific settings slow_start = local.is_application ? each.value.slow_start : null From 14e3ea8be416a1a10df6fbfa8a245f5614f4fc92 Mon Sep 17 00:00:00 2001 From: jakeasaurus Date: Mon, 13 Jan 2025 10:59:10 -0500 Subject: [PATCH 24/36] few tweaks --- modules/aws/lb/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/aws/lb/main.tf b/modules/aws/lb/main.tf index b7c029bd..e0cfa755 100644 --- a/modules/aws/lb/main.tf +++ b/modules/aws/lb/main.tf @@ -87,7 +87,7 @@ resource "aws_lb_target_group" "target_group" { } dynamic "stickiness" { - for_each = each.value.stickiness != null ? each.value.stickiness : {} + for_each = each.value.stickiness != null ? each.value.stickiness : [] content { type = stickiness.value.type cookie_duration = stickiness.value.cookie_duration From 61cf6a6768a90a7e812f4c552d058b0842a085ff Mon Sep 17 00:00:00 2001 From: jakeasaurus Date: Mon, 13 Jan 2025 11:47:09 -0500 Subject: [PATCH 25/36] updated variable --- modules/aws/lb/variables.tf | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/modules/aws/lb/variables.tf b/modules/aws/lb/variables.tf index ab2d655e..4b69026a 100644 --- a/modules/aws/lb/variables.tf +++ b/modules/aws/lb/variables.tf @@ -170,6 +170,11 @@ variable "target_group_name_prefix" { variable "target_groups" { description = "Map of target group configurations" type = map(object({ + name = string + port = number + protocol = string + target_type = string + vpc_id = string protocol_version = optional(string) connection_termination = optional(bool) lambda_multi_value_headers_enabled = optional(bool) @@ -197,7 +202,6 @@ variable "target_groups" { })) default = {} } - # Listener Variables variable "listeners" { description = "Map of listener configurations" From 88a1f3d79ff9d70beeb9210fc616cce24cc420dc Mon Sep 17 00:00:00 2001 From: jakeasaurus Date: Mon, 13 Jan 2025 11:57:18 -0500 Subject: [PATCH 26/36] added missing attributes: --- modules/aws/lb/variables.tf | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modules/aws/lb/variables.tf b/modules/aws/lb/variables.tf index 4b69026a..c8d8a599 100644 --- a/modules/aws/lb/variables.tf +++ b/modules/aws/lb/variables.tf @@ -175,6 +175,11 @@ variable "target_groups" { protocol = string target_type = string vpc_id = string + deregistration_delay = optional(number) + slow_start = optional(number) + load_balancing_algorithm_type = optional(string) + target_group_proxy_protocol_v2 = optional(bool) + target_group_preserve_client_ip = optional(bool) protocol_version = optional(string) connection_termination = optional(bool) lambda_multi_value_headers_enabled = optional(bool) @@ -202,6 +207,7 @@ variable "target_groups" { })) default = {} } + # Listener Variables variable "listeners" { description = "Map of listener configurations" From b270bcd88ef01d175b3e9fcc5f4608b4a30f4d8f Mon Sep 17 00:00:00 2001 From: jakeasaurus Date: Mon, 13 Jan 2025 12:04:41 -0500 Subject: [PATCH 27/36] updated listener rules var --- modules/aws/lb/variables.tf | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/aws/lb/variables.tf b/modules/aws/lb/variables.tf index c8d8a599..e880decb 100644 --- a/modules/aws/lb/variables.tf +++ b/modules/aws/lb/variables.tf @@ -287,21 +287,21 @@ variable "listener_rules" { })) }) - conditions = list(object({ #no set, order matters + conditions = list(object({ host_header = optional(object({ - values = set(string) + values = list(string) })) - http_header = optional(object({ + http_header = optional(map(object({ http_header_name = string values = list(string) - })) + }))) path_pattern = optional(object({ values = list(string) })) - query_string = optional(list(object({ + query_string = optional(map(object({ key = optional(string) value = string }))) From 0bef23cf61cc265143ec7c4ea8fd0be8c2265fa7 Mon Sep 17 00:00:00 2001 From: jakeasaurus Date: Mon, 13 Jan 2025 15:39:14 -0500 Subject: [PATCH 28/36] updated syntax --- modules/aws/lb/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/aws/lb/main.tf b/modules/aws/lb/main.tf index e0cfa755..a9f4913f 100644 --- a/modules/aws/lb/main.tf +++ b/modules/aws/lb/main.tf @@ -261,7 +261,7 @@ resource "aws_lb_listener_rule" "listener_rule" { # Common source IP condition (works for both ALB and NLB) dynamic "source_ip" { - for_each = condition.value.source_ip != null ? condition.value.source_ip : {} + for_each = condition.value.source_ip != null ? { source_ip = condition.value.source_ip } : {} content { values = source_ip.value.values } From 33ac1ba71e29b190d6557f1323eb19f023d3911c Mon Sep 17 00:00:00 2001 From: Jakeasaurus <47454060+Jakeasaurus@users.noreply.github.com> Date: Mon, 13 Jan 2025 21:15:19 +0000 Subject: [PATCH 29/36] chore: terraform fmt and terraform-docs --- modules/aws/lb/README.md | 67 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/modules/aws/lb/README.md b/modules/aws/lb/README.md index 1446e71e..7b11692e 100644 --- a/modules/aws/lb/README.md +++ b/modules/aws/lb/README.md @@ -39,3 +39,70 @@ module "alb" { } } ``` + + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [aws_lb.load_balancer](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb) | resource | +| [aws_lb_listener.listener](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb_listener) | resource | +| [aws_lb_listener_rule.listener_rule](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb_listener_rule) | resource | +| [aws_lb_target_group.target_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb_target_group) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [access\_logs](#input\_access\_logs) | Access logs configuration for the LB |
map(object({
bucket = string
prefix = string
enabled = bool
}))
| `null` | no | +| [customer\_owned\_ipv4\_pool](#input\_customer\_owned\_ipv4\_pool) | The ID of the customer owned ipv4 pool to use for this load balancer | `string` | `null` | no | +| [desync\_mitigation\_mode](#input\_desync\_mitigation\_mode) | Determines how the load balancer handles requests that might pose a security risk to your application | `string` | `"defensive"` | no | +| [drop\_invalid\_header\_fields](#input\_drop\_invalid\_header\_fields) | Indicates whether invalid header fields are dropped in application load balancers | `bool` | `false` | no | +| [enable\_cross\_zone\_load\_balancing](#input\_enable\_cross\_zone\_load\_balancing) | If true, cross-zone load balancing of the load balancer will be enabled | `bool` | `false` | no | +| [enable\_deletion\_protection](#input\_enable\_deletion\_protection) | If true, deletion of the load balancer will be disabled | `bool` | `false` | no | +| [enable\_http2](#input\_enable\_http2) | Indicates whether HTTP/2 is enabled in application load balancers | `bool` | `true` | no | +| [enable\_waf\_fail\_open](#input\_enable\_waf\_fail\_open) | Indicates whether to allow a WAF-enabled load balancer to route requests to targets if it is unable to forward the request to AWS WAF | `bool` | `false` | no | +| [idle\_timeout](#input\_idle\_timeout) | The time in seconds that the connection is allowed to be idle | `number` | `60` | no | +| [internal](#input\_internal) | If true, the LB will be internal | `bool` | `false` | no | +| [ip\_address\_type](#input\_ip\_address\_type) | The type of IP addresses used by the subnets for your load balancer | `string` | `"ipv4"` | no | +| [listener\_rules](#input\_listener\_rules) | Map of listener rule configurations |
map(object({
listener_key = string
priority = optional(number)

action = object({
type = string
target_group_arn = optional(string)

fixed_response = optional(object({
content_type = string
message_body = optional(string)
status_code = optional(string)
}))

redirect = optional(object({
path = optional(string)
host = optional(string)
port = optional(string)
protocol = optional(string)
query = optional(string)
status_code = string
}))
})

conditions = list(object({
host_header = optional(object({
values = list(string)
}))

http_header = optional(map(object({
http_header_name = string
values = list(string)
})))

path_pattern = optional(object({
values = list(string)
}))

query_string = optional(map(object({
key = optional(string)
value = string
})))

source_ip = optional(object({
values = list(string)
}))
}))
}))
| `{}` | no | +| [listeners](#input\_listeners) | Map of listener configurations |
map(object({
port = number
protocol = string
ssl_policy = optional(string)
certificate_arn = optional(string)
alpn_policy = optional(string)

authenticate_oidc = optional(object({
authorization_endpoint = string
client_id = string
client_secret = string
issuer = string
token_endpoint = string
user_info_endpoint = string
}))

authenticate_cognito = optional(object({
user_pool_arn = string
user_pool_client_id = string
user_pool_domain = string
}))

mutual_authentication = optional(object({
mode = string # Only valid field, can be "verify" or "strict"
}))

default_action = object({
type = string
target_group_arn = optional(string)

fixed_response = optional(object({
content_type = string
message_body = optional(string)
status_code = optional(string)
}))

redirect = optional(object({
path = optional(string)
host = optional(string)
port = optional(string)
protocol = optional(string)
query = optional(string)
status_code = string
}))
})
}))
| `{}` | no | +| [load\_balancer\_type](#input\_load\_balancer\_type) | Type of load balancer. Valid values are application or network | `string` | `"network"` | no | +| [name](#input\_name) | Name of the load balancer | `string` | n/a | yes | +| [security\_groups](#input\_security\_groups) | List of security group IDs to assign to the LB | `list(string)` | `[]` | no | +| [subnet\_mappings](#input\_subnet\_mappings) | List of subnet mapping configurations | `list(map(string))` | `[]` | no | +| [subnets](#input\_subnets) | List of subnet IDs to attach to the LB | `list(string)` | `[]` | no | +| [tags](#input\_tags) | A map of tags to assign to the resource | `map(string)` | `{}` | no | +| [target\_group\_name](#input\_target\_group\_name) | Name of the target group | `string` | `null` | no | +| [target\_group\_name\_prefix](#input\_target\_group\_name\_prefix) | Prefix for the target group name | `string` | `null` | no | +| [target\_groups](#input\_target\_groups) | Map of target group configurations |
map(object({
name = string
port = number
protocol = string
target_type = string
vpc_id = string
deregistration_delay = optional(number)
slow_start = optional(number)
load_balancing_algorithm_type = optional(string)
target_group_proxy_protocol_v2 = optional(bool)
target_group_preserve_client_ip = optional(bool)
protocol_version = optional(string)
connection_termination = optional(bool)
lambda_multi_value_headers_enabled = optional(bool)
health_check = map(object({
enabled = optional(bool, true)
healthy_threshold = optional(number, 3)
interval = optional(number, 30)
matcher = optional(string)
path = optional(string)
port = optional(string, "traffic-port")
protocol = optional(string, "HTTP")
timeout = optional(number, 5)
unhealthy_threshold = optional(number, 3)
success_codes = optional(string)
grace_period_seconds = optional(number)
}))

stickiness = set(object({
type = string
cookie_duration = optional(number)
cookie_name = optional(string)
}))

tags = optional(map(string), {})
}))
| `{}` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| [arn](#output\_arn) | The ARN of the load balancer | +| [arn\_suffix](#output\_arn\_suffix) | The ARN suffix for use with CloudWatch Metrics | +| [dns\_name](#output\_dns\_name) | The DNS name of the load balancer | +| [id](#output\_id) | The ID of the load balancer | +| [listener\_rules](#output\_listener\_rules) | Map of listener rules created and their attributes | +| [listeners](#output\_listeners) | Map of listeners created and their attributes | +| [name](#output\_name) | The name of the load balancer | +| [target\_groups](#output\_target\_groups) | Map of target groups created and their attributes | +| [vpc\_id](#output\_vpc\_id) | The VPC ID of the load balancer | +| [zone\_id](#output\_zone\_id) | The canonical hosted zone ID of the load balancer | + \ No newline at end of file From 8c6813a014bcfcd14659631c28f3c17f61ac4cff Mon Sep 17 00:00:00 2001 From: Zachary Hill Date: Thu, 9 Jan 2025 20:04:43 -0500 Subject: [PATCH 30/36] Module - AWS Amplify (#85) * feat: add aws amplify module * chore: terraform fmt and terraform-docs * ignore jscpd in the github actions test workflow --------- Co-authored-by: zachreborn --- .github/workflows/test.yml | 1 + .jscpd.json | 5 +- modules/aws/amplify/README.md | 212 +++++++++++++++++++++++++++++ modules/aws/amplify/main.tf | 137 +++++++++++++++++++ modules/aws/amplify/outputs.tf | 4 + modules/aws/amplify/variables.tf | 222 +++++++++++++++++++++++++++++++ 6 files changed, 577 insertions(+), 4 deletions(-) create mode 100755 modules/aws/amplify/README.md create mode 100755 modules/aws/amplify/main.tf create mode 100755 modules/aws/amplify/outputs.tf create mode 100755 modules/aws/amplify/variables.tf diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2545c062..6a511dda 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -59,6 +59,7 @@ jobs: uses: super-linter/super-linter@v7 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + VALIDATE_JSCPD: false VALIDATE_MARKDOWN: false VALIDATE_MARKDOWN_PRETTIER: false VALIDATE_NATURAL_LANGUAGE: false diff --git a/.jscpd.json b/.jscpd.json index c5c45d5f..6a733d43 100644 --- a/.jscpd.json +++ b/.jscpd.json @@ -1,8 +1,5 @@ { "ignore": [ - "**/*.md" - ], - "pattern": [ - "**/*.tf" + "**/README.md" ] } \ No newline at end of file diff --git a/modules/aws/amplify/README.md b/modules/aws/amplify/README.md new file mode 100755 index 00000000..e9810e06 --- /dev/null +++ b/modules/aws/amplify/README.md @@ -0,0 +1,212 @@ + + + + + + + + +[![Contributors][contributors-shield]][contributors-url] +[![Forks][forks-shield]][forks-url] +[![Stargazers][stars-shield]][stars-url] +[![Issues][issues-shield]][issues-url] +[![MIT License][license-shield]][license-url] +[![LinkedIn][linkedin-shield]][linkedin-url] + + +
+
+ + Logo + + +

Amplify

+

+ This module created and manages an Amplify app, branches, and domain associations. Amplify is a continuous deployment and hosting service for modern web applications. For more information, see the AWS Amplify documentation. +
+ Explore the docs » +
+
+ Zachary Hill + · + Report Bug + · + Request Feature +

+
+ + +
+ Table of Contents +
    +
  1. Usage
  2. +
  3. Requirements
  4. +
  5. Providers
  6. +
  7. Modules
  8. +
  9. Resources
  10. +
  11. Inputs
  12. +
  13. Outputs
  14. +
  15. License
  16. +
  17. Contact
  18. +
  19. Acknowledgments
  20. +
+
+ + + +## Usage + +### Simple Example + +``` +module "example_website" { + source = "github.com/zachreborn/terraform-modules//modules/aws/amplify" + + description = "example Website - Based on Astro" + name = "example_astro_website" + repository = "https://github.com/example/example_astro_website" + branches = { + main = { + domain_name = "example.org" + framework = "Astro" + stage = "PRODUCTION" + sub_domains = ["www"] + }, + staging = { + basic_auth_credentials = var.example_basic_auth_credentials + domain_name = "staging.example.org" + enable_basic_auth = true + framework = "Astro" + }, + dev = { + basic_auth_credentials = var.example_basic_auth_credentials + domain_name = "dev.example.org" + enable_basic_auth = true + framework = "Astro" + } + } + + custom_rules = [ + { + source = "/<*>" + status = "404-200" + target = "/404" + } + ] +} +``` + +_For more examples, please refer to the [Documentation](https://github.com/zachreborn/terraform-modules)_ + +

(back to top)

+ + + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0.0 | +| [aws](#requirement\_aws) | >= 4.0.0 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | >= 4.0.0 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [aws_amplify_app.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/amplify_app) | resource | +| [aws_amplify_branch.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/amplify_branch) | resource | +| [aws_amplify_domain_association.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/amplify_domain_association) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [access\_token](#input\_access\_token) | Access token for the Amplify App. | `string` | `null` | no | +| [auto\_branch\_creation\_config](#input\_auto\_branch\_creation\_config) | Auto branch creation config for the Amplify App. |
map(object({
basic_auth_credentials = optional(string) # Basic auth credentials for the branch. Must be input as "username:password".
build_spec = optional(string) # Build spec for the branch.
enable_auto_build = optional(bool) # Enable auto build for the branch.
enable_basic_auth = optional(bool) # Enable basic auth for the branch.
enable_performance_mode = optional(bool) # Enable performance mode for the branch.
enable_pull_request_preview = optional(bool) # Enable pull request preview for the branch.
environment_variables = optional(map(string)) # Map of environment variables for the branch.
framework = optional(string) # The framework for the branch.
pull_request_environment_name = optional(string) # The name of the pull request environment.
stage = optional(string) # Description of the stage. Valid values are PRODUCTION, BETA, DEVELOPMENT, EXPERIMENTAL, PULL_REQUEST.
}))
| `null` | no | +| [auto\_branch\_creation\_patterns](#input\_auto\_branch\_creation\_patterns) | Patterns for auto branch creation. | `list(string)` | `null` | no | +| [basic\_auth\_credentials](#input\_basic\_auth\_credentials) | Basic auth credentials for the Amplify App. Must be input as 'username:password'. | `string` | `null` | no | +| [branches](#input\_branches) | A map of branches for the Amplify App. The key becomes the branch name and the value is an object of branch attributes or settings. |
map(object({
basic_auth_credentials = optional(string) # Basic auth credentials for the branch. Must be input as "username:password".
certificate_type = optional(string, "AMPLIFY_MANAGED") # The certificate type for the domain association. Valid values are AMPLIFY_MANAGED or CUSTOM.
custom_certificate_arn = optional(string) # The ARN for the custom certificate.
description = optional(string) # The description of the branch.
display_name = optional(string) # The display name of the branch. This gets used as the default domain prefix.
domain_name = string # The domain name for the domain association.
enable_auto_build = optional(bool, true) # Enable auto build for the branch.
enable_auto_sub_domain = optional(bool, false) # Enable auto sub domain for the domain association.
enable_basic_auth = optional(bool) # Enable basic auth for the branch.
enable_certificate = optional(bool, true) # Enable certificate for the domain association.
enable_notification = optional(bool) # Enable notification for the branch.
enable_performance_mode = optional(bool) # Enable performance mode for the branch.
enable_pull_request_preview = optional(bool) # Enable pull request preview for the branch.
environment_variables = optional(map(string)) # Map of environment variables for the branch.
framework = optional(string) # The framework for the branch.
pull_request_environment_name = optional(string) # The name of the pull request environment.
stage = optional(string) # The stage for the branch. Valid values are PRODUCTION, BETA, DEVELOPMENT, EXPERIMENTAL, PULL_REQUEST.
sub_domains = optional(set(string)) # A list of sub domains to associate with the branch.
ttl = optional(number) # The TTL for the branch.
wait_for_verification = optional(bool, true) # Wait for verification for the domain association.
}))
| n/a | yes | +| [build\_spec](#input\_build\_spec) | Build spec for the Amplify App. | `string` | `null` | no | +| [cache\_config\_type](#input\_cache\_config\_type) | Cache config type for the Amplify App. Valid values are AMPLIFY\_MANAGED, AMPLIFY\_MANAGED\_NO\_COOKIES, | `string` | `"AMPLIFY_MANAGED"` | no | +| [custom\_headers](#input\_custom\_headers) | Custom headers string for the Amplify App. | `string` | `null` | no | +| [custom\_rules](#input\_custom\_rules) | List of custom rules for the Amplify App. |
list(object({
condition = optional(string) # Condition for a URL redirect or rewrite.
source = string # Source pattern for URL redirect or rewrite.
status = optional(string) # Status code for URL redirect or rewrite. Valid values are 200, 301, 302, 404, 404-200.
target = string # Target pattern for URL redirect or rewrite.
}))
| `null` | no | +| [description](#input\_description) | Description of the Amplify App. | `string` | `null` | no | +| [enable\_auto\_branch\_creation](#input\_enable\_auto\_branch\_creation) | Enable auto branch creation for the Amplify App. | `bool` | `false` | no | +| [enable\_basic\_auth](#input\_enable\_basic\_auth) | Enable basic auth for the Amplify App. | `bool` | `false` | no | +| [enable\_branch\_auto\_build](#input\_enable\_branch\_auto\_build) | Enable branch auto build for the Amplify App. | `bool` | `false` | no | +| [enable\_branch\_auto\_deletion](#input\_enable\_branch\_auto\_deletion) | Enable branch auto deletion for the Amplify App. | `bool` | `false` | no | +| [environment\_variables](#input\_environment\_variables) | Environment variables in a map for the Amplify App. | `map(string)` | `null` | no | +| [iam\_service\_role\_arn](#input\_iam\_service\_role\_arn) | IAM service role ARN for the Amplify App. | `string` | `null` | no | +| [name](#input\_name) | Name of the Amplify App. | `string` | n/a | yes | +| [oauth\_token](#input\_oauth\_token) | OAuth token for the Amplify App. | `string` | `null` | no | +| [platform](#input\_platform) | Platform for the Amplify App. Options are WEB or WEB\_COMPUTE. | `string` | `"WEB"` | no | +| [repository](#input\_repository) | Repository for the Amplify App. This could be hosted in AWS Code Commit, Bitbucket, GitHub, GitLab, etc. | `string` | `null` | no | +| [tags](#input\_tags) | Tags for the Amplify App. | `map(string)` |
{
"created_by": "terraform",
"environment": "prod",
"terraform": "true"
}
| no | + +## Outputs + +No outputs. + + + + +## License + +Distributed under the MIT License. See `LICENSE.txt` for more information. + +

(back to top)

+ + + +## Contact + +Zachary Hill - [![LinkedIn][linkedin-shield]][linkedin-url] - zhill@zacharyhill.co + +Project Link: [https://github.com/zachreborn/terraform-modules](https://github.com/zachreborn/terraform-modules) + +

(back to top)

+ + + +## Acknowledgments + +- [Zachary Hill](https://zacharyhill.co) +- [Jake Jones](https://github.com/jakeasarus) + +

(back to top)

+ + + + +[contributors-shield]: https://img.shields.io/github/contributors/zachreborn/terraform-modules.svg?style=for-the-badge +[contributors-url]: https://github.com/zachreborn/terraform-modules/graphs/contributors +[forks-shield]: https://img.shields.io/github/forks/zachreborn/terraform-modules.svg?style=for-the-badge +[forks-url]: https://github.com/zachreborn/terraform-modules/network/members +[stars-shield]: https://img.shields.io/github/stars/zachreborn/terraform-modules.svg?style=for-the-badge +[stars-url]: https://github.com/zachreborn/terraform-modules/stargazers +[issues-shield]: https://img.shields.io/github/issues/zachreborn/terraform-modules.svg?style=for-the-badge +[issues-url]: https://github.com/zachreborn/terraform-modules/issues +[license-shield]: https://img.shields.io/github/license/zachreborn/terraform-modules.svg?style=for-the-badge +[license-url]: https://github.com/zachreborn/terraform-modules/blob/master/LICENSE.txt +[linkedin-shield]: https://img.shields.io/badge/-LinkedIn-black.svg?style=for-the-badge&logo=linkedin&colorB=555 +[linkedin-url]: https://www.linkedin.com/in/zachary-hill-5524257a/ +[product-screenshot]: /images/screenshot.webp +[Terraform.io]: https://img.shields.io/badge/Terraform-7B42BC?style=for-the-badge&logo=terraform +[Terraform-url]: https://terraform.io diff --git a/modules/aws/amplify/main.tf b/modules/aws/amplify/main.tf new file mode 100755 index 00000000..7d27f306 --- /dev/null +++ b/modules/aws/amplify/main.tf @@ -0,0 +1,137 @@ +########################### +# Provider Configuration +########################### +terraform { + required_version = ">= 1.0.0" + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 4.0.0" + } + } +} + +########################### +# Data Sources +########################### + + +########################### +# Locals +########################### + +########################### +# Module Configuration +########################### + +########################### +# Amplify App +########################### +resource "aws_amplify_app" "this" { + access_token = var.access_token + auto_branch_creation_patterns = var.auto_branch_creation_patterns + basic_auth_credentials = var.basic_auth_credentials != null ? base64encode(var.basic_auth_credentials) : null + build_spec = var.build_spec + custom_headers = var.custom_headers + description = var.description + enable_auto_branch_creation = var.enable_auto_branch_creation + enable_basic_auth = var.enable_basic_auth + enable_branch_auto_build = var.enable_branch_auto_build + enable_branch_auto_deletion = var.enable_branch_auto_deletion + environment_variables = var.environment_variables + name = var.name + iam_service_role_arn = var.iam_service_role_arn + oauth_token = var.oauth_token + platform = var.platform + repository = var.repository + tags = var.tags + + dynamic "auto_branch_creation_config" { + for_each = var.auto_branch_creation_config != null ? var.auto_branch_creation_config : {} + content { + basic_auth_credentials = auto_branch_creation_config.value.basic_auth_credentials != null ? base64encode(auto_branch_creation_config.value.basic_auth_credentials) : null + build_spec = auto_branch_creation_config.value.build_spec + enable_auto_build = auto_branch_creation_config.value.enable_auto_build + enable_basic_auth = auto_branch_creation_config.value.enable_basic_auth + enable_performance_mode = auto_branch_creation_config.value.enable_performance_mode + enable_pull_request_preview = auto_branch_creation_config.value.enable_pull_request_preview + environment_variables = auto_branch_creation_config.value.environment_variables + framework = auto_branch_creation_config.value.framework + pull_request_environment_name = auto_branch_creation_config.value.pull_request_environment_name + stage = auto_branch_creation_config.value.stage + } + } + + dynamic "cache_config" { + for_each = var.cache_config_type != null ? [true] : [] + content { + type = var.cache_config_type + } + } + dynamic "custom_rule" { + for_each = var.custom_rules != null ? var.custom_rules : [] + content { + condition = custom_rule.value.condition + source = custom_rule.value.source + status = custom_rule.value.status + target = custom_rule.value.target + } + } +} + +########################### +# Amplify App Branch +########################### +resource "aws_amplify_branch" "this" { + for_each = var.branches != null ? var.branches : {} + app_id = aws_amplify_app.this.id + basic_auth_credentials = each.value.basic_auth_credentials != null ? base64encode(each.value.basic_auth_credentials) : null + branch_name = each.key + description = each.value.description + display_name = each.value.display_name != null ? each.value.display_name : each.key + enable_auto_build = each.value.enable_auto_build + enable_basic_auth = each.value.enable_basic_auth + enable_notification = each.value.enable_notification + enable_performance_mode = each.value.enable_performance_mode + enable_pull_request_preview = each.value.enable_pull_request_preview + environment_variables = each.value.environment_variables + framework = each.value.framework + pull_request_environment_name = each.value.pull_request_environment_name + stage = each.value.stage + tags = var.tags + ttl = each.value.ttl +} + +########################### +# Amplify App Domain Association +########################### +resource "aws_amplify_domain_association" "this" { + for_each = var.branches + app_id = aws_amplify_app.this.id + domain_name = each.value.domain_name + enable_auto_sub_domain = each.value.enable_auto_sub_domain + wait_for_verification = each.value.wait_for_verification + dynamic "certificate_settings" { + for_each = each.value.enable_certificate ? [true] : [] + content { + custom_certificate_arn = each.value.custom_certificate_arn + type = each.value.certificate_type + } + } + + dynamic "sub_domain" { + for_each = var.branches + content { + branch_name = each.key + prefix = "" + } + } + + dynamic "sub_domain" { + for_each = each.value.sub_domains != null ? each.value.sub_domains : [] + content { + branch_name = each.key + prefix = sub_domain.key + } + } +} diff --git a/modules/aws/amplify/outputs.tf b/modules/aws/amplify/outputs.tf new file mode 100755 index 00000000..9a2435c6 --- /dev/null +++ b/modules/aws/amplify/outputs.tf @@ -0,0 +1,4 @@ +########################### +# Resource Outputs +########################### + diff --git a/modules/aws/amplify/variables.tf b/modules/aws/amplify/variables.tf new file mode 100755 index 00000000..7ae4f557 --- /dev/null +++ b/modules/aws/amplify/variables.tf @@ -0,0 +1,222 @@ +########################### +# Resource Variables +########################### + +########################### +# Amplify App +########################### + +variable "access_token" { + description = "Access token for the Amplify App." + type = string + default = null +} + +variable "auto_branch_creation_config" { + description = "Auto branch creation config for the Amplify App." + type = map(object({ + basic_auth_credentials = optional(string) # Basic auth credentials for the branch. Must be input as "username:password". + build_spec = optional(string) # Build spec for the branch. + enable_auto_build = optional(bool) # Enable auto build for the branch. + enable_basic_auth = optional(bool) # Enable basic auth for the branch. + enable_performance_mode = optional(bool) # Enable performance mode for the branch. + enable_pull_request_preview = optional(bool) # Enable pull request preview for the branch. + environment_variables = optional(map(string)) # Map of environment variables for the branch. + framework = optional(string) # The framework for the branch. + pull_request_environment_name = optional(string) # The name of the pull request environment. + stage = optional(string) # Description of the stage. Valid values are PRODUCTION, BETA, DEVELOPMENT, EXPERIMENTAL, PULL_REQUEST. + })) + default = null +} + +variable "auto_branch_creation_patterns" { + description = "Patterns for auto branch creation." + type = list(string) + default = null +} + +variable "basic_auth_credentials" { + description = "Basic auth credentials for the Amplify App. Must be input as 'username:password'." + type = string + sensitive = false + default = null +} + +variable "build_spec" { + description = "Build spec for the Amplify App." + type = string + default = null +} + +variable "cache_config_type" { + description = "Cache config type for the Amplify App. Valid values are AMPLIFY_MANAGED, AMPLIFY_MANAGED_NO_COOKIES, " + type = string + default = "AMPLIFY_MANAGED" + validation { + condition = var.cache_config_type == "AMPLIFY_MANAGED" || var.cache_config_type == "AMPLIFY_MANAGED_NO_COOKIES" + error_message = "Cache config type must be either AMPLIFY_MANAGED or AMPLIFY_MANAGED_NO_COOKIES." + } +} + +variable "custom_headers" { + description = "Custom headers string for the Amplify App." + type = string + default = null +} + +variable "custom_rules" { + description = "List of custom rules for the Amplify App." + type = list(object({ + condition = optional(string) # Condition for a URL redirect or rewrite. + source = string # Source pattern for URL redirect or rewrite. + status = optional(string) # Status code for URL redirect or rewrite. Valid values are 200, 301, 302, 404, 404-200. + target = string # Target pattern for URL redirect or rewrite. + })) + default = null + # Example: + # custom_rules = [ + # { + # source = "/<*>" + # status = "404-200" + # target = "/404" + # }, + # { + # source = "https://www.example.org" + # status = "301" + # target = "https://example.org" + # } + # ] +} + +variable "description" { + description = "Description of the Amplify App." + type = string + default = null +} + +variable "enable_auto_branch_creation" { + description = "Enable auto branch creation for the Amplify App." + type = bool + default = false +} + +variable "enable_basic_auth" { + description = "Enable basic auth for the Amplify App." + type = bool + default = false +} + +variable "enable_branch_auto_build" { + description = "Enable branch auto build for the Amplify App." + type = bool + default = false +} + +variable "enable_branch_auto_deletion" { + description = "Enable branch auto deletion for the Amplify App." + type = bool + default = false +} + +variable "environment_variables" { + description = "Environment variables in a map for the Amplify App." + type = map(string) + default = null +} + +variable "name" { + description = "Name of the Amplify App." + type = string +} + +variable "iam_service_role_arn" { + description = "IAM service role ARN for the Amplify App." + type = string + default = null +} + +variable "oauth_token" { + description = "OAuth token for the Amplify App." + type = string + default = null +} + +variable "platform" { + description = "Platform for the Amplify App. Options are WEB or WEB_COMPUTE." + type = string + default = "WEB" + validation { + condition = var.platform == "WEB" || var.platform == "WEB_COMPUTE" + error_message = "Platform must be either WEB or WEB_COMPUTE." + } +} + +variable "repository" { + description = "Repository for the Amplify App. This could be hosted in AWS Code Commit, Bitbucket, GitHub, GitLab, etc." + type = string + default = null +} + +########################### +# Amplify Branch +########################### + +variable "branches" { + description = "A map of branches for the Amplify App. The key becomes the branch name and the value is an object of branch attributes or settings." + type = map(object({ + basic_auth_credentials = optional(string) # Basic auth credentials for the branch. Must be input as "username:password". + certificate_type = optional(string, "AMPLIFY_MANAGED") # The certificate type for the domain association. Valid values are AMPLIFY_MANAGED or CUSTOM. + custom_certificate_arn = optional(string) # The ARN for the custom certificate. + description = optional(string) # The description of the branch. + display_name = optional(string) # The display name of the branch. This gets used as the default domain prefix. + domain_name = string # The domain name for the domain association. + enable_auto_build = optional(bool, true) # Enable auto build for the branch. + enable_auto_sub_domain = optional(bool, false) # Enable auto sub domain for the domain association. + enable_basic_auth = optional(bool) # Enable basic auth for the branch. + enable_certificate = optional(bool, true) # Enable certificate for the domain association. + enable_notification = optional(bool) # Enable notification for the branch. + enable_performance_mode = optional(bool) # Enable performance mode for the branch. + enable_pull_request_preview = optional(bool) # Enable pull request preview for the branch. + environment_variables = optional(map(string)) # Map of environment variables for the branch. + framework = optional(string) # The framework for the branch. + pull_request_environment_name = optional(string) # The name of the pull request environment. + stage = optional(string) # The stage for the branch. Valid values are PRODUCTION, BETA, DEVELOPMENT, EXPERIMENTAL, PULL_REQUEST. + sub_domains = optional(set(string)) # A list of sub domains to associate with the branch. + ttl = optional(number) # The TTL for the branch. + wait_for_verification = optional(bool, true) # Wait for verification for the domain association. + })) + # Example: + # branches = { + # main = { + # domain_name = "example.org" + # framework = "Astro" + # stage = "PRODUCTION" + # sub_domains = ["www"] + # }, + # staging = { + # basic_auth_credentials = var.example_basic_auth_credentials + # domain_name = "staging.example.org" + # enable_basic_auth = true + # framework = "Astro" + # }, + # dev = { + # basic_auth_credentials = var.example_basic_auth_credentials + # domain_name = "dev.example.org" + # enable_basic_auth = true + # framework = "Astro" + # } +} + +########################### +# General Variables +########################### + +variable "tags" { + description = "Tags for the Amplify App." + type = map(string) + default = { + created_by = "terraform" # Your name goes here + terraform = "true" + environment = "prod" + } +} From a0fbdaaf1d1503d8133febc85cbd34eaa6f3c09c Mon Sep 17 00:00:00 2001 From: Zachary Hill Date: Thu, 9 Jan 2025 21:03:17 -0500 Subject: [PATCH 31/36] Deprecate tfsec (#113) * removed the tfsec scan * converting nighly scan from tfsec to checkov --- .github/workflows/scan.yml | 41 +++++++++++++++++++ .../scheduled_tfsec_security_scan.yml | 32 --------------- .github/workflows/test.yml | 14 ------- 3 files changed, 41 insertions(+), 46 deletions(-) create mode 100644 .github/workflows/scan.yml delete mode 100644 .github/workflows/scheduled_tfsec_security_scan.yml diff --git a/.github/workflows/scan.yml b/.github/workflows/scan.yml new file mode 100644 index 00000000..e4df70fe --- /dev/null +++ b/.github/workflows/scan.yml @@ -0,0 +1,41 @@ +--- +name: Checkov Scan + +on: + # Allows this workflow to be run manually from the Actions tab in GitHub. + workflow_dispatch: + + # Runs the workflow on a schedule, every 12 hours. + schedule: + - cron: "33 */12 * * *" + +jobs: + scan: + name: Checkov Scan + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + steps: + - name: Clone repo + uses: actions/checkout@v4 + + - name: Checkov Scan + uses: bridgecrewio/checkov-action@v12 + with: + # This will add both a CLI output to the console and create a results.sarif file + output_format: cli,sarif + output_file_path: console,results.sarif + + - name: Upload SARIF file + uses: github/codeql-action/upload-sarif@v3 + # Results are generated only on a success or failure + # this is required since GitHub by default won't run the next step + # when the previous one has failed. Security checks that do not pass will 'fail'. + # An alternative is to add `continue-on-error: true` to the previous step + # Or 'soft_fail: true' to checkov. + if: success() || failure() + with: + sarif_file: results.sarif diff --git a/.github/workflows/scheduled_tfsec_security_scan.yml b/.github/workflows/scheduled_tfsec_security_scan.yml deleted file mode 100644 index 629dadd3..00000000 --- a/.github/workflows/scheduled_tfsec_security_scan.yml +++ /dev/null @@ -1,32 +0,0 @@ ---- -name: Nightly - tfsec Security Scan - -on: - workflow_dispatch: - schedule: - - cron: "33 */12 * * *" - -jobs: - tfsec: - name: Run tfsec Security Scan Report - runs-on: ubuntu-latest - permissions: - actions: read - contents: read - security-events: write - - steps: - - name: Clone repo - uses: actions/checkout@v4 - - - name: Run tfsec scan with SARIF output - uses: aquasecurity/tfsec-sarif-action@master - with: - sarif_file: tfsec.sarif - full_repo_scan: true - - - name: Upload SARIF file - uses: github/codeql-action/upload-sarif@v3 - with: - # Path to SARIF file relative to the root of the repository - sarif_file: tfsec.sarif diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6a511dda..c8ba81e5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -28,20 +28,6 @@ jobs: id: fmt run: terraform fmt -check -diff -recursive - test_tfsec: - name: tfsec - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Run tfsec and write pull request comments - uses: aquasecurity/tfsec-pr-commenter-action@main - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - tfsec_args: --force-all-dirs - test_linter: name: Linter runs-on: ubuntu-latest From e34e5122e5f245811da97a6b49bd869f30a27d19 Mon Sep 17 00:00:00 2001 From: Zachary Hill Date: Thu, 9 Jan 2025 21:12:14 -0500 Subject: [PATCH 32/36] updated scan with continue-on-error (#114) --- .github/workflows/scan.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/scan.yml b/.github/workflows/scan.yml index e4df70fe..f8ab0747 100644 --- a/.github/workflows/scan.yml +++ b/.github/workflows/scan.yml @@ -25,6 +25,8 @@ jobs: - name: Checkov Scan uses: bridgecrewio/checkov-action@v12 with: + # Ensures that the scan will continue even if there are errors + continue-on-error: true # This will add both a CLI output to the console and create a results.sarif file output_format: cli,sarif output_file_path: console,results.sarif From 627d15fe903b1c3b8814a7f48c304bcb55f9abad Mon Sep 17 00:00:00 2001 From: Zachary Hill Date: Thu, 9 Jan 2025 21:17:34 -0500 Subject: [PATCH 33/36] continue-on-error to soft_fail (#115) --- .github/workflows/scan.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/scan.yml b/.github/workflows/scan.yml index f8ab0747..9f736ff1 100644 --- a/.github/workflows/scan.yml +++ b/.github/workflows/scan.yml @@ -25,12 +25,13 @@ jobs: - name: Checkov Scan uses: bridgecrewio/checkov-action@v12 with: - # Ensures that the scan will continue even if there are errors - continue-on-error: true # This will add both a CLI output to the console and create a results.sarif file output_format: cli,sarif output_file_path: console,results.sarif + # Ensures that the scan will continue even if there are errors + soft_fail: true + - name: Upload SARIF file uses: github/codeql-action/upload-sarif@v3 # Results are generated only on a success or failure From 1152a5ed936572046b5e06a40cfa5b2ae301846d Mon Sep 17 00:00:00 2001 From: Jake Jones Date: Thu, 9 Jan 2025 21:48:22 -0500 Subject: [PATCH 34/36] VPC Module - Allow disabling of the internet gateway (#107) * updated igw args to allow false == 0 count * added new logic for igw * added two new examples for disabling the igw * fixed index of the pointers * corrected variable to enable_internet_gateway * added type to all vpc variables * chore: terraform fmt and terraform-docs --------- Co-authored-by: Jakeasaurus Co-authored-by: Zachary Hill --- modules/aws/vpc/README.md | 115 ++++++++++++++++++++++++++--------- modules/aws/vpc/main.tf | 19 ++++-- modules/aws/vpc/variables.tf | 94 +++++++++++++++++++--------- 3 files changed, 165 insertions(+), 63 deletions(-) diff --git a/modules/aws/vpc/README.md b/modules/aws/vpc/README.md index 34656c36..84657811 100755 --- a/modules/aws/vpc/README.md +++ b/modules/aws/vpc/README.md @@ -1,7 +1,7 @@ - + + [![Contributors][contributors-shield]][contributors-url] [![Forks][forks-shield]][forks-url] [![Stargazers][stars-shield]][stars-url] @@ -18,7 +19,6 @@ [![MIT License][license-shield]][license-url] [![LinkedIn][linkedin-shield]][linkedin-url] -
@@ -41,7 +41,6 @@

-
Table of Contents @@ -59,11 +58,14 @@
- + ## Usage + ### Simple Example + This example sends uses an internet gateway for the public subnets and NAT gateways for the internal subnets. It utilizes the 10.11.0.0/16 subnet space with /24 subnets for each segmented subnet per availability zone. + ``` module "vpc" { source = "github.com/zachreborn/terraform-modules//modules/aws/vpc" @@ -81,7 +83,9 @@ module "vpc" { ``` ### Firewall Example + This example sends all egress traffic out a EC2 instance acting as a firewall. It also changes the default VPC CIDR block and subnets. + ``` module "vpc" { source = "github.com/zachreborn/terraform-modules//modules/aws/vpc" @@ -101,7 +105,9 @@ module "vpc" { ``` ### Setting Subnet Example + This example sends uses an internet gateway for the public subnets and NAT gateways for the internal subnets. It utilizes a unique 10.100.0.0/16 subnet space with /24 subnets for each segmented subnet per availability zone. + ``` module "vpc" { source = "github.com/zachreborn/terraform-modules//modules/aws/vpc" @@ -125,7 +131,9 @@ module "vpc" { ``` ### Disabling Unneeded Subnets + This example disabled unused subnets and associated resources. In the example we leave only the public and private subnets enabled. + ```hcl module "vpc" { source = "github.com/zachreborn/terraform-modules//modules/aws/vpc" @@ -148,6 +156,57 @@ module "vpc" { } ``` +### Disabling the Internet Gateway + +This example disables the internet gateway, making this VPC a private VPC. This is useful for VPCs which do not need to communicate with the internet, or do so via an egress inspection VPC, SDWAN, or other solution. + +```hcl +module "vpc" { + source = "github.com/zachreborn/terraform-modules//modules/aws/vpc" + + name = "client_prod_vpc" + vpc_cidr = "10.11.0.0/16" + azs = ["us-east-1a", "us-east-1b", "us-east-1c"] + db_subnets_list = [] + dmz_subnets_list = [] + mgmt_subnets_list = [] + private_subnets_list = ["10.11.0.0/24", "10.11.1.0/24", "10.11.2.0/24"] + public_subnets_list = [] + workspaces_subnets_list = [] + tags = { + terraform = "true" + created_by = "Zachary Hill" + environment = "prod" + project = "core_infrastructure" + } +} +``` + +Alternatively, you can disable the internet gateway by setting the `enable_internet_gateway` variable to `false`. This is useful if you still want to have public subnets. + +```hcl +module "vpc" { + source = "github.com/zachreborn/terraform-modules//modules/aws/vpc" + + name = "client_prod_vpc" + vpc_cidr = "10.11.0.0/16" + azs = ["us-east-1a", "us-east-1b", "us-east-1c"] + db_subnets_list = [] + dmz_subnets_list = [] + mgmt_subnets_list = [] + private_subnets_list = ["10.11.0.0/24", "10.11.1.0/24", "10.11.2.0/24"] + public_subnets_list = ["10.11.200.0/24", "10.11.201.0/24", "10.11.202.0/24"] + workspaces_subnets_list = [] + enable_internet_gateway = false + tags = { + terraform = "true" + created_by = "Zachary Hill" + environment = "prod" + project = "core_infrastructure" + } +} +``` + _For more examples, please refer to the [Documentation](https://github.com/zachreborn/terraform-modules)_

(back to top)

@@ -227,17 +286,18 @@ _For more examples, please refer to the [Documentation](https://github.com/zachr | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [azs](#input\_azs) | A list of Availability zones in the region | `list` |
[
"us-east-2a",
"us-east-2b",
"us-east-2c"
]
| no | +| [azs](#input\_azs) | A list of Availability zones in the region | `list(string)` |
[
"us-east-2a",
"us-east-2b",
"us-east-2c"
]
| no | | [cloudwatch\_name\_prefix](#input\_cloudwatch\_name\_prefix) | (Optional, Forces new resource) Creates a unique name beginning with the specified prefix. | `string` | `"flow_logs_"` | no | | [cloudwatch\_retention\_in\_days](#input\_cloudwatch\_retention\_in\_days) | (Optional) Specifies the number of days you want to retain log events in the specified log group. Possible values are: 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 3653, and 0. If you select 0, the events in the log group are always retained and never expire. | `number` | `90` | no | -| [db\_propagating\_vgws](#input\_db\_propagating\_vgws) | A list of VGWs the db route table should propagate. | `list` | `[]` | no | -| [db\_subnets\_list](#input\_db\_subnets\_list) | A list of database subnets inside the VPC. | `list` |
[
"10.11.11.0/24",
"10.11.12.0/24",
"10.11.13.0/24"
]
| no | -| [dmz\_propagating\_vgws](#input\_dmz\_propagating\_vgws) | A list of VGWs the DMZ route table should propagate. | `list` | `[]` | no | -| [dmz\_subnets\_list](#input\_dmz\_subnets\_list) | A list of DMZ subnets inside the VPC. | `list` |
[
"10.11.101.0/24",
"10.11.102.0/24",
"10.11.103.0/24"
]
| no | +| [db\_propagating\_vgws](#input\_db\_propagating\_vgws) | A list of VGWs the db route table should propagate. | `list(string)` | `null` | no | +| [db\_subnets\_list](#input\_db\_subnets\_list) | A list of database subnets inside the VPC. | `list(string)` |
[
"10.11.11.0/24",
"10.11.12.0/24",
"10.11.13.0/24"
]
| no | +| [dmz\_propagating\_vgws](#input\_dmz\_propagating\_vgws) | A list of VGWs the DMZ route table should propagate. | `list(string)` | `null` | no | +| [dmz\_subnets\_list](#input\_dmz\_subnets\_list) | A list of DMZ subnets inside the VPC. | `list(string)` |
[
"10.11.101.0/24",
"10.11.102.0/24",
"10.11.103.0/24"
]
| no | | [enable\_dns\_hostnames](#input\_enable\_dns\_hostnames) | (Optional) A boolean flag to enable/disable DNS hostnames in the VPC. Defaults false. | `bool` | `true` | no | | [enable\_dns\_support](#input\_enable\_dns\_support) | (Optional) A boolean flag to enable/disable DNS support in the VPC. Defaults true. | `bool` | `true` | no | | [enable\_firewall](#input\_enable\_firewall) | (Optional) A boolean flag to enable/disable the use of a firewall instance within the VPC. Defaults False. | `bool` | `false` | no | | [enable\_flow\_logs](#input\_enable\_flow\_logs) | (Optional) A boolean flag to enable/disable the use of flow logs with the resources. Defaults True. | `bool` | `true` | no | +| [enable\_internet\_gateway](#input\_enable\_internet\_gateway) | (Optional) A boolean flag to enable/disable the use of Internet gateways. Defaults True. | `bool` | `true` | no | | [enable\_nat\_gateway](#input\_enable\_nat\_gateway) | (Optional) A boolean flag to enable/disable the use of NAT gateways in the private subnets. Defaults True. | `bool` | `true` | no | | [enable\_s3\_endpoint](#input\_enable\_s3\_endpoint) | (Optional) A boolean flag to enable/disable the use of a S3 endpoint with the VPC. Defaults False | `bool` | `false` | no | | [enable\_ssm\_vpc\_endpoints](#input\_enable\_ssm\_vpc\_endpoints) | (Optional) A boolean flag to enable/disable SSM (Systems Manager) VPC endpoints. Defaults true. | `bool` | `false` | no | @@ -246,8 +306,8 @@ _For more examples, please refer to the [Documentation](https://github.com/zachr | [flow\_log\_format](#input\_flow\_log\_format) | (Optional) The fields to include in the flow log record, in the order in which they should appear. For more information, see Flow Log Records. Default: fields are in the order that they are described in the Flow Log Records section. | `string` | `null` | no | | [flow\_max\_aggregation\_interval](#input\_flow\_max\_aggregation\_interval) | (Optional) The maximum interval of time during which a flow of packets is captured and aggregated into a flow log record. Valid Values: 60 seconds (1 minute) or 600 seconds (10 minutes). Default: 600. | `number` | `60` | no | | [flow\_traffic\_type](#input\_flow\_traffic\_type) | (Optional) The type of traffic to capture. Valid values: ACCEPT,REJECT, ALL. | `string` | `"ALL"` | no | -| [fw\_dmz\_network\_interface\_id](#input\_fw\_dmz\_network\_interface\_id) | Firewall DMZ eni id | `list(any)` | `[]` | no | -| [fw\_network\_interface\_id](#input\_fw\_network\_interface\_id) | Firewall network interface id | `list` | `[]` | no | +| [fw\_dmz\_network\_interface\_id](#input\_fw\_dmz\_network\_interface\_id) | Firewall DMZ eni id | `list(string)` | `null` | no | +| [fw\_network\_interface\_id](#input\_fw\_network\_interface\_id) | Firewall network interface id | `list(string)` | `null` | no | | [iam\_policy\_name\_prefix](#input\_iam\_policy\_name\_prefix) | (Optional, Forces new resource) Creates a unique name beginning with the specified prefix. Conflicts with name. | `string` | `"flow_log_policy_"` | no | | [iam\_policy\_path](#input\_iam\_policy\_path) | (Optional, default '/') Path in which to create the policy. See IAM Identifiers for more information. | `string` | `"/"` | no | | [iam\_role\_description](#input\_iam\_role\_description) | (Optional) The description of the role. | `string` | `"Role utilized for VPC flow logs. This role allows creation of log streams and adding logs to the log streams in cloudwatch"` | no | @@ -255,18 +315,18 @@ _For more examples, please refer to the [Documentation](https://github.com/zachr | [instance\_tenancy](#input\_instance\_tenancy) | A tenancy option for instances launched into the VPC | `string` | `"default"` | no | | [key\_name\_prefix](#input\_key\_name\_prefix) | (Optional) Creates an unique alias beginning with the specified prefix. The name must start with the word alias followed by a forward slash (alias/). | `string` | `"alias/flow_logs_key_"` | no | | [map\_public\_ip\_on\_launch](#input\_map\_public\_ip\_on\_launch) | (Optional) Specify true to indicate that instances launched into the subnet should be assigned a public IP address. Default is false. | `bool` | `true` | no | -| [mgmt\_propagating\_vgws](#input\_mgmt\_propagating\_vgws) | A list of VGWs the mgmt route table should propagate. | `list` | `[]` | no | -| [mgmt\_subnets\_list](#input\_mgmt\_subnets\_list) | A list of mgmt subnets inside the VPC. | `list` |
[
"10.11.61.0/24",
"10.11.62.0/24",
"10.11.63.0/24"
]
| no | +| [mgmt\_propagating\_vgws](#input\_mgmt\_propagating\_vgws) | A list of VGWs the mgmt route table should propagate. | `list(any)` | `null` | no | +| [mgmt\_subnets\_list](#input\_mgmt\_subnets\_list) | A list of mgmt subnets inside the VPC. | `list(string)` |
[
"10.11.61.0/24",
"10.11.62.0/24",
"10.11.63.0/24"
]
| no | | [name](#input\_name) | (Required) Name to be tagged on all of the resources as an identifier | `string` | n/a | yes | -| [private\_propagating\_vgws](#input\_private\_propagating\_vgws) | A list of VGWs the private route table should propagate. | `list` | `[]` | no | -| [private\_subnets\_list](#input\_private\_subnets\_list) | A list of private subnets inside the VPC. | `list` |
[
"10.11.1.0/24",
"10.11.2.0/24",
"10.11.3.0/24"
]
| no | -| [public\_propagating\_vgws](#input\_public\_propagating\_vgws) | A list of VGWs the public route table should propagate. | `list` | `[]` | no | -| [public\_subnets\_list](#input\_public\_subnets\_list) | A list of public subnets inside the VPC. | `list` |
[
"10.11.201.0/24",
"10.11.202.0/24",
"10.11.203.0/24"
]
| no | +| [private\_propagating\_vgws](#input\_private\_propagating\_vgws) | A list of VGWs the private route table should propagate. | `list(any)` | `null` | no | +| [private\_subnets\_list](#input\_private\_subnets\_list) | A list of private subnets inside the VPC. | `list(string)` |
[
"10.11.1.0/24",
"10.11.2.0/24",
"10.11.3.0/24"
]
| no | +| [public\_propagating\_vgws](#input\_public\_propagating\_vgws) | A list of VGWs the public route table should propagate. | `list(any)` | `null` | no | +| [public\_subnets\_list](#input\_public\_subnets\_list) | A list of public subnets inside the VPC. | `list(string)` |
[
"10.11.201.0/24",
"10.11.202.0/24",
"10.11.203.0/24"
]
| no | | [single\_nat\_gateway](#input\_single\_nat\_gateway) | (Optional) A boolean flag to enable/disable use of only a single shared NAT Gateway across all of your private networks. Defaults False. | `bool` | `false` | no | -| [tags](#input\_tags) | (Optional) A mapping of tags to assign to the object. | `map` |
{
"created_by": "",
"environment": "prod",
"priority": "high",
"terraform": "true"
}
| no | +| [tags](#input\_tags) | (Optional) A mapping of tags to assign to the object. | `map(string)` |
{
"created_by": "",
"environment": "prod",
"priority": "high",
"terraform": "true"
}
| no | | [vpc\_cidr](#input\_vpc\_cidr) | The CIDR block for the VPC | `string` | `"10.11.0.0/16"` | no | -| [workspaces\_propagating\_vgws](#input\_workspaces\_propagating\_vgws) | A list of VGWs the workspaces route table should propagate. | `list` | `[]` | no | -| [workspaces\_subnets\_list](#input\_workspaces\_subnets\_list) | A list of workspaces subnets inside the VPC. | `list` |
[
"10.11.21.0/24",
"10.11.22.0/24",
"10.11.23.0/24"
]
| no | +| [workspaces\_propagating\_vgws](#input\_workspaces\_propagating\_vgws) | A list of VGWs the workspaces route table should propagate. | `list(any)` | `null` | no | +| [workspaces\_subnets\_list](#input\_workspaces\_subnets\_list) | A list of workspaces subnets inside the VPC. | `list(string)` |
[
"10.11.21.0/24",
"10.11.22.0/24",
"10.11.23.0/24"
]
| no | ## Outputs @@ -298,15 +358,15 @@ _For more examples, please refer to the [Documentation](https://github.com/zachr + ## License Distributed under the MIT License. See `LICENSE.txt` for more information.

(back to top)

- - + ## Contact Zachary Hill - [![LinkedIn][linkedin-shield]][linkedin-url] - zhill@zacharyhill.co @@ -315,19 +375,18 @@ Project Link: [https://github.com/zachreborn/terraform-modules](https://github.c

(back to top)

- - + ## Acknowledgments -* [Zachary Hill](https://zacharyhill.co) -* [Jake Jones](https://github.com/jakeasarus) +- [Zachary Hill](https://zacharyhill.co) +- [Jake Jones](https://github.com/jakeasarus)

(back to top)

- + [contributors-shield]: https://img.shields.io/github/contributors/zachreborn/terraform-modules.svg?style=for-the-badge [contributors-url]: https://github.com/zachreborn/terraform-modules/graphs/contributors [forks-shield]: https://img.shields.io/github/forks/zachreborn/terraform-modules.svg?style=for-the-badge @@ -342,4 +401,4 @@ Project Link: [https://github.com/zachreborn/terraform-modules](https://github.c [linkedin-url]: https://www.linkedin.com/in/zachary-hill-5524257a/ [product-screenshot]: /images/screenshot.webp [Terraform.io]: https://img.shields.io/badge/Terraform-7B42BC?style=for-the-badge&logo=terraform -[Terraform-url]: https://terraform.io \ No newline at end of file +[Terraform-url]: https://terraform.io diff --git a/modules/aws/vpc/main.tf b/modules/aws/vpc/main.tf index f4f29e5e..81788bdf 100644 --- a/modules/aws/vpc/main.tf +++ b/modules/aws/vpc/main.tf @@ -14,7 +14,13 @@ terraform { data "aws_caller_identity" "current" {} data "aws_region" "current" {} +########################### +# Locals +########################### + locals { + # Disable the IGW if either enable_internet_gateway is false or public_subnets_list is empty + enable_igw = var.enable_internet_gateway ? ((length(var.public_subnets_list) != 0 || var.public_subnets_list != null) ? true : false) : false service_name = "com.amazonaws.${data.aws_region.current.name}.s3" } @@ -194,20 +200,23 @@ resource "aws_subnet" "workspaces_subnets" { ########################### resource "aws_internet_gateway" "igw" { + count = local.enable_igw ? 1 : 0 tags = merge(var.tags, ({ "Name" = format("%s-igw", var.name) })) vpc_id = aws_vpc.vpc.id } resource "aws_route_table" "public_route_table" { + count = length(var.public_subnets_list) != 0 ? 1 : 0 propagating_vgws = var.public_propagating_vgws tags = merge(var.tags, ({ "Name" = format("%s-rt-public", var.name) })) vpc_id = aws_vpc.vpc.id } resource "aws_route" "public_default_route" { + count = local.enable_igw ? 1 : 0 destination_cidr_block = "0.0.0.0/0" - gateway_id = aws_internet_gateway.igw.id - route_table_id = aws_route_table.public_route_table.id + gateway_id = aws_internet_gateway.igw[0].id + route_table_id = aws_route_table.public_route_table[0].id } resource "aws_eip" "nateip" { @@ -218,8 +227,8 @@ resource "aws_eip" "nateip" { resource "aws_nat_gateway" "natgw" { depends_on = [aws_internet_gateway.igw] + count = var.enable_nat_gateway ? (local.enable_igw ? (var.single_nat_gateway ? 1 : length(var.azs)) : 0) : 0 allocation_id = element(aws_eip.nateip[*].id, (var.single_nat_gateway ? 0 : count.index)) - count = var.enable_nat_gateway ? (var.single_nat_gateway ? 1 : length(var.azs)) : 0 subnet_id = element(aws_subnet.public_subnets[*].id, (var.single_nat_gateway ? 0 : count.index)) } @@ -347,7 +356,7 @@ resource "aws_vpc_endpoint_route_table_association" "private_s3" { resource "aws_vpc_endpoint_route_table_association" "public_s3" { count = var.enable_s3_endpoint ? length(var.public_subnets_list) : 0 vpc_endpoint_id = aws_vpc_endpoint.s3[count.index] - route_table_id = aws_route_table.public_route_table.id + route_table_id = aws_route_table.public_route_table[0].id } resource "aws_route_table_association" "private" { @@ -358,7 +367,7 @@ resource "aws_route_table_association" "private" { resource "aws_route_table_association" "public" { count = length(var.public_subnets_list) - route_table_id = aws_route_table.public_route_table.id + route_table_id = aws_route_table.public_route_table[0].id subnet_id = element(aws_subnet.public_subnets[*].id, count.index) } diff --git a/modules/aws/vpc/variables.tf b/modules/aws/vpc/variables.tf index 3224b008..19c8a0a4 100644 --- a/modules/aws/vpc/variables.tf +++ b/modules/aws/vpc/variables.tf @@ -1,28 +1,32 @@ ########################### # VPC ########################### - variable "vpc_cidr" { description = "The CIDR block for the VPC" - default = "10.11.0.0/16" type = string + default = "10.11.0.0/16" } variable "enable_dns_hostnames" { description = "(Optional) A boolean flag to enable/disable DNS hostnames in the VPC. Defaults false." - default = true type = bool + default = true } variable "enable_dns_support" { description = "(Optional) A boolean flag to enable/disable DNS support in the VPC. Defaults true." - default = true type = bool + default = true } variable "instance_tenancy" { description = "A tenancy option for instances launched into the VPC" + type = string default = "default" + validation { + condition = can(regex("^(default|dedicated)$", var.instance_tenancy)) + error_message = "instance_tenancy must be either default or dedicated" + } } ########################### @@ -30,8 +34,8 @@ variable "instance_tenancy" { ########################### variable "enable_ssm_vpc_endpoints" { - type = bool description = "(Optional) A boolean flag to enable/disable SSM (Systems Manager) VPC endpoints. Defaults true." + type = bool default = false } @@ -41,42 +45,49 @@ variable "enable_ssm_vpc_endpoints" { variable "azs" { description = "A list of Availability zones in the region" + type = list(string) default = ["us-east-2a", "us-east-2b", "us-east-2c"] } variable "db_subnets_list" { description = "A list of database subnets inside the VPC." + type = list(string) default = ["10.11.11.0/24", "10.11.12.0/24", "10.11.13.0/24"] } variable "dmz_subnets_list" { description = "A list of DMZ subnets inside the VPC." + type = list(string) default = ["10.11.101.0/24", "10.11.102.0/24", "10.11.103.0/24"] } variable "map_public_ip_on_launch" { description = "(Optional) Specify true to indicate that instances launched into the subnet should be assigned a public IP address. Default is false." - default = true type = bool + default = true } variable "mgmt_subnets_list" { description = "A list of mgmt subnets inside the VPC." + type = list(string) default = ["10.11.61.0/24", "10.11.62.0/24", "10.11.63.0/24"] } variable "private_subnets_list" { description = "A list of private subnets inside the VPC." + type = list(string) default = ["10.11.1.0/24", "10.11.2.0/24", "10.11.3.0/24"] } variable "public_subnets_list" { description = "A list of public subnets inside the VPC." + type = list(string) default = ["10.11.201.0/24", "10.11.202.0/24", "10.11.203.0/24"] } variable "workspaces_subnets_list" { description = "A list of workspaces subnets inside the VPC." + type = list(string) default = ["10.11.21.0/24", "10.11.22.0/24", "10.11.23.0/24"] } @@ -86,6 +97,7 @@ variable "workspaces_subnets_list" { variable "single_nat_gateway" { description = "(Optional) A boolean flag to enable/disable use of only a single shared NAT Gateway across all of your private networks. Defaults False." + type = bool default = false } @@ -95,43 +107,50 @@ variable "single_nat_gateway" { variable "db_propagating_vgws" { description = "A list of VGWs the db route table should propagate." - default = [] + type = list(string) + default = null } variable "dmz_propagating_vgws" { description = "A list of VGWs the DMZ route table should propagate." - default = [] + type = list(string) + default = null } variable "fw_dmz_network_interface_id" { - type = list(any) description = "Firewall DMZ eni id" - default = [] + type = list(string) + default = null } variable "fw_network_interface_id" { description = "Firewall network interface id" - default = [] + type = list(string) + default = null } variable "mgmt_propagating_vgws" { description = "A list of VGWs the mgmt route table should propagate." - default = [] + type = list(any) + default = null } variable "private_propagating_vgws" { description = "A list of VGWs the private route table should propagate." - default = [] + type = list(any) + default = null } variable "public_propagating_vgws" { description = "A list of VGWs the public route table should propagate." - default = [] + type = list(any) + default = null } variable "workspaces_propagating_vgws" { description = "A list of VGWs the workspaces route table should propagate." - default = [] + type = list(any) + default = null } ########################### @@ -139,74 +158,82 @@ variable "workspaces_propagating_vgws" { ########################### variable "cloudwatch_name_prefix" { description = "(Optional, Forces new resource) Creates a unique name beginning with the specified prefix." - default = "flow_logs_" type = string + default = "flow_logs_" } variable "cloudwatch_retention_in_days" { description = "(Optional) Specifies the number of days you want to retain log events in the specified log group. Possible values are: 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 3653, and 0. If you select 0, the events in the log group are always retained and never expire." - default = 90 type = number + default = 90 + validation { + condition = can(index([1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 3653, 0], var.cloudwatch_retention_in_days)) + error_message = "cloudwatch_retention_in_days must be one of: 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 3653, 0." + } } variable "iam_policy_name_prefix" { description = "(Optional, Forces new resource) Creates a unique name beginning with the specified prefix. Conflicts with name." - default = "flow_log_policy_" type = string + default = "flow_log_policy_" } variable "iam_policy_path" { - type = string description = "(Optional, default '/') Path in which to create the policy. See IAM Identifiers for more information." + type = string default = "/" } variable "iam_role_description" { - type = string description = "(Optional) The description of the role." + type = string default = "Role utilized for VPC flow logs. This role allows creation of log streams and adding logs to the log streams in cloudwatch" } variable "iam_role_name_prefix" { - type = string description = "(Required, Forces new resource) Creates a unique friendly name beginning with the specified prefix. Conflicts with name." + type = string default = "flow_logs_role_" } variable "key_name_prefix" { description = "(Optional) Creates an unique alias beginning with the specified prefix. The name must start with the word alias followed by a forward slash (alias/)." - default = "alias/flow_logs_key_" type = string + default = "alias/flow_logs_key_" } variable "flow_deliver_cross_account_role" { - type = string description = "(Optional) The ARN of the IAM role that posts logs to CloudWatch Logs in a different account." + type = string default = null } variable "flow_log_destination_type" { - type = string description = "(Optional) The type of the logging destination. Valid values: cloud-watch-logs, s3. Default: cloud-watch-logs." + type = string default = "cloud-watch-logs" } variable "flow_log_format" { - type = string description = "(Optional) The fields to include in the flow log record, in the order in which they should appear. For more information, see Flow Log Records. Default: fields are in the order that they are described in the Flow Log Records section." + type = string default = null } variable "flow_max_aggregation_interval" { - type = number description = "(Optional) The maximum interval of time during which a flow of packets is captured and aggregated into a flow log record. Valid Values: 60 seconds (1 minute) or 600 seconds (10 minutes). Default: 600." + type = number default = 60 } variable "flow_traffic_type" { - type = string description = "(Optional) The type of traffic to capture. Valid values: ACCEPT,REJECT, ALL." + type = string default = "ALL" + validation { + condition = can(index(["ACCEPT", "REJECT", "ALL"], var.flow_traffic_type)) + error_message = "flow_traffic_type must be one of: ACCEPT, REJECT, ALL." + } } ############################################################### @@ -215,26 +242,32 @@ variable "flow_traffic_type" { variable "enable_firewall" { description = "(Optional) A boolean flag to enable/disable the use of a firewall instance within the VPC. Defaults False." - default = false type = bool + default = false } variable "enable_nat_gateway" { description = "(Optional) A boolean flag to enable/disable the use of NAT gateways in the private subnets. Defaults True." + type = bool default = true +} + +variable "enable_internet_gateway" { + description = "(Optional) A boolean flag to enable/disable the use of Internet gateways. Defaults True." type = bool + default = true } variable "enable_s3_endpoint" { description = "(Optional) A boolean flag to enable/disable the use of a S3 endpoint with the VPC. Defaults False" - default = false type = bool + default = false } variable "enable_flow_logs" { description = "(Optional) A boolean flag to enable/disable the use of flow logs with the resources. Defaults True." - default = true type = bool + default = true } variable "name" { @@ -244,6 +277,7 @@ variable "name" { variable "tags" { description = "(Optional) A mapping of tags to assign to the object." + type = map(string) default = { terraform = "true" created_by = "" From 6714d14a8a31bf0718a9630406c7b572d28f3bd9 Mon Sep 17 00:00:00 2001 From: jakeasaurus Date: Fri, 17 Jan 2025 09:36:52 -0500 Subject: [PATCH 35/36] few minor changes --- modules/aws/lb/main.tf | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/modules/aws/lb/main.tf b/modules/aws/lb/main.tf index a9f4913f..eebcc7a7 100644 --- a/modules/aws/lb/main.tf +++ b/modules/aws/lb/main.tf @@ -1,9 +1,29 @@ +########################### +# Provider Configuration +########################### +terraform { + required_version = ">= 1.0.0" + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 4.0.0" + } + } +} + +########################### +# Locals +########################### + locals { is_application = var.load_balancer_type == "application" is_network = var.load_balancer_type == "network" } +########################################################### # Load Balancer +########################################################### + resource "aws_lb" "load_balancer" { # Common settings name = var.name @@ -52,6 +72,10 @@ resource "aws_lb" "load_balancer" { ) } +########################################################### +# Target Group +########################################################### + resource "aws_lb_target_group" "target_group" { for_each = var.target_groups @@ -101,7 +125,10 @@ resource "aws_lb_target_group" "target_group" { ) } +########################################################### # Listeners +########################################################### + resource "aws_lb_listener" "listener" { for_each = var.listeners @@ -181,8 +208,11 @@ resource "aws_lb_listener" "listener" { } } +########################################################### +# Listener Rules +########################################################### -# Listener Rules (Application Load Balancer only) +# (Application Load Balancer only) resource "aws_lb_listener_rule" "listener_rule" { # Common settings for_each = var.listener_rules From 463e11185f35e600f55d6996e09459c94360bde3 Mon Sep 17 00:00:00 2001 From: Jakeasaurus <47454060+Jakeasaurus@users.noreply.github.com> Date: Fri, 17 Jan 2025 14:37:37 +0000 Subject: [PATCH 36/36] chore: terraform fmt and terraform-docs --- modules/aws/lb/README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/aws/lb/README.md b/modules/aws/lb/README.md index 7b11692e..3dfc4f15 100644 --- a/modules/aws/lb/README.md +++ b/modules/aws/lb/README.md @@ -43,13 +43,16 @@ module "alb" { ## Requirements -No requirements. +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0.0 | +| [aws](#requirement\_aws) | >= 4.0.0 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | n/a | +| [aws](#provider\_aws) | >= 4.0.0 | ## Modules