Haven’t we all used that old copy-paste document from way back which a guy at the office made for standard device configuration?
There’s absolutely nothing wrong with using a template cli configuration file, but the backside with using a static template like that is that it doesn’t take new firmware/syntax changes into account.
With Ansible, this will be handled by the library itself, and you can use the same configuration file to configure a bunch of different versions of FortiOS.
This article will go into how I got started to use Ansible for my base configuration and also show a few examples of my playbooks.
Getting started
I’m using a managed Macbook pro with an M1 chip. For some reason I could not get Ansible to run properly on it, so I’m using an Ubuntu VM to execute all my playbooks. I would’ve preferred to run it natively on my mac, but this would have to do for the time being.
This link will take you to the install guide, but it’s basically three steps:
When you have installed that you have all the building blocks required to get started. However, I strongly recommend that you get yourself an editor with support for the YAML linter. (A linter is “syntax highlighter with rules” more or less.) Personally I run Visual Studio Code.
Now that you have both Ansible install, and an editor to start creating files with, lets get going!
Creating your first host file
To define which unit you are going to configure with your Ansible script you will need a file which specifies a few things. First of all, here’s an example of the content of a host file I use when I try things in my lab.
[fortigates]
#fw01 ansible_host=10.200.200.199 ansible_user="admin" ansible_password="fortinet"
#FW01 ansible_host=10.0.0.1 ansible_user="admin" ansible_password="fortinet"
FW01_HOME ansible_host=192.168.68.199 ansible_user="admin" ansible_password="fortinet" fortigate_hostname="FW01"
[fortigates:vars]
ansible_network_os=fortinet.fortios.fortios
Note that a line with # in the start will mean that it’s a comment and will be ignored when you run your playbook.
I’ll explain each part of this. We’ll look into the row which is not excluded.
But first we’ll look into the first row of the file.
[fortigates]
This is a group value which we will reference when we want to run stuff towards our fortigates that we declare into this group. You can name them whatever you want, for instance [branch_offices], [datacenter-firewalls] or whatever fits into your current environment.
FW01_HOME
This is the name of the inventory item. So this is what you see when your playbooks run
per@ansible:~/GitHub/ftnt/Tools/Ansible$ ansible-playbook -i hosts playbooks/fortigate_connect_fmg.yml
PLAY [fortigates]**********************************************************************************************************************************************************************
TASK [Gathering Facts] *****************************************************************************************************************************************************************
ok: [FW01_HOME]
TASK [Configure central management.] ***************************************************************************************************************************************************
changed: [FW01_HOME]
PLAY RECAP *****************************************************************************************************************************************************************************
FW01_HOME : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
ansible_host=192.168.68.199
the ansible_host part of the code is the destination from where we reach this device. This can also include a different port. Depending in your Ansible connection method this can change from various protocols such as HTTPS or SSH to telnet etc. Note that the FortiOS collection is using HTTP-api as connection method and is more or less the same thing that happens when you log into your FortiGate using your browser.
ansible_user="admin"
This is the user used to connect to your device.
ansible_password="fortinet"
This might feel self-explanatory but I’ll describe it anyway. This is the password that your user will use when connecting to your device.
I have also added another variable which I want to load into my playbooks.
fortigate_hostname="FW01"
I would recommend that you declare all unique variables in the host file (or in a separate file other than the playbook) to make your playbooks scale a bit better. If you run your Ansible playbooks towards multiple devices at the same time you want the unique configuration to be happening with altering the script itself before proceed from FW01 to FW02 for instance.
Now that we have declared to which devices we want to run our playbooks we can start creating them.
Let’s write a simple playbook that sets the hostname of a FortiGate using the variable set in the hosts file.
---
- hosts: fortigates
collections:
- fortinet.fortios
connection: httpapi
vars:
vdom: "root"
ansible_httpapi_use_ssl: yes
ansible_httpapi_validate_certs: no
ansible_httpapi_port: 443
tasks:
- name: Configure global attributes.
fortios_system_global:
vdom: "{{ vdom }}"
system_global:
hostname: "{{ fortigate_hostname }}"
This playbook will connect to all your [fortigates] using the fortinet.fortios ansible galaxy collection.
It will configure the hostname in the VDOM named ‘root’ in this case (so if you have VDOMs enabled you will need to change this to global.)
The script will then jump into system global (config system global) and set the hostname to whatever the variable {{ fortigate_hostname }} resolves to. In our case in this article it’s FW01. (set hostname FW01)
I hope this article gets you enough of information to get started with Ansible to leverage it for at least some standardization with your base configuration.





Leave a comment