NOTE: For information regarding the 1.0 upgrade see our upgrade guide
AWS Network Firewall is a managed network security service that makes it easy to deploy threat prevention for Amazon VPCs. This module can be used to deploy an AWS Network Firewall resource in the desired VPC, automating all the routing and logging configuration when the resource is deployed.
The module only handles the creation of the infrastructure, leaving full freedom to the user when defining the firewall rules (which should be done outside the module). Same applies to IAM roles and KMS keys when you define the firewall logging - rememeber that it is a best practice to encryt at rest your firewall logs.
To create AWS Network Firewall in your VPC, you need to provide the following information:
network_firewall_name
= (Required|string) Name to provide the AWS Network Firewall resource.network_firewall_description
= (Required|string) A friendly description of the firewall resource.network_firewall_policy
= (Required|string) ARN of the firewall policy to apply in the AWS Network Firewall resource. Check the definition of AWS Network Firewall Policies and AWS Network Firewall Rule Groups to see how you can create firewall policies.network_firewall_delete_protection
= (Optional|bool) A boolean flag indicating whether it is possible to delete the firewall. Defaults tofalse
.network_firewall_policy_change_protection
= (Optional|bool) To indicate whether it is possible to change the associated firewall policy after creation. Defaults tofalse
.network_firewall_subnet_change_protection
= (Optional|bool) To indicate whether it is possible to change the associated subnet(s) after creation. Defaults tofalse
.network_firewall_encryption_key_arn
= (Optional|string) ARN of Customer managed KMS key for data encryption. By default, AWS managed key will be used.vpc_id
= (Required|string) ID of the VPC where the AWS Network Firewall resource should be placed.vpc_subnets
= (Required|map(string)) Map of subnet IDs to place the Network Firewall endpoints. The expected format of the map is the Availability Zone as key, and the ID of the subnet as value. Example (supposing us-east-1 as AWS Region):
vpc_subnets = {
us-east-1a = subnet-IDa
us-east-1b = subnet-IDb
us-east-1c = subnet-IDc
}
number_azs
= (Required|number) Number of Availability Zones to place the AWS Network Firewall endpoints.routing_configuration
= (Required|any) Configuration of the routing desired in the VPC. Depending the VPC type, the information to provide is different. The configuration types supported are:single_vpc
,intra_vpc_inspection
,centralized_inspection_without_egress
, andcentralized_inspection_with_egress
. Only one key (option) can be defined. More information about the differences between each of the VPC types (and examples) can be checked in the section below.tags
= (Optional|map(string)) List of tags to apply to the AWS Network Firewall resource.
Once the AWS Network Firewall resource is created, the routing to the firewall endpoints need to be created. However, depending the VPC and how we want to inspect the traffic, this routing configuration is going to be different. The module supports the routing configuration of 4 different types of VPCs, covering the most common Inspection Deployment models with with AWS Network Firewall.
The first use case is when the firewall endpoints are located in the VPC to inspect the traffic from/to workloads in that same VPC. When using this routing configuration, it is expected to place the firewall endpoints in subnets between the Internet gateway (IGW) and the public subnets (where you can place the Elastic Load Balancers and NAT gateways). The module expects in this configuration three variables:
igw_route_table
= (Required|string) VPC route table ID associated to an Internet gateway. In this route table it will be created routes pointing to the Network Firewall endpoints with destination the CIDR blocks provided in theprotected_subnet_cidr_blocks
variable.protected_subnet_route_tables
= (Required|map(string)) Map of the VPC subnet route tables where the resources to protect (using the Network Firewall resource) are located - expected format of the map is Availability Zone (key) --> VPC route table (value). In these route tables it will be created the default route table pointing to the Network Firewall endpoints - ensuring Availability Zone affinity.protected_subnet_cidr_blocks
= (Required|map(string)) Map of IPv4 CIDR blocks indicating the subnets where the resources to protect (using the Network Firewall resource) are located - expected format of the map is Availability Zone (key) --> IPv4 CIDR block (value).
An example of the definition of this routing configuration is the following one:
routing_configuration = {
single_vpc = {
igw_route_table = rtb-ID
protected_subnet_route_tables = {
us-east-1a = rtb-IDa
us-east-1b = rtb-IDb
us-east-1c = rtb-IDc
}
protected_subnet_cidr_blocks = {
us-east-1a = "10.0.0.0/24"
us-east-1b = "10.0.1.0/24"
us-east-1c = "10.0.2.0/24"
}
}
}
When placing firewall endpoints to inspect traffic between workloads inside the same VPC (between your EC2 instances and the database layer, for example) you can take advantage of the VPC routing enhacement - which allows you to include more specific routing than the local one. The module expects in this configuration two variables:
number_routes
= (Required|number) Number of configured items in theroutes
variable.routes
= (Required|list(map(any))) List of intra-VPC route configurations. Important to note that only one direction is configured per item in this list, so in most situations you will need two items per group of subnets to inspect. Each item expects a map of strings with two values:source_subnet_route_tables
= (Required|map(string)) VPC route table of the source subnet - expected format of the map is Availability Zone (key) --> VPC route table (value)destination_subnet_cidr_blocks
= (Required|map(string)). IPv4 CIDR blocks of the destination subnet - expected format of the map is Availability Zone (key) --> IPv4 CIDR block (value)
An example of the definition of this routing configuration is the following one.
routing_configuration = {
intra_vpc_inspection = {
number_routes = 2
routes = {
{
source_subnet_route_tables = {
us-east-1a = rtb-IDa
us-east-1b = rtb-IDb
us-east-1c = rtb-IDc
}
destination_subnet_cidr_blocks = {
us-east-1a = "10.0.0.0/24"
us-east-1b = "10.0.1.0/24"
us-east-1c = "10.0.2.0/24"
}
},
{
source_subnet_route_tables = {
us-east-1a = rtb-IDaa
us-east-1b = rtb-IDbb
us-east-1c = rtb-IDcc
}
destination_subnet_cidr_blocks = {
us-east-1a = "10.0.3.0/24"
us-east-1b = "10.0.4.0/24"
us-east-1c = "10.0.5.0/24"
}
}
}
}
}
The use case covers the creation of a centralized Inspection VPC in a hub-and-spoke architecture with AWS Transit Gateway and/or AWS Cloud WAN, with the idea of managing the traffic inspection at scale. When using the key centralized_inspection_without_egress
it is supposed that the Inspection VPC created is only used to place the Transit Gateway or Cloud WAN's core network ENIs and the firewall endpoints. In this configuration, you can configurate the following variables:
connectivity_subnet_route_tables
= (Optional|map(string)) Map of VPC subnet route tables where the Transit Gateway or Cloud WAN's core network ENIs are located. In these route tables a default route pointing to the Network Firewall endpoints is created - expected format of the map is Availability Zone (key) --> VPC route table (value)
An example of the definition of this routing configuration is the following one:
routing_configuration = {
centralized_inspection_without_egress = {
connectivity_subnet_route_tables = {
us-east-1a = rtb-IDa
us-east-1b = rtb-IDb
us-east-1c = rtb-IDc
}
}
}
The use case covers the creation of a centralized Inspection VPC in a hub-and-spoke architecture with AWS Transit Gateway or AWS Cloud WAN, with the idea of managing the traffic inspection at scale. When using the key centralized_inspection_with_egress
it is supposed that the Inspection VPC also has access to the Internet, to centralize inspection and egress traffic at the same time. In this configuration, you can configurate the following variables:
connectivity_subnet_route_tables
= (Optional|map(string)) Map of VPC subnet route tables where the Transit Gateway or Cloud WAN's core network ENIs are located. In these route tables a default route pointing to the Network Firewall endpoints is created - expected format of the map is Availability Zone (key) --> VPC route table (value)public_subnet_route_tables
= (Required|map(string)) Map of VPC public subnet route tables. In these route tables, routes are created pointing to the Network Firewall endpoints with destination the CIDR blocks defined in thenetwork_cidr_blocks
variable. The expected format of the map is Availability Zone (key) --> VPC route table (value)network_cidr_blocks
= (Required|list(string)) List of IPv4 CIDR blocks defining the AWS network.
An example of the definition of this routing configuration is the following one:
routing_configuration = {
centralized_inspection_with_egress = {
connectivity_subnet_route_tables = {
us-east-1a = rtb-IDa
us-east-1b = rtb-IDb
us-east-1c = rtb-IDc
}
public_subnet_route_tables = {
us-east-1a = rtb-IDaa
us-east-1b = rtb-IDbb
us-east-1c = rtb-IDcc
}
network_cidr_blocks = ["10.0.0.0/8", "192.168.0.0/24"]
}
}
You can enable AWS Network Firewall logging for the stateful engine. You can record the flow logs and/or alert logs, with only one destination per log type:
- Amazon S3 bucket.
- Amazon CloudWatch log group.
- Amazon Kinesis Data Firehose stream.
For more information about the logging in AWS Network Firewall, check the AWS Network Firewall documentation.
Regarding the format of the variable, you can define either flow_log
or alert_log
configurations; with only 1 destination in each one of them. As mentioned above, 3 different destinations can be configured:
s3_bucket
= (Optional|map(string)) Configuration of an S3 bucket as logging destination. Two attributes are expected:bucketName
= (Required|string) Name of the S3 bucket to deliver the logs.logPrefix
= (Optional|string) Path inside the S3 bucket.
cloudwatch_logs
= (Optional|map(string)) Configuration of a CloudWatch log group as logging destination. Only the attributelogGroupName
(Required|string) is expected.kinesis_firehose
= (Optional|map(string)) Configuration of a Kinesis Data Firehose stream as logging desintation. Only the attributedeliveryStreamName
(Required|string) is expected.
Example definition of each type:
logging_configuration = {
flow_log = {
s3_bucket = {
bucketName = "my-bucket"
logPrefix = "/logs"
}
}
}
logging_configuration = {
alert_log = {
cloudwatch_logs = {
logGroupName = "my-log-group"
}
}
}
logging_configuration = {
alert_log = {
kinesis_firehose = {
deliveryStreamName = "my-stream"
}
}
}
- Reference Architecture: Inspection Deployment models with with AWS Network Firewall
- Blog post: Deployment models for AWS Network Firewall
- Blog post: Deployment models for AWS Network Firewall with VPC routing enhancements
Name | Version |
---|---|
terraform | >= 1.3.0 |
aws | >= 3.73.0 |
Name | Version |
---|---|
aws | >= 3.73.0 |
Name | Source | Version |
---|---|---|
central_inspection_with_egress_routing | ./modules/central_inspection_with_egress_routing | n/a |
intra_vpc_routing | ./modules/intra_vpc_routing | n/a |
logging | ./modules/logging | n/a |
tags | aws-ia/label/aws | 0.0.5 |
Name | Type |
---|---|
aws_networkfirewall_firewall.anfw | resource |
aws_route.connectivity_to_firewall_endpoint | resource |
aws_route.connectivity_to_firewall_endpoint_without_egress | resource |
aws_route.igw_route_table_to_protected_subnets | resource |
aws_route.protected_route_table_to_internet | resource |
Name | Description | Type | Default | Required |
---|---|---|---|---|
network_firewall_description | A friendly description of the firewall resource. | string |
n/a | yes |
network_firewall_name | Name to give the AWS Network Firewall resource created. | string |
n/a | yes |
network_firewall_policy | ARN of the firewall policy to include in AWS Network Firewall. | string |
n/a | yes |
number_azs | Number of Availability Zones to place the Network Firewall endpoints. | number |
n/a | yes |
vpc_id | VPC ID to place the Network Firewall endpoints. | string |
n/a | yes |
vpc_subnets | Map of subnet IDs to place the Network Firewall endpoints. The expected format of the map is the Availability Zone as key, and the ID of the subnet as value. Example (supposing us-east-1 as AWS Region): vpc_subnets = { |
map(string) |
n/a | yes |
logging_configuration | Configuration of the logging desired for the Network Firewall. You can configure at most 2 destinations for your logs, 1 for FLOW logs and 1 for ALERT logs. More information about the format of the variable (and examples) can be found in the README. |
any |
{} |
no |
network_firewall_delete_protection | A boolean flag indicating whether it is possible to delete the firewall. Defaults to false . |
bool |
false |
no |
network_firewall_encryption_key_arn | Customer managed KMS Key ARN for encryption at rest. | string |
null |
no |
network_firewall_policy_change_protection | A boolean flag indicating whether it is possible to change the associated firewall policy. Defaults to false . |
bool |
false |
no |
network_firewall_subnet_change_protection | A boolean flag indicating whether it is possible to change the associated subnet(s). Defaults to false . |
bool |
false |
no |
routing_configuration | Configuration of the routing desired in the VPC. Depending the VPC type, the information to provide is different. The configuration types supported are: single_vpc , intra_vpc_inspection , centralized_inspection_without_egress , and centralized_inspection_with_egress . Only one key (option) can be definedMore information about the differences between each the routing configurations (and examples) can be checked in the README. |
any |
{} |
no |
tags | Tags to apply to the resources. | map(string) |
{} |
no |
Name | Description |
---|---|
aws_network_firewall | Full output of aws_networkfirewall_firewall resource. |