Skip to main content

Managing FortiOS using Terraform

You want to manage your FortiOS device like Fortigate using a more reliable and a “zero-touch” environment. The Fortinet’s main goal with this provider, I guess, is for those who want to fully automate their environments on AWS, Azure, GCP or another cloud provider. But you can also use this provider to maintain your Fortigate box as well in a very efficient way.

Yeah, I know, Ansible. Maybe It’s a better way to do this kind of management using Ansible, but I just want to show you that it is possible to do it in a different way. Maybe in the future I can write a post showing how to use Ansible to manage your FortiOS or your Fortigate box.

I will just show how to make simple things. If this could be useful to you, I’m pretty sure you will easily understand the provider’s documentation and make your own configs.

But let’s go to business.

First of all, we need to use our provider. To keep things simple, let’s create a directory called “fortios”

mkdir fortios
cd fortios

Now create a file called vars.tf. We will use this file for.. of course, our variables.

vim vars.tf

And let’s define our provider and the information about our Fortigate.

terraform {
  required_providers {
    fortios = { source = fortinetdev/fortios }
  }
}

provider fortios {
  hostname = 192.168.0.1:443  #your fortigate
  token = your token # wait a sec.. I will tell you how to create yours
  insecure = true #if you don’t want to trouble yourself with certificates. But maybe you should
}

Alright, this is what we need to start. Well, almost everything. To create your own token, go on your Fortigate and create an api-user.

config system api-user
  edit "tf-admin"
    set comments "Terraform"
    set accprofile "admin_terraform"
    config trusthost
      edit 1
        set ipv4-trusthost 192.168.0.100 255.255.255.255
      next
    end
next
end

As you can see, I’ve created an api-user “admin_terraform” and this user is allowed only from the IP 192.168.0.100/32. After you create the user, an api-key will be generated.

Now, we are able to set some configs in our Fortigate. Let’s play!

Create a new file named as system.tf.

resource fortios_system_global default_global {
  hostname = My_Fortigate
}

resource fortios_system_settings default_settings {
  gui_advanced_polity = enable
  gui_allow_unnamed_policy = enable
  gui_dynamic_routing = enable
}

Well, that’s enough here. If you are used to using the FortiOS CLI, you probably know what we just did. Easy right? Let me show you how to manage your Addresses Objects for example.

resource fortios_firewall_address PREFIX_10-8 {
  allow_routing = disable
  name             = PREFIX_10/8
  subnet           = 10.0.0.0 255.0.0.0
  type               = ipmask
  visibility         = enable
}
resource "fortios_firewall_address" "PREFIX_172-16-12" {
  allow_routing = "disable"
  name          = "PREFIX_172.16/12"
  subnet        = "172.16.0.0 255.240.0.0"
  type          = "ipmask"
  visibility    = "enable"
}

resource "fortios_firewall_address" "PREFIX_192-168-16" {
  allow_routing = "disable"
  name          = "PREFIX_192.168/16"
  subnet        = "192.168.0.0 255.255.0.0"
  type          = "ipmask"
  visibility    = "enable"
}

resource "fortios_firewall_addrgrp" "rfc-1918" {
  allow_routing = "disable"
  color         = "26"
  exclude       = "disable"
  name          = "RFC_1918"
  type          = "folder"
  visibility    = "enable"

  member { name = fortios_firewall_address.PREFIX_10-8.name }
  member { name = fortios_firewall_address.PREFIX_172-16-12.name }
  member { name = fortios_firewall_address.PREFIX_192-168-16.name }
}

Yeah, we’ve just created three objects for our subnets and a group called RFC_1918 using them.

Now, let’s make a firewall rule just for fun.

resource fortios_firewall_policy rule_01 {
  action = "accept"
  dstaddr { name = fortios_firewall_addrgrp.rfc-1918.name }
  dstaddr_negate = "enable"
  dstintf   { name = wan1 }
  logtraffic = "all"
  name    = "LAN to WAN"
  nat = "enable"
  schedule = "always"
  service { name = "ALL" }
  srcaddr { name = fortios_firewall_address.PREFIX_192-168-16.name }
  srcintf { name = lan1 }
  ssl_ssh_profile  = "certificate-inspection"
  utm_status       = "enable"
}

Again, I’m pretty sure if you are familiar with FortiOS CLI, you will do pretty good using Terraform.

Quick tip to use terraform (after installing it of course).

Download the provider and set everything to work.

terraform init

Check if your configuration is valid.

terraform validate

Shows the changes required to run the configuration that you have defined.

terraform plan

Apply your configuration.

terraform apply

That’s it.. thank you for reading.

FortiOS provider for Terraform

fortigate-terraform in Github