Uses forked version of fortios provider
Requires FortiOS >= 7.0.3
Uses sub-table resources in BGP and SDWAN parent tables. Do not mix and match here.
Intended for use with https://registry.terraform.io/modules/poroping/advpn-sdwan-hub/fortios
terraform {
required_version = ">= 1.0.1"
backend "local" {}
required_providers {
fortios = {
source = "poroping/fortios"
version = ">= 3.1.4"
}
}
}
### Hub configuration
## Assumes hub has been created with sister module registry.terraform.io/modules/poroping/advpn-sdwan-hub/fortios
## Hub config has been abbreviated for readbility and is incomplete
data "fortios_system_interface" "hub1_1" {
provider = fortios.hub1
name = "port1"
}
data "fortios_system_interface" "hub1_2" {
provider = fortios.hub1
name = "port2"
}
locals {
hub1_interfaces = [
{
interface_name = data.fortios_system_interface.hub1_1.name
interface_id = 1
local_gw = null
cost = null
nat_ip = null
tunnel_subnet = "169.254.101.0/24"
},
{
interface_name = data.fortios_system_interface.hub1_2.name
interface_id = 2
local_gw = null
cost = null
nat_ip = null
tunnel_subnet = "169.254.102.0/24"
}
]
hub1_bgp_as = 64420
}
module "advpnhub1" {
providers = {
fortios = fortios.hub1
}
source = "poroping/advpn-sdwan-hub/fortios"
version = "~> 1.0.0"
bgp_as = local.hub1_bgp_as
interfaces = local.hub1_interfaces
hub_id = 1
vdom = "root"
sla_loopback_ip = "169.254.255.1/32"
}
### Spoke
provider "fortios" {
alias = "spoke1"
hostname = "192.168.1.99"
token = "supertokens"
vdom = "root"
insecure = "true"
}
provider "fortios" {
alias = "spoke2"
hostname = "192.168.2.99"
token = "supertokens"
vdom = "root"
insecure = "true"
}
provider "fortios" {
alias = "spoke3"
hostname = "192.168.3.99"
token = "supertokens"
vdom = "root"
insecure = "true"
}
data "fortios_system_interface" "spoke1" {
provider = fortios.spoke1
name = "port1"
}
data "fortios_system_interface" "spoke1_2" {
provider = fortios.spoke1
name = "wwan"
}
data "fortios_system_interface" "spoke2" {
provider = fortios.spoke2
name = "wan1"
}
data "fortios_system_interface" "spoke2_2" {
provider = fortios.spoke2
name = "wan2"
}
data "fortios_system_interface" "spoke3" {
provider = fortios.spoke3
name = "vlanx"
}
data "fortios_system_interface" "spoke3_2" {
provider = fortios.spoke3
name = "vlany"
}
locals {
spoke1_interfaces = [
{
interface_name = data.fortios_system_interface.spoke1.name
interface_id = 1
local_gw = null
cost = 10
},
{
interface_name = data.fortios_system_interface.spoke1_2.name
interface_id = 2
local_gw = null
cost = 100
},
]
spoke2_interfaces = [
{
interface_name = data.fortios_system_interface.spoke2.name
interface_id = 1
local_gw = null
cost = null
},
{
interface_name = data.fortios_system_interface.spoke2_2.name
interface_id = 2
local_gw = null
cost = null
},
]
spoke3_interfaces = [
{
interface_name = data.fortios_system_interface.spoke3.name
interface_id = 1
local_gw = null
cost = 10
},
{
interface_name = data.fortios_system_interface.spoke3_2.name
interface_id = 2
local_gw = null
cost = 20
},
]
}
### BGP Prereqs, only single device shown for brevity
resource "fortios_router_bgp" "spoke1" {
provider = fortios.spoke1
vdomparam = "root"
ibgp_multipath = "enable"
router_id = "192.168.1.255"
additional_path = "enable"
additional_path_select = 4
as = local.hub1_bgp_as
recursive_next_hop = "enable" # if not 7.x then need to static route all tunnel subnets towards hub.
# ignore subtables
lifecycle {
ignore_changes = [
aggregate_address,
aggregate_address6,
network,
network6,
neighbor,
neighbor_group,
neighbor_range,
neighbor_range6,
admin_distance
]
}
}
module "advpnspoke1" {
providers = {
fortios = fortios.spoke1
}
source = "poroping/advpn-sdwan-spoke/fortios"
version = "~> 0.0.1"
bgp_as = local.hub1_bgp_as
interfaces = local.spoke1_interfaces
hub_links = module.advpnhub1.hub.links
hub_id = module.advpnhub1.hub.hub_id
hub_loopback = module.advpnhub1.hub.hub_loopback
vdom = "root"
spoke_id = 1
ipsec_psk = module.advpnhub1.psk
}
module "advpnspoke2" {
providers = {
fortios = fortios.spoke2
}
source = "poroping/advpn-sdwan-spoke/fortios"
version = "~> 0.0.1"
bgp_as = local.hub1_bgp_as
interfaces = local.spoke2_interfaces
hub_links = module.advpnhub1.hub.links
hub_id = module.advpnhub1.hub.hub_id
hub_loopback = module.advpnhub1.hub.hub_loopback
vdom = "root"
spoke_id = 2
ipsec_psk = module.advpnhub1.psk
hub_sla = {
"jitter" : 30,
"latency" : 150,
"packetloss" : 1
}
}
module "advpnspoke3" {
providers = {
fortios = fortios.spoke3
}
source = "poroping/advpn-sdwan-spoke/fortios"
version = "~> 0.0.1"
bgp_as = local.hub1_bgp_as
interfaces = local.spoke3_interfaces
hub_links = module.advpnhub1.hub.links
hub_id = module.advpnhub1.hub.hub_id
hub_loopback = module.advpnhub1.hub.hub_loopback
vdom = "root"
spoke_id = 3
ipsec_psk = module.advpnhub1.psk
hub_sla = {
"jitter" : 20,
"latency" : 100,
"packetloss" : 0
}
}
### Ensure SDWAN is enabled
### Ensure firewall policies are created
### Suggested SNAT route change enabled or blackhole routes utilised
Name | Version |
---|---|
fortios | >= 3.1.4 |
Name | Description | Type | Default | Required |
---|---|---|---|---|
hub_id | Hub ID - single digit int. | number |
n/a | yes |
hub_links | Set of links on hub to peer with. | list(object({ |
n/a | yes |
hub_loopback | Hub loopback IP address | string |
n/a | yes |
interfaces | Set of interfaces to use to peer with hubs. | list(object({ |
n/a | yes |
ipsec_psk | Pre-shared key for IPSEC tunnels. | string |
n/a | yes |
spoke_id | Spoke ID - Between 1 and 254. | number |
n/a | yes |
bgp_as | BGP AS to use for ADVPN. | number |
65000 |
no |
hub_sla | Hub SLA values. | object({ |
{ |
no |
ip_fragmentation | Determine whether IP packets are fragmented before or after IPsec encapsulation. | string |
null |
no |
ipsec_dhgrp | List of dhgrp separated by whitespace. | string |
"14" |
no |
ipsec_proposal | List of proposals separated by whitespace. | string |
"aes256-sha256" |
no |
networks | A set of BGP networks. | set(string) |
[] |
no |
overlay_networks | A set of overlay networks. | set(string) |
[] |
no |
underlay_networks | A set of underlay networks. | set(string) |
[] |
no |
vdom | VDOM to apply configuration. | string |
"root" |
no |