Fortigate SDWAN – All-In-One internet resilience

SDWAN is booming, and lots of vendors are promoting their SDWAN. According to Wikipedia, any SDWAN should have these characteristics:

  • The ability to support multiple connection types, such as MPLSframe relay and higher capacity LTE wireless communications
  • The ability to do dynamic path selection, for load sharing and resiliency purposes
  • A simple interface that is easy to configure and manage
  • The ability to support VPNs, and third party services such as WAN optimization controllers, firewalls and web gateways
Continue reading “Fortigate SDWAN – All-In-One internet resilience”

Fortigate config management in Github

After Github opened its free repository function to free users, I’m using Github private repository to store lots of my applications config file. I usually don’t use version management because they usually never changes after initial deployment. However, especially while I write blog post I need to make changes just to check the functionality. And sometimes I forgot to rollback config and need to check manually on the device.

In this post, I show you how to integrate Fortigate config backup script and Github API. And in the next post I will deploy them in CloudFunction so that it can be invoked by Fortigate automation stitch.

Continue reading “Fortigate config management in Github”

Fortigate RestAPI Config Backup – FortiOS 6.0.4

Previously I wrote a post how to backup the Fortigate config using session based authentication. As per the API reference, this is considered legacy, and other authentication method –API token, is preferred. In this post, I demonstrate how to use FortiOS RestAPI with API token. And I will introduce how to parse current configuration.

I used FortiOS 6.0.4 to deploy this, and it is most likely not working with other version(especially 5.x).

The flow is as follows:

  1. Create access profile for API user
  2. Create API user in Fortigate
  3. Generate API token for API user
  4. Send request and get the backup config
Continue reading “Fortigate RestAPI Config Backup – FortiOS 6.0.4”

Fortigate Config Change Notification

Whenever changes are made in configuration, Fortigate posts notification at Slack channel.

Fortigate automation is composed of three elements:

  1. automation trigger … available trigger -HA Failover, Config change, Log, IOC, High CPU, Conserve mode
  2. automation action … available action -Email, IP Ban, AWS lambda, Webhook
  3. automation stitch … Combination of trigger and action
Continue reading “Fortigate Config Change Notification”

Python 100 project #37: Fortigate config backup via scp

Backup network device configuration is tedious job. I created backup script so that you can retrieve fortigate config.

Output Example:

Here is the code:

def backup_config(ip, username, password, full=False, path=None):
    Retrieve fortigate configuration and save it to the local path
    :param ip: a string for target ip address
    :param username: a string for username who has read access
    :param password: a string for password
    :param full: boolean . Get full config if True, Get minimum config(diff from the factory default conifg) if False
    :param path: path to save the backup file
    :return: Name of the file saved with full path
    import paramiko
    from scp import SCPClient

    ssh = paramiko.client.SSHClient()
    # ssh.load_system_host_keys()
    ssh.connect(ip, username=username, password=password)

    with SCPClient(ssh.get_transport()) as scp:
        if full:
            config = 'fgt_config'
            config = 'sys_config'

    return "DONE!"

Python 100 project #30: Fortigate Policy to CSV

Today I made a script it takes fortigate config, and make a csv file for firewall policies.

If I use API, it can be much easier, as it does not require any data transformation required to collect those data. But still there are lots of cases (and most of the cases for me) the API is not enabled on the unit. In those cases, I need to use text based config file to make a parameter sheet.


Output Example:

>>> from fortigate_helper import policy_to_dict
>>> from helper.dict_helper import to_csv
>>> policies = policy_to_dict('data_source/fg_sample_config.txt')
>>> to_csv(policies, 'data_out/fg_sample_policies.csv')


Here is the code:

def policy_to_dict(file):
    from collections import defaultdict

    parameters = [

    policy_dict = defaultdict(dict)

    policy_statements = []

    with open(file, "r") as f:
        in_policy = False
        for line in f:
            line = line.strip()
            # check if it's under 'config firewall policy' section. Emit 'next' also.
            if in_policy and line != "next":

                if line == "end":

                if line == "config firewall policy":
                    in_policy = True

    if policy_statements:

        for statement in policy_statements:
            op, param, *val = statement.split()
            if op == "edit":
                policy_id = param
            elif op == "set" and param in parameters:
                policy_dict[policy_id][param] = ' '.join(val)

    return policy_dict


Python 100 project #10: FortiAnalyzer Past week Top Website

One thing I found out during the API exploration of various vendor, Fortinet is one of the vendor which has a broad set of those interfaces among their product lines. It was surprising as I had thought Fortinet had been one of the most locked in company in terms of API (as the document is extremely difficult to find).

Some of their product can be deployed onto the AWS quite easily, hence it’s easy to evaluate, and once you have access to the right channel, it has quite a bunch of resource to support you.


Output Example:

Streaming Media and Download 137171.941
Advertising 49508.214
Business 45659.808
Internet Radio and TV 27932.994
Information Technology 25066.791
Health and Wellness 18918.331
Government and Legal Organizations 18881.806
Web Hosting 18608.554
Shopping 10576.678
Education 9224.136
Games 9083.764
Newly Observed Domain 7193.726
Personal Websites and Blogs 7054.746
Society and Lifestyles 4378.23
Unrated 3771.063
Content Servers 2933.707
Search Engines and Portals 1620.786
Meaningless Content 1577.338
Restaurant and Dining 535.872
Proxy Avoidance 494.937
Malicious Websites 188.418
Newsgroups and Message Boards 160.979
News and Media 138.786
Social Networking 64.236
Information and Computer Security 51.736
Reference 44.47
Finance and Banking 42.153
Travel 29.101
Web Analytics 17.174
Entertainment 8.232
Web-based Applications 3.737
Instant Messaging 2.95

Because I usually watch Netflix for a few hours everyday, it occupies most of the internet usage.


Here is the code:

Most of the connection sequence, I used the class provided by Fortinet team (FNTNLIB).

import operator

import fmg_jsonapi

IPADDR = "your-fortianalyzer-ipaddress"
USER = "admin"
PASSWD = "your-admin-password"

def get_top_website_params():
    from datetime import datetime, timedelta

    current_time =
    week_before = current_time - timedelta(days=7)

    top_web_params = {
        "case-sensitive": "false",
        "device": [{"devid": "All_Devices"}],
        "filter": "",
        "limit": 100,
        "sort-by": [
                "field": "bandwidth",
                "order": "desc"
        "time-range": {
            "end": current_time.strftime("%Y-%m-%d %H:%M"),
            "start": week_before.strftime("%Y-%m-%d %H:%M"),
        "url": "/fortiview/adom/root/top-websites/run"

    return top_web_params

def get_task_params(task_id):
    task_params = {
        "url": "/fortiview/adom/root/top-sources/run/" + str(task_id)

    return task_params

def get_data():
    conn = fmg_jsonapi.FortiManagerJSON()
    # conn.verbose('on')
    # conn.debug('on')
    conn.login(IPADDR, USER, PASSWD)

    # create top website viewer tasks
    params1 = [{"apiver": 3}]
    status, data = conn.http_request('add', params1)

    task_id = data['tid']
    params2 = [{"apiver": 3}]
    status, data = conn.http_request('get', params2)

    # conn.verbose('off')
    # conn.debug('off')

    return data

if __name__ == "__main__":

    d = get_data()

    traffic_data = {}
    for category in d['data']:
        traffic_data[category['catdesc']] = float(category['bandwidth'])

    sorted_traffic_data = sorted(traffic_data.items(), key=operator.itemgetter(1), reverse=True)

    for cat in sorted_traffic_data:
        print(cat[0], cat[1]/1000)



これをEcho Spot, Echo Showなどと組み合わせれば、音声で過去一週間でどのようなWebサイトが閲覧されたかが表示される。