Source Code
Now that FortiOS 7.0 has been out for a bit, I decided it was time to redesign my home SDWAN/ADVPN lab for 7.0.1. I started off building it manually, but then I thought, why not use Terraform to build the infrastructure so that I can easily add or remove devices as needed. I am going write this a multi part series starting with a single FortiGate that I use as a router.
Lab Design
The design is similar to this reference design. The lab I am creating will use FEC and packet duplication which are not part of the design in the link. I am using EVE-NG for this lab, my old lab is running in ESXI. I recently made the move to EVE so that I could adjust things like link quality on the fly without a wan emulator. I am running KVM/libvirt for any vms that cannot run in EVE. In this post will be focusing on the Core-DC device, which is a FGT that is used as a datacenter router.
Configuration
The Core-DC device has a pretty simple configuration. The IP address and interface information is as follows.
Interface | IP Address | Description |
---|---|---|
lo0 | 172.28.255.252/32 |
Loopback |
port1 | 172.28.0.2/30 |
To-Hub1 |
port2 | 172.28.0.6/30 |
To-Hub2 |
port3 | 172.28.254.1/24 |
Local-LAN |
port10 | 10.6.20.142/24 |
Management |
The only interface that has been configured so far is the port10 for management access. We will also be setting up BGP to speak to both hubs. We will be advertising the Local-LAN subnet to both BGP peers.
Terraform Code
main.tf
This tells Terraform to download the FortiOS provider when you run terraform init
terraform {
required_providers {
fortios = {
source = "fortinetdev/fortios"
}
}
}
This file tells Terraform to use the FortiOS provider, sets the hostname, and the api key. I have insecure set to true because I am running in a lab.
provider.tf
provider "fortios" {
hostname = var.hostname
token = var.token
insecure = "true"
}
The following variables are to setup communication to the FortiGate. You don’t need two files, I just do it so I can add terraform.tfvars
to my .gitignore
and still push my variables file to github/gitlab.
variables.tf
Variables for hostname and API key.
variable "hostname" {}
variable "token" {}
terraform.tfvars
Set these to your device’s management IP/FQDN and API key.
hostname = <MANAGEMENT IP>
token = <API KEY>
interfaces.tf
This is where the bulk of the configuration happens. We are adding a loopback and configuring settings on three physical interfaces.
resource "fortios_system_interface" "lo0" {
ip = "172.28.255.253 255.255.255.255"
allowaccess = "ping https ssh snmp http telnet fgfm radius-acct probe-response fabric ftm speed-test"
name = "lo0"
role = "lan"
type = "loopback"
vdom = "root"
mode = "static"
status = "up"
}
resource "fortios_system_interface" "port1" {
name = "port1"
ip = "172.28.0.2 255.255.255.252"
status = "up"
device_identification = "enable"
speed = "auto"
role = "lan"
allowaccess = "ping"
mode = "static"
type = "physical"
vdom = "root"
alias = "To-Hub1"
}
resource "fortios_system_interface" "port2" {
name = "port2"
ip = "172.28.0.6 255.255.255.252"
status = "up"
device_identification = "enable"
speed = "auto"
role = "lan"
allowaccess = "ping"
mode = "static"
type = "physical"
vdom = "root"
alias = "To-Hub2"
}
resource "fortios_system_interface" "port3" {
name = "port3"
ip = "172.28.254.1 255.255.255.0"
status = "up"
device_identification = "enable"
speed = "auto"
role = "lan"
allowaccess = "ping"
mode = "static"
type = "physical"
vdom = "root"
alias = "LAN"
bgp.tf
eBGP settings for the Fortigate.
resource "fortios_router_bgp" "bgp" {
as = "64999"
ebgp_multipath = "enable"
router_id = "172.28.255.252"
graceful_restart = "enable"
neighbor {
ip = "172.28.0.1"
remote_as = "65000"
soft_reconfiguration = "enable"
}
neighbor {
ip = "172.28.0.5"
remote_as = "65000"
soft_reconfiguration = "enable"
}
network {
id = "1"
prefix = "172.28.254.0 255.255.255.0"
}
}
policy.tf
This is last portion of the configuration. It is just and any <> any rule to allow all traffic in both directions. Which essentially disables bypasses all security and turns this FortiGate into a router.
resource "fortios_firewall_policy" "allow-all" {
action = "accept"
logtraffic = "all"
name = "allow-all"
policyid = 1
schedule = "always"
dstaddr {
name = "all"
}
dstintf {
name = "any"
}
service {
name = "ALL"
}
srcaddr {
name = "all"
}
srcintf {
name = "any"
}
}
Running terraform apply
When we run terraform apply
we see the following. There are 8 total resources that will be created. A few of them I didn’t cover. The log settings and system global, but they are in the source code.
Terraform used the selected providers to generate the following execution plan.
Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# fortios_firewall_policy.allow-all will be created
+ resource "fortios_firewall_policy" "allow-all" {
+ action = "accept"
+ dynamic_sort_subtable = "false"
+ logtraffic = "all"
+ policyid = 1
+ schedule = "always"
+ dstaddr {
+ name = "all"
}
+ dstintf {
+ name = "any"
}
+ service {
+ name = "ALL"
}
+ srcaddr {
+ name = "all"
}
+ srcintf {
+ name = "any"
}
}
# fortios_log_setting.log will be created
+ resource "fortios_log_setting" "log" {
+ dynamic_sort_subtable = "false"
+ fwpolicy_implicit_log = "enable")
}
# fortios_router_bgp.bgp will be created
+ resource "fortios_router_bgp" "bgp" {
+ as = 64999
+ dynamic_sort_subtable = "false"
+ ebgp_multipath = "enable"
+ graceful_restart = "enable"
+ router_id = "172.28.255.252"
+ neighbor {
+ ip = "172.28.0.1"
+ remote_as = 65000
+ soft_reconfiguration = "enable"
}
+ neighbor {
+ ip = "172.28.0.5"
+ remote_as = 65000
+ soft_reconfiguration = "enable"
}
+ network {
+ id = 1
+ prefix = "172.28.254.0 255.255.255.0"
}
}
# fortios_system_global.sysglobal will be created
+ resource "fortios_system_global" "sysglobal" {
+ admintimeout = 480
+ hostname = "Core-DC"
+ timezone = "12"
}
# fortios_system_interface.lo0 will be created
+ resource "fortios_system_interface" "lo0" {
+ allowaccess = "ping https ssh snmp http telnet fgfm radius-acct probe-response fabric ftm speed-test"
+ dynamic_sort_subtable = "false"
+ ip = "172.28.255.253 255.255.255.255"
+ mode = "static"
+ name = "lo0"
+ role = "lan"
+ status = "up"
+ type = "loopback"
+ vdom = "root"
# fortios_system_interface.port1 will be created
+ resource "fortios_system_interface" "port1" {
+ alias = "To-Hub1"
+ allowaccess = "ping"
+ device_identification = "enable"
+ dynamic_sort_subtable = "false"
+ ip = "172.28.0.2 255.255.255.252"
+ mode = "static"
+ name = "port1"
+ role = "lan"
+ speed = "auto"
+ status = "up"
+ type = "physical"
+ vdom = "root"
# fortios_system_interface.port2 will be created
+ resource "fortios_system_interface" "port2" {
+ alias = "To-Hub2"
+ allowaccess = "ping"
+ device_identification = "enable"
+ dynamic_sort_subtable = "false"
+ ip = "172.28.0.6 255.255.255.252"
+ mode = "static"
+ name = "port2"
+ role = "lan"
+ speed = "auto"
+ status = "up"
+ type = "physical"
+ vdom = "root"
}
# fortios_system_interface.port3 will be created
+ resource "fortios_system_interface" "port3" {
+ alias = "LAN"
+ allowaccess = "ping"
+ device_identification = "enable"
+ dynamic_sort_subtable = "false"
+ ip = "172.28.254.1 255.255.255.0"
+ mode = "static"
+ name = "port3"
+ role = "lan"
+ speed = "auto"
+ status = "up"
+ type = "physical"
+ vdom = "root"
}
Plan: 8 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
fortios_log_setting.log: Creating...
fortios_system_global.sysglobal: Creating...
fortios_system_interface.lo0: Creating...
fortios_firewall_policy.allow-all: Creating...
fortios_system_interface.port1: Creating...
fortios_system_interface.port3: Creating...
fortios_system_interface.port2: Creating...
fortios_router_bgp.bgp: Creating...
fortios_log_setting.log: Creation complete after 0s [id=LogSetting]
fortios_system_global.sysglobal: Creation complete after 0s [id=SystemGlobal]
fortios_firewall_policy.allow-all: Creation complete after 0s [id=1]
fortios_system_interface.port1: Creation complete after 0s [id=port1]
fortios_system_interface.lo0: Creation complete after 0s [id=lo0]
fortios_system_interface.port2: Creation complete after 0s [id=port2]
fortios_router_bgp.bgp: Creation complete after 0s [id=RouterBgp]
fortios_system_interface.port3: Creation complete after 0s [id=port3]
Apply complete! Resources: 8 added, 0 changed, 0 destroyed.
Checking that it all worked
We see that 8 resources were create so lets take a look at a few of them.
BGP
config router bgp
set as 64999
set router-id 172.28.255.252
set ebgp-multipath enable
set graceful-restart enable
config neighbor
edit "172.28.0.1"
set soft-reconfiguration enable
set remote-as 65000
next
edit "172.28.0.5"
set soft-reconfiguration enable
set remote-as 65000
next
end
config network
edit 1
set prefix 172.28.254.0 255.255.255.0
next
end
config redistribute "connected"
end
config redistribute "rip"
end
config redistribute "ospf"
end
config redistribute "static"
end
config redistribute "isis"
end
config redistribute6 "connected"
end
config redistribute6 "rip"
end
config redistribute6 "ospf"
end
config redistribute6 "static"
end
config redistribute6 "isis"
end
end
Loopback interface
config system interface
edit "lo0"
set vdom "root"
set ip 172.28.255.253 255.255.255.255
set allowaccess ping https ssh snmp http telnet fgfm radius-acct probe-response fabric ftm speed-test
set type loopback
set role lan
set snmp-index 15
next
end
Everything went as expected. In the next post I plan to create some variables so I can create the two hubs at the same time. Here is the source code used in this post.