Deploy AWS Network Firewall on Multi-VPC environment with open source tools (P3)
Tung Nguyen Xuan
Posted on October 29, 2022
Architecture
- Reference : https://aws.amazon.com/vi/blogs/networking-and-content-delivery/deployment-models-for-aws-network-firewall/
Deploy Multi-VPC
Reference : https://github.com/tnx-journey-to-cloud/terraform-aws-vpc
We create a VPC module with Terraform to reuse and call it whenever we deploy a VPC in Multi-VPC environment such as Spoke, Ingress, Egress, ...
main.tf
resource "aws_vpc" "vpc" {
cidr_block = var.vpc_cidr_block
enable_dns_support = var.enable_dns_support
enable_dns_hostnames = var.enable_dns_hostnames
instance_tenancy = var.instance_tenancy
tags = merge(
var.tags,
{
"Name" : "${var.prefix}-vpc-${var.vpc_name}"
}
)
}
resource "aws_subnet" "this" {
for_each = var.subnets
vpc_id = aws_vpc.vpc.id
cidr_block = each.value.cidr
availability_zone = each.value.az
map_public_ip_on_launch = true
tags = merge(
{
"Name" = "${var.prefix}-${each.key}-${each.value.az}"
},
var.tags,
each.value.subnet_tags
)
lifecycle {
create_before_destroy = true
}
}
resource "aws_vpc_endpoint" "s3" {
vpc_id = aws_vpc.vpc.id
service_name = "com.amazonaws.${data.aws_region.current.name}.s3"
vpc_endpoint_type = "Gateway"
route_table_ids = [for k, v in aws_route_table.this : v.id]
tags = merge(
{
"Name" = "${var.prefix}-s3-gwendpoint-${data.aws_region.current.name}"
}
)
lifecycle {
create_before_destroy = true
}
}
resource "aws_vpc_endpoint" "dynamodb" {
vpc_id = aws_vpc.vpc.id
service_name = "com.amazonaws.${data.aws_region.current.name}.dynamodb"
vpc_endpoint_type = "Gateway"
route_table_ids = [for k, v in aws_route_table.this : v.id]
tags = merge(
{
"Name" = "${var.prefix}-s3-gwendpoint-${data.aws_region.current.name}"
}
)
lifecycle {
create_before_destroy = true
}
}
resource "aws_security_group" "endpoint" {
description = "Allow ECR inbound traffic"
vpc_id = aws_vpc.vpc.id
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = [aws_vpc.vpc.cidr_block]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = merge(
{
"Name" = "${var.prefix}-sg-vpce-${data.aws_region.current.name}"
}
)
}
resource "aws_vpc_endpoint" "endpoint" {
depends_on = [
aws_subnet.this
]
for_each = var.endpoints
vpc_id = aws_vpc.vpc.id
service_name = "com.amazonaws.${data.aws_region.current.name}.${each.key}"
vpc_endpoint_type = "Interface"
security_group_ids = [
aws_security_group.endpoint[0].id,
]
subnet_ids = [for k, v in aws_subnet.this : v.id]
private_dns_enabled = true
tags = merge(
{
"Name" = "${var.prefix}-${replace(each.key, ".", "-")}-int-endpoint-${data.aws_region.current.name}"
}
)
}
variables.tf
variable "prefix" {
description = "The description for each environment, ie: bin-dev"
type = string
}
variable "enable_dns_hostnames" {
description = "(Optional) A boolean flag to enable/disable DNS support in the VPC. Defaults true."
type = bool
default = true
}
variable "enable_dns_support" {
description = "(Optional) A boolean flag to enable/disable DNS hostnames in the VPC. Defaults false."
type = bool
default = true
}
variable "instance_tenancy" {
description = "(Optional) A tenancy option for instances launched into the VPC. Default is default, which ensures that EC2 instances launched in this VPC use the EC2 instance tenancy attribute specified when the EC2 instance is launched. The only other option is dedicated, which ensures that EC2 instances launched in this VPC are run on dedicated tenancy instances regardless of the tenancy attribute specified at launch. This has a dedicated per region fee of $2 per hour, plus an hourly per instance usage fee."
type = string
default = "default"
}
variable "tags" {
description = "The tags for the resources"
type = map(any)
default = {}
}
variable "vpc_name" {
description = "The VPC name"
type = string
}
variable "vpc_cidr_block" {
description = "The CIDR block for the VPC"
type = string
}
variable "subnets" {
description = "Public subnet setting, cidr and availability zone (az) name are required"
type = map(object({
cidr = string
az = string
route_table_name = string
subnet_tags = optional(map(any))
}))
variable "endpoints" {
type = set(string)
description = "Set of predefined Service names for creating VPC Interface Endpoints"
}
variable "igw_config" {
description = "Optional, if set this vpc will create internet gw and route to rtb_name"
type = map(any)
default = {
igw_enable = false
rtb_name = ""
}
}
variable "ngw_config" {
description = "Optional, if set this vpc will create nat gw and route to rtb_name"
type = map(any)
default = {
ngw_enable = false
subnet_name = "" # subnetname that ngw will attach
rtb_name = "" # route table that ngw will attach routes to
}
}
variable "route_table_setting" {
type = any
description = "(required) route table infomation"
}
outputs.tf
output "vpc_id" {
description = "The ID of the VPC"
value = try(aws_vpc.vpc.id, "")
}
output "vpc_arn" {
description = "The ARN of the VPC"
value = try(aws_vpc.vpc.arn, "")
}
output "vpc_owner_id" {
description = "The ID of the AWS account that owns the VPC"
value = try(aws_vpc.vpc.owner_id, "")
}
output "subnet_ids" {
description = "List of IDs of subnets"
value = { for k, v in aws_subnet.this : k => v.id }
}
output "subnet_arns" {
description = "List of ARNs of subnets"
value = { for k, v in aws_subnet.this : k => v.arn }
}
output "subnets_cidr_blocks" {
description = "List of cidr_blocks of subnets"
value = { for k, v in aws_subnet.this : k => v.cidr_block }
}
output "route_table_ids" {
description = "List of IDs of route tables"
value = { for k, v in aws_route_table.this : k => v.id }
}
output "route_table_association_ids" {
description = "List of IDs of the route table association"
value = {
for k, v in aws_route_table_association.this : k => v.id
}
}
routetables.tf
resource "aws_internet_gateway" "igw" {
count = try(var.igw_config["igw_enable"], false) ? 1 : 0
vpc_id = aws_vpc.vpc.id
tags = merge(
{
"Name" : "${var.prefix}-igw-${var.vpc_name}"
}
)
}
resource "aws_route" "public_internet_gateway" {
count = try(length(var.igw_config["rtb_name"]), 0) > 0 ? 1 : 0
route_table_id = aws_route_table.this[var.igw_config["rtb_name"]].id
destination_cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.igw[0].id
timeouts {
create = "5m"
}
depends_on = [
aws_internet_gateway.igw[0],
aws_route_table.this
]
}
resource "aws_route_table" "this" {
for_each = toset([for rtb in var.subnets : rtb["route_table_name"]])
vpc_id = aws_vpc.vpc.id
dynamic "route" {
for_each = try({ for k, v in var.route_table_setting[each.key] : k => v }, {})
content {
# One of the following destinations must be provided
cidr_block = route.value.cidr_block
ipv6_cidr_block = lookup(route.value, "ipv6_cidr_block", null)
# One of the following targets must be provided
egress_only_gateway_id = lookup(route.value, "egress_only_gateway_id", null)
gateway_id = lookup(route.value, "gateway_id", null)
instance_id = lookup(route.value, "instance_id", null)
nat_gateway_id = lookup(route.value, "nat_gateway_id", null)
network_interface_id = lookup(route.value, "network_interface_id", null)
transit_gateway_id = lookup(route.value, "transit_gateway_id", null)
vpc_endpoint_id = lookup(route.value, "vpc_endpoint_id", null)
vpc_peering_connection_id = lookup(route.value, "vpc_peering_connection_id", null)
}
}
timeouts {
create = "5m"
update = "5m"
}
tags = merge(
{
"Name" : replace("${var.prefix}-rtb-${var.vpc_name}-${each.value}", "_", "-")
}
)
}
resource "aws_route_table_association" "this" {
for_each = var.subnets
depends_on = [
aws_route_table.this
]
subnet_id = aws_subnet.this[each.key].id
route_table_id = aws_route_table.this[each.value.route_table_name].id
}
###############################################
## NAT GW
###############################################
resource "aws_eip" "nat_gw_eip" {
count = try(var.ngw_config["ngw_enable"], false) ? 1 : 0
tags = merge(
{
"Name" : "${var.prefix}-igw-${var.vpc_name}"
}
)
}
resource "aws_nat_gateway" "ngw" {
count = try(var.ngw_config["ngw_enable"], false) ? 1 : 0
allocation_id = aws_eip.nat_gw_eip[0].id
subnet_id = aws_subnet.this[var.ngw_config["subnet_name"]].id
depends_on = [aws_internet_gateway.igw[0]]
tags = merge(
{
"Name" : "${var.prefix}-igw-${var.vpc_name}"
}
)
}
resource "aws_route" "nat_gateway" {
count = try(length(var.ngw_config["rtb_name"]), 0) > 0 ? 1 : 0
route_table_id = aws_route_table.this[var.ngw_config["rtb_name"]].id
destination_cidr_block = "0.0.0.0/0"
nat_gateway_id = aws_nat_gateway.ngw[0].id
timeouts {
create = "5m"
}
depends_on = [
aws_nat_gateway.ngw[0],
aws_route_table.this
]
}
Deploy Transit Gateway
- Reference : https://github.com/hungran/terraform-aws-tgw
main.tf
################################################################################
# Transit Gateway
################################################################################
resource "aws_ec2_transit_gateway" "tgw" {
description = coalesce(var.description, var.tgw_name)
amazon_side_asn = "64512"
default_route_table_association = "disable"
default_route_table_propagation = "disable"
auto_accept_shared_attachments = "enable"
multicast_support = var.enable_mutlicast_support ? "enable" : "disable"
vpn_ecmp_support = var.enable_vpn_ecmp_support ? "enable" : "disable"
dns_support = "enable"
transit_gateway_cidr_blocks = var.transit_gateway_cidr_blocks
timeouts {
create = try(var.timeouts.create, null)
update = try(var.timeouts.update, null)
delete = try(var.timeouts.delete, null)
}
tags = merge(
var.tags,
{
"Name" : "${var.prefix}-tgw-${var.tgw_name}"
}
)
}
################################################################################
# Route Table / Routes
################################################################################
resource "aws_ec2_transit_gateway_route_table" "spoke" {
transit_gateway_id = aws_ec2_transit_gateway.tgw.id
tags = merge(
var.tags,
{
"Name" : "${var.prefix}-tgw-${var.tgw_name}-rtb-spoke"
}
)
}
resource "aws_ec2_transit_gateway_route_table" "firewall" {
transit_gateway_id = aws_ec2_transit_gateway.tgw.id
tags = merge(
var.tags,
{
"Name" : "${var.prefix}-tgw-${var.tgw_name}-rtb-firewall"
}
)
}
resource "aws_ec2_transit_gateway_vpc_attachment" "vpc_attachments" {
for_each = var.vpc_attachments
transit_gateway_id = aws_ec2_transit_gateway.tgw.id
vpc_id = each.value.vpc_id
subnet_ids = each.value.subnet_ids
dns_support = "enable"
ipv6_support = "disable"
appliance_mode_support = "enable"
transit_gateway_default_route_table_association = false
transit_gateway_default_route_table_propagation = false
tags = merge(
var.tags,
{
"Name" : "${var.prefix}-tgw-${var.tgw_name}-vpc-attachment-${each.key}"
}
)
}
resource "aws_ec2_transit_gateway_route_table_association" "vpc_associate_spoke_rtb" {
depends_on = [
aws_ec2_transit_gateway_vpc_attachment.vpc_attachments
]
for_each = aws_ec2_transit_gateway_vpc_attachment.vpc_attachments
transit_gateway_attachment_id = each.value.id
transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.spoke.id
}
resource "aws_ec2_transit_gateway_route_table_propagation" "vpc_propagate_firewall_rbt" {
depends_on = [
aws_ec2_transit_gateway_vpc_attachment.vpc_attachments
]
for_each = aws_ec2_transit_gateway_vpc_attachment.vpc_attachments
transit_gateway_attachment_id = each.value.id
transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.firewall.id
}
# resource "aws_ec2_transit_gateway_route" "vpn_routes" {
# depends_on = [
# aws_ec2_transit_gateway_route_table.vpn
# ]
# for_each = var.vpn_routes
# transit_gateway_attachment_id = var.transit_gateway_attachment_vpn_id
# transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.vpn.id
# destination_cidr_block = each.value.vpn_routes
# }
resource "aws_ec2_transit_gateway_vpc_attachment" "inspection" {
for_each = var.vpc_inspection_attachments
transit_gateway_id = aws_ec2_transit_gateway.tgw.id
vpc_id = each.value.vpc_id
subnet_ids = each.value.subnet_ids
dns_support = "enable"
ipv6_support = "disable"
appliance_mode_support = "enable"
transit_gateway_default_route_table_association = false
transit_gateway_default_route_table_propagation = false
tags = merge(
var.tags,
{
"Name" : "${var.prefix}-tgw-${var.tgw_name}-inspection-vpc-attachment-${each.key}"
}
)
}
resource "aws_ec2_transit_gateway_route_table_association" "vpc_inspection_associate_rtb" {
depends_on = [
aws_ec2_transit_gateway_vpc_attachment.inspection
]
for_each = aws_ec2_transit_gateway_vpc_attachment.inspection
transit_gateway_attachment_id = each.value.id
transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.firewall.id
}
resource "aws_ec2_transit_gateway_route" "inspection" {
depends_on = [
aws_ec2_transit_gateway_vpc_attachment.inspection
]
for_each = aws_ec2_transit_gateway_vpc_attachment.inspection
destination_cidr_block = "0.0.0.0/0"
transit_gateway_attachment_id = each.value.id
transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.spoke.id
}
variables.tf
variable "amazon_side_asn" {
description = "The Autonomous System Number (ASN) for the AWS side of a Border Gateway Protocol (BGP) session. You can use the default ASN, or you can specify a private ASN in the 64512-65534 or 4200000000-4294967294 ranges."
type = number
default = 64512
}
variable "description" {
description = "Set the description of your transit gateway to help you identify it in the future."
type = string
default = ""
}
variable "enable_mutlicast_support" {
description = "Enables the ability to create multicast domains in this transit gateway."
type = bool
default = false
}
variable "enable_vpn_ecmp_support" {
description = "Equal cost multipath (ECMP) routing for VPN Connections that are attached to this transit gateway."
type = bool
default = true
}
variable "prefix" {
description = "The descriptio for each environment, ie: bin-dev"
type = string
}
variable "tags" {
description = "The tags for the resources"
type = map(any)
default = {}
}
variable "tgw_name" {
description = "TGW Name"
type = string
}
variable "transit_gateway_cidr_blocks" {
description = "One or more IPv4 or IPv6 CIDR blocks for the transit gateway. Must be a size /24 CIDR block or larger for IPv4, or a size /64 CIDR block or larger for IPv6"
type = list(string)
default = []
}
variable "timeouts" {
description = "Create, update, and delete timeout configurations for the transit gateway"
type = map(string)
default = {}
}
variable "vpc_attachments" {
description = "vpc and subnet ids for attachment transit gateway"
type = map(object({
vpc_id = string
subnet_ids = list(string)
}))
}
variable "vpc_inspection_attachments" {
description = "vpc and subnet ids for attachment transit gateway"
type = map(object({
vpc_id = string
subnet_ids = list(string)
}))
}
outputs.tf
output "tgw_spoke_route_table_ids" {
value = aws_ec2_transit_gateway_route_table.spoke.id
}
output "tgw_firewall_route_table_ids" {
value = aws_ec2_transit_gateway_route_table.firewall.id
}
output "tgw_id" {
value = aws_ec2_transit_gateway.tgw.id
}
output "tgw_vpc_attachment_ids" {
value = { for k, v in aws_ec2_transit_gateway_vpc_attachment.vpc_attachments : k => v.id }
}
output "tgw_vpc_inspection_attachment_ids" {
value = { for k, v in aws_ec2_transit_gateway_vpc_attachment.inspection : k => v.id }
}
Deploy AWS Network Firewall
main.tf
resource "aws_networkfirewall_firewall" "this" {
name = "${var.prefix}-nfw-${var.nfw_name}"
description = coalesce(var.description, var.nfw_name)
firewall_policy_arn = aws_networkfirewall_firewall_policy.this.arn
vpc_id = var.vpc_id
firewall_policy_change_protection = var.firewall_policy_change_protection
subnet_change_protection = var.subnet_change_protection
dynamic "subnet_mapping" {
for_each = toset(var.subnet_mapping)
content {
subnet_id = subnet_mapping.value
}
}
tags = var.tags
}
################# new suricata rule group #################
resource "aws_networkfirewall_rule_group" "suricata_stateful_group" {
count = length(var.suricata_stateful_rule_group) > 0 ? length(var.suricata_stateful_rule_group) : 0
type = "STATEFUL"
name = var.suricata_stateful_rule_group[count.index]["name"]
description = var.suricata_stateful_rule_group[count.index]["description"]
capacity = var.suricata_stateful_rule_group[count.index]["capacity"]
rule_group {
rules_source {
rules_string = try(file(var.suricata_stateful_rule_group[count.index]["rules_file"]), "")
}
dynamic "rule_variables" {
for_each = lookup(var.suricata_stateful_rule_group[count.index],"rule_variables",{})
content {
dynamic "ip_sets" {
for_each = rule_variables.key == "ip_sets" ? rule_variables.value : []
content {
key = ip_sets.value["key"]
ip_set {
definition = ip_sets.value["ip_set"]
}
}
}
dynamic "port_sets" {
for_each = rule_variables.key == "port_sets" ? rule_variables.value : []
content {
key = port_sets.value["key"]
port_set {
definition = port_sets.value["port_sets"]
}
}
}
}
}
}
tags = merge(var.tags)
}
#####################################################################################
resource "aws_networkfirewall_rule_group" "domain_stateful_group" {
count = length(var.domain_stateful_rule_group) > 0 ? length(var.domain_stateful_rule_group) : 0
type = "STATEFUL"
name = var.domain_stateful_rule_group[count.index]["name"]
description = var.domain_stateful_rule_group[count.index]["description"]
capacity = var.domain_stateful_rule_group[count.index]["capacity"]
rule_group {
dynamic "rule_variables" {
for_each = lookup(var.domain_stateful_rule_group[count.index],"rule_variables",[])
content {
ip_sets {
key = rule_variables.value["key"]
ip_set {
definition = rule_variables.value["ip_set"]
}
}
}
}
rules_source {
rules_source_list {
generated_rules_type = var.domain_stateful_rule_group[count.index]["actions"]
target_types = var.domain_stateful_rule_group[count.index]["protocols"]
targets = var.domain_stateful_rule_group[count.index]["domain_list"]
}
}
}
tags = merge(var.tags)
}
resource "aws_networkfirewall_rule_group" "fivetuple_stateful_group" {
count = length(var.fivetuple_stateful_rule_group) > 0 ? length(var.fivetuple_stateful_rule_group) : 0
type = "STATEFUL"
name = var.fivetuple_stateful_rule_group[count.index]["name"]
description = var.fivetuple_stateful_rule_group[count.index]["description"]
capacity = var.fivetuple_stateful_rule_group[count.index]["capacity"]
rule_group {
rules_source {
dynamic "stateful_rule" {
for_each = var.fivetuple_stateful_rule_group[count.index].rule_config
content {
action = upper(stateful_rule.value.actions["type"])
header {
destination = stateful_rule.value.destination_ipaddress
destination_port = stateful_rule.value.destination_port
direction = upper(stateful_rule.value.direction)
protocol = upper(stateful_rule.value.protocol)
source = stateful_rule.value.source_ipaddress
source_port = stateful_rule.value.source_port
}
rule_option {
keyword = "sid"
settings = ["${stateful_rule.value.sid}; msg:\"${try(stateful_rule.value.description,"")}\""]
}
}
}
}
}
tags = merge(var.tags)
}
resource "aws_networkfirewall_rule_group" "stateless_group" {
count = length(var.stateless_rule_group) > 0 ? length(var.stateless_rule_group) : 0
type = "STATELESS"
name = var.stateless_rule_group[count.index]["name"]
description = var.stateless_rule_group[count.index]["description"]
capacity = var.stateless_rule_group[count.index]["capacity"]
rule_group {
rules_source {
stateless_rules_and_custom_actions {
dynamic "stateless_rule" {
for_each = var.stateless_rule_group[count.index].rule_config
content {
priority = stateless_rule.value.priority
rule_definition {
actions = ["aws:${stateless_rule.value.actions["type"]}"]
match_attributes {
source {
address_definition = stateless_rule.value.source_ipaddress
}
# If protocol is TCP : 6 or UDP :17 get source ports from variables and set in source_port block
dynamic "source_port" {
for_each = contains(stateless_rule.value.protocols_number, 6) || contains(stateless_rule.value.protocols_number, 17) ? try(toset([{
from = stateless_rule.value.source_from_port,
to = stateless_rule.value.source_to_port
}]), [] ) : []
content {
from_port = source_port.value.from
to_port = source_port.value.to
}
}
destination {
address_definition = stateless_rule.value.destination_ipaddress
}
# If protocol is TCP : 6 or UDP :17 get destination ports from variables and set in destination_port block
dynamic "destination_port" {
for_each = contains(stateless_rule.value.protocols_number, 6) || contains(stateless_rule.value.protocols_number, 17) ? try(toset([{
from = stateless_rule.value.destination_from_port,
to = stateless_rule.value.destination_to_port
}]), [] ) : []
content {
from_port = destination_port.value.from
to_port = destination_port.value.to
}
}
protocols = stateless_rule.value.protocols_number
tcp_flag {
flags = stateless_rule.value.tcp_flag["flags"]
masks = stateless_rule.value.tcp_flag["masks"]
}
}
}
}
}
}
}
}
tags = merge(var.tags)
}
resource "aws_networkfirewall_firewall_policy" "this" {
name = "${var.prefix}-nfw-policy-${var.nfw_name}"
firewall_policy {
stateless_default_actions = ["aws:${var.stateless_default_actions}"]
stateless_fragment_default_actions = ["aws:${var.stateless_fragment_default_actions}"]
#Stateless Rule Group Reference
dynamic "stateless_rule_group_reference" {
for_each = local.this_stateless_group_arn
content {
# Priority is sequentially as per index in stateless_rule_group list
priority = index(local.this_stateless_group_arn, stateless_rule_group_reference.value) + 1
resource_arn = stateless_rule_group_reference.value
}
}
#StateFul Rule Group Reference
dynamic "stateful_rule_group_reference" {
for_each = local.this_stateful_group_arn
content {
resource_arn = stateful_rule_group_reference.value
}
}
}
tags = merge(var.tags)
}
###################### Logging Config ######################
resource "aws_cloudwatch_log_group" "nfw" {
for_each = try(var.logging_config, {})
name = "/aws/network-firewall/${each.key}"
tags = merge(var.tags)
retention_in_days = each.value.retention_in_days
}
resource "aws_networkfirewall_logging_configuration" "this" {
count = try(length(var.logging_config),0) > 0 ? 1 : 0
firewall_arn = aws_networkfirewall_firewall.this.arn
logging_configuration {
dynamic "log_destination_config" {
for_each = var.logging_config
content {
log_destination = {
logGroup = aws_cloudwatch_log_group.nfw[log_destination_config.key].name
}
log_destination_type = "CloudWatchLogs"
log_type = upper(log_destination_config.key)
}
}
}
}
variables.tf
variable "prefix" {
description = "The descriptio for each environment, ie: bin-dev"
type = string
}
variable "tags" {
description = "The tags for the resources"
type = map(any)
default = {}
}
variable "description" {
default = ""
}
variable "fivetuple_stateful_rule_group" {
description = "Config for 5-tuple type stateful rule group"
type = list(any)
default = []
}
variable "domain_stateful_rule_group" {
description = "Config for domain type stateful rule group"
type = list(any)
default = []
}
variable "suricata_stateful_rule_group" {
description = "Config for Suricata type stateful rule group"
type = list(any)
default = []
}
variable "stateless_rule_group" {
description = "Config for stateless rule group"
type = list(any)
}
variable "nfw_name" {
description = "firewall name"
type = string
default = "example"
}
variable "subnet_mapping" {
description = "Subnet ids mapping to have individual firewall endpoint"
}
variable "vpc_id" {
description = "VPC ID"
type = string
}
variable "stateless_default_actions" {
description = "Default stateless Action"
type = string
default = "forward_to_sfe"
}
variable "stateless_fragment_default_actions" {
description = "Default Stateless action for fragmented packets"
type = string
default = "forward_to_sfe"
}
variable "firewall_policy_change_protection" {
type = string
description = "(optional) we set false because we apply gitops for this"
default = false
}
variable "subnet_change_protection" {
type = string
description = "(optional) we set false because we apply gitops for this"
default = false
}
variable "logging_config" {
type = map(any)
description = "(optional) Logging config for network firewall"
default = {}
}
outputs.tf
output "id" {
description = "Created Network Firewall ID from network_firewall module"
value = aws_networkfirewall_firewall.this.id
}
output "arn" {
description = "Created Network Firewall ARN from network_firewall module"
value = aws_networkfirewall_firewall.this.arn
}
output "endpoint_id" {
description = "Created Network Firewall endpoint id"
value = flatten(aws_networkfirewall_firewall.this.firewall_status[*].sync_states[*].*.attachment[*])[*].endpoint_id
}
Our Cloud Journey's members:
💖 💪 🙅 🚩
Tung Nguyen Xuan
Posted on October 29, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
devops Deploy AWS Network Firewall on Multi-VPC environment with open source tools (P3)
October 29, 2022