Dit artikel beschrijft handvaten voor Ansible tasks voor het maken van FortiGate backups voor FortiGates met verschillende versies en API releases.
In onze beheeromgeving gebruiken we Ansible voor het aansturen van onze FOSS servers en software, maar ook voor bulk changes op networking devices en nuttige automation voor onze hosted diensten.
Voor onze beheer klanten maken we dagelijks backups van de devices en waar mogelijk doen we dit met de door de vendor beschikbaar gestelde Ansible collections.
In dit voorbeeld wordt de FortiOS collection van FortiNet gebruikt, deze is te vinden via: https://ansible-galaxy-fortios-docs.readthedocs.io/en/latest/index.html.
Onderstaande voorbeelden beschrijven Ansible tasks waarmee backups kunnen worden gemaakt van FortiGates met verschillende versie FortiOS.
Ansible tasks:
Ansible begrippen als inventory en variaben alsmede connectivity zijn buiten scope van het artikel, om te beginnen definieren we onderstaande parameters in ons denkbeeldige <backup-fortigates.yml> playbook:
---
- hosts: fortigates # Alle FortiGates in de Inventory
ignore_unreachable: yes # Doorgaan als een FortiGate onbereikbaar is
ignore_errors: yes # Doorgaan als er een fout plaatsvind
gather_facts: no # Deze moeten via API uitgevraagd worden
connection: ansible.netcommon.httpapi
collections:
- fortinet.fortios
vars:
date: "{{ lookup('pipe', 'date +%Y-%m-%d-%Hh%Mm') }}"
ansible_network_os: fortinet.fortios.fortios
ansible_httpapi_use_ssl: yes
ansible_httpapi_validate_certs: no
ansible_httpapi_port: "{{ ansible_port }}"
ansible_user: "{{ api_access_user }}"
ansible_password: "{{ api_access_token }}"
backup_location: ./backup
tasks:
Generiek voor zowel FortiOS 6 en 7 is de < fortios_configuration_fact> module, hiermee vragen we de <system_global> selector uit die veel informatie over het FortiGate device geeft. We registreren de uitkomst als <fortios_facts> en maken er daarna, een werkbaar geformatteerd, Ansible <fact> genaamd <fortios_major> van voor gebruik in andere plays:
- name: Gather FortiOS facts
fortinet.fortios.fortios_configuration_fact:
selector: system_global
register: fortios_facts
- set_fact:
fortios_major: "{{ fortios_facts.meta.version | regex_replace('^v', '') | split('.') | first | int }}"
Optionele debug tasks om de fact uit te lezen.
- name: Run when FortiOS major version = 6
debug:
msg: "Major version is {{ fortios_major }}"
when: fortios_major == "6"
- name: Run when FortiOS major version = 7
debug:
msg: "Major version is {{ fortios_major }}"
when: fortios_major == "7"
Wanneer we de FortiOS versie in het Ansible fact hebben opgeslagen kunnen we met <block:>Â en <when:> verschillende plays afdwingen voor verschillende versies FortiOS.
Voor versie 7 gebruiken we de module <fortios_monitor> met de selector <backup.system.config>. We registreren de uitkomst als <backup_v7> voor later gebruik:
- name: Backup v7 FortiOS
when: fortios_major == "7" and inventory_hostname != 'not-this-fgate.example.com' #*
block:
- name: Backup a virtual domain v7.
fortios_monitor:
selector: 'backup.system.config'
vdom: 'root'
params:
scope: 'global'
register: backup_v7
Voor versie 6 gebruiken we de module <fortios_monitor_fact> met de selector <system_config_backup>, dus anders dan voor versie 7! We registreren de uitkomst als <backup_v6> voor later gebruik:
- name: Backup v6 FortiOS
when: fortios_major == "6" or inventory_hostname == 'and-this-fgate.example.com' #*
block:
- name: Backup a virtual domain v6.
fortios_monitor_fact:
selector: 'system_config_backup'
vdom: 'root'
params:
scope: 'global'
register: backup_v6
* Zowel in de versie 6 en 7 backup <block:> valt wellicht op dat er in de <when:> statement respectievelijk een AND en OR zijn meegenomen voor de <inventory_hostname> in de syntax. Dit is om uitzonderingen te kunnen maken. Sommige hardware uitvoeringen van de FortiGate gebruiken ondanks FortiOS 7 toch nog de oude API en dus de oude selector.
De geregistreerde variabelen <backup_v7> en <backup_v6> worden samengevoegd in een nieuwe Ansible fact <device_backup>. Waarvan de <failed> key in een debug weergeven wordt.
- name: Pick and combine the backup result
set_fact:
device_backup: >-
{{ backup_v7 if (backup_v7 is defined and not backup_v7 is skipped) else backup_v6 }}
- name: Debug device_backup
debug:
var: device_backup.failed
Hoewel de <*backup*> selectors in de nieuwere versies ook parameters bevatten voor het direct aanmaken van een destination file en directory kiezen wij ervoor dat zelf te controleren door de content van de data van de <meta.raw> key uit de <device_backup> variabele te schrijven naar een dynamisch opgebouwde filenaam, dit proberen we alleen als de <failed> key van <device_backup> de waarde false heeft:
- name: Write backup content to disk
copy:
content: |
{{ device_backup.meta.raw }}
dest: "{{backup_location}}-{{inventory_hostname}}-{{date}}.cfg"
when: device_backup.failed == false
Tot slot importeren we enkele generieke tasks in het playbook voor de reporting van de backup naar csv logs voor email notificatie en naar json logs voor verwerking in ons monitoring systeem.
De geimporteerde reporting tasks leunen op de <device_backup> variabele. Het samenvoegen van de V6 en V7 backup resultaten zijn daarom een onmisbare stap in dit multi versie FortiGate backup playbook.





