From 2eb0384c4f4a5132c9a7aef270bf4c443314d046 Mon Sep 17 00:00:00 2001 From: Andrei Ilas Date: Tue, 8 Apr 2025 10:26:52 +0300 Subject: [PATCH] Add IPv6 Support --- docs/terraformoptions.adoc | 4 + docs/terraformoptions.md | 4 + examples/drg/version.tf | 2 +- examples/hub-spoke/version.tf | 2 +- examples/module_composition/README.md | 6 ++ examples/module_composition/main.tf | 28 ++++--- examples/module_composition/variables.tf | 26 +++++++ examples/module_composition/version.tf | 2 +- modules/subnet/subnet.tf | 32 ++++---- modules/subnet/variables.tf | 6 ++ modules/subnet/versions.tf | 2 +- outputs.tf | 6 ++ terraform.tfvars.example | 9 +++ variables.tf | 32 ++++++++ vcn.tf | 48 ++++++++---- vcn_defaultresources.tf | 41 ++++++++++- vcn_gateways.tf | 93 +++++++++++++++++++++++- versions.tf | 2 +- 18 files changed, 298 insertions(+), 47 deletions(-) diff --git a/docs/terraformoptions.adoc b/docs/terraformoptions.adoc index f5da55d..e5c6104 100644 --- a/docs/terraformoptions.adoc +++ b/docs/terraformoptions.adoc @@ -24,6 +24,7 @@ | create_nat_gateway | Whether to create an NAT gateway. | bool | false| | create_service_gateway | Whether to create a service gateway to use Oracle Services. | bool | false| | enable_ipv6 | (Updatable) Whether IPv6 is enabled for the VCN. If enabled, Oracle will assign the VCN a IPv6 /56 CIDR block. | bool | false| +| igw_ngw_mixed_route_table_display_name | (Updatable) Name of the Mixed Route Table (NGW for IPv4, IGW for IPv6). Does not have to be unique. | string | igw-ngw-mixed-gateway | | internet_gateway_display_name | (Updatable) Name of Internet Gateway. Does not have to be unique.| string | internet-gateway| | internet_gateway_route_rules | (Updatable) List of routing rules to add to Internet Gateway Route Table.| list(map(string)) | null| | local_peering_gateways | Map of Local Peering Gateways to attach to the VCN | map(any) | null| @@ -32,8 +33,11 @@ | nat_gateway_public_ip_id | OCID of reserved IP address for NAT gateway. If default value "none" is used, then a public IP address is selected from Oracle’s public IP pool. | string | none| | nat_gateway_route_rules | (Updatable) List of routing rules to add to NAT Gateway Route Table | list(map(string)) | null| | service_gateway_display_name | (Updatable) Name of Service Gateway. Does not have to be unique. | string | service-gateway| +| vcn_byoipv6cidr_details | (Optional)List of BYOIPv6 CIDR blocks to be used for the VCN. | list(object) | [] | | vcn_cidrs | (Updatable) The list of IPv4 CIDR blocks the VCN will use. The CIDR block specified for the VCN must not overlap with the CIDR block of another network. | string | ["10.0.0.0/16"]| | vcn_dns_label | (Optional)A DNS label for the VCN, used in conjunction with the VNIC’s hostname and subnet’s DNS label to form a fully qualified domain name (FQDN) for each VNIC within this subnet. DNS resolution for hostnames in the VCN is disabled if null. | string | vcnmodule| +| vcn_ipv6private_cidr_blocks | (Optional)List of IPv6 private CIDR blocks to be used for the VCN. | list(string) | []| +| vcn_is_oracle_gua_allocation_enabled | (Optional)If Oracle will assign the VCN a IPv6 /56 CIDR block when IPv6 is enabled. | bool | true| | vcn_name | (Optional)(Updatable) The name of the VCN that will be appended to the label_prefix. | string | vcn| ### Subnets diff --git a/docs/terraformoptions.md b/docs/terraformoptions.md index f5da55d..e5c6104 100644 --- a/docs/terraformoptions.md +++ b/docs/terraformoptions.md @@ -24,6 +24,7 @@ | create_nat_gateway | Whether to create an NAT gateway. | bool | false| | create_service_gateway | Whether to create a service gateway to use Oracle Services. | bool | false| | enable_ipv6 | (Updatable) Whether IPv6 is enabled for the VCN. If enabled, Oracle will assign the VCN a IPv6 /56 CIDR block. | bool | false| +| igw_ngw_mixed_route_table_display_name | (Updatable) Name of the Mixed Route Table (NGW for IPv4, IGW for IPv6). Does not have to be unique. | string | igw-ngw-mixed-gateway | | internet_gateway_display_name | (Updatable) Name of Internet Gateway. Does not have to be unique.| string | internet-gateway| | internet_gateway_route_rules | (Updatable) List of routing rules to add to Internet Gateway Route Table.| list(map(string)) | null| | local_peering_gateways | Map of Local Peering Gateways to attach to the VCN | map(any) | null| @@ -32,8 +33,11 @@ | nat_gateway_public_ip_id | OCID of reserved IP address for NAT gateway. If default value "none" is used, then a public IP address is selected from Oracle’s public IP pool. | string | none| | nat_gateway_route_rules | (Updatable) List of routing rules to add to NAT Gateway Route Table | list(map(string)) | null| | service_gateway_display_name | (Updatable) Name of Service Gateway. Does not have to be unique. | string | service-gateway| +| vcn_byoipv6cidr_details | (Optional)List of BYOIPv6 CIDR blocks to be used for the VCN. | list(object) | [] | | vcn_cidrs | (Updatable) The list of IPv4 CIDR blocks the VCN will use. The CIDR block specified for the VCN must not overlap with the CIDR block of another network. | string | ["10.0.0.0/16"]| | vcn_dns_label | (Optional)A DNS label for the VCN, used in conjunction with the VNIC’s hostname and subnet’s DNS label to form a fully qualified domain name (FQDN) for each VNIC within this subnet. DNS resolution for hostnames in the VCN is disabled if null. | string | vcnmodule| +| vcn_ipv6private_cidr_blocks | (Optional)List of IPv6 private CIDR blocks to be used for the VCN. | list(string) | []| +| vcn_is_oracle_gua_allocation_enabled | (Optional)If Oracle will assign the VCN a IPv6 /56 CIDR block when IPv6 is enabled. | bool | true| | vcn_name | (Optional)(Updatable) The name of the VCN that will be appended to the label_prefix. | string | vcn| ### Subnets diff --git a/examples/drg/version.tf b/examples/drg/version.tf index 53a8749..edeaeaa 100644 --- a/examples/drg/version.tf +++ b/examples/drg/version.tf @@ -2,7 +2,7 @@ terraform { required_providers { oci = { source = "oracle/oci" - version = ">=4.67.3" + version = ">=6.32.0" } } required_version = ">= 1.0.0" diff --git a/examples/hub-spoke/version.tf b/examples/hub-spoke/version.tf index 53a8749..edeaeaa 100644 --- a/examples/hub-spoke/version.tf +++ b/examples/hub-spoke/version.tf @@ -2,7 +2,7 @@ terraform { required_providers { oci = { source = "oracle/oci" - version = ">=4.67.3" + version = ">=6.32.0" } } required_version = ">= 1.0.0" diff --git a/examples/module_composition/README.md b/examples/module_composition/README.md index d2dd7fa..14b0206 100644 --- a/examples/module_composition/README.md +++ b/examples/module_composition/README.md @@ -66,6 +66,12 @@ module "vcn" { vcn_name = var.vcn_name lockdown_default_seclist = var.lockdown_default_seclist attached_drg_id = var.attached_drg_id + + # IPv6 parameters (Optional) + vcn_is_oracle_gua_allocation_enabled = var.vcn_is_oracle_gua_allocation_enabled # Enable Global Unicast Address (GUA) VCN allocation + vcn_ipv6private_cidr_blocks = var.vcn_ipv6private_cidr_blocks # List with IPv6 private CIDR blocks + vcn_byoipv6cidr_details = var.vcn_byoipv6cidr_details # List with BYOIPv6 CIDR blocks + ipv6_private_subnet_route_table_display_name = var.ipv6_private_subnet_route_table_display_name # Name of the route table used for private subnets } ``` diff --git a/examples/module_composition/main.tf b/examples/module_composition/main.tf index f16df34..8a5bac4 100644 --- a/examples/module_composition/main.tf +++ b/examples/module_composition/main.tf @@ -18,20 +18,24 @@ module "vcn" { defined_tags = var.defined_tags # vcn parameters - create_internet_gateway = var.create_internet_gateway # boolean: true or false - lockdown_default_seclist = var.lockdown_default_seclist # boolean: true or false - create_nat_gateway = var.create_nat_gateway # boolean: true or false - create_service_gateway = var.create_service_gateway # boolean: true or false - enable_ipv6 = var.enable_ipv6 - vcn_cidrs = var.vcn_cidrs # List of IPv4 CIDRs - vcn_dns_label = var.vcn_dns_label - vcn_name = var.vcn_name + create_internet_gateway = var.create_internet_gateway # boolean: true or false + lockdown_default_seclist = var.lockdown_default_seclist # boolean: true or false + create_nat_gateway = var.create_nat_gateway # boolean: true or false + create_service_gateway = var.create_service_gateway # boolean: true or false + enable_ipv6 = var.enable_ipv6 + vcn_cidrs = var.vcn_cidrs # List of IPv4 CIDRs + vcn_dns_label = var.vcn_dns_label + vcn_name = var.vcn_name + vcn_is_oracle_gua_allocation_enabled = var.vcn_is_oracle_gua_allocation_enabled # boolean: true or false + vcn_ipv6private_cidr_blocks = var.vcn_ipv6private_cidr_blocks # List of IPv6 private CIDRs + vcn_byoipv6cidr_details = var.vcn_byoipv6cidr_details # List of IPv6 BYO CIDR details # gateways parameters - internet_gateway_display_name = var.internet_gateway_display_name - nat_gateway_display_name = var.nat_gateway_display_name - service_gateway_display_name = var.service_gateway_display_name - attached_drg_id = var.attached_drg_id + internet_gateway_display_name = var.internet_gateway_display_name + nat_gateway_display_name = var.nat_gateway_display_name + service_gateway_display_name = var.service_gateway_display_name + igw_ngw_mixed_route_table_display_name = var.igw_ngw_mixed_route_table_display_name + attached_drg_id = var.attached_drg_id } # Outputs diff --git a/examples/module_composition/variables.tf b/examples/module_composition/variables.tf index 4ed2385..d8ca75f 100644 --- a/examples/module_composition/variables.tf +++ b/examples/module_composition/variables.tf @@ -139,3 +139,29 @@ variable "service_gateway_display_name" { default = "sgw" } +variable "vcn_is_oracle_gua_allocation_enabled" { + description = "If Oracle will assign the VCN a IPv6 /56 CIDR block when IPv6 is enabled." + type = bool + default = false +} + +variable "vcn_ipv6private_cidr_blocks" { + description = "List of private IPv6 CIDR blocks to be used for the VCN." + type = list(string) + default = [] +} + +variable "vcn_byoipv6cidr_details" { + description = "List of BYOIPv6 CIDR blocks to be used for the VCN." + type = list(object({ + byoipv6range_id = string + ipv6cidr_block = string + })) + default = [] +} + +variable "igw_ngw_mixed_route_table_display_name" { + description = "(Updatable) Name of Route Table. Does not have to be unique." + type = string + default = "igw-ngw-mixed-gateway" +} \ No newline at end of file diff --git a/examples/module_composition/version.tf b/examples/module_composition/version.tf index 53a8749..edeaeaa 100644 --- a/examples/module_composition/version.tf +++ b/examples/module_composition/version.tf @@ -2,7 +2,7 @@ terraform { required_providers { oci = { source = "oracle/oci" - version = ">=4.67.3" + version = ">=6.32.0" } } required_version = ">= 1.0.0" diff --git a/modules/subnet/subnet.tf b/modules/subnet/subnet.tf index 7aff453..4d89f69 100644 --- a/modules/subnet/subnet.tf +++ b/modules/subnet/subnet.tf @@ -3,14 +3,14 @@ locals { dhcp_default_options = data.oci_core_dhcp_options.dhcp_options.options.0.id - // Tenancy-specific availability domains in region + // Tenancy-specific availability domains in region // Common reference for data source re-used throughout module ads = data.oci_identity_availability_domains.all.availability_domains // Map of parsed availability domain numbers to tenancy-specific names // Used by resources with AD placement for generic selection ad_numbers_to_names = local.ads != null ? { - for ad in local.ads : parseint(substr(ad.name, -1, -1), 10) => ad.name + for ad in local.ads : parseint(substr(ad.name, -1, -1), 10) => ad.name } : { -1 : "" } # Fallback handles failure when unavailable but not required // List of availability domain numbers in region @@ -23,24 +23,30 @@ data "oci_identity_availability_domains" "all" { } resource "oci_core_subnet" "vcn_subnet" { - for_each = var.subnets - cidr_block = each.value.cidr_block - compartment_id = var.compartment_id - vcn_id = var.vcn_id + for_each = var.subnets + + cidr_block = each.value.cidr_block + compartment_id = var.compartment_id + vcn_id = var.vcn_id availability_domain = lookup(each.value, "availability_domain", null) != null ? local.ad_numbers_to_names[each.value.availability_domain] : null - + defined_tags = var.defined_tags dhcp_options_id = local.dhcp_default_options display_name = lookup(each.value, "name", each.key) dns_label = lookup(each.value, "dns_label", null) freeform_tags = var.freeform_tags #commented for IPV6 support - #ipv6cidr_block = var.enable_ipv6 == false ? null : each.value.ipv6cidr_block - #ipv6cidr_blocks = var.enable_ipv6 == false ? null : [each.value.ipv6cidr_block] - #prohibit_internet_ingress = var.enable_ipv6 && lookup(each.value,"type","public") == "public" ? each.value.prohibit_internet_ingress : false - prohibit_public_ip_on_vnic = lookup(each.value, "type", "public") == "public" ? false : true - route_table_id = lookup(each.value, "type", "public") == "public" ? var.ig_route_id : var.nat_route_id - security_list_ids = null + # ipv6cidr_block = var.enable_ipv6 == false ? null : each.value.ipv6cidr_block + ipv6cidr_blocks = var.enable_ipv6 == false ? null : each.value.ipv6cidr_blocks + prohibit_internet_ingress = lookup(each.value, "type", "public") == "public" ? false : true + # prohibit_public_ip_on_vnic = lookup(each.value, "type", "public") == "public" ? false : true + route_table_id = lookup(each.value, "type", "public") == "public" ? ( + lookup(each.value, "igw_ngw_mixed_rt", false) == true ? + var.igw_ngw_mixed_route_id : + var.ig_route_id + ) : var.nat_route_id + + security_list_ids = null lifecycle { ignore_changes = [defined_tags, dns_label, freeform_tags] diff --git a/modules/subnet/variables.tf b/modules/subnet/variables.tf index 19ee3b1..78f0717 100644 --- a/modules/subnet/variables.tf +++ b/modules/subnet/variables.tf @@ -34,6 +34,12 @@ variable "nat_route_id" { type = string } +variable "igw_ngw_mixed_route_id" { + description = "IPv6 route table id with IGW for IPv6 and NGW for IPv4." + type = string + default = null +} + variable "defined_tags" { description = "predefined and scoped to a namespace to tag the resources created using defined tags." type = map(string) diff --git a/modules/subnet/versions.tf b/modules/subnet/versions.tf index 03e7559..053c983 100644 --- a/modules/subnet/versions.tf +++ b/modules/subnet/versions.tf @@ -5,7 +5,7 @@ terraform { required_providers { oci = { source = "oracle/oci" - version = ">=4.67.3" + version = ">=6.32.0" } } required_version = ">= 1.0.0" diff --git a/outputs.tf b/outputs.tf index 8a1d5f1..a11baaf 100644 --- a/outputs.tf +++ b/outputs.tf @@ -27,6 +27,11 @@ output "ig_route_id" { value = join(",", oci_core_route_table.ig[*].id) } +output "igw_ngw_mixed_route_id" { + description = "id of the internet gateway & nat gateway mixed route table" + value = one(oci_core_route_table.igw_ngw_mixed_route_id[*].id) +} + output "nat_route_id" { description = "id of VCN NAT gateway route table" value = join(",", oci_core_route_table.nat[*].id) @@ -37,6 +42,7 @@ output "sgw_route_id" { value = join(",", oci_core_route_table.service_gw[*].id) } + # New complete outputs for each resources with provider parity. Auto-updating. # Usefull for module composition. diff --git a/terraform.tfvars.example b/terraform.tfvars.example index 791909d..095d0dd 100644 --- a/terraform.tfvars.example +++ b/terraform.tfvars.example @@ -115,6 +115,15 @@ attached_drg_id = null # sub3 = {cidr_block="10.0.6.0/24",availability_domain=1} #} +#Subnets when `enable_ipv6 = true` +## Supported notation for ipv6cidr_blocks is "newbits, netnum" or "IPv6_CIDR" +## E.g.: ipv6cidr_blocks=["8, 0", "FC00::/64"] +#subnets = { +# sub1 = {name = "subnet1", type="public", cidr_block = "10.0.4.0/24"} +# sub2 = {cidr_block="10.0.5.0/24",ipv6cidr_blocks=["8, 0"], igw_ngw_mixed_rt=true} +# sub3 = {cidr_block="10.0.7.0/24",type="private",ipv6cidr_blocks=["8, 1"]} +#} + #Logging #enable_vcn_logging = true #log_retention_duration = 30 \ No newline at end of file diff --git a/variables.tf b/variables.tf index 3e7dbce..91b2477 100644 --- a/variables.tf +++ b/variables.tf @@ -64,6 +64,27 @@ variable "enable_ipv6" { default = false } +variable "vcn_is_oracle_gua_allocation_enabled" { + description = "If Oracle will assign the VCN a IPv6 /56 CIDR block when IPv6 is enabled." + type = bool + default = true +} + +variable "vcn_ipv6private_cidr_blocks" { + description = "List of IPv6 private CIDR blocks to be used for the VCN." + type = list(string) + default = [] +} + +variable "vcn_byoipv6cidr_details" { + description = "List of BYOIPv6 CIDR blocks to be used for the VCN." + type = list(object({ + byoipv6range_id = string + ipv6cidr_block = string + })) + default = [] +} + variable "lockdown_default_seclist" { description = "whether to remove all default security rules from the VCN Default Security List" default = true @@ -143,6 +164,17 @@ variable "service_gateway_display_name" { } } +variable "igw_ngw_mixed_route_table_display_name" { + description = "(Updatable) Name of the Mixed Route Table (NGW for IPv4, IGW for IPv6). Does not have to be unique." + type = string + default = "igw-ngw-mixed-gateway" + + validation { + condition = length(var.igw_ngw_mixed_route_table_display_name) > 0 + error_message = "The igw_ngw_mixed_route_table_display_name value cannot be an empty string." + } +} + variable "internet_gateway_route_rules" { description = "(Updatable) List of routing rules to add to Internet Gateway Route Table" type = list(map(string)) diff --git a/vcn.tf b/vcn.tf index 50a8bdd..3e298d9 100644 --- a/vcn.tf +++ b/vcn.tf @@ -4,17 +4,27 @@ resource "oci_core_vcn" "vcn" { # We still allow module users to declare a cidr using `vcn_cidr` instead of the now recommended `vcn_cidrs`, but internally we map both to `cidr_blocks` # The module always use the new list of string structure and let the customer update his module definition block at his own pace. - cidr_blocks = var.vcn_cidrs[*] - compartment_id = var.compartment_id - display_name = var.label_prefix == "none" ? var.vcn_name : "${var.label_prefix}-${var.vcn_name}" - dns_label = var.vcn_dns_label - is_ipv6enabled = var.enable_ipv6 + cidr_blocks = var.vcn_cidrs[*] + compartment_id = var.compartment_id + display_name = var.label_prefix == "none" ? var.vcn_name : "${var.label_prefix}-${var.vcn_name}" + dns_label = var.vcn_dns_label + is_ipv6enabled = var.enable_ipv6 + is_oracle_gua_allocation_enabled = var.enable_ipv6 ? var.vcn_is_oracle_gua_allocation_enabled : null + ipv6private_cidr_blocks = var.enable_ipv6 ? var.vcn_ipv6private_cidr_blocks : null + + dynamic "byoipv6cidr_details" { + for_each = var.enable_ipv6 ? var.vcn_byoipv6cidr_details : [] + content { + byoipv6range_id = byoipv6cidr_details.value.byoipv6range_id + ipv6cidr_block = byoipv6cidr_details.value.ipv6cidr_block + } + } freeform_tags = var.freeform_tags defined_tags = var.defined_tags lifecycle { - ignore_changes = [defined_tags, dns_label, freeform_tags] + ignore_changes = [defined_tags, dns_label, freeform_tags, is_ipv6enabled, is_oracle_gua_allocation_enabled] } } @@ -22,13 +32,14 @@ resource "oci_core_vcn" "vcn" { module "subnet" { source = "./modules/subnet" - compartment_id = var.compartment_id - tenancy_id = var.tenancy_id - subnets = var.subnets - enable_ipv6 = var.enable_ipv6 - vcn_id = oci_core_vcn.vcn.id - ig_route_id = var.create_internet_gateway ? oci_core_route_table.ig[0].id : null - nat_route_id = var.create_nat_gateway ? oci_core_route_table.nat[0].id : null + compartment_id = var.compartment_id + tenancy_id = var.tenancy_id + subnets = local.enriched_subnets + enable_ipv6 = var.enable_ipv6 + vcn_id = oci_core_vcn.vcn.id + ig_route_id = var.create_internet_gateway ? oci_core_route_table.ig[0].id : null + nat_route_id = var.create_nat_gateway ? oci_core_route_table.nat[0].id : null + igw_ngw_mixed_route_id = var.enable_ipv6 && var.create_internet_gateway && var.create_nat_gateway ? oci_core_route_table.igw_ngw_mixed_route_id[0].id : null freeform_tags = var.freeform_tags @@ -41,6 +52,17 @@ locals { subnet = { for key, value in var.subnets : key => contains(keys(value), "name") ? value.name : key } + + subnet_ipv6_cidr_blocks = var.enable_ipv6 ? { + for key, value in var.subnets : key => contains(keys(value), "ipv6cidr_blocks") ? + { "ipv6cidr_blocks" : [for entry in value["ipv6cidr_blocks"] : length(regexall("^\\d+,[ ]?\\d+$", entry)) > 0 ? cidrsubnet(coalesce([for cidr in oci_core_vcn.vcn.ipv6cidr_blocks : cidr]...), tonumber(split(",", entry)[0]), tonumber(trim(split(",", entry)[1], " "))) : entry] } : + { "ipv6cidr_blocks" : [] } + } : {} + + enriched_subnets = { for k, v in var.subnets : + k => merge(v, lookup(local.subnet_ipv6_cidr_blocks, k, null)) + } + service_logdef = { for k in local.subnet : format("%s_%s", k, "log") => { loggroup = "loggrp", service = "flowlogs", resource = k } } } diff --git a/vcn_defaultresources.tf b/vcn_defaultresources.tf index 3a527f3..8ce38dd 100644 --- a/vcn_defaultresources.tf +++ b/vcn_defaultresources.tf @@ -21,24 +21,46 @@ resource "oci_core_default_security_list" "restore_default" { egress_security_rules { // allow all egress traffic - destination = "0.0.0.0/0" + destination = local.anywhere protocol = "all" } + dynamic "egress_security_rules" { + //allow all egress traffic for IPv6 + for_each = var.enable_ipv6 ? [0] : [] + content { + destination = local.anywhere_ipv6 + protocol = "all" + } + } + ingress_security_rules { // allow all SSH protocol = "6" - source = "0.0.0.0/0" + source = local.anywhere tcp_options { min = 22 max = 22 } } + dynamic "ingress_security_rules" { + //allow all SSH for IPv6 + for_each = var.enable_ipv6 ? [0] : [] + content { + protocol = "6" + source = local.anywhere_ipv6 + tcp_options { + min = 22 + max = 22 + } + } + } + ingress_security_rules { // allow ICMP for all type 3 code 4 protocol = "1" - source = "0.0.0.0/0" + source = local.anywhere icmp_options { type = "3" @@ -46,6 +68,19 @@ resource "oci_core_default_security_list" "restore_default" { } } + dynamic "ingress_security_rules" { + //allow ICMPv6 for all type 2 code 0 (Packet Too Big) + for_each = var.enable_ipv6 ? [0] : [] + content { + protocol = "58" + source = local.anywhere_ipv6 + icmp_options { + type = "2" + code = "0" + } + } + } + dynamic "ingress_security_rules" { //allow all ICMP from all VCN CIDRs for_each = oci_core_vcn.vcn.cidr_blocks diff --git a/vcn_gateways.tf b/vcn_gateways.tf index 0bb54fa..a6ce3c4 100644 --- a/vcn_gateways.tf +++ b/vcn_gateways.tf @@ -190,7 +190,7 @@ resource "oci_core_nat_gateway" "nat_gateway" { freeform_tags = var.freeform_tags defined_tags = var.defined_tags - public_ip_id = var.nat_gateway_public_ip_id != "none" ? var.nat_gateway_public_ip_id != "RESERVED" ? var.nat_gateway_public_ip_id : join(",",oci_core_public_ip.nat_gateway_public_ip.*.id) : null + public_ip_id = var.nat_gateway_public_ip_id != "none" ? var.nat_gateway_public_ip_id != "RESERVED" ? var.nat_gateway_public_ip_id : join(",", oci_core_public_ip.nat_gateway_public_ip.*.id) : null vcn_id = oci_core_vcn.vcn.id @@ -301,6 +301,97 @@ resource "oci_core_route_table" "nat" { count = var.create_nat_gateway ? 1 : 0 } +resource "oci_core_route_table" "igw_ngw_mixed_route_id" { + compartment_id = var.compartment_id + display_name = var.igw_ngw_mixed_route_table_display_name + + freeform_tags = var.freeform_tags + defined_tags = var.defined_tags + + route_rules { + # * With this route table, NAT Gateway is always declared as the default gateway for IPv4 + destination = local.anywhere + destination_type = "CIDR_BLOCK" + network_entity_id = oci_core_nat_gateway.nat_gateway[0].id + description = "Terraformed - Auto-generated at NAT Gateway creation: NAT Gateway as default gateway for IPv4" + } + + route_rules { + # * With this route table, IGW Gateway is always declared as the default gateway for IPv6 + destination = local.anywhere_ipv6 + destination_type = "CIDR_BLOCK" + network_entity_id = oci_core_internet_gateway.ig[0].id + description = "Terraformed - Auto-generated at NAT Gateway creation: IGW Gateway as default gateway for IPv6" + } + + dynamic "route_rules" { + # * filter var.nat_gateway_route_rules for routes with "drg" as destination + # * and steer traffic to the attached DRG if available + for_each = var.nat_gateway_route_rules != null ? { for k, v in var.nat_gateway_route_rules : k => v + if v.network_entity_id == "drg" && var.attached_drg_id != null } : {} + + content { + destination = route_rules.value.destination + destination_type = route_rules.value.destination_type + network_entity_id = var.attached_drg_id + description = route_rules.value.description + } + } + + dynamic "route_rules" { + # * filter var.nat_gateway_route_rules for routes with "nat_gateway" as destination + # * and steer traffic to the module created NAT Gateway + for_each = var.nat_gateway_route_rules != null ? { for k, v in var.nat_gateway_route_rules : k => v + if v.network_entity_id == "nat_gateway" } : {} + + content { + destination = route_rules.value.destination + destination_type = route_rules.value.destination_type + network_entity_id = oci_core_nat_gateway.nat_gateway[0].id + description = route_rules.value.description + } + } + + dynamic "route_rules" { + # * filter var.nat_gateway_route_rules for routes with "lpg@" as destination + # * and steer traffic to the attached LPG if available + for_each = var.nat_gateway_route_rules != null ? { for k, v in var.nat_gateway_route_rules : k => v + if startswith(v.network_entity_id, "lpg@") && var.local_peering_gateways != null } : {} + + content { + destination = route_rules.value.destination + destination_type = route_rules.value.destination_type + network_entity_id = oci_core_local_peering_gateway.lpg[split("@", route_rules.value.network_entity_id)[1]].id + description = route_rules.value.description + } + } + + dynamic "route_rules" { + # * filter var.nat_gateway_route_rules for generic routes + # * can take any Named Value : String, Input Variable, Local Value, Data Source, Resource, Module Output ... + # * useful for gateways that are not managed by the module + for_each = var.nat_gateway_route_rules != null ? { for k, v in var.nat_gateway_route_rules : k => v + if contains(["drg", "nat_gateway"], v.network_entity_id) == false && startswith(v.network_entity_id, "lpg@") == false } : {} + + content { + destination = route_rules.value.destination + destination_type = route_rules.value.destination_type + network_entity_id = route_rules.value.network_entity_id + description = route_rules.value.description + } + } + + vcn_id = oci_core_vcn.vcn.id + + # ignore changes to route rules to avoid recreation issues due to #101. + # A fix may still be needed for when new custom route rules are added. + + lifecycle { + ignore_changes = [defined_tags, freeform_tags] + } + + count = var.create_nat_gateway && var.create_internet_gateway && var.enable_ipv6 ? 1 : 0 +} ############################# diff --git a/versions.tf b/versions.tf index 5f5edac..b24b9f1 100644 --- a/versions.tf +++ b/versions.tf @@ -2,7 +2,7 @@ terraform { required_providers { oci = { source = "oracle/oci" - version = ">=4.67.3" + version = ">=6.32.0" } } required_version = ">= 1.0.0"