diff --git a/examples/network-firewall/README.md b/examples/network-firewall/README.md
new file mode 100644
index 000000000..38d856916
--- /dev/null
+++ b/examples/network-firewall/README.md
@@ -0,0 +1,64 @@
+VPC with Network Firewall
+
+This configuration creates a VPC with the following resources across multiple AZs
+
+- Internet gateway
+- NAT gateway per AZ
+- public, private and firewall subnets
+- AWS network firewall
+
+The routing tables for such a deployment model follows the [AWS blog suggestion](https://aws.amazon.com/blogs/networking-and-content-delivery/deployment-models-for-aws-network-firewall/), particularly "2) AWS Network Firewall is deployed to protect traffic between an AWS service in a public subnet and IGW"
+
+## Usage
+
+To run this example you need to execute:
+
+```bash
+$ terraform init
+$ terraform plan
+$ terraform apply
+```
+
+Note that this example may create resources which can cost money (AWS Elastic IP, for example). Run `terraform destroy` when you don't need these resources.
+
+## Requirements
+
+| Name | Version |
+|------|---------|
+| [terraform](#requirement\_terraform) | >= 1.0 |
+| [aws](#requirement\_aws) | >= 5.46 |
+| [random](#requirement\_random) | >= 3.0 |
+
+## Providers
+
+| Name | Version |
+|------|---------|
+| [random](#provider\_random) | >= 3.0 |
+
+## Modules
+
+| Name | Source | Version |
+|------|--------|---------|
+| [kms](#module\_kms) | git::https://github.com/withclutch/terraform-modules-registry | aws-kms_v1.204 |
+| [vpc](#module\_vpc) | ../../ | n/a |
+
+## Resources
+
+| Name | Type |
+|------|------|
+| [random_pet.this](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/pet) | resource |
+
+## Inputs
+
+No inputs.
+
+## Outputs
+
+| Name | Description |
+|------|-------------|
+| [firewall\_subnets](#output\_firewall\_subnets) | List of IDs of firewall subnets |
+| [nat\_public\_ips](#output\_nat\_public\_ips) | List of public Elastic IPs created for AWS NAT Gateway |
+| [network\_firewall\_arn](#output\_network\_firewall\_arn) | ARN of the Network Firewall |
+| [private\_subnets](#output\_private\_subnets) | List of IDs of private subnets |
+| [public\_subnets](#output\_public\_subnets) | List of IDs of public subnets |
+| [vpc\_id](#output\_vpc\_id) | The ID of the VPC |
diff --git a/examples/network-firewall/main.tf b/examples/network-firewall/main.tf
new file mode 100644
index 000000000..236ab822a
--- /dev/null
+++ b/examples/network-firewall/main.tf
@@ -0,0 +1,88 @@
+provider "aws" {
+ region = local.region
+}
+
+locals {
+ region = "us-east-2"
+ name_prefix = random_pet.this.id
+ environment = "test"
+}
+
+resource "random_pet" "this" {
+ length = 2
+ separator = "-"
+}
+
+################################################################################
+# KMS Module
+################################################################################
+
+module "kms" {
+ source = "git::https://github.com/withclutch/terraform-modules-registry?ref=aws-kms_v1.204"
+
+ name = "${local.name_prefix}-kms"
+ environment = "test"
+ description = "KMS key used to test the ${local.name_prefix} AWS Network Firewall"
+ allow_usage_in_network_log_groups = true
+}
+
+################################################################################
+# VPC Module
+################################################################################
+
+module "vpc" {
+ source = "../../"
+
+ environment = "test"
+ name = "nf-example"
+
+ ######### VPC ##########
+ cidr = "10.0.0.0/16"
+ azs = ["${local.region}a", "${local.region}b", "${local.region}c"]
+
+ ######### Subnets ##########
+ private_subnets = ["10.0.0.0/24", "10.0.1.0/24", "10.0.2.0/24"]
+ public_subnets = ["10.0.4.0/24", "10.0.5.0/24", "10.0.6.0/24"]
+ firewall_subnets = ["10.0.3.0/28", "10.0.3.16/28", "10.0.3.32/28"]
+
+ create_multiple_public_route_tables = true
+
+ ######### NAT Gateway ##########
+ enable_nat_gateway = true
+ one_nat_gateway_per_az = true
+
+ ########## Firewall ##########
+ create_network_firewall = true
+ enable_network_firewall = true
+
+ ######### Firewall Logs ##########
+ firewall_logs_retention_in_days = 14
+ firewall_logs_kms_key_arn = module.kms.key_arn
+ create_logging_configuration = true
+
+ ######### Firewall Rules and Filter ##########
+ firewall_log_types = ["FLOW", "ALERT"]
+ firewall_managed_rules = [
+ "AbusedLegitMalwareDomainsStrictOrder",
+ "BotNetCommandAndControlDomainsStrictOrder",
+ "AbusedLegitBotNetCommandAndControlDomainsStrictOrder",
+ "MalwareDomainsStrictOrder",
+ "ThreatSignaturesIOCStrictOrder",
+ "ThreatSignaturesPhishingStrictOrder",
+ "ThreatSignaturesBotnetWebStrictOrder",
+ "ThreatSignaturesEmergingEventsStrictOrder",
+ "ThreatSignaturesDoSStrictOrder",
+ "ThreatSignaturesMalwareWebStrictOrder",
+ "ThreatSignaturesExploitsStrictOrder",
+ "ThreatSignaturesWebAttacksStrictOrder",
+ "ThreatSignaturesScannersStrictOrder",
+ "ThreatSignaturesBotnetStrictOrder",
+ "ThreatSignaturesMalwareStrictOrder",
+ "ThreatSignaturesMalwareCoinminingStrictOrder",
+ "ThreatSignaturesFUPStrictOrder",
+ "ThreatSignaturesSuspectStrictOrder",
+ "ThreatSignaturesBotnetWindowsStrictOrder",
+ ]
+
+ depends_on = [module.kms]
+}
diff --git a/examples/network-firewall/outputs.tf b/examples/network-firewall/outputs.tf
new file mode 100644
index 000000000..ed4dfb298
--- /dev/null
+++ b/examples/network-firewall/outputs.tf
@@ -0,0 +1,41 @@
+################################################################################
+# VPC
+################################################################################
+
+output "vpc_id" {
+ description = "The ID of the VPC"
+ value = module.vpc.vpc_id
+}
+
+################################################################################
+# Subnets
+################################################################################
+
+output "private_subnets" {
+ description = "List of IDs of private subnets"
+ value = module.vpc.private_subnets
+}
+
+output "public_subnets" {
+ description = "List of IDs of public subnets"
+ value = module.vpc.public_subnets
+}
+
+output "firewall_subnets" {
+ description = "List of IDs of firewall subnets"
+ value = module.vpc.firewall_subnets
+}
+
+################################################################################
+# NAT Gateway
+################################################################################
+
+output "nat_public_ips" {
+ description = "List of public Elastic IPs created for AWS NAT Gateway"
+ value = module.vpc.nat_public_ips
+}
+
+output "network_firewall_arn" {
+ description = "ARN of the Network Firewall"
+ value = module.vpc.network_firewall_arn
+}
diff --git a/examples/network-firewall/variables.tf b/examples/network-firewall/variables.tf
new file mode 100644
index 000000000..e69de29bb
diff --git a/examples/network-firewall/versions.tf b/examples/network-firewall/versions.tf
new file mode 100644
index 000000000..c20408bf6
--- /dev/null
+++ b/examples/network-firewall/versions.tf
@@ -0,0 +1,14 @@
+terraform {
+ required_version = ">= 1.0"
+
+ required_providers {
+ aws = {
+ source = "hashicorp/aws"
+ version = ">= 5.46"
+ }
+ random = {
+ source = "hashicorp/random"
+ version = ">= 3.0"
+ }
+ }
+}
diff --git a/main.tf b/main.tf
index 77cba6715..2bf350b6f 100644
--- a/main.tf
+++ b/main.tf
@@ -6,6 +6,7 @@ locals {
len_redshift_subnets = max(length(var.redshift_subnets), length(var.redshift_subnet_ipv6_prefixes))
len_intra_subnets = max(length(var.intra_subnets), length(var.intra_subnet_ipv6_prefixes))
len_outpost_subnets = max(length(var.outpost_subnets), length(var.outpost_subnet_ipv6_prefixes))
+ len_firewall_subnets = max(length(var.firewall_subnets), length(var.firewall_subnet_ipv6_prefixes))
max_subnet_length = max(
local.len_private_subnets,
@@ -13,8 +14,18 @@ locals {
local.len_elasticache_subnets,
local.len_database_subnets,
local.len_redshift_subnets,
+ local.len_firewall_subnets,
)
+ // TODO - comment what this line does
+ firewall_sync_states = try(module.firewall[0].status[0].sync_states, {})
+ firewall_vpce = {
+ for state in local.firewall_sync_states : state.availability_zone => {
+ cidr_block = one([for subnet in aws_subnet.firewall : subnet.cidr_block if subnet.id == state.attachment[0].subnet_id])
+ endpoint_id = state.attachment[0].endpoint_id
+ }
+ }
+
# Use `local.vpc_id` to give a hint to Terraform that subnets should be deleted before secondary CIDR blocks can be free!
vpc_id = try(aws_vpc_ipv4_cidr_block_association.this[0].vpc_id, aws_vpc.this[0].id, "")
@@ -153,7 +164,7 @@ resource "aws_route_table_association" "public" {
}
resource "aws_route" "public_internet_gateway" {
- count = local.create_public_subnets && var.create_igw ? local.num_public_route_tables : 0
+ count = local.create_public_subnets && var.create_igw && !(var.enable_network_firewall && local.len_firewall_subnets > 0) ? local.num_public_route_tables : 0
route_table_id = aws_route_table.public[count.index].id
destination_cidr_block = "0.0.0.0/0"
@@ -164,6 +175,32 @@ resource "aws_route" "public_internet_gateway" {
}
}
+resource "aws_route_table_association" "public_internet_gateway" {
+ count = local.create_vpc && var.create_igw && var.enable_network_firewall && local.len_firewall_subnets > 0 ? 1 : 0
+
+ gateway_id = aws_internet_gateway.this[0].id
+ route_table_id = aws_route_table.internet_gateway[0].id
+}
+
+resource "aws_route_table_association" "firewall" {
+ count = local.create_vpc && local.len_firewall_subnets > 0 ? local.len_firewall_subnets : 0
+
+ subnet_id = element(aws_subnet.firewall.*.id, count.index)
+ route_table_id = aws_route_table.firewall[0].id
+}
+
+resource "aws_route" "public_firewall" {
+ count = local.create_vpc && var.enable_network_firewall ? local.len_public_subnets : 0
+
+ route_table_id = element(aws_route_table.public.*.id, count.index)
+ destination_cidr_block = "0.0.0.0/0"
+ vpc_endpoint_id = local.firewall_vpce[aws_subnet.public[count.index].availability_zone].endpoint_id
+
+ timeouts {
+ create = "5m"
+ }
+}
+
resource "aws_route" "public_internet_gateway_ipv6" {
count = local.create_public_subnets && var.create_igw && var.enable_ipv6 ? local.num_public_route_tables : 0
@@ -223,6 +260,145 @@ resource "aws_network_acl_rule" "public_outbound" {
ipv6_cidr_block = lookup(var.public_outbound_acl_rules[count.index], "ipv6_cidr_block", null)
}
+################################################################################
+# Firewall Subnets
+################################################################################
+
+locals {
+ create_firewall_subnets = local.create_vpc && local.len_firewall_subnets > 0
+}
+
+resource "aws_subnet" "firewall" {
+ count = local.create_firewall_subnets ? local.len_firewall_subnets : 0
+
+ vpc_id = local.vpc_id
+ cidr_block = var.firewall_subnets[count.index]
+ availability_zone = length(regexall("^[a-z]{2}-", element(var.azs, count.index))) > 0 ? element(var.azs, count.index) : null
+ availability_zone_id = length(regexall("^[a-z]{2}-", element(var.azs, count.index))) == 0 ? element(var.azs, count.index) : null
+ assign_ipv6_address_on_creation = var.enable_ipv6 && var.firewall_subnet_ipv6_native ? true : var.firewall_subnet_assign_ipv6_address_on_creation
+
+ ipv6_cidr_block = var.enable_ipv6 && length(var.firewall_subnet_ipv6_prefixes) > 0 ? cidrsubnet(aws_vpc.this[0].ipv6_cidr_block, 8, var.firewall_subnet_ipv6_prefixes[count.index]) : null
+
+ tags = merge(
+ {
+ "Name" = format(
+ "%s-${var.firewall_subnet_suffix}-%s",
+ var.name,
+ element(var.azs, count.index),
+ )
+ },
+ var.tags,
+ var.firewall_subnet_tags,
+ )
+}
+
+
+resource "aws_route_table" "firewall" {
+ count = local.create_vpc && var.create_firewall_subnet_route_table && local.len_firewall_subnets > 0 ? 1 : 0
+
+ vpc_id = local.vpc_id
+
+ tags = merge(
+ {
+ "Name" = "${var.name}-${var.firewall_subnet_suffix}"
+ },
+ var.tags,
+ var.firewall_route_table_tags,
+ )
+}
+
+resource "aws_route" "firewall_internet_gateway" {
+ count = local.create_vpc && var.create_igw && local.len_firewall_subnets > 0 ? 1 : 0
+
+ route_table_id = aws_route_table.firewall[count.index].id
+ destination_cidr_block = "0.0.0.0/0"
+ gateway_id = aws_internet_gateway.this[0].id
+
+ timeouts {
+ create = "5m"
+ }
+}
+
+resource "aws_route_table" "internet_gateway" {
+ count = local.create_vpc && var.enable_network_firewall && local.len_firewall_subnets > 0 ? 1 : 0
+ vpc_id = local.vpc_id
+
+ tags = merge(
+ {
+ "Name" = format("%s-internet-gateway-${var.public_subnet_suffix}", var.name)
+ },
+ var.tags,
+ var.public_route_table_tags,
+ )
+}
+
+resource "aws_route" "internet_gateway_firewall" {
+ count = local.create_vpc && var.enable_network_firewall && local.len_firewall_subnets > 0 ? local.len_public_subnets : 0
+
+ route_table_id = aws_route_table.internet_gateway[0].id
+ destination_cidr_block = aws_subnet.public[count.index].cidr_block
+
+
+ vpc_endpoint_id = local.firewall_vpce[aws_subnet.public[count.index].availability_zone].endpoint_id // TODO testing
+ #vpc_endpoint_id = element(local.firewall_endpoint_ids_ordered_by_azs, count.index)
+}
+
+################################################################################
+# Firewall Network ACLs
+################################################################################
+
+locals {
+ create_firewall_network_acl = local.create_firewall_subnets && var.firewall_dedicated_network_acl
+}
+
+resource "aws_network_acl" "firewall" {
+ count = local.create_firewall_network_acl ? 1 : 0
+
+ vpc_id = local.vpc_id
+ subnet_ids = aws_subnet.firewall[*].id
+
+ tags = merge(
+ { "Name" = "${var.name}-${var.firewall_subnet_suffix}" },
+ var.tags,
+ var.firewall_acl_tags,
+ )
+}
+
+resource "aws_network_acl_rule" "firewall_inbound" {
+ count = local.create_firewall_network_acl ? length(var.firewall_inbound_acl_rules) : 0
+
+ network_acl_id = aws_network_acl.firewall[0].id
+
+ egress = false
+ rule_number = var.firewall_inbound_acl_rules[count.index]["rule_number"]
+ rule_action = var.firewall_inbound_acl_rules[count.index]["rule_action"]
+ from_port = lookup(var.firewall_inbound_acl_rules[count.index], "from_port", null)
+ to_port = lookup(var.firewall_inbound_acl_rules[count.index], "to_port", null)
+ icmp_code = lookup(var.firewall_inbound_acl_rules[count.index], "icmp_code", null)
+ icmp_type = lookup(var.firewall_inbound_acl_rules[count.index], "icmp_type", null)
+ protocol = var.firewall_inbound_acl_rules[count.index]["protocol"]
+ cidr_block = lookup(var.firewall_inbound_acl_rules[count.index], "cidr_block", null)
+ ipv6_cidr_block = lookup(var.firewall_inbound_acl_rules[count.index], "ipv6_cidr_block", null)
+}
+
+resource "aws_network_acl_rule" "firewall_outbound" {
+ count = local.create_firewall_network_acl ? length(var.firewall_outbound_acl_rules) : 0
+
+ network_acl_id = aws_network_acl.firewall[0].id
+
+ egress = true
+ rule_number = var.firewall_outbound_acl_rules[count.index]["rule_number"]
+ rule_action = var.firewall_outbound_acl_rules[count.index]["rule_action"]
+ from_port = lookup(var.firewall_outbound_acl_rules[count.index], "from_port", null)
+ to_port = lookup(var.firewall_outbound_acl_rules[count.index], "to_port", null)
+ icmp_code = lookup(var.firewall_outbound_acl_rules[count.index], "icmp_code", null)
+ icmp_type = lookup(var.firewall_outbound_acl_rules[count.index], "icmp_type", null)
+ protocol = var.firewall_outbound_acl_rules[count.index]["protocol"]
+ cidr_block = lookup(var.firewall_outbound_acl_rules[count.index], "cidr_block", null)
+ ipv6_cidr_block = lookup(var.firewall_outbound_acl_rules[count.index], "ipv6_cidr_block", null)
+}
+
+
################################################################################
# Private Subnets
################################################################################
diff --git a/network-firewall.tf b/network-firewall.tf
new file mode 100644
index 000000000..2ffeade4e
--- /dev/null
+++ b/network-firewall.tf
@@ -0,0 +1,127 @@
+locals {
+ aws_managed_rules_prefix_arn = "arn:aws:network-firewall:${var.region}:aws-managed:stateful-rulegroup"
+ firewall_managed_rules = distinct(var.firewall_managed_rules)
+ name = "${var.name}-network-firewall"
+}
+
+### TODO - AWS Network Firewall Managed and Custom Rules will be reviewed/implemented in next release - ###
+module "firewall" {
+ source = "terraform-aws-modules/network-firewall/aws"
+ version = "~> 1.0"
+
+ count = var.create_network_firewall ? 1 : 0
+
+ name = local.name
+ description = var.firewall_description
+
+ delete_protection = var.firewall_delete_protection
+ firewall_policy_change_protection = var.firewall_policy_change_protection
+ subnet_change_protection = var.firewall_subnet_change_protection
+
+
+ vpc_id = aws_vpc.this[0].id
+ subnet_mapping = { for subnet_id in aws_subnet.firewall.*.id :
+ "subnet-${subnet_id}" => {
+ subnet_id = subnet_id
+ ip_address_type = "IPV4"
+ }
+ }
+
+ ### Logging configuration ###
+ create_logging_configuration = var.create_logging_configuration
+ logging_configuration_destination_config = [
+ {
+ log_destination = {
+ logGroup = module.logs_alerts[0].cloudwatch_log_group_name
+ }
+ log_destination_type = "CloudWatchLogs"
+ log_type = "ALERT"
+ },
+ {
+ log_destination = {
+ logGroup = module.logs_flow[0].cloudwatch_log_group_name
+ }
+ log_destination_type = "CloudWatchLogs"
+ log_type = "FLOW"
+ },
+ ]
+
+ encryption_configuration = {
+ key_id = module.kms[0].key_arn
+ type = "CUSTOMER_KMS"
+ }
+
+ ### Policy ###
+ policy_name = local.name
+ policy_description = "Default network firewall policy for ${local.name}"
+
+ policy_stateful_rule_group_reference = {
+ for i, rule_group in local.firewall_managed_rules : rule_group => {
+ resource_arn = "${local.aws_managed_rules_prefix_arn}/${rule_group}",
+ priority = i + 1,
+ }
+ }
+
+ policy_stateful_engine_options = {
+ rule_order = "STRICT_ORDER"
+ }
+ policy_stateless_default_actions = ["aws:forward_to_sfe"]
+ policy_stateless_fragment_default_actions = ["aws:forward_to_sfe"]
+
+ tags = var.tags
+
+ depends_on = [module.kms, module.logs_alerts, module.logs_flow]
+}
+
+module "logs_alerts" {
+ source = "git::https://github.com/withclutch/terraform-modules-registry?ref=aws-log-group_v1.194"
+
+ count = var.create_network_firewall ? 1 : 0
+
+ name = "${local.name}-alerts"
+ tenant = var.tenant
+ region = var.region
+ environment = var.environment
+
+ retention_in_days = var.firewall_logs_retention_in_days
+ kms_key_arn = module.kms[0].key_arn
+ create_datadog_subscription_filter = true
+
+ tags = merge(var.tags, var.firewall_log_tags)
+
+ depends_on = [module.kms]
+}
+
+module "logs_flow" {
+ source = "git::https://github.com/withclutch/terraform-modules-registry?ref=aws-log-group_v1.194"
+
+ count = var.create_network_firewall ? 1 : 0
+
+ name = "${local.name}-flow"
+ tenant = var.tenant
+ region = var.region
+ environment = var.environment
+
+ retention_in_days = var.firewall_logs_retention_in_days
+ kms_key_arn = module.kms[0].key_arn
+ create_datadog_subscription_filter = false
+
+ tags = merge(var.tags, var.firewall_log_tags)
+
+ depends_on = [module.kms]
+}
+
+module "kms" {
+ source = "git::https://github.com/withclutch/terraform-modules-registry?ref=aws-kms_v1.204"
+ count = var.create_network_firewall ? 1 : 0
+
+ name = "${local.name}-kms"
+ description = "KMS key used for ${local.name} AWS Network Firewall"
+ region = var.region
+ environment = var.environment
+ namespace = var.namespace
+ tenant = var.tenant
+ tags = var.tags
+ allow_usage_in_network_log_groups = true
+}
+
diff --git a/outputs.tf b/outputs.tf
index c2367e210..c5759124d 100644
--- a/outputs.tf
+++ b/outputs.tf
@@ -2,6 +2,7 @@ locals {
redshift_route_table_ids = aws_route_table.redshift[*].id
public_route_table_ids = aws_route_table.public[*].id
private_route_table_ids = aws_route_table.private[*].id
+ firewall_route_table_ids = aws_route_table.firewall[*].id
}
################################################################################
@@ -500,6 +501,55 @@ output "intra_network_acl_arn" {
value = try(aws_network_acl.intra[0].arn, null)
}
+################################################################################
+# Firewall Subnets
+################################################################################
+
+output "firewall_subnet_objects" {
+ description = "A list of all firewall subnets, containing the full objects."
+ value = aws_subnet.firewall
+}
+
+output "firewall_subnets" {
+ description = "List of IDs of firewall subnets"
+ value = aws_subnet.firewall[*].id
+}
+
+output "firewall_subnet_arns" {
+ description = "List of ARNs of firewall subnets"
+ value = aws_subnet.firewall[*].arn
+}
+
+output "firewall_subnets_cidr_blocks" {
+ description = "List of cidr_blocks of firewall subnets"
+ value = compact(aws_subnet.firewall[*].cidr_block)
+}
+
+output "firewall_subnets_ipv6_cidr_blocks" {
+ description = "List of IPv6 cidr_blocks of firewall subnets in an IPv6 enabled VPC"
+ value = compact(aws_subnet.firewall[*].ipv6_cidr_block)
+}
+
+output "firewall_route_table_ids" {
+ description = "List of IDs of firewall route tables"
+ value = local.firewall_route_table_ids
+}
+
+output "firewall_route_table_association_ids" {
+ description = "List of IDs of the firewall route table association"
+ value = aws_route_table_association.firewall[*].id
+}
+
+output "firewall_network_acl_id" {
+ description = "ID of the firewall network ACL"
+ value = try(aws_network_acl.firewall[0].id, null)
+}
+
+output "firewall_network_acl_arn" {
+ description = "ARN of the firewall network ACL"
+ value = try(aws_network_acl.firewall[0].arn, null)
+}
+
################################################################################
# NAT Gateway
################################################################################
@@ -649,6 +699,20 @@ output "vpc_flow_log_deliver_cross_account_role" {
value = try(aws_flow_log.this[0].deliver_cross_account_role, null)
}
+################################################################################
+# Firewall
+################################################################################
+
+output "firewall_status" {
+ description = "Nested list of information about the current status of the firewall"
+ value = try(module.firewall[0].status, {})
+}
+
+output "network_firewall_arn" {
+ description = "ARN of the Network Firewall"
+ value = try(module.firewall[0].arn, {})
+}
+
################################################################################
# Static values (arguments)
################################################################################
diff --git a/variables.tf b/variables.tf
index 095cc8bdf..33e90dce4 100644
--- a/variables.tf
+++ b/variables.tf
@@ -1166,6 +1166,210 @@ variable "outpost_acl_tags" {
default = {}
}
+################################################################################
+# Firewall
+################################################################################
+
+variable "create_firewall_subnet_route_table" {
+ description = "Whether route table for firewall should be created"
+ type = bool
+ default = true
+}
+
+variable "create_network_firewall" {
+ description = "Whether network firewall should be created"
+ type = bool
+ default = false
+}
+
+variable "enable_network_firewall" {
+ description = "Whether network firewall should be enabled"
+ type = bool
+ default = false
+}
+
+variable "firewall_managed_rules" {
+ description = "List of firewall managed rules"
+ type = list(string)
+ default = []
+}
+
+variable "firewall_log_types" {
+ description = "The Types of Network Firewall Logs to send"
+ type = list(string)
+ default = ["FLOW", "ALERT"]
+}
+
+variable "firewall_log_tags" {
+ description = "Additional tags for the Firewall Logs"
+ type = map(string)
+ default = {}
+}
+
+variable "create_logging_configuration" {
+ description = "Controls if a Logging Configuration should be created"
+ type = bool
+ default = false
+}
+
+variable "region" {
+ description = "Main region used to deploy the resources. May differ for multi-region databases"
+ type = string
+ default = "us-east-2"
+}
+
+variable "environment" {
+ description = "Environment used to deploy the resources, also used in the naming convention"
+ type = string
+}
+
+variable "namespace" {
+ description = "The namespace used in the naming convention"
+ type = string
+ default = "clutch"
+}
+
+variable "tenant" {
+ description = "The tenant used in the naming convention"
+ type = string
+ default = "app"
+}
+
+variable "firewall_description" {
+ description = "Description of the network firewall."
+ type = string
+ default = null
+}
+
+variable "firewall_delete_protection" {
+ description = "A boolean flag indicating whether it is possible to delete the firewall. Defaults to `true`"
+ type = bool
+ default = true
+}
+
+variable "firewall_subnet_change_protection" {
+ description = "A boolean flag indicating whether it is possible to change the associated subnet(s). Defaults to `true`"
+ type = bool
+ default = true
+}
+
+variable "firewall_policy_change_protection" {
+ description = "A boolean flag indicating whether it is possible to change the associated firewall policy. Defaults to `false`"
+ type = bool
+ default = true
+}
+
+variable "firewall_logs_retention_in_days" {
+ type = string
+ description = "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, and 3653."
+}
+
+variable "firewall_logs_kms_key_arn" {
+ description = "The Amazon Resource Name (ARN) of the key used for encrypting the log group"
+ type = string
+}
+
+resource "random_id" "suffix_name" {
+ byte_length = 1
+}
+
+################################################################################
+# Firewall Subnet
+################################################################################
+
+variable "firewall_subnets" {
+ description = "A list of firewall subnets inside the VPC"
+ type = list(string)
+ default = []
+
+ validation {
+ condition = var.create_network_firewall == false || length(var.firewall_subnets) > 0
+ error_message = "The 'firewall_subnets' variable must be set when 'create_network_firewall' is true."
+ }
+}
+
+variable "firewall_subnet_assign_ipv6_address_on_creation" {
+ description = "Specify true to indicate that network interfaces created in the specified subnet should be assigned an IPv6 address. Default is `false`"
+ type = bool
+ default = false
+}
+
+variable "firewall_subnet_ipv6_prefixes" {
+ description = "Assigns IPv6 firewall subnet id based on the Amazon provided /56 prefix base 10 integer (0-256). Must be of equal length to the corresponding IPv4 subnet list"
+ type = list(string)
+ default = []
+}
+
+variable "firewall_subnet_ipv6_native" {
+ description = "Indicates whether to create an IPv6-only subnet. Default: `false`"
+ type = bool
+ default = false
+}
+
+variable "firewall_subnet_suffix" {
+ description = "Suffix to append to firewall subnets name"
+ type = string
+ default = "firewall"
+}
+
+variable "firewall_subnet_tags" {
+ description = "Additional tags for the firewall subnets"
+ type = map(string)
+ default = {}
+}
+
+variable "firewall_route_table_tags" {
+ description = "Additional tags for the firewall route tables"
+ type = map(string)
+ default = {}
+}
+
+################################################################################
+# Firewall Network ACLs
+################################################################################
+
+variable "firewall_dedicated_network_acl" {
+ description = "Whether to use dedicated network ACL (not default) and custom rules for firewall subnets"
+ type = bool
+ default = false
+}
+
+variable "firewall_inbound_acl_rules" {
+ description = "Firewall subnets inbound network ACLs"
+ type = list(map(string))
+ default = [
+ {
+ rule_number = 100
+ rule_action = "allow"
+ from_port = 0
+ to_port = 0
+ protocol = "-1"
+ cidr_block = "0.0.0.0/0"
+ },
+ ]
+}
+
+variable "firewall_outbound_acl_rules" {
+ description = "Firewall subnets outbound network ACLs"
+ type = list(map(string))
+ default = [
+ {
+ rule_number = 100
+ rule_action = "allow"
+ from_port = 0
+ to_port = 0
+ protocol = "-1"
+ cidr_block = "0.0.0.0/0"
+ },
+ ]
+}
+
+variable "firewall_acl_tags" {
+ description = "Additional tags for the firewall subnets network ACL"
+ type = map(string)
+ default = {}
+}
+
################################################################################
# Internet Gateway
################################################################################