How to Export CSVs from FortiGate

FortiManager comes with a convenient built-in way to extract almost any data from the UI using a simple web based export tool, however this same functionality is not available when accessing the FortiGate UI directly.

I’ve released a simple Python script to connect to a FortiGate web UI using supplied credentials, and then pull any required REST data and convert it automatically to CSV format.

Example

% python fortigate2csv.py -f 1.2.3.4 -u dan -v management -i address -o address.csv
Enter password:
Connecting to 1.2.3.4 (management) as dan
Successfully logged in as dan
Fetching data...
Logging out of firewall
Saving to address.csv
Done!
% cat address.csv
name,type,subnet,fqdn,associated-interface,visibility,allow-routing,comment
hst-1,ipmask,10.10.10.1 255.255.255.255,,v123,enable,disable,description of host 1
hst-2,ipmask,10.10.10.2 255.255.255.255,,v123,enable,disable,description of host 2
login.microsoft.com,fqdn,,login.microsoft.com,,enable,disable,comment goes here
....

Extending the script

The code is very simple and hopefully self-explanatory, it also comes with a number of defaults to get you started. If you wish to add another type of object, you will simply need to add the API endpoint, along with a list of required headers, for example:

# SNAT Mapping
elif args.item == 'snat':
    data = f.get(f'{base_url}api/v2/cmdb/firewall/central-snat-map/?vdom={args.vdom}').json()
    headers = ['policyid', 'status', 'orig-addr', 'dst-addr', 'srcintf', 'dstintf', 
        'nat', 'nat-ippool', 'comments']

If a field contains a list, instead of a string/int, the list is converted to a space-separated list of q_origin_keys. There is an override for ipv4_addresses headers to display both the IP and the CIDR netmask in the same field:

if header == 'ipv4_addresses': # parse list, extract ip mask for each item within the field
    for x in row[header]:
        subitems.append(f"{x['ip']}/{x['cidr_netmask']}")
else: # parse list, extract q_origin_key for each item within the field
    for x in row[header]:
        subitems.append(x['q_origin_key'])

# join with a space, can't use comma due to csv
row_data.append(' '.join(map(str, subitems))) 

Available on GitHub

The full source code can be found here and is GPL-3.0 licensed for use in your projects ✌️