@@ -6,15 +6,26 @@ locals {
66 len_redshift_subnets = max (length (var. redshift_subnets ), length (var. redshift_subnet_ipv6_prefixes ))
77 len_intra_subnets = max (length (var. intra_subnets ), length (var. intra_subnet_ipv6_prefixes ))
88 len_outpost_subnets = max (length (var. outpost_subnets ), length (var. outpost_subnet_ipv6_prefixes ))
9+ len_firewall_subnets = max (length (var. firewall_subnets ), length (var. firewall_subnet_ipv6_prefixes ))
910
1011 max_subnet_length = max (
1112 local. len_private_subnets ,
1213 local. len_public_subnets ,
1314 local. len_elasticache_subnets ,
1415 local. len_database_subnets ,
1516 local. len_redshift_subnets ,
17+ local. len_firewall_subnets ,
1618 )
1719
20+ // TODO - comment what this line does
21+ firewall_sync_states = try (module. firewall [0 ]. status [0 ]. sync_states , {})
22+ firewall_vpce = {
23+ for state in local . firewall_sync_states : state . availability_zone => {
24+ cidr_block = one ([ for subnet in aws_subnet . firewall : subnet . cidr_block if subnet . id == state . attachment [0 ]. subnet_id ])
25+ endpoint_id = state.attachment[0 ].endpoint_id
26+ }
27+ }
28+
1829 # Use `local.vpc_id` to give a hint to Terraform that subnets should be deleted before secondary CIDR blocks can be free!
1930 vpc_id = try (aws_vpc_ipv4_cidr_block_association. this [0 ]. vpc_id , aws_vpc. this [0 ]. id , " " )
2031
@@ -153,7 +164,7 @@ resource "aws_route_table_association" "public" {
153164}
154165
155166resource "aws_route" "public_internet_gateway" {
156- count = local. create_public_subnets && var. create_igw ? local. num_public_route_tables : 0
167+ count = local. create_public_subnets && var. create_igw && ! (var . enable_network_firewall && local . len_firewall_subnets > 0 ) ? local. num_public_route_tables : 0
157168
158169 route_table_id = aws_route_table. public [count . index ]. id
159170 destination_cidr_block = " 0.0.0.0/0"
@@ -164,6 +175,32 @@ resource "aws_route" "public_internet_gateway" {
164175 }
165176}
166177
178+ resource "aws_route_table_association" "public_internet_gateway" {
179+ count = local. create_vpc && var. create_igw && var. enable_network_firewall && local. len_firewall_subnets > 0 ? 1 : 0
180+
181+ gateway_id = aws_internet_gateway. this [0 ]. id
182+ route_table_id = aws_route_table. internet_gateway [0 ]. id
183+ }
184+
185+ resource "aws_route_table_association" "firewall" {
186+ count = local. create_vpc && local. len_firewall_subnets > 0 ? local. len_firewall_subnets : 0
187+
188+ subnet_id = element (aws_subnet. firewall . * . id , count. index )
189+ route_table_id = aws_route_table. firewall [0 ]. id
190+ }
191+
192+ resource "aws_route" "public_firewall" {
193+ count = local. create_vpc && var. enable_network_firewall ? local. len_public_subnets : 0
194+
195+ route_table_id = element (aws_route_table. public . * . id , count. index )
196+ destination_cidr_block = " 0.0.0.0/0"
197+ vpc_endpoint_id = local. firewall_vpce [aws_subnet . public [count . index ]. availability_zone ]. endpoint_id
198+
199+ timeouts {
200+ create = " 5m"
201+ }
202+ }
203+
167204resource "aws_route" "public_internet_gateway_ipv6" {
168205 count = local. create_public_subnets && var. create_igw && var. enable_ipv6 ? local. num_public_route_tables : 0
169206
@@ -223,6 +260,145 @@ resource "aws_network_acl_rule" "public_outbound" {
223260 ipv6_cidr_block = lookup (var. public_outbound_acl_rules [count . index ], " ipv6_cidr_block" , null )
224261}
225262
263+ # ###############################################################################
264+ # Firewall Subnets
265+ # ###############################################################################
266+
267+ locals {
268+ create_firewall_subnets = local. create_vpc && local. len_firewall_subnets > 0
269+ }
270+
271+ resource "aws_subnet" "firewall" {
272+ count = local. create_firewall_subnets ? local. len_firewall_subnets : 0
273+
274+ vpc_id = local. vpc_id
275+ cidr_block = var. firewall_subnets [count . index ]
276+ availability_zone = length (regexall (" ^[a-z]{2}-" , element (var. azs , count. index ))) > 0 ? element (var. azs , count. index ) : null
277+ availability_zone_id = length (regexall (" ^[a-z]{2}-" , element (var. azs , count. index ))) == 0 ? element (var. azs , count. index ) : null
278+ assign_ipv6_address_on_creation = var. enable_ipv6 && var. firewall_subnet_ipv6_native ? true : var. firewall_subnet_assign_ipv6_address_on_creation
279+
280+ 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
281+
282+ tags = merge (
283+ {
284+ " Name" = format (
285+ " %s-${ var . firewall_subnet_suffix } -%s" ,
286+ var. name ,
287+ element (var. azs , count. index ),
288+ )
289+ },
290+ var. tags ,
291+ var. firewall_subnet_tags ,
292+ )
293+ }
294+
295+
296+ resource "aws_route_table" "firewall" {
297+ count = local. create_vpc && var. create_firewall_subnet_route_table && local. len_firewall_subnets > 0 ? 1 : 0
298+
299+ vpc_id = local. vpc_id
300+
301+ tags = merge (
302+ {
303+ " Name" = " ${ var . name } -${ var . firewall_subnet_suffix } "
304+ },
305+ var. tags ,
306+ var. firewall_route_table_tags ,
307+ )
308+ }
309+
310+ resource "aws_route" "firewall_internet_gateway" {
311+ count = local. create_vpc && var. create_igw && local. len_firewall_subnets > 0 ? 1 : 0
312+
313+ route_table_id = aws_route_table. firewall [count . index ]. id
314+ destination_cidr_block = " 0.0.0.0/0"
315+ gateway_id = aws_internet_gateway. this [0 ]. id
316+
317+ timeouts {
318+ create = " 5m"
319+ }
320+ }
321+
322+ resource "aws_route_table" "internet_gateway" {
323+ count = local. create_vpc && var. enable_network_firewall && local. len_firewall_subnets > 0 ? 1 : 0
324+ vpc_id = local. vpc_id
325+
326+ tags = merge (
327+ {
328+ " Name" = format (" %s-internet-gateway-${ var . firewall_subnet_suffix } " , var. name )
329+ },
330+ var. tags ,
331+ var. public_route_table_tags ,
332+ )
333+ }
334+
335+ resource "aws_route" "internet_gateway_firewall" {
336+ count = local. create_vpc && var. enable_network_firewall && local. len_firewall_subnets > 0 ? local. len_public_subnets : 0
337+
338+ route_table_id = aws_route_table. internet_gateway [0 ]. id
339+ destination_cidr_block = aws_subnet. public [count . index ]. cidr_block
340+
341+
342+ vpc_endpoint_id = local. firewall_vpce [aws_subnet . public [count . index ]. availability_zone ]. endpoint_id // TODO testing
343+ # vpc_endpoint_id = element(local.firewall_endpoint_ids_ordered_by_azs, count.index)
344+ }
345+
346+ # ###############################################################################
347+ # Firewall Network ACLs
348+ # ###############################################################################
349+
350+ locals {
351+ create_firewall_network_acl = local. create_firewall_subnets && var. firewall_dedicated_network_acl
352+ }
353+
354+ resource "aws_network_acl" "firewall" {
355+ count = local. create_firewall_network_acl ? 1 : 0
356+
357+ vpc_id = local. vpc_id
358+ subnet_ids = aws_subnet. firewall [* ]. id
359+
360+ tags = merge (
361+ { " Name" = " ${ var . name } -${ var . firewall_subnet_suffix } " },
362+ var. tags ,
363+ var. firewall_acl_tags ,
364+ )
365+ }
366+
367+ resource "aws_network_acl_rule" "firewall_inbound" {
368+ count = local. create_firewall_network_acl ? length (var. firewall_inbound_acl_rules ) : 0
369+
370+ network_acl_id = aws_network_acl. firewall [0 ]. id
371+
372+ egress = false
373+ rule_number = var. firewall_inbound_acl_rules [count . index ][" rule_number" ]
374+ rule_action = var. firewall_inbound_acl_rules [count . index ][" rule_action" ]
375+ from_port = lookup (var. firewall_inbound_acl_rules [count . index ], " from_port" , null )
376+ to_port = lookup (var. firewall_inbound_acl_rules [count . index ], " to_port" , null )
377+ icmp_code = lookup (var. firewall_inbound_acl_rules [count . index ], " icmp_code" , null )
378+ icmp_type = lookup (var. firewall_inbound_acl_rules [count . index ], " icmp_type" , null )
379+ protocol = var. firewall_inbound_acl_rules [count . index ][" protocol" ]
380+ cidr_block = lookup (var. firewall_inbound_acl_rules [count . index ], " cidr_block" , null )
381+ ipv6_cidr_block = lookup (var. firewall_inbound_acl_rules [count . index ], " ipv6_cidr_block" , null )
382+ }
383+
384+ resource "aws_network_acl_rule" "firewall_outbound" {
385+ count = local. create_firewall_network_acl ? length (var. firewall_outbound_acl_rules ) : 0
386+
387+ network_acl_id = aws_network_acl. firewall [0 ]. id
388+
389+ egress = true
390+ rule_number = var. firewall_outbound_acl_rules [count . index ][" rule_number" ]
391+ rule_action = var. firewall_outbound_acl_rules [count . index ][" rule_action" ]
392+ from_port = lookup (var. firewall_outbound_acl_rules [count . index ], " from_port" , null )
393+ to_port = lookup (var. firewall_outbound_acl_rules [count . index ], " to_port" , null )
394+ icmp_code = lookup (var. firewall_outbound_acl_rules [count . index ], " icmp_code" , null )
395+ icmp_type = lookup (var. firewall_outbound_acl_rules [count . index ], " icmp_type" , null )
396+ protocol = var. firewall_outbound_acl_rules [count . index ][" protocol" ]
397+ cidr_block = lookup (var. firewall_outbound_acl_rules [count . index ], " cidr_block" , null )
398+ ipv6_cidr_block = lookup (var. firewall_outbound_acl_rules [count . index ], " ipv6_cidr_block" , null )
399+ }
400+
401+
226402# ###############################################################################
227403# Private Subnets
228404# ###############################################################################
0 commit comments