├── README.md ├── api_prefix_list_not_working.py └── fw_api_test.py /README.md: -------------------------------------------------------------------------------- 1 | ## fw_api_test 2 | Main library to interface with the Fortigate API 3 | It's best to use it with Fortigates running code 5.4 and later, as 5.2 lacks lots of API calls. 4 | 5 | Consider taking a look at the [Ansible modules](https://github.com/eoprede/ansible_fortios_api) that are based on this library, as they provide lots of additional functionality for managing the Fortigate Firewalls. 6 | 7 | ### Usage: 8 | 9 | ##### Instantiate object 10 | ``` 11 | fw = fortigate_api('1.2.3.4:10443', un, pw) 12 | ``` 13 | Proxy servers are supported as well: 14 | Note that you will need to install socks5 for requests library: http://docs.python-requests.org/en/master/user/advanced/#socks 15 | ``` 16 | proxy={'https': 'socks5://127.0.0.1:9000'} 17 | fw = fortigate_api('1.2.3.4:10443', un, pw, proxies=proxy) 18 | ``` 19 | You can enable HTTPS warnings if you are using real certs: 20 | ``` 21 | fw = fortigate_api('1.2.3.4:10443', un, pw, disable_warnings=False) 22 | ``` 23 | 24 | #### Show parameters of an object 25 | For example, to print all the interfaces: 26 | ``` 27 | a = fw.show(['cmdb', 'system', 'interface']) 28 | fw.print_data(a) 29 | ``` 30 | You can print only specific interface: 31 | ``` 32 | a = fw.show('cmdb/system/interface/port1') # note that you can provide either string or a list for API path 33 | fw.print_data(a) 34 | ``` 35 | Sometimes it's hard to find the exact API path, so you can display the API schema (beware that it's very large) 36 | ``` 37 | fw.show(['cmdb', 'system', 'interface'], params={'action':'schema'})) 38 | ``` 39 | or for all the configurable objects (9M file), you can do 40 | ``` 41 | fw.show(['cmdb'], params={'action':'schema'})) 42 | ``` 43 | 44 | #### Edit parameters of an object 45 | For example, edit route 1 and display OK if change successful: 46 | ``` 47 | a = fw.edit(['cmdb', 'router', 'static', '1'], data={"device": "FW_IP_outbound","dst": "0.0.0.0 0.0.0.0","gateway": "10.0.1.1","comment": "Default route for FW outbound"}) 48 | fw.print_data(a) 49 | ``` 50 | 51 | #### Remove object 52 | For example, remove DHCP server 1 53 | ``` 54 | fw.remove(['cmdb', 'system.dhcp', 'server', '1']) 55 | ``` 56 | 57 | #### Create new object 58 | For example, create new firewall rule: 59 | ``` 60 | policy = {"action": "accept", 61 | "dstaddr": [{"name": "all"}], 62 | "dstintf": [{"name": "Ext1"}], 63 | "name": "Allow_all_in", 64 | "nat": "disable", 65 | "policyid": 1, 66 | "schedule": "always", 67 | "service": [{"name": "ALL"}], 68 | "srcaddr": [{"name": "all"}], 69 | "srcintf": [{"name": "Ext2"}], 70 | "status": "disable"} 71 | fw.create (['cmdb','firewall','policy'], data=policy) 72 | ``` 73 | 74 | #### Move policy around 75 | By default, new policy is being placed at the end of the rules list. You can move it aroud as needed with the following code: 76 | ``` 77 | fw.edit(['cmdb', 'firewall', 'policy', '3'], params={"action": "move", "before": "1"}) 78 | fw.edit(['cmdb', 'firewall', 'policy', '3'], params={"action": "move", "after": "1"}) 79 | ``` 80 | Note that you are referencing policies by their ID and not their position in the list. The first example above does not guarantee that the rule will be placed 1st in the rule list, as policy with ID 1 can be located anywhere in the list. 81 | 82 | #### Working with VDOMs 83 | By default, you are working with VDOM root, but you can specify any other VDOM with params={'vdom':'WAN'} 84 | For example, previous API call with VDOM would look like this: 85 | ``` 86 | fw.create (['cmdb','firewall','policy'], params={'vdom':'WAN'}, data=policy) 87 | ``` 88 | 89 | #### Known issues 90 | * Error checking is non-existent. For example, failed authentication would be raised as a JSON exception (as there would be nothing to decode from an API response, as there would be none) 91 | -------------------------------------------------------------------------------- /api_prefix_list_not_working.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import pprint 4 | import json 5 | import requests 6 | import time 7 | import getpass 8 | 9 | 10 | class fortigate_api: 11 | 12 | def __init__(self, ip, un, pw, verify=False, proxies=None, disable_warnings=True): 13 | if disable_warnings: 14 | requests.packages.urllib3.disable_warnings() 15 | unpw = {'username':un,'secretkey':pw} 16 | self.verify = verify 17 | self.ip = ip 18 | self.proxies=proxies 19 | auth = requests.post('https://'+self.ip+'/logincheck', data=unpw, verify=self.verify, proxies=self.proxies) 20 | self.cookies = auth.cookies 21 | for cookie in self.cookies: 22 | if cookie.name == "ccsrftoken": 23 | csrftoken = cookie.value[1:-1] # token stored as a list 24 | self.header = {"X-CSRFTOKEN": csrftoken} 25 | 26 | def __enter__(self): 27 | return self 28 | 29 | def __del__(self): 30 | requests.post('https://'+self.ip+'/logout', verify=self.verify, cookies=self.cookies, proxies=self.proxies) 31 | 32 | def __exit__(self, *args): 33 | pass 34 | 35 | def get(self, path, api='v2', params=None): 36 | if isinstance(path, list): 37 | path = '/'.join(path) + '/' 38 | return requests.get('https://'+self.ip+'/api/'+api+'/'+path, cookies=self.cookies, verify=self.verify, proxies=self.proxies, params=params) 39 | 40 | def put(self, path, api='v2', params=None, data=None): 41 | if isinstance(path, list): 42 | path = '/'.join(path) + '/' 43 | return requests.put('https://'+self.ip+'/api/'+api+'/'+path, headers=self.header,cookies=self.cookies, 44 | verify=self.verify, proxies=self.proxies, params=params, json={'json': data}) 45 | 46 | def post(self, path, api='v2', params=None, data=None, files=None): 47 | if isinstance(path, list): 48 | path = '/'.join(path) + '/' 49 | return requests.post('https://'+self.ip+'/api/'+api+'/'+path, headers=self.header,cookies=self.cookies, 50 | verify=self.verify, proxies=self.proxies, params=params, json={'json': data}, 51 | files=files) 52 | 53 | def delete(self, path, api='v2', params=None, data=None): 54 | if isinstance(path, list): 55 | path = '/'.join(path) + '/' 56 | return requests.delete('https://'+self.ip+'/api/'+api+'/'+path, headers=self.header,cookies=self.cookies, 57 | verify=self.verify, proxies=self.proxies, params=params, json={'json': data}) 58 | 59 | def show(self, path, api='v2', params=None): 60 | response = json.loads(self.get(path, api=api, params=params).content) 61 | return response 62 | 63 | def edit(self, path, api='v2', params=None, data=None): 64 | response = json.loads(self.put(path, api=api, params=params, data=data).content) 65 | return response 66 | 67 | def create(self, path, api='v2', params=None, data=None, files=None): 68 | response = json.loads(self.post(path, api=api, params=params, data=data, files=files).content) 69 | return response 70 | 71 | def remove(self, path, api='v2', params=None, data=None): 72 | response = json.loads(self.delete(path, api=api, params=params, data=data).content) 73 | return response 74 | 75 | @staticmethod 76 | def print_data(response, verbose=False): 77 | if response['status']=='success': 78 | if verbose: 79 | pprint.pprint (response) 80 | elif response['http_method']=='GET': 81 | pprint.pprint (response['results']) 82 | else: 83 | print ('OK!') 84 | else: 85 | print ('Fail!') 86 | pprint.pprint (response) 87 | 88 | 89 | 90 | def main(): 91 | un = "admin" 92 | pw = getpass.getpass() 93 | proxy = None 94 | 95 | fw = '10.0.1.2:10443' 96 | 97 | prefixlists = [ 98 | {"name":"default_only","rule":[{"prefix":"0.0.0.0 0.0.0.0"}]}, 99 | {"name":"dwre_sf_block6","rule":[{"prefix":"10.254.162.0 255.255.255.0","ge":25}]} 100 | ] 101 | 102 | try: 103 | t = fortigate_api(fw, un, pw, proxies=proxy) 104 | t.print_data (t.edit(['cmdb', 'router', 'prefix-list', 'dwre_sf_block6'], data = prefixlists[1])) 105 | t.print_data (t.show(['cmdb', 'router', 'prefix-list', 'dwre_sf_block6'])) 106 | 107 | except: 108 | print ('something went wrong') 109 | raise 110 | 111 | if __name__ == "__main__": 112 | main() 113 | -------------------------------------------------------------------------------- /fw_api_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import pprint 4 | import requests 5 | import getpass 6 | 7 | 8 | class fortigate_api: 9 | 10 | _secure=True 11 | 12 | def __init__(self, ip, un, pw, verify=False, proxies=None, disable_warnings=True, secure=True): 13 | if disable_warnings: 14 | requests.packages.urllib3.disable_warnings() 15 | unpw = {'username':un,'secretkey':pw} 16 | self._secure=secure 17 | self.verify = verify 18 | self.ip = ip 19 | self.proxies=proxies 20 | if self._secure: 21 | http='https://' 22 | else: 23 | http='http://' 24 | auth = requests.post(http+self.ip+'/logincheck', data=unpw, verify=self.verify, proxies=self.proxies) 25 | self.cookies = auth.cookies 26 | for cookie in self.cookies: 27 | if cookie.name == "ccsrftoken": 28 | csrftoken = cookie.value[1:-1] # token stored as a list 29 | self.header = {"X-CSRFTOKEN": csrftoken} 30 | 31 | def __enter__(self): 32 | return self 33 | 34 | def __del__(self): 35 | if self._secure: 36 | http='https://' 37 | else: 38 | http='http://' 39 | try: 40 | requests.post(http+self.ip+'/logout', verify=self.verify, cookies=self.cookies, proxies=self.proxies) 41 | except AttributeError: 42 | print ("Looks like connection to "+self.ip+" has never been established") 43 | 44 | 45 | 46 | def __exit__(self, *args): 47 | pass 48 | 49 | def get(self, path, api='v2', params=None): 50 | if isinstance(path, list): 51 | path = '/'.join(path) + '/' 52 | if self._secure: 53 | http='https://' 54 | else: 55 | http='http://' 56 | return requests.get(http+self.ip+'/api/'+api+'/'+path, cookies=self.cookies, verify=self.verify, proxies=self.proxies, params=params) 57 | 58 | def put(self, path, api='v2', params=None, data=None): 59 | if isinstance(path, list): 60 | path = '/'.join(path) + '/' 61 | if self._secure: 62 | http='https://' 63 | else: 64 | http='http://' 65 | return requests.put(http+self.ip+'/api/'+api+'/'+path, headers=self.header,cookies=self.cookies, 66 | verify=self.verify, proxies=self.proxies, params=params, json={'json': data}) 67 | 68 | def post(self, path, api='v2', params=None, data=None, files=None): 69 | if isinstance(path, list): 70 | path = '/'.join(path) + '/' 71 | if self._secure: 72 | http='https://' 73 | else: 74 | http='http://' 75 | return requests.post(http+self.ip+'/api/'+api+'/'+path, headers=self.header,cookies=self.cookies, 76 | verify=self.verify, proxies=self.proxies, params=params, json={'json': data}, 77 | files=files) 78 | 79 | def delete(self, path, api='v2', params=None, data=None): 80 | if isinstance(path, list): 81 | path = '/'.join(path) + '/' 82 | if self._secure: 83 | http='https://' 84 | else: 85 | http='http://' 86 | return requests.delete(http+self.ip+'/api/'+api+'/'+path, headers=self.header,cookies=self.cookies, 87 | verify=self.verify, proxies=self.proxies, params=params, json={'json': data}) 88 | 89 | def show(self, path, api='v2', params=None): 90 | response = self.get(path, api=api, params=params) 91 | return response.json() 92 | 93 | def edit(self, path, api='v2', params=None, data=None): 94 | response = self.put(path, api=api, params=params, data=data) 95 | return response.json() 96 | 97 | def create(self, path, api='v2', params=None, data=None, files=None): 98 | response = self.post(path, api=api, params=params, data=data, files=files) 99 | return response.json() 100 | 101 | def remove(self, path, api='v2', params=None, data=None): 102 | response = self.delete(path, api=api, params=params, data=data) 103 | return response.json() 104 | 105 | @staticmethod 106 | def print_data(response, verbose=False): 107 | if response['status']=='success': 108 | if verbose: 109 | pprint.pprint (response) 110 | elif response['http_method']=='GET': 111 | pprint.pprint (response['results']) 112 | else: 113 | print ('OK!') 114 | else: 115 | print ('Fail!') 116 | pprint.pprint (response) 117 | 118 | 119 | 120 | def main(): 121 | un = "admin" 122 | pw = getpass.getpass() 123 | #proxy={'http': 'socks5://127.0.0.1:9000'} 124 | proxy = None 125 | 126 | fw = '192.168.3.19' 127 | 128 | intf = { 129 | "name": "testagg", 130 | "vdom": "root", 131 | "allowaccess": "ping", 132 | "ip": "1.1.1.1 255.255.255.0", 133 | "role": "lan", 134 | "type": "aggregate", 135 | "member": [ 136 | { 137 | "interface-name": "port6" 138 | }, 139 | { 140 | "interface-name": "port7" 141 | } 142 | ] 143 | } 144 | 145 | try: 146 | t = fortigate_api(fw, un, pw, proxies=proxy) 147 | t.print_data (t.show('cmdb/system/interface')) 148 | t.print_data (t.create('cmdb/system/interface', data=intf)) 149 | 150 | except: 151 | print ('something went wrong') 152 | raise 153 | 154 | if __name__ == "__main__": 155 | main() 156 | --------------------------------------------------------------------------------