This is a mirror of the official AWS VPC module from github. (Prevents failed clones happening frequently when using github).
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1316 lines
51KB

  1. locals {
  2. max_subnet_length = max(
  3. length(var.private_subnets),
  4. length(var.elasticache_subnets),
  5. length(var.database_subnets),
  6. length(var.redshift_subnets),
  7. )
  8. nat_gateway_count = var.single_nat_gateway ? 1 : var.one_nat_gateway_per_az ? length(var.azs) : local.max_subnet_length
  9. # Use `local.vpc_id` to give a hint to Terraform that subnets should be deleted before secondary CIDR blocks can be free!
  10. vpc_id = element(
  11. concat(
  12. aws_vpc_ipv4_cidr_block_association.this.*.vpc_id,
  13. aws_vpc.this.*.id,
  14. [""],
  15. ),
  16. 0,
  17. )
  18. }
  19. ################################################################################
  20. # VPC
  21. ################################################################################
  22. resource "aws_vpc" "this" {
  23. count = var.create_vpc ? 1 : 0
  24. cidr_block = var.cidr
  25. instance_tenancy = var.instance_tenancy
  26. enable_dns_hostnames = var.enable_dns_hostnames
  27. enable_dns_support = var.enable_dns_support
  28. enable_classiclink = var.enable_classiclink
  29. enable_classiclink_dns_support = var.enable_classiclink_dns_support
  30. assign_generated_ipv6_cidr_block = var.enable_ipv6
  31. tags = merge(
  32. {
  33. "Name" = format("%s", var.name)
  34. },
  35. var.tags,
  36. var.vpc_tags,
  37. )
  38. }
  39. resource "aws_vpc_ipv4_cidr_block_association" "this" {
  40. count = var.create_vpc && length(var.secondary_cidr_blocks) > 0 ? length(var.secondary_cidr_blocks) : 0
  41. vpc_id = aws_vpc.this[0].id
  42. cidr_block = element(var.secondary_cidr_blocks, count.index)
  43. }
  44. resource "aws_default_security_group" "this" {
  45. count = var.create_vpc && var.manage_default_security_group ? 1 : 0
  46. vpc_id = aws_vpc.this[0].id
  47. dynamic "ingress" {
  48. for_each = var.default_security_group_ingress
  49. content {
  50. self = lookup(ingress.value, "self", null)
  51. cidr_blocks = compact(split(",", lookup(ingress.value, "cidr_blocks", "")))
  52. ipv6_cidr_blocks = compact(split(",", lookup(ingress.value, "ipv6_cidr_blocks", "")))
  53. prefix_list_ids = compact(split(",", lookup(ingress.value, "prefix_list_ids", "")))
  54. security_groups = compact(split(",", lookup(ingress.value, "security_groups", "")))
  55. description = lookup(ingress.value, "description", null)
  56. from_port = lookup(ingress.value, "from_port", 0)
  57. to_port = lookup(ingress.value, "to_port", 0)
  58. protocol = lookup(ingress.value, "protocol", "-1")
  59. }
  60. }
  61. dynamic "egress" {
  62. for_each = var.default_security_group_egress
  63. content {
  64. self = lookup(egress.value, "self", null)
  65. cidr_blocks = compact(split(",", lookup(egress.value, "cidr_blocks", "")))
  66. ipv6_cidr_blocks = compact(split(",", lookup(egress.value, "ipv6_cidr_blocks", "")))
  67. prefix_list_ids = compact(split(",", lookup(egress.value, "prefix_list_ids", "")))
  68. security_groups = compact(split(",", lookup(egress.value, "security_groups", "")))
  69. description = lookup(egress.value, "description", null)
  70. from_port = lookup(egress.value, "from_port", 0)
  71. to_port = lookup(egress.value, "to_port", 0)
  72. protocol = lookup(egress.value, "protocol", "-1")
  73. }
  74. }
  75. tags = merge(
  76. {
  77. "Name" = format("%s", var.default_security_group_name)
  78. },
  79. var.tags,
  80. var.default_security_group_tags,
  81. )
  82. }
  83. ################################################################################
  84. # DHCP Options Set
  85. ################################################################################
  86. resource "aws_vpc_dhcp_options" "this" {
  87. count = var.create_vpc && var.enable_dhcp_options ? 1 : 0
  88. domain_name = var.dhcp_options_domain_name
  89. domain_name_servers = var.dhcp_options_domain_name_servers
  90. ntp_servers = var.dhcp_options_ntp_servers
  91. netbios_name_servers = var.dhcp_options_netbios_name_servers
  92. netbios_node_type = var.dhcp_options_netbios_node_type
  93. tags = merge(
  94. {
  95. "Name" = format("%s", var.name)
  96. },
  97. var.tags,
  98. var.dhcp_options_tags,
  99. )
  100. }
  101. resource "aws_vpc_dhcp_options_association" "this" {
  102. count = var.create_vpc && var.enable_dhcp_options ? 1 : 0
  103. vpc_id = local.vpc_id
  104. dhcp_options_id = aws_vpc_dhcp_options.this[0].id
  105. }
  106. ################################################################################
  107. # Internet Gateway
  108. ################################################################################
  109. resource "aws_internet_gateway" "this" {
  110. count = var.create_vpc && var.create_igw && length(var.public_subnets) > 0 ? 1 : 0
  111. vpc_id = local.vpc_id
  112. tags = merge(
  113. {
  114. "Name" = format("%s", var.name)
  115. },
  116. var.tags,
  117. var.igw_tags,
  118. )
  119. }
  120. resource "aws_egress_only_internet_gateway" "this" {
  121. count = var.create_vpc && var.create_egress_only_igw && var.enable_ipv6 && local.max_subnet_length > 0 ? 1 : 0
  122. vpc_id = local.vpc_id
  123. tags = merge(
  124. {
  125. "Name" = format("%s", var.name)
  126. },
  127. var.tags,
  128. var.igw_tags,
  129. )
  130. }
  131. ################################################################################
  132. # Default route
  133. ################################################################################
  134. resource "aws_default_route_table" "default" {
  135. count = var.create_vpc && var.manage_default_route_table ? 1 : 0
  136. default_route_table_id = aws_vpc.this[0].default_route_table_id
  137. propagating_vgws = var.default_route_table_propagating_vgws
  138. dynamic "route" {
  139. for_each = var.default_route_table_routes
  140. content {
  141. # One of the following destinations must be provided
  142. cidr_block = route.value.cidr_block
  143. ipv6_cidr_block = lookup(route.value, "ipv6_cidr_block", null)
  144. # One of the following targets must be provided
  145. egress_only_gateway_id = lookup(route.value, "egress_only_gateway_id", null)
  146. gateway_id = lookup(route.value, "gateway_id", null)
  147. instance_id = lookup(route.value, "instance_id", null)
  148. nat_gateway_id = lookup(route.value, "nat_gateway_id", null)
  149. network_interface_id = lookup(route.value, "network_interface_id", null)
  150. transit_gateway_id = lookup(route.value, "transit_gateway_id", null)
  151. vpc_endpoint_id = lookup(route.value, "vpc_endpoint_id", null)
  152. vpc_peering_connection_id = lookup(route.value, "vpc_peering_connection_id", null)
  153. }
  154. }
  155. tags = merge(
  156. { "Name" = var.name },
  157. var.tags,
  158. var.default_route_table_tags,
  159. )
  160. }
  161. ################################################################################
  162. # Publiс routes
  163. ################################################################################
  164. resource "aws_route_table" "public" {
  165. count = var.create_vpc && length(var.public_subnets) > 0 ? 1 : 0
  166. vpc_id = local.vpc_id
  167. tags = merge(
  168. {
  169. "Name" = format("%s-${var.public_subnet_suffix}", var.name)
  170. },
  171. var.tags,
  172. var.public_route_table_tags,
  173. )
  174. }
  175. resource "aws_route" "public_internet_gateway" {
  176. count = var.create_vpc && var.create_igw && length(var.public_subnets) > 0 ? 1 : 0
  177. route_table_id = aws_route_table.public[0].id
  178. destination_cidr_block = "0.0.0.0/0"
  179. gateway_id = aws_internet_gateway.this[0].id
  180. timeouts {
  181. create = "5m"
  182. }
  183. }
  184. resource "aws_route" "public_internet_gateway_ipv6" {
  185. count = var.create_vpc && var.create_igw && var.enable_ipv6 && length(var.public_subnets) > 0 ? 1 : 0
  186. route_table_id = aws_route_table.public[0].id
  187. destination_ipv6_cidr_block = "::/0"
  188. gateway_id = aws_internet_gateway.this[0].id
  189. }
  190. ################################################################################
  191. # Private routes
  192. # There are as many routing tables as the number of NAT gateways
  193. ################################################################################
  194. resource "aws_route_table" "private" {
  195. count = var.create_vpc && local.max_subnet_length > 0 ? local.nat_gateway_count : 0
  196. vpc_id = local.vpc_id
  197. tags = merge(
  198. {
  199. "Name" = var.single_nat_gateway ? "${var.name}-${var.private_subnet_suffix}" : format(
  200. "%s-${var.private_subnet_suffix}-%s",
  201. var.name,
  202. element(var.azs, count.index),
  203. )
  204. },
  205. var.tags,
  206. var.private_route_table_tags,
  207. )
  208. }
  209. ################################################################################
  210. # Database routes
  211. ################################################################################
  212. resource "aws_route_table" "database" {
  213. count = var.create_vpc && var.create_database_subnet_route_table && length(var.database_subnets) > 0 ? var.single_nat_gateway || var.create_database_internet_gateway_route ? 1 : length(var.database_subnets) : 0
  214. vpc_id = local.vpc_id
  215. tags = merge(
  216. {
  217. "Name" = var.single_nat_gateway || var.create_database_internet_gateway_route ? "${var.name}-${var.database_subnet_suffix}" : format(
  218. "%s-${var.database_subnet_suffix}-%s",
  219. var.name,
  220. element(var.azs, count.index),
  221. )
  222. },
  223. var.tags,
  224. var.database_route_table_tags,
  225. )
  226. }
  227. resource "aws_route" "database_internet_gateway" {
  228. count = var.create_vpc && var.create_igw && var.create_database_subnet_route_table && length(var.database_subnets) > 0 && var.create_database_internet_gateway_route && false == var.create_database_nat_gateway_route ? 1 : 0
  229. route_table_id = aws_route_table.database[0].id
  230. destination_cidr_block = "0.0.0.0/0"
  231. gateway_id = aws_internet_gateway.this[0].id
  232. timeouts {
  233. create = "5m"
  234. }
  235. }
  236. resource "aws_route" "database_nat_gateway" {
  237. count = var.create_vpc && var.create_database_subnet_route_table && length(var.database_subnets) > 0 && false == var.create_database_internet_gateway_route && var.create_database_nat_gateway_route && var.enable_nat_gateway ? var.single_nat_gateway ? 1 : length(var.database_subnets) : 0
  238. route_table_id = element(aws_route_table.database.*.id, count.index)
  239. destination_cidr_block = "0.0.0.0/0"
  240. nat_gateway_id = element(aws_nat_gateway.this.*.id, count.index)
  241. timeouts {
  242. create = "5m"
  243. }
  244. }
  245. resource "aws_route" "database_ipv6_egress" {
  246. count = var.create_vpc && var.create_egress_only_igw && var.enable_ipv6 && var.create_database_subnet_route_table && length(var.database_subnets) > 0 && var.create_database_internet_gateway_route ? 1 : 0
  247. route_table_id = aws_route_table.database[0].id
  248. destination_ipv6_cidr_block = "::/0"
  249. egress_only_gateway_id = aws_egress_only_internet_gateway.this[0].id
  250. timeouts {
  251. create = "5m"
  252. }
  253. }
  254. ################################################################################
  255. # Redshift routes
  256. ################################################################################
  257. resource "aws_route_table" "redshift" {
  258. count = var.create_vpc && var.create_redshift_subnet_route_table && length(var.redshift_subnets) > 0 ? 1 : 0
  259. vpc_id = local.vpc_id
  260. tags = merge(
  261. {
  262. "Name" = "${var.name}-${var.redshift_subnet_suffix}"
  263. },
  264. var.tags,
  265. var.redshift_route_table_tags,
  266. )
  267. }
  268. ################################################################################
  269. # Elasticache routes
  270. ################################################################################
  271. resource "aws_route_table" "elasticache" {
  272. count = var.create_vpc && var.create_elasticache_subnet_route_table && length(var.elasticache_subnets) > 0 ? 1 : 0
  273. vpc_id = local.vpc_id
  274. tags = merge(
  275. {
  276. "Name" = "${var.name}-${var.elasticache_subnet_suffix}"
  277. },
  278. var.tags,
  279. var.elasticache_route_table_tags,
  280. )
  281. }
  282. ################################################################################
  283. # Intra routes
  284. ################################################################################
  285. resource "aws_route_table" "intra" {
  286. count = var.create_vpc && length(var.intra_subnets) > 0 ? 1 : 0
  287. vpc_id = local.vpc_id
  288. tags = merge(
  289. {
  290. "Name" = "${var.name}-${var.intra_subnet_suffix}"
  291. },
  292. var.tags,
  293. var.intra_route_table_tags,
  294. )
  295. }
  296. ################################################################################
  297. # Public subnet
  298. ################################################################################
  299. resource "aws_subnet" "public" {
  300. count = var.create_vpc && length(var.public_subnets) > 0 && (false == var.one_nat_gateway_per_az || length(var.public_subnets) >= length(var.azs)) ? length(var.public_subnets) : 0
  301. vpc_id = local.vpc_id
  302. cidr_block = element(concat(var.public_subnets, [""]), count.index)
  303. availability_zone = length(regexall("^[a-z]{2}-", element(var.azs, count.index))) > 0 ? element(var.azs, count.index) : null
  304. availability_zone_id = length(regexall("^[a-z]{2}-", element(var.azs, count.index))) == 0 ? element(var.azs, count.index) : null
  305. map_public_ip_on_launch = var.map_public_ip_on_launch
  306. assign_ipv6_address_on_creation = var.public_subnet_assign_ipv6_address_on_creation == null ? var.assign_ipv6_address_on_creation : var.public_subnet_assign_ipv6_address_on_creation
  307. ipv6_cidr_block = var.enable_ipv6 && length(var.public_subnet_ipv6_prefixes) > 0 ? cidrsubnet(aws_vpc.this[0].ipv6_cidr_block, 8, var.public_subnet_ipv6_prefixes[count.index]) : null
  308. tags = merge(
  309. {
  310. "Name" = format(
  311. "%s-${var.public_subnet_suffix}-%s",
  312. var.name,
  313. element(var.azs, count.index),
  314. )
  315. },
  316. var.tags,
  317. var.public_subnet_tags,
  318. )
  319. }
  320. ################################################################################
  321. # Private subnet
  322. ################################################################################
  323. resource "aws_subnet" "private" {
  324. count = var.create_vpc && length(var.private_subnets) > 0 ? length(var.private_subnets) : 0
  325. vpc_id = local.vpc_id
  326. cidr_block = var.private_subnets[count.index]
  327. availability_zone = length(regexall("^[a-z]{2}-", element(var.azs, count.index))) > 0 ? element(var.azs, count.index) : null
  328. availability_zone_id = length(regexall("^[a-z]{2}-", element(var.azs, count.index))) == 0 ? element(var.azs, count.index) : null
  329. assign_ipv6_address_on_creation = var.private_subnet_assign_ipv6_address_on_creation == null ? var.assign_ipv6_address_on_creation : var.private_subnet_assign_ipv6_address_on_creation
  330. ipv6_cidr_block = var.enable_ipv6 && length(var.private_subnet_ipv6_prefixes) > 0 ? cidrsubnet(aws_vpc.this[0].ipv6_cidr_block, 8, var.private_subnet_ipv6_prefixes[count.index]) : null
  331. tags = merge(
  332. {
  333. "Name" = format(
  334. "%s-${var.private_subnet_suffix}-%s",
  335. var.name,
  336. element(var.azs, count.index),
  337. )
  338. },
  339. var.tags,
  340. var.private_subnet_tags,
  341. )
  342. }
  343. ################################################################################
  344. # Outpost subnet
  345. ################################################################################
  346. resource "aws_subnet" "outpost" {
  347. count = var.create_vpc && length(var.outpost_subnets) > 0 ? length(var.outpost_subnets) : 0
  348. vpc_id = local.vpc_id
  349. cidr_block = var.outpost_subnets[count.index]
  350. availability_zone = var.outpost_az
  351. assign_ipv6_address_on_creation = var.outpost_subnet_assign_ipv6_address_on_creation == null ? var.assign_ipv6_address_on_creation : var.outpost_subnet_assign_ipv6_address_on_creation
  352. ipv6_cidr_block = var.enable_ipv6 && length(var.outpost_subnet_ipv6_prefixes) > 0 ? cidrsubnet(aws_vpc.this[0].ipv6_cidr_block, 8, var.outpost_subnet_ipv6_prefixes[count.index]) : null
  353. outpost_arn = var.outpost_arn
  354. tags = merge(
  355. {
  356. "Name" = format(
  357. "%s-${var.outpost_subnet_suffix}-%s",
  358. var.name,
  359. var.outpost_az,
  360. )
  361. },
  362. var.tags,
  363. var.outpost_subnet_tags,
  364. )
  365. }
  366. ################################################################################
  367. # Database subnet
  368. ################################################################################
  369. resource "aws_subnet" "database" {
  370. count = var.create_vpc && length(var.database_subnets) > 0 ? length(var.database_subnets) : 0
  371. vpc_id = local.vpc_id
  372. cidr_block = var.database_subnets[count.index]
  373. availability_zone = length(regexall("^[a-z]{2}-", element(var.azs, count.index))) > 0 ? element(var.azs, count.index) : null
  374. availability_zone_id = length(regexall("^[a-z]{2}-", element(var.azs, count.index))) == 0 ? element(var.azs, count.index) : null
  375. assign_ipv6_address_on_creation = var.database_subnet_assign_ipv6_address_on_creation == null ? var.assign_ipv6_address_on_creation : var.database_subnet_assign_ipv6_address_on_creation
  376. ipv6_cidr_block = var.enable_ipv6 && length(var.database_subnet_ipv6_prefixes) > 0 ? cidrsubnet(aws_vpc.this[0].ipv6_cidr_block, 8, var.database_subnet_ipv6_prefixes[count.index]) : null
  377. tags = merge(
  378. {
  379. "Name" = format(
  380. "%s-${var.database_subnet_suffix}-%s",
  381. var.name,
  382. element(var.azs, count.index),
  383. )
  384. },
  385. var.tags,
  386. var.database_subnet_tags,
  387. )
  388. }
  389. resource "aws_db_subnet_group" "database" {
  390. count = var.create_vpc && length(var.database_subnets) > 0 && var.create_database_subnet_group ? 1 : 0
  391. name = lower(var.name)
  392. description = "Database subnet group for ${var.name}"
  393. subnet_ids = aws_subnet.database.*.id
  394. tags = merge(
  395. {
  396. "Name" = format("%s", var.name)
  397. },
  398. var.tags,
  399. var.database_subnet_group_tags,
  400. )
  401. }
  402. ################################################################################
  403. # Redshift subnet
  404. ################################################################################
  405. resource "aws_subnet" "redshift" {
  406. count = var.create_vpc && length(var.redshift_subnets) > 0 ? length(var.redshift_subnets) : 0
  407. vpc_id = local.vpc_id
  408. cidr_block = var.redshift_subnets[count.index]
  409. availability_zone = length(regexall("^[a-z]{2}-", element(var.azs, count.index))) > 0 ? element(var.azs, count.index) : null
  410. availability_zone_id = length(regexall("^[a-z]{2}-", element(var.azs, count.index))) == 0 ? element(var.azs, count.index) : null
  411. assign_ipv6_address_on_creation = var.redshift_subnet_assign_ipv6_address_on_creation == null ? var.assign_ipv6_address_on_creation : var.redshift_subnet_assign_ipv6_address_on_creation
  412. ipv6_cidr_block = var.enable_ipv6 && length(var.redshift_subnet_ipv6_prefixes) > 0 ? cidrsubnet(aws_vpc.this[0].ipv6_cidr_block, 8, var.redshift_subnet_ipv6_prefixes[count.index]) : null
  413. tags = merge(
  414. {
  415. "Name" = format(
  416. "%s-${var.redshift_subnet_suffix}-%s",
  417. var.name,
  418. element(var.azs, count.index),
  419. )
  420. },
  421. var.tags,
  422. var.redshift_subnet_tags,
  423. )
  424. }
  425. resource "aws_redshift_subnet_group" "redshift" {
  426. count = var.create_vpc && length(var.redshift_subnets) > 0 && var.create_redshift_subnet_group ? 1 : 0
  427. name = lower(var.name)
  428. description = "Redshift subnet group for ${var.name}"
  429. subnet_ids = aws_subnet.redshift.*.id
  430. tags = merge(
  431. {
  432. "Name" = format("%s", var.name)
  433. },
  434. var.tags,
  435. var.redshift_subnet_group_tags,
  436. )
  437. }
  438. ################################################################################
  439. # ElastiCache subnet
  440. ################################################################################
  441. resource "aws_subnet" "elasticache" {
  442. count = var.create_vpc && length(var.elasticache_subnets) > 0 ? length(var.elasticache_subnets) : 0
  443. vpc_id = local.vpc_id
  444. cidr_block = var.elasticache_subnets[count.index]
  445. availability_zone = length(regexall("^[a-z]{2}-", element(var.azs, count.index))) > 0 ? element(var.azs, count.index) : null
  446. availability_zone_id = length(regexall("^[a-z]{2}-", element(var.azs, count.index))) == 0 ? element(var.azs, count.index) : null
  447. assign_ipv6_address_on_creation = var.elasticache_subnet_assign_ipv6_address_on_creation == null ? var.assign_ipv6_address_on_creation : var.elasticache_subnet_assign_ipv6_address_on_creation
  448. ipv6_cidr_block = var.enable_ipv6 && length(var.elasticache_subnet_ipv6_prefixes) > 0 ? cidrsubnet(aws_vpc.this[0].ipv6_cidr_block, 8, var.elasticache_subnet_ipv6_prefixes[count.index]) : null
  449. tags = merge(
  450. {
  451. "Name" = format(
  452. "%s-${var.elasticache_subnet_suffix}-%s",
  453. var.name,
  454. element(var.azs, count.index),
  455. )
  456. },
  457. var.tags,
  458. var.elasticache_subnet_tags,
  459. )
  460. }
  461. resource "aws_elasticache_subnet_group" "elasticache" {
  462. count = var.create_vpc && length(var.elasticache_subnets) > 0 && var.create_elasticache_subnet_group ? 1 : 0
  463. name = var.name
  464. description = "ElastiCache subnet group for ${var.name}"
  465. subnet_ids = aws_subnet.elasticache.*.id
  466. }
  467. ################################################################################
  468. # Intra subnets - private subnet without NAT gateway
  469. ################################################################################
  470. resource "aws_subnet" "intra" {
  471. count = var.create_vpc && length(var.intra_subnets) > 0 ? length(var.intra_subnets) : 0
  472. vpc_id = local.vpc_id
  473. cidr_block = var.intra_subnets[count.index]
  474. availability_zone = length(regexall("^[a-z]{2}-", element(var.azs, count.index))) > 0 ? element(var.azs, count.index) : null
  475. availability_zone_id = length(regexall("^[a-z]{2}-", element(var.azs, count.index))) == 0 ? element(var.azs, count.index) : null
  476. assign_ipv6_address_on_creation = var.intra_subnet_assign_ipv6_address_on_creation == null ? var.assign_ipv6_address_on_creation : var.intra_subnet_assign_ipv6_address_on_creation
  477. ipv6_cidr_block = var.enable_ipv6 && length(var.intra_subnet_ipv6_prefixes) > 0 ? cidrsubnet(aws_vpc.this[0].ipv6_cidr_block, 8, var.intra_subnet_ipv6_prefixes[count.index]) : null
  478. tags = merge(
  479. {
  480. "Name" = format(
  481. "%s-${var.intra_subnet_suffix}-%s",
  482. var.name,
  483. element(var.azs, count.index),
  484. )
  485. },
  486. var.tags,
  487. var.intra_subnet_tags,
  488. )
  489. }
  490. ################################################################################
  491. # Default Network ACLs
  492. ################################################################################
  493. resource "aws_default_network_acl" "this" {
  494. count = var.create_vpc && var.manage_default_network_acl ? 1 : 0
  495. default_network_acl_id = element(concat(aws_vpc.this.*.default_network_acl_id, [""]), 0)
  496. # The value of subnet_ids should be any subnet IDs that are not set as subnet_ids
  497. # for any of the non-default network ACLs
  498. subnet_ids = setsubtract(
  499. compact(flatten([
  500. aws_subnet.public.*.id,
  501. aws_subnet.private.*.id,
  502. aws_subnet.intra.*.id,
  503. aws_subnet.database.*.id,
  504. aws_subnet.redshift.*.id,
  505. aws_subnet.elasticache.*.id,
  506. aws_subnet.outpost.*.id,
  507. ])),
  508. compact(flatten([
  509. aws_network_acl.public.*.subnet_ids,
  510. aws_network_acl.private.*.subnet_ids,
  511. aws_network_acl.intra.*.subnet_ids,
  512. aws_network_acl.database.*.subnet_ids,
  513. aws_network_acl.redshift.*.subnet_ids,
  514. aws_network_acl.elasticache.*.subnet_ids,
  515. aws_network_acl.outpost.*.subnet_ids,
  516. ]))
  517. )
  518. dynamic "ingress" {
  519. for_each = var.default_network_acl_ingress
  520. content {
  521. action = ingress.value.action
  522. cidr_block = lookup(ingress.value, "cidr_block", null)
  523. from_port = ingress.value.from_port
  524. icmp_code = lookup(ingress.value, "icmp_code", null)
  525. icmp_type = lookup(ingress.value, "icmp_type", null)
  526. ipv6_cidr_block = lookup(ingress.value, "ipv6_cidr_block", null)
  527. protocol = ingress.value.protocol
  528. rule_no = ingress.value.rule_no
  529. to_port = ingress.value.to_port
  530. }
  531. }
  532. dynamic "egress" {
  533. for_each = var.default_network_acl_egress
  534. content {
  535. action = egress.value.action
  536. cidr_block = lookup(egress.value, "cidr_block", null)
  537. from_port = egress.value.from_port
  538. icmp_code = lookup(egress.value, "icmp_code", null)
  539. icmp_type = lookup(egress.value, "icmp_type", null)
  540. ipv6_cidr_block = lookup(egress.value, "ipv6_cidr_block", null)
  541. protocol = egress.value.protocol
  542. rule_no = egress.value.rule_no
  543. to_port = egress.value.to_port
  544. }
  545. }
  546. tags = merge(
  547. {
  548. "Name" = format("%s", var.default_network_acl_name)
  549. },
  550. var.tags,
  551. var.default_network_acl_tags,
  552. )
  553. }
  554. ################################################################################
  555. # Public Network ACLs
  556. ################################################################################
  557. resource "aws_network_acl" "public" {
  558. count = var.create_vpc && var.public_dedicated_network_acl && length(var.public_subnets) > 0 ? 1 : 0
  559. vpc_id = element(concat(aws_vpc.this.*.id, [""]), 0)
  560. subnet_ids = aws_subnet.public.*.id
  561. tags = merge(
  562. {
  563. "Name" = format("%s-${var.public_subnet_suffix}", var.name)
  564. },
  565. var.tags,
  566. var.public_acl_tags,
  567. )
  568. }
  569. resource "aws_network_acl_rule" "public_inbound" {
  570. count = var.create_vpc && var.public_dedicated_network_acl && length(var.public_subnets) > 0 ? length(var.public_inbound_acl_rules) : 0
  571. network_acl_id = aws_network_acl.public[0].id
  572. egress = false
  573. rule_number = var.public_inbound_acl_rules[count.index]["rule_number"]
  574. rule_action = var.public_inbound_acl_rules[count.index]["rule_action"]
  575. from_port = lookup(var.public_inbound_acl_rules[count.index], "from_port", null)
  576. to_port = lookup(var.public_inbound_acl_rules[count.index], "to_port", null)
  577. icmp_code = lookup(var.public_inbound_acl_rules[count.index], "icmp_code", null)
  578. icmp_type = lookup(var.public_inbound_acl_rules[count.index], "icmp_type", null)
  579. protocol = var.public_inbound_acl_rules[count.index]["protocol"]
  580. cidr_block = lookup(var.public_inbound_acl_rules[count.index], "cidr_block", null)
  581. ipv6_cidr_block = lookup(var.public_inbound_acl_rules[count.index], "ipv6_cidr_block", null)
  582. }
  583. resource "aws_network_acl_rule" "public_outbound" {
  584. count = var.create_vpc && var.public_dedicated_network_acl && length(var.public_subnets) > 0 ? length(var.public_outbound_acl_rules) : 0
  585. network_acl_id = aws_network_acl.public[0].id
  586. egress = true
  587. rule_number = var.public_outbound_acl_rules[count.index]["rule_number"]
  588. rule_action = var.public_outbound_acl_rules[count.index]["rule_action"]
  589. from_port = lookup(var.public_outbound_acl_rules[count.index], "from_port", null)
  590. to_port = lookup(var.public_outbound_acl_rules[count.index], "to_port", null)
  591. icmp_code = lookup(var.public_outbound_acl_rules[count.index], "icmp_code", null)
  592. icmp_type = lookup(var.public_outbound_acl_rules[count.index], "icmp_type", null)
  593. protocol = var.public_outbound_acl_rules[count.index]["protocol"]
  594. cidr_block = lookup(var.public_outbound_acl_rules[count.index], "cidr_block", null)
  595. ipv6_cidr_block = lookup(var.public_outbound_acl_rules[count.index], "ipv6_cidr_block", null)
  596. }
  597. ################################################################################
  598. # Private Network ACLs
  599. ################################################################################
  600. resource "aws_network_acl" "private" {
  601. count = var.create_vpc && var.private_dedicated_network_acl && length(var.private_subnets) > 0 ? 1 : 0
  602. vpc_id = element(concat(aws_vpc.this.*.id, [""]), 0)
  603. subnet_ids = aws_subnet.private.*.id
  604. tags = merge(
  605. {
  606. "Name" = format("%s-${var.private_subnet_suffix}", var.name)
  607. },
  608. var.tags,
  609. var.private_acl_tags,
  610. )
  611. }
  612. resource "aws_network_acl_rule" "private_inbound" {
  613. count = var.create_vpc && var.private_dedicated_network_acl && length(var.private_subnets) > 0 ? length(var.private_inbound_acl_rules) : 0
  614. network_acl_id = aws_network_acl.private[0].id
  615. egress = false
  616. rule_number = var.private_inbound_acl_rules[count.index]["rule_number"]
  617. rule_action = var.private_inbound_acl_rules[count.index]["rule_action"]
  618. from_port = lookup(var.private_inbound_acl_rules[count.index], "from_port", null)
  619. to_port = lookup(var.private_inbound_acl_rules[count.index], "to_port", null)
  620. icmp_code = lookup(var.private_inbound_acl_rules[count.index], "icmp_code", null)
  621. icmp_type = lookup(var.private_inbound_acl_rules[count.index], "icmp_type", null)
  622. protocol = var.private_inbound_acl_rules[count.index]["protocol"]
  623. cidr_block = lookup(var.private_inbound_acl_rules[count.index], "cidr_block", null)
  624. ipv6_cidr_block = lookup(var.private_inbound_acl_rules[count.index], "ipv6_cidr_block", null)
  625. }
  626. resource "aws_network_acl_rule" "private_outbound" {
  627. count = var.create_vpc && var.private_dedicated_network_acl && length(var.private_subnets) > 0 ? length(var.private_outbound_acl_rules) : 0
  628. network_acl_id = aws_network_acl.private[0].id
  629. egress = true
  630. rule_number = var.private_outbound_acl_rules[count.index]["rule_number"]
  631. rule_action = var.private_outbound_acl_rules[count.index]["rule_action"]
  632. from_port = lookup(var.private_outbound_acl_rules[count.index], "from_port", null)
  633. to_port = lookup(var.private_outbound_acl_rules[count.index], "to_port", null)
  634. icmp_code = lookup(var.private_outbound_acl_rules[count.index], "icmp_code", null)
  635. icmp_type = lookup(var.private_outbound_acl_rules[count.index], "icmp_type", null)
  636. protocol = var.private_outbound_acl_rules[count.index]["protocol"]
  637. cidr_block = lookup(var.private_outbound_acl_rules[count.index], "cidr_block", null)
  638. ipv6_cidr_block = lookup(var.private_outbound_acl_rules[count.index], "ipv6_cidr_block", null)
  639. }
  640. ################################################################################
  641. # Outpost Network ACLs
  642. ################################################################################
  643. resource "aws_network_acl" "outpost" {
  644. count = var.create_vpc && var.outpost_dedicated_network_acl && length(var.outpost_subnets) > 0 ? 1 : 0
  645. vpc_id = element(concat(aws_vpc.this.*.id, [""]), 0)
  646. subnet_ids = aws_subnet.outpost.*.id
  647. tags = merge(
  648. {
  649. "Name" = format("%s-${var.outpost_subnet_suffix}", var.name)
  650. },
  651. var.tags,
  652. var.outpost_acl_tags,
  653. )
  654. }
  655. resource "aws_network_acl_rule" "outpost_inbound" {
  656. count = var.create_vpc && var.outpost_dedicated_network_acl && length(var.outpost_subnets) > 0 ? length(var.outpost_inbound_acl_rules) : 0
  657. network_acl_id = aws_network_acl.outpost[0].id
  658. egress = false
  659. rule_number = var.outpost_inbound_acl_rules[count.index]["rule_number"]
  660. rule_action = var.outpost_inbound_acl_rules[count.index]["rule_action"]
  661. from_port = lookup(var.outpost_inbound_acl_rules[count.index], "from_port", null)
  662. to_port = lookup(var.outpost_inbound_acl_rules[count.index], "to_port", null)
  663. icmp_code = lookup(var.outpost_inbound_acl_rules[count.index], "icmp_code", null)
  664. icmp_type = lookup(var.outpost_inbound_acl_rules[count.index], "icmp_type", null)
  665. protocol = var.outpost_inbound_acl_rules[count.index]["protocol"]
  666. cidr_block = lookup(var.outpost_inbound_acl_rules[count.index], "cidr_block", null)
  667. ipv6_cidr_block = lookup(var.outpost_inbound_acl_rules[count.index], "ipv6_cidr_block", null)
  668. }
  669. resource "aws_network_acl_rule" "outpost_outbound" {
  670. count = var.create_vpc && var.outpost_dedicated_network_acl && length(var.outpost_subnets) > 0 ? length(var.outpost_outbound_acl_rules) : 0
  671. network_acl_id = aws_network_acl.outpost[0].id
  672. egress = true
  673. rule_number = var.outpost_outbound_acl_rules[count.index]["rule_number"]
  674. rule_action = var.outpost_outbound_acl_rules[count.index]["rule_action"]
  675. from_port = lookup(var.outpost_outbound_acl_rules[count.index], "from_port", null)
  676. to_port = lookup(var.outpost_outbound_acl_rules[count.index], "to_port", null)
  677. icmp_code = lookup(var.outpost_outbound_acl_rules[count.index], "icmp_code", null)
  678. icmp_type = lookup(var.outpost_outbound_acl_rules[count.index], "icmp_type", null)
  679. protocol = var.outpost_outbound_acl_rules[count.index]["protocol"]
  680. cidr_block = lookup(var.outpost_outbound_acl_rules[count.index], "cidr_block", null)
  681. ipv6_cidr_block = lookup(var.outpost_outbound_acl_rules[count.index], "ipv6_cidr_block", null)
  682. }
  683. ################################################################################
  684. # Intra Network ACLs
  685. ################################################################################
  686. resource "aws_network_acl" "intra" {
  687. count = var.create_vpc && var.intra_dedicated_network_acl && length(var.intra_subnets) > 0 ? 1 : 0
  688. vpc_id = element(concat(aws_vpc.this.*.id, [""]), 0)
  689. subnet_ids = aws_subnet.intra.*.id
  690. tags = merge(
  691. {
  692. "Name" = format("%s-${var.intra_subnet_suffix}", var.name)
  693. },
  694. var.tags,
  695. var.intra_acl_tags,
  696. )
  697. }
  698. resource "aws_network_acl_rule" "intra_inbound" {
  699. count = var.create_vpc && var.intra_dedicated_network_acl && length(var.intra_subnets) > 0 ? length(var.intra_inbound_acl_rules) : 0
  700. network_acl_id = aws_network_acl.intra[0].id
  701. egress = false
  702. rule_number = var.intra_inbound_acl_rules[count.index]["rule_number"]
  703. rule_action = var.intra_inbound_acl_rules[count.index]["rule_action"]
  704. from_port = lookup(var.intra_inbound_acl_rules[count.index], "from_port", null)
  705. to_port = lookup(var.intra_inbound_acl_rules[count.index], "to_port", null)
  706. icmp_code = lookup(var.intra_inbound_acl_rules[count.index], "icmp_code", null)
  707. icmp_type = lookup(var.intra_inbound_acl_rules[count.index], "icmp_type", null)
  708. protocol = var.intra_inbound_acl_rules[count.index]["protocol"]
  709. cidr_block = lookup(var.intra_inbound_acl_rules[count.index], "cidr_block", null)
  710. ipv6_cidr_block = lookup(var.intra_inbound_acl_rules[count.index], "ipv6_cidr_block", null)
  711. }
  712. resource "aws_network_acl_rule" "intra_outbound" {
  713. count = var.create_vpc && var.intra_dedicated_network_acl && length(var.intra_subnets) > 0 ? length(var.intra_outbound_acl_rules) : 0
  714. network_acl_id = aws_network_acl.intra[0].id
  715. egress = true
  716. rule_number = var.intra_outbound_acl_rules[count.index]["rule_number"]
  717. rule_action = var.intra_outbound_acl_rules[count.index]["rule_action"]
  718. from_port = lookup(var.intra_outbound_acl_rules[count.index], "from_port", null)
  719. to_port = lookup(var.intra_outbound_acl_rules[count.index], "to_port", null)
  720. icmp_code = lookup(var.intra_outbound_acl_rules[count.index], "icmp_code", null)
  721. icmp_type = lookup(var.intra_outbound_acl_rules[count.index], "icmp_type", null)
  722. protocol = var.intra_outbound_acl_rules[count.index]["protocol"]
  723. cidr_block = lookup(var.intra_outbound_acl_rules[count.index], "cidr_block", null)
  724. ipv6_cidr_block = lookup(var.intra_outbound_acl_rules[count.index], "ipv6_cidr_block", null)
  725. }
  726. ################################################################################
  727. # Database Network ACLs
  728. ################################################################################
  729. resource "aws_network_acl" "database" {
  730. count = var.create_vpc && var.database_dedicated_network_acl && length(var.database_subnets) > 0 ? 1 : 0
  731. vpc_id = element(concat(aws_vpc.this.*.id, [""]), 0)
  732. subnet_ids = aws_subnet.database.*.id
  733. tags = merge(
  734. {
  735. "Name" = format("%s-${var.database_subnet_suffix}", var.name)
  736. },
  737. var.tags,
  738. var.database_acl_tags,
  739. )
  740. }
  741. resource "aws_network_acl_rule" "database_inbound" {
  742. count = var.create_vpc && var.database_dedicated_network_acl && length(var.database_subnets) > 0 ? length(var.database_inbound_acl_rules) : 0
  743. network_acl_id = aws_network_acl.database[0].id
  744. egress = false
  745. rule_number = var.database_inbound_acl_rules[count.index]["rule_number"]
  746. rule_action = var.database_inbound_acl_rules[count.index]["rule_action"]
  747. from_port = lookup(var.database_inbound_acl_rules[count.index], "from_port", null)
  748. to_port = lookup(var.database_inbound_acl_rules[count.index], "to_port", null)
  749. icmp_code = lookup(var.database_inbound_acl_rules[count.index], "icmp_code", null)
  750. icmp_type = lookup(var.database_inbound_acl_rules[count.index], "icmp_type", null)
  751. protocol = var.database_inbound_acl_rules[count.index]["protocol"]
  752. cidr_block = lookup(var.database_inbound_acl_rules[count.index], "cidr_block", null)
  753. ipv6_cidr_block = lookup(var.database_inbound_acl_rules[count.index], "ipv6_cidr_block", null)
  754. }
  755. resource "aws_network_acl_rule" "database_outbound" {
  756. count = var.create_vpc && var.database_dedicated_network_acl && length(var.database_subnets) > 0 ? length(var.database_outbound_acl_rules) : 0
  757. network_acl_id = aws_network_acl.database[0].id
  758. egress = true
  759. rule_number = var.database_outbound_acl_rules[count.index]["rule_number"]
  760. rule_action = var.database_outbound_acl_rules[count.index]["rule_action"]
  761. from_port = lookup(var.database_outbound_acl_rules[count.index], "from_port", null)
  762. to_port = lookup(var.database_outbound_acl_rules[count.index], "to_port", null)
  763. icmp_code = lookup(var.database_outbound_acl_rules[count.index], "icmp_code", null)
  764. icmp_type = lookup(var.database_outbound_acl_rules[count.index], "icmp_type", null)
  765. protocol = var.database_outbound_acl_rules[count.index]["protocol"]
  766. cidr_block = lookup(var.database_outbound_acl_rules[count.index], "cidr_block", null)
  767. ipv6_cidr_block = lookup(var.database_outbound_acl_rules[count.index], "ipv6_cidr_block", null)
  768. }
  769. ################################################################################
  770. # Redshift Network ACLs
  771. ################################################################################
  772. resource "aws_network_acl" "redshift" {
  773. count = var.create_vpc && var.redshift_dedicated_network_acl && length(var.redshift_subnets) > 0 ? 1 : 0
  774. vpc_id = element(concat(aws_vpc.this.*.id, [""]), 0)
  775. subnet_ids = aws_subnet.redshift.*.id
  776. tags = merge(
  777. {
  778. "Name" = format("%s-${var.redshift_subnet_suffix}", var.name)
  779. },
  780. var.tags,
  781. var.redshift_acl_tags,
  782. )
  783. }
  784. resource "aws_network_acl_rule" "redshift_inbound" {
  785. count = var.create_vpc && var.redshift_dedicated_network_acl && length(var.redshift_subnets) > 0 ? length(var.redshift_inbound_acl_rules) : 0
  786. network_acl_id = aws_network_acl.redshift[0].id
  787. egress = false
  788. rule_number = var.redshift_inbound_acl_rules[count.index]["rule_number"]
  789. rule_action = var.redshift_inbound_acl_rules[count.index]["rule_action"]
  790. from_port = lookup(var.redshift_inbound_acl_rules[count.index], "from_port", null)
  791. to_port = lookup(var.redshift_inbound_acl_rules[count.index], "to_port", null)
  792. icmp_code = lookup(var.redshift_inbound_acl_rules[count.index], "icmp_code", null)
  793. icmp_type = lookup(var.redshift_inbound_acl_rules[count.index], "icmp_type", null)
  794. protocol = var.redshift_inbound_acl_rules[count.index]["protocol"]
  795. cidr_block = lookup(var.redshift_inbound_acl_rules[count.index], "cidr_block", null)
  796. ipv6_cidr_block = lookup(var.redshift_inbound_acl_rules[count.index], "ipv6_cidr_block", null)
  797. }
  798. resource "aws_network_acl_rule" "redshift_outbound" {
  799. count = var.create_vpc && var.redshift_dedicated_network_acl && length(var.redshift_subnets) > 0 ? length(var.redshift_outbound_acl_rules) : 0
  800. network_acl_id = aws_network_acl.redshift[0].id
  801. egress = true
  802. rule_number = var.redshift_outbound_acl_rules[count.index]["rule_number"]
  803. rule_action = var.redshift_outbound_acl_rules[count.index]["rule_action"]
  804. from_port = lookup(var.redshift_outbound_acl_rules[count.index], "from_port", null)
  805. to_port = lookup(var.redshift_outbound_acl_rules[count.index], "to_port", null)
  806. icmp_code = lookup(var.redshift_outbound_acl_rules[count.index], "icmp_code", null)
  807. icmp_type = lookup(var.redshift_outbound_acl_rules[count.index], "icmp_type", null)
  808. protocol = var.redshift_outbound_acl_rules[count.index]["protocol"]
  809. cidr_block = lookup(var.redshift_outbound_acl_rules[count.index], "cidr_block", null)
  810. ipv6_cidr_block = lookup(var.redshift_outbound_acl_rules[count.index], "ipv6_cidr_block", null)
  811. }
  812. ################################################################################
  813. # Elasticache Network ACLs
  814. ################################################################################
  815. resource "aws_network_acl" "elasticache" {
  816. count = var.create_vpc && var.elasticache_dedicated_network_acl && length(var.elasticache_subnets) > 0 ? 1 : 0
  817. vpc_id = element(concat(aws_vpc.this.*.id, [""]), 0)
  818. subnet_ids = aws_subnet.elasticache.*.id
  819. tags = merge(
  820. {
  821. "Name" = format("%s-${var.elasticache_subnet_suffix}", var.name)
  822. },
  823. var.tags,
  824. var.elasticache_acl_tags,
  825. )
  826. }
  827. resource "aws_network_acl_rule" "elasticache_inbound" {
  828. count = var.create_vpc && var.elasticache_dedicated_network_acl && length(var.elasticache_subnets) > 0 ? length(var.elasticache_inbound_acl_rules) : 0
  829. network_acl_id = aws_network_acl.elasticache[0].id
  830. egress = false
  831. rule_number = var.elasticache_inbound_acl_rules[count.index]["rule_number"]
  832. rule_action = var.elasticache_inbound_acl_rules[count.index]["rule_action"]
  833. from_port = lookup(var.elasticache_inbound_acl_rules[count.index], "from_port", null)
  834. to_port = lookup(var.elasticache_inbound_acl_rules[count.index], "to_port", null)
  835. icmp_code = lookup(var.elasticache_inbound_acl_rules[count.index], "icmp_code", null)
  836. icmp_type = lookup(var.elasticache_inbound_acl_rules[count.index], "icmp_type", null)
  837. protocol = var.elasticache_inbound_acl_rules[count.index]["protocol"]
  838. cidr_block = lookup(var.elasticache_inbound_acl_rules[count.index], "cidr_block", null)
  839. ipv6_cidr_block = lookup(var.elasticache_inbound_acl_rules[count.index], "ipv6_cidr_block", null)
  840. }
  841. resource "aws_network_acl_rule" "elasticache_outbound" {
  842. count = var.create_vpc && var.elasticache_dedicated_network_acl && length(var.elasticache_subnets) > 0 ? length(var.elasticache_outbound_acl_rules) : 0
  843. network_acl_id = aws_network_acl.elasticache[0].id
  844. egress = true
  845. rule_number = var.elasticache_outbound_acl_rules[count.index]["rule_number"]
  846. rule_action = var.elasticache_outbound_acl_rules[count.index]["rule_action"]
  847. from_port = lookup(var.elasticache_outbound_acl_rules[count.index], "from_port", null)
  848. to_port = lookup(var.elasticache_outbound_acl_rules[count.index], "to_port", null)
  849. icmp_code = lookup(var.elasticache_outbound_acl_rules[count.index], "icmp_code", null)
  850. icmp_type = lookup(var.elasticache_outbound_acl_rules[count.index], "icmp_type", null)
  851. protocol = var.elasticache_outbound_acl_rules[count.index]["protocol"]
  852. cidr_block = lookup(var.elasticache_outbound_acl_rules[count.index], "cidr_block", null)
  853. ipv6_cidr_block = lookup(var.elasticache_outbound_acl_rules[count.index], "ipv6_cidr_block", null)
  854. }
  855. ################################################################################
  856. # NAT Gateway
  857. ################################################################################
  858. # Workaround for interpolation not being able to "short-circuit" the evaluation of the conditional branch that doesn't end up being used
  859. # Source: https://github.com/hashicorp/terraform/issues/11566#issuecomment-289417805
  860. #
  861. # The logical expression would be
  862. #
  863. # nat_gateway_ips = var.reuse_nat_ips ? var.external_nat_ip_ids : aws_eip.nat.*.id
  864. #
  865. # but then when count of aws_eip.nat.*.id is zero, this would throw a resource not found error on aws_eip.nat.*.id.
  866. locals {
  867. nat_gateway_ips = split(
  868. ",",
  869. var.reuse_nat_ips ? join(",", var.external_nat_ip_ids) : join(",", aws_eip.nat.*.id),
  870. )
  871. }
  872. resource "aws_eip" "nat" {
  873. count = var.create_vpc && var.enable_nat_gateway && false == var.reuse_nat_ips ? local.nat_gateway_count : 0
  874. vpc = true
  875. tags = merge(
  876. {
  877. "Name" = format(
  878. "%s-%s",
  879. var.name,
  880. element(var.azs, var.single_nat_gateway ? 0 : count.index),
  881. )
  882. },
  883. var.tags,
  884. var.nat_eip_tags,
  885. )
  886. }
  887. resource "aws_nat_gateway" "this" {
  888. count = var.create_vpc && var.enable_nat_gateway ? local.nat_gateway_count : 0
  889. allocation_id = element(
  890. local.nat_gateway_ips,
  891. var.single_nat_gateway ? 0 : count.index,
  892. )
  893. subnet_id = element(
  894. aws_subnet.public.*.id,
  895. var.single_nat_gateway ? 0 : count.index,
  896. )
  897. tags = merge(
  898. {
  899. "Name" = format(
  900. "%s-%s",
  901. var.name,
  902. element(var.azs, var.single_nat_gateway ? 0 : count.index),
  903. )
  904. },
  905. var.tags,
  906. var.nat_gateway_tags,
  907. )
  908. depends_on = [aws_internet_gateway.this]
  909. }
  910. resource "aws_route" "private_nat_gateway" {
  911. count = var.create_vpc && var.enable_nat_gateway ? local.nat_gateway_count : 0
  912. route_table_id = element(aws_route_table.private.*.id, count.index)
  913. destination_cidr_block = "0.0.0.0/0"
  914. nat_gateway_id = element(aws_nat_gateway.this.*.id, count.index)
  915. timeouts {
  916. create = "5m"
  917. }
  918. }
  919. resource "aws_route" "private_ipv6_egress" {
  920. count = var.create_vpc && var.create_egress_only_igw && var.enable_ipv6 ? length(var.private_subnets) : 0
  921. route_table_id = element(aws_route_table.private.*.id, count.index)
  922. destination_ipv6_cidr_block = "::/0"
  923. egress_only_gateway_id = element(aws_egress_only_internet_gateway.this.*.id, 0)
  924. }
  925. ################################################################################
  926. # Route table association
  927. ################################################################################
  928. resource "aws_route_table_association" "private" {
  929. count = var.create_vpc && length(var.private_subnets) > 0 ? length(var.private_subnets) : 0
  930. subnet_id = element(aws_subnet.private.*.id, count.index)
  931. route_table_id = element(
  932. aws_route_table.private.*.id,
  933. var.single_nat_gateway ? 0 : count.index,
  934. )
  935. }
  936. resource "aws_route_table_association" "outpost" {
  937. count = var.create_vpc && length(var.outpost_subnets) > 0 ? length(var.outpost_subnets) : 0
  938. subnet_id = element(aws_subnet.outpost.*.id, count.index)
  939. route_table_id = element(
  940. aws_route_table.private.*.id,
  941. var.single_nat_gateway ? 0 : count.index,
  942. )
  943. }
  944. resource "aws_route_table_association" "database" {
  945. count = var.create_vpc && length(var.database_subnets) > 0 ? length(var.database_subnets) : 0
  946. subnet_id = element(aws_subnet.database.*.id, count.index)
  947. route_table_id = element(
  948. coalescelist(aws_route_table.database.*.id, aws_route_table.private.*.id),
  949. var.create_database_subnet_route_table ? var.single_nat_gateway || var.create_database_internet_gateway_route ? 0 : count.index : count.index,
  950. )
  951. }
  952. resource "aws_route_table_association" "redshift" {
  953. count = var.create_vpc && length(var.redshift_subnets) > 0 && false == var.enable_public_redshift ? length(var.redshift_subnets) : 0
  954. subnet_id = element(aws_subnet.redshift.*.id, count.index)
  955. route_table_id = element(
  956. coalescelist(aws_route_table.redshift.*.id, aws_route_table.private.*.id),
  957. var.single_nat_gateway || var.create_redshift_subnet_route_table ? 0 : count.index,
  958. )
  959. }
  960. resource "aws_route_table_association" "redshift_public" {
  961. count = var.create_vpc && length(var.redshift_subnets) > 0 && var.enable_public_redshift ? length(var.redshift_subnets) : 0
  962. subnet_id = element(aws_subnet.redshift.*.id, count.index)
  963. route_table_id = element(
  964. coalescelist(aws_route_table.redshift.*.id, aws_route_table.public.*.id),
  965. var.single_nat_gateway || var.create_redshift_subnet_route_table ? 0 : count.index,
  966. )
  967. }
  968. resource "aws_route_table_association" "elasticache" {
  969. count = var.create_vpc && length(var.elasticache_subnets) > 0 ? length(var.elasticache_subnets) : 0
  970. subnet_id = element(aws_subnet.elasticache.*.id, count.index)
  971. route_table_id = element(
  972. coalescelist(
  973. aws_route_table.elasticache.*.id,
  974. aws_route_table.private.*.id,
  975. ),
  976. var.single_nat_gateway || var.create_elasticache_subnet_route_table ? 0 : count.index,
  977. )
  978. }
  979. resource "aws_route_table_association" "intra" {
  980. count = var.create_vpc && length(var.intra_subnets) > 0 ? length(var.intra_subnets) : 0
  981. subnet_id = element(aws_subnet.intra.*.id, count.index)
  982. route_table_id = element(aws_route_table.intra.*.id, 0)
  983. }
  984. resource "aws_route_table_association" "public" {
  985. count = var.create_vpc && length(var.public_subnets) > 0 ? length(var.public_subnets) : 0
  986. subnet_id = element(aws_subnet.public.*.id, count.index)
  987. route_table_id = aws_route_table.public[0].id
  988. }
  989. ################################################################################
  990. # Customer Gateways
  991. ################################################################################
  992. resource "aws_customer_gateway" "this" {
  993. for_each = var.customer_gateways
  994. bgp_asn = each.value["bgp_asn"]
  995. ip_address = each.value["ip_address"]
  996. type = "ipsec.1"
  997. tags = merge(
  998. {
  999. Name = format("%s-%s", var.name, each.key)
  1000. },
  1001. var.tags,
  1002. var.customer_gateway_tags,
  1003. )
  1004. }
  1005. ################################################################################
  1006. # VPN Gateway
  1007. ################################################################################
  1008. resource "aws_vpn_gateway" "this" {
  1009. count = var.create_vpc && var.enable_vpn_gateway ? 1 : 0
  1010. vpc_id = local.vpc_id
  1011. amazon_side_asn = var.amazon_side_asn
  1012. availability_zone = var.vpn_gateway_az
  1013. tags = merge(
  1014. {
  1015. "Name" = format("%s", var.name)
  1016. },
  1017. var.tags,
  1018. var.vpn_gateway_tags,
  1019. )
  1020. }
  1021. resource "aws_vpn_gateway_attachment" "this" {
  1022. count = var.vpn_gateway_id != "" ? 1 : 0
  1023. vpc_id = local.vpc_id
  1024. vpn_gateway_id = var.vpn_gateway_id
  1025. }
  1026. resource "aws_vpn_gateway_route_propagation" "public" {
  1027. count = var.create_vpc && var.propagate_public_route_tables_vgw && (var.enable_vpn_gateway || var.vpn_gateway_id != "") ? 1 : 0
  1028. route_table_id = element(aws_route_table.public.*.id, count.index)
  1029. vpn_gateway_id = element(
  1030. concat(
  1031. aws_vpn_gateway.this.*.id,
  1032. aws_vpn_gateway_attachment.this.*.vpn_gateway_id,
  1033. ),
  1034. count.index,
  1035. )
  1036. }
  1037. resource "aws_vpn_gateway_route_propagation" "private" {
  1038. count = var.create_vpc && var.propagate_private_route_tables_vgw && (var.enable_vpn_gateway || var.vpn_gateway_id != "") ? length(var.private_subnets) : 0
  1039. route_table_id = element(aws_route_table.private.*.id, count.index)
  1040. vpn_gateway_id = element(
  1041. concat(
  1042. aws_vpn_gateway.this.*.id,
  1043. aws_vpn_gateway_attachment.this.*.vpn_gateway_id,
  1044. ),
  1045. count.index,
  1046. )
  1047. }
  1048. resource "aws_vpn_gateway_route_propagation" "intra" {
  1049. count = var.create_vpc && var.propagate_intra_route_tables_vgw && (var.enable_vpn_gateway || var.vpn_gateway_id != "") ? length(var.intra_subnets) : 0
  1050. route_table_id = element(aws_route_table.intra.*.id, count.index)
  1051. vpn_gateway_id = element(
  1052. concat(
  1053. aws_vpn_gateway.this.*.id,
  1054. aws_vpn_gateway_attachment.this.*.vpn_gateway_id,
  1055. ),
  1056. count.index,
  1057. )
  1058. }
  1059. ################################################################################
  1060. # Defaults
  1061. ################################################################################
  1062. resource "aws_default_vpc" "this" {
  1063. count = var.manage_default_vpc ? 1 : 0
  1064. enable_dns_support = var.default_vpc_enable_dns_support
  1065. enable_dns_hostnames = var.default_vpc_enable_dns_hostnames
  1066. enable_classiclink = var.default_vpc_enable_classiclink
  1067. tags = merge(
  1068. {
  1069. "Name" = format("%s", var.default_vpc_name)
  1070. },
  1071. var.tags,
  1072. var.default_vpc_tags,
  1073. )
  1074. }