vladimirs-git / fortigate-api Goto Github PK
View Code? Open in Web Editor NEWPython package for configuring Fortigate (Fortios) devices using REST API
License: Apache License 2.0
Python package for configuring Fortigate (Fortios) devices using REST API
License: Apache License 2.0
In the token check the URL that is checked is .../cmdb/system/status. However this is an undocumented endpoint and might not be supported in future FortiOS versions. I propose that that the following endpoint be used instead: .../monitor/system/status
Hi,
Regarding the policy filters how can I try to get all policies filtered by destination address?
For example to extract all policies that allora traffic to a specific il say 192.168.1.2?
Thanks in advance for your help
Hi I'm trying to user the API to read policies from one firewall and create the very same on another.
reading work perfectly but when I create the policy i get error 500.
I read all policies
for policy in oldfgt.policy.get():
if policy["status"] == "enable":
policies.append(policy)
the filter on which i want i my array then:
for policy in policies:
print("create "+policy['name']);
if confirm_choice() == 'c':
try:
response = newfgt.policy.create(data=policy)
print("policy.create", response)
except:
print("exception "+policy['name'])
else:
print("skip "+policy['name'])
Should I remove some filed on the object?
policyid and uuid ar e then as read from the source, mut I remove those fields?
Thanks in advance
When installing the fortigate-api using pip, it crashes and fails on 'requests' not being present.
× Getting requirements to build wheel did not run successfully.
│ exit code: 1
╰─> [21 lines of output]
Traceback (most recent call last):
File "/tmp/tmp9j5_wgaq_in_process.py", line 363, in <module>
main()
File "/tmp/tmp9j5_wgaq_in_process.py", line 345, in main
json_out['return_val'] = hook(**hook_input['kwargs'])
File "/tmp/tmp9j5_wgaq_in_process.py", line 130, in get_requires_for_build_wheel
return hook(config_settings)
File "/tmp/pip-build-env-6rdrkzvm/overlay/lib/python3.10/site-packages/setuptools/build_meta.py", line 177, in get_requires_for_build_wheel
return self._get_build_requires(
File "/tmp/pip-build-env-6rdrkzvm/overlay/lib/python3.10/site-packages/setuptools/build_meta.py", line 159, in _get_build_requires
self.run_setup()
File "/tmp/pip-build-env-6rdrkzvm/overlay/lib/python3.10/site-packages/setuptools/build_meta.py", line 281, in run_setup
super(_BuildMetaLegacyBackend,
File "/tmp/pip-build-env-6rdrkzvm/overlay/lib/python3.10/site-packages/setuptools/build_meta.py", line 174, in run_setup
exec(code, locals())
File "<string>", line 7, in <module>
File "/tmp/pip-req-build-psl84rhi/fortigate_api/__init__.py", line 3, in <module>
from fortigate_api.fortigate import Fortigate
File "/tmp/pip-req-build-psl84rhi/fortigate_api/fortigate.py", line 12, in <module>
import requests
ModuleNotFoundError: No module named 'requests'
[end of output]
Using a fresh virtualenv the following can be seen. I'm not able to understand yet, why pypi wouldn't honor the "install_requires" argument (or so it seems).
hostname ~/tmp
$ venvcreate
Requirement already satisfied: pip in ./venv/lib/python3.10/site-packages (22.0.4)
Collecting pip
Using cached pip-22.2.1-py3-none-any.whl (2.0 MB)
Requirement already satisfied: setuptools in ./venv/lib/python3.10/site-packages (58.1.0)
Collecting setuptools
Using cached setuptools-63.3.0-py3-none-any.whl (1.2 MB)
Installing collected packages: setuptools, pip
Attempting uninstall: setuptools
Found existing installation: setuptools 58.1.0
Uninstalling setuptools-58.1.0:
Successfully uninstalled setuptools-58.1.0
Attempting uninstall: pip
Found existing installation: pip 22.0.4
Uninstalling pip-22.0.4:
Successfully uninstalled pip-22.0.4
Successfully installed pip-22.2.1 setuptools-63.3.0
(venv) hostname ~/tmp
$ pip install fortigate-api
Collecting fortigate-api
Using cached fortigate_api-0.2.5.tar.gz (30 kB)
Preparing metadata (setup.py) ... error
error: subprocess-exited-with-error
× python setup.py egg_info did not run successfully.
│ exit code: 1
╰─> [10 lines of output]
Traceback (most recent call last):
File "<string>", line 2, in <module>
File "<pip-setuptools-caller>", line 34, in <module>
File "/tmp/pip-install-dsvb5kv5/fortigate-api_01b828e11cff462d9af5d9c172bd885d/setup.py", line 7, in <module>
import fortigate_api as package
File "/tmp/pip-install-dsvb5kv5/fortigate-api_01b828e11cff462d9af5d9c172bd885d/fortigate_api/__init__.py", line 3, in <module>
from fortigate_api.fortigate import Fortigate
File "/tmp/pip-install-dsvb5kv5/fortigate-api_01b828e11cff462d9af5d9c172bd885d/fortigate_api/fortigate.py", line 12, in <module>
import requests
ModuleNotFoundError: No module named 'requests'
[end of output]
note: This error originates from a subprocess, and is likely not a problem with pip.
error: metadata-generation-failed
× Encountered error while generating package metadata.
╰─> See above for output.
note: This is an issue with the package mentioned above, not pip.
hint: See above for details.
python version: 3.10.5
prior versions don't seem to have this issue.
Hello. Is it possible to add execution of execute commands and wake-on-lan command?
Hi,
I am trying to access a REST endpoint that needs to be supplied a query parameter, but due the the URL formatting I am not able to do this.
Example:
from fortigate_api import Fortigate
fgt = Fortigate(host='127.0.0.1', username='user', password='password')
fgt.get('api/v2/monitor/router/lookup?destination=0.0.0.0')
Will return an error "{'error_message': 'Failed to resolve FQDN'}"
because the URL is formatted to be: api/v2/monitor/router/lookup?destination=0.0.0.0/
The _valid_url
function does this:
fortigate-api/fortigate_api/fortigate.py
Line 430 in b19f7bd
Will probably either need to remove the trailing /
from the url, or may extend the get function to also accept parameters.
Happy to raise a PR for this, just not sure which solution you would have preferred.
A hacky workaround I've found is to add an additional query parameter to the URL so that the /
ends up as part of that:
fgt.get('api/v2/monitor/router/lookup?destination=0.0.0.0&ignore')
Thanks,
Aaron
Currently the get token from cookies function has the following loop:
while True:
# fortios < v7
cookie_name = "ccsrftoken"
if cookies := [o for o in session.cookies if o and o.name == cookie_name]:
break
# fortios >= v7
cookie_name += "_"
if cookies := [o for o in session.cookies if o and o.name.startswith(cookie_name)]:
break
raise ValueError("Invalid login credentials. Cookie 'ccsrftoken' is missing.")
token = str(cookies[0].value).strip('"')
return token
In my opinion the logic could be significantly simplified and the loop removed. I've tested it on 7.2.8 and it works flawlessly :)
Let me know what you think!
(Of course the tests would need to be adjusted as they currently check for the underscore as well)
cookie_prefix = "ccsrftoken"
if cookies := [o for o in session.cookies if o and o.name.startswith(cookie_prefix)]:
token = str(cookies[0].value).strip('"')
return token
else:
raise ValueError("Invalid login credentials. Cookie 'ccsrftoken' is missing.")
I would like to ask how the policy and address group are associated, is it through the groups attribute in the policy
Inside the login function the logic for user/password authentication seems flawed.
try:
session.post(
url=f"{self.url}/logincheck",
data=urlencode([("username", self.username), ("secretkey", self.password)]),
timeout=self.timeout,
verify=self.verify,
)
except Exception as ex:
raise self._hide_secret_ex(ex)
token = self._get_token_from_cookies(session)
session.headers.update({"X-CSRFTOKEN": token})
response = session.get(url=f"{self.url}/api/v2/cmdb/system/vdom")
response.raise_for_status()
self._session = session
Let me know what you think about my suggestion!
# password
try:
response: Response = session.post(
url=f"{self.url}/logincheck",
data=urlencode([("username", self.username), ("secretkey", self.password)]),
timeout=self.timeout,
verify=self.verify,
)
except Exception as ex:
raise self._hide_secret_ex(ex)
response.raise_for_status()
token = self._get_token_from_cookies(session)
session.headers.update({"X-CSRFTOKEN": token})
self._session = session
Because the output is already filtered with results dictionary , there is no api call to fetch fortigate serial number can anyone provide me with the url
Hi,
This is a bug in the native Fortigate API (tested on 6.2.0), but if you have a workaround to delete objects, here is the sample code.
from fortigate_api import FortigateAPI
fgt = FortigateAPI(
host="XXX",
username="XXX",
password="XXX",
)
subnet = "42.42.42.42/32"
subnet_name = f"my_vip_{subnet}"
data = {
"name": subnet_name,
"obj-type": "ip",
"subnet": subnet,
"type": "ipmask",
}
print(fgt.address.create(data)) # This works
print(fgt.address.get(uid=subnet_name)) # KO
print(fgt.address.get(filter=f"name=@{subnet_name}")) # This works
print(fgt.address.delete(uid=subnet_name)) # KO
print(fgt.address.delete(filter=f"name=@{subnet_name}")) # KO
hi,
I want to add/delete the system dhcp list with REST API.
But I could find the proper API.
And my environment is,
python 3.10.6
FortiGate 60E with v6.2.4
Thanks in advanced !
Perlang
Hi,
after having upgraded the fortigate to version 7.2.4 I get this error
ValueError: invalid login credentials, absent cookie ccsrftoken
I double checked the credentials and the login still work on an old version of fortigate
Ho can I debug this further?
thanks in advance
DC
Really appreciate your efforts to maintain this project.
I have query regarding adding new IPs under VDOM. We have below function which actually add IPs to firewall.
*response = api.cmdb.firewall.address.create(data)
Also, is it possible to use port 8443 for create firewall address operation?
Thanks!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.