kaisero / firerest Goto Github PK
View Code? Open in Web Editor NEWPython library for interacting with Cisco Firepower Management Center REST API
License: GNU General Public License v3.0
Python library for interacting with Cisco Firepower Management Center REST API
License: GNU General Public License v3.0
Currently if Connection is refused by FMC (e.g. not reachable) ConnectionError is thrown.
ConnectionError: HTTPSConnectionPool(host='fmc.example.com', port=443): Max
retries exceeded with url: /api/fmc_platform/v1/auth/generatetoken (Caused by
NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x10dc3f490>:
Failed to establish a new connection: [Errno 61] Connection refused'))
This should be replaced with a more user friendly custom exception
Looking at the 6.6.6 API for documentation for this endpoint, it should be 'above_category' instead of 'before_category'?
I don't think category supports the other parameters defined in this class either.
I can do a pull request to manually change it but thought I would check if these classes are automatically generated?
The api call for getting all audit records is
/api/fmc_platform/v1/domain/{domainUUID}/audit/auditrecords
But when I implement this using this library, I get a 404 error. When I dig into the error, I see the API endpoint the library querying is
/api/fmc_config/v1/domain/{domainUUID}/audit/auditrecords
The source code I used to produce this problem
import fireREST as fr
from ..config import HOSTNAME, USERNAME, PASSWORD, DOMAIN
# Try establishing a connection and exit out if the credentials
# are not correct
try:
fmc = fr.FMC(hostname=HOSTNAME, username=USERNAME, password=PASSWORD, domain=DOMAIN)
except fr.exceptions.AuthError:
print('Auth error, check your credentials')
exit(0)
all_audits = fmc.audit.auditrecords.get()
Traceback
Traceback (most recent call last):
File "C:\Users\User\Python\Python310\lib\site-packages\fireREST\utils.py", line 190, in wrapper
response.raise_for_status()
File "C:\Users\User\Python\Python310\lib\site-packages\requests\models.py", line 960, in raise_for_status
raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 404 Client Error: 404 for url: https://10.106.38.119/api/fmc_config/v1/domain/e276abec-e0f2-11e3-8169-6d9ed49b625f/audit/auditrecords?limit=1000&expanded=True
FMC version 6.7.0
fireREST version 1.0.4
My goal is to create a manual nat rule by specifying the nat policy for the rule by name, and the translated/original sources for the rule by as host or network objects by name. It appears that I'm only able to use uuids.
I get a ResourceNotFoundError/404 when attempting to create a manual nat rule using container_name:
from fireREST import FMC
fmc = FMC(hostname='fmchost', username='user', password='pass')
data = {'translatedSource':{'type':'Host', 'id':'guid-of-host-object'}, 'originalSource':{'type': 'Host', 'id': 'guid-of-another-host-object'}, 'dns': True, 'natType':'STATIC'}
fmc.policy.ftdnatpolicy.manualnatrule.create(container_name='Test NAT', section='before_auto', data=data)
returns:
Traceback (most recent call last):
File "/path/to/venv/lib/python3.8/site-packages/fireREST/utils.py", line 191, in wrapper
response.raise_for_status()
File "/path/to/venv/lib/python3.8/site-packages/requests/models.py", line 943, in raise_for_status
raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 404 Client Error: 404 for url: https://fmchost/api/fmc_config/v1/domain/e276abec-e0f2-11e3-8169-6d9ed49b625f/policy/ftdnatpolicies/None/manualnatrules?section=before_auto
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/path/to/venv/lib/python3.8/site-packages/fireREST/utils.py", line 169, in wrapper
return f(*args, **kwargs)
File "/path/to/venv/lib/python3.8/site-packages/fireREST/fmc/policy/ftdnatpolicy/manualnatrule/__init__.py", line 30, in create
return super().create(data=data, container_uuid=container_uuid, container_name=container_name, params=params)
File "/path/to/venv/lib/python3.8/site-packages/fireREST/utils.py", line 78, in wrapper
return f(*args, **kwargs)
File "/path/to/venv/lib/python3.8/site-packages/fireREST/fmc/__init__.py", line 426, in create
return self.conn.post(url, data, params, self.IGNORE_FOR_CREATE)
File "/path/to/venv/lib/python3.8/site-packages/fireREST/fmc/__init__.py", line 196, in post
return self._request('post', url, params=params, data=data)
File "<decorator-gen-2>", line 2, in wrapper
File "/path/to/venv/lib/python3.8/site-packages/retry/api.py", line 73, in retry_decorator
return __retry_internal(partial(f, *args, **kwargs), exceptions, tries, delay, max_delay, backoff, jitter,
File "/path/to/venv/lib/python3.8/site-packages/retry/api.py", line 33, in __retry_internal
return f()
File "/path/to/venv/lib/python3.8/site-packages/fireREST/utils.py", line 197, in wrapper
raise_for_status(response)
File "/path/to/venv/lib/python3.8/site-packages/fireREST/utils.py", line 241, in raise_for_status
raise exceptions.get(status_code,
fireREST.exceptions.ResourceNotFoundError: No data found for: /None
The above works if i use container_uuid instead of container_name.
Also, I'm not able to reference translatedSource or originalSource by name:
data={'translatedSource': {'type': 'Host', 'name': 'host1'}, 'originalSource': {'type': 'Host', 'name': 'host2'}, 'dns': True, 'natType': 'STATIC'}
fmc.policy.ftdnatpolicy.manualnatrule.create(container_uuid='uuid-of-nat-policy', section='before_auto', data=data)
Traceback (most recent call last):
File "/path/to/venv/lib/python3.8/site-packages/fireREST/utils.py", line 191, in wrapper
response.raise_for_status()
File "/path/to/venv/lib/python3.8/site-packages/requests/models.py", line 943, in raise_for_status
raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 400 Client Error: 400 for url: https://fmchost/api/fmc_config/v1/domain/e276abec-e0f2-11e3-8169-6d9ed49b625f/policy/ftdnatpolicies/005056B9-24B2-0ed3-0000-008589936073/manualnatrules?section=before_auto
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/path/to/venv/lib/python3.8/site-packages/fireREST/utils.py", line 169, in wrapper
return f(*args, **kwargs)
File "/path/to/venv/lib/python3.8/site-packages/fireREST/fmc/policy/ftdnatpolicy/manualnatrule/__init__.py", line 30, in create
return super().create(data=data, container_uuid=container_uuid, container_name=container_name, params=params)
File "/path/to/venv/lib/python3.8/site-packages/fireREST/utils.py", line 78, in wrapper
return f(*args, **kwargs)
File "/path/to/venv/lib/python3.8/site-packages/fireREST/fmc/__init__.py", line 426, in create
return self.conn.post(url, data, params, self.IGNORE_FOR_CREATE)
File "/path/to/venv/lib/python3.8/site-packages/fireREST/fmc/__init__.py", line 196, in post
return self._request('post', url, params=params, data=data)
File "<decorator-gen-2>", line 2, in wrapper
File "/path/to/venv/lib/python3.8/site-packages/retry/api.py", line 73, in retry_decorator
return __retry_internal(partial(f, *args, **kwargs), exceptions, tries, delay, max_delay, backoff, jitter,
File "/path/to/venv/lib/python3.8/site-packages/retry/api.py", line 33, in __retry_internal
return f()
File "/path/to/venv/lib/python3.8/site-packages/fireREST/utils.py", line 197, in wrapper
raise_for_status(response)
File "/path/to/venv/lib/python3.8/site-packages/fireREST/utils.py", line 241, in raise_for_status
raise exceptions.get(status_code,
fireREST.exceptions.GenericApiError: <html> The original source cannot be empty. Select a Network Object or a<br>Network Object Group<br><br> Empty original source is not allowed<br><br></html>
Good day,
Working on interfacing with our firewall and receiving the following error on some requests:
TypeError: inner_function() takes 1 positional argument but 2 were given
An example is:
...
>>> api.get_device_id_by_name('TESTFW')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: inner_function() takes 1 positional argument but 2 were given
As well as:
>>> api.get_accesspolicy_id_by_name('test-policy')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: inner_function() takes 1 positional argument but 2 were given
Python: 3.7.3
FMC: 6.6.0.1
fireREST: 0.1.4
Firstly, great library! Really saves me a heap of time compared to access the FMC API directly.
I'm trying to run through ruleset sequentially to move lots of access rules into categories, however I think this could be triggered on also everything that relies on resolve_by_name.
Mostly working but hit a issue that I have not been expecting. I'm really not parsing responses for invalid token because from my understanding the wrapper @utils.handle_errors on Connection _request should be handling token refresh and retry.
That reasoning seems to be okay but I also happened to be using resolve_by_name and that doesnt seem to be protected by handle_errors.
Can the wrapper in resolve_by_name also be sent through handle_errors?
In the meantime, I will update my code to not be as lazy and only utilise the resolve_by_name on the first call to get the UUID for future calls.
I happened to be running it in a debugging session in FMC and also had pigtail running.
VSCode Stack Trace
Traceback (most recent call last):
File "C:\Program Files\Python39\lib\runpy.py", line 197, in _run_module_as_main
return _run_code(code, main_globals, None,
File "C:\Program Files\Python39\lib\runpy.py", line 87, in _run_code
exec(code, run_globals)
File "c:\Users\ictcg\.vscode\extensions\ms-python.python-2021.9.1246542782\pythonFiles\lib\python\debugpy\__main__.py", line 45, in <module>
cli.main()
File "c:\Users\ictcg\.vscode\extensions\ms-python.python-2021.9.1246542782\pythonFiles\lib\python\debugpy/..\debugpy\server\cli.py", line 444, in main
run()
File "c:\Users\ictcg\.vscode\extensions\ms-python.python-2021.9.1246542782\pythonFiles\lib\python\debugpy/..\debugpy\server\cli.py", line 285, in run_file
runpy.run_path(target_as_str, run_name=compat.force_str("__main__"))
File "C:\Program Files\Python39\lib\runpy.py", line 268, in run_path
return _run_module_code(code, init_globals, run_name,
File "C:\Program Files\Python39\lib\runpy.py", line 97, in _run_module_code
_run_code(code, mod_globals, init_globals,
File "C:\Program Files\Python39\lib\runpy.py", line 87, in _run_code
exec(code, run_globals)
File "Z:\Documents\Code\cisco-FMC-client/update_access_policy_categories.py", line 92, in <module>
update_access_policy_categories(fmc,POLICY_NAME)
File "Z:\Documents\Code\cisco-FMC-client/update_access_policy_categories.py", line 22, in update_access_policy_categories
category = fmc.policy.accesspolicy.category.get(
File "z:\Documents\Code\cisco-FMC-client\venv\lib\site-packages\fireREST\utils.py", line 109, in wrapper
if item['name'] == container_name:
TypeError: string indices must be integers
Pigtail stack trace
TCAT: 09-26 05:45:17 INFO: __REDACTED__ - - 443 POST /api/fmc_config/v1/domain/__REDACTED__ /policy/accesspolicies/__REDACTED__ /accessrules category=__REDACTED__ 201 - 1100 3308 https://__REDACTED__ FireREST/1.0.8 -
TCAT: 09-26 05:45:17 [ajp-nio-127.0.0.1-9009-exec-6] ERROR com.cisco.api.external.rest.common.utils.TokenValidationUtils - Access Token has expired. Please get renewed access token.
TCAT: 09-26 05:45:17 [ajp-nio-127.0.0.1-9009-exec-6] ERROR com.cisco.api.external.rest.common.filters.AuthenticationFilter - Access Token invalid.
TCAT: 09-26 05:45:17 [ajp-nio-127.0.0.1-9009-exec-6] ERROR com.cisco.api.external.rest.common.filters.AuthenticationFilter - Access token invalid.
TCAT: 09-26 05:45:17 APIException:Access token invalid.
TCAT: 09-26 05:45:17 at com.cisco.api.external.rest.common.filters.AuthenticationFilter.authenticateAccessToken(AuthenticationFilter.java:307)
TCAT: 09-26 05:45:17 at com.cisco.api.external.rest.common.filters.AuthenticationFilter.beforeHandle(AuthenticationFilter.java:151)
TCAT: 09-26 05:45:17 at org.restlet.routing.Filter.handle(Filter.java:195)
TCAT: 09-26 05:45:17 at org.restlet.routing.Filter.doHandle(Filter.java:150)
TCAT: 09-26 05:45:17 at org.restlet.routing.Filter.handle(Filter.java:197)
TCAT: 09-26 05:45:17 at org.restlet.routing.Filter.doHandle(Filter.java:150)
TCAT: 09-26 05:45:17 at com.cisco.api.external.rest.common.filter.AuditFilter.doHandle(AuditFilter.java:133)
TCAT: 09-26 05:45:17 at org.restlet.routing.Filter.handle(Filter.java:197)
TCAT: 09-26 05:45:17 at org.restlet.routing.Filter.doHandle(Filter.java:150)
TCAT: 09-26 05:45:17 at org.restlet.routing.Filter.handle(Filter.java:197)
TCAT: 09-26 05:45:17 at org.restlet.routing.Filter.doHandle(Filter.java:150)
TCAT: 09-26 05:45:17 at org.restlet.routing.Filter.handle(Filter.java:197)
TCAT: 09-26 05:45:17 at org.restlet.routing.Filter.doHandle(Filter.java:150)
TCAT: 09-26 05:45:17 at org.restlet.engine.application.StatusFilter.doHandle(StatusFilter.java:140)
TCAT: 09-26 05:45:17 at org.restlet.routing.Filter.handle(Filter.java:197)
TCAT: 09-26 05:45:17 at org.restlet.routing.Filter.doHandle(Filter.java:150)
TCAT: 09-26 05:45:17 at org.restlet.routing.Filter.handle(Filter.java:197)
TCAT: 09-26 05:45:17 at org.restlet.engine.CompositeHelper.handle(CompositeHelper.java:202)
TCAT: 09-26 05:45:17 at org.restlet.engine.application.ApplicationHelper.handle(ApplicationHelper.java:75)
TCAT: 09-26 05:45:17 at org.restlet.Application.handle(Application.java:385)
TCAT: 09-26 05:45:17 at org.restlet.routing.Filter.doHandle(Filter.java:150)
TCAT: 09-26 05:45:17 at org.restlet.routing.Filter.handle(Filter.java:197)
TCAT: 09-26 05:45:17 at org.restlet.routing.Router.doHandle(Router.java:422)
TCAT: 09-26 05:45:17 at org.restlet.routing.Router.handle(Router.java:639)
TCAT: 09-26 05:45:17 at org.restlet.routing.Filter.doHandle(Filter.java:150)
TCAT: 09-26 05:45:17 at org.restlet.routing.Filter.handle(Filter.java:197)
TCAT: 09-26 05:45:17 at org.restlet.routing.Router.doHandle(Router.java:422)
TCAT: 09-26 05:45:17 at org.restlet.routing.Router.handle(Router.java:639)
TCAT: 09-26 05:45:17 at org.restlet.routing.Filter.doHandle(Filter.java:150)
TCAT: 09-26 05:45:17 at org.restlet.routing.Filter.handle(Filter.java:197)
TCAT: 09-26 05:45:17 at org.restlet.routing.Filter.doHandle(Filter.java:150)
TCAT: 09-26 05:45:17 at org.restlet.routing.Filter.handle(Filter.java:197)
TCAT: 09-26 05:45:17 at org.restlet.routing.Filter.doHandle(Filter.java:150)
TCAT: 09-26 05:45:17 at org.restlet.engine.application.StatusFilter.doHandle(StatusFilter.java:140)
TCAT: 09-26 05:45:17 at org.restlet.routing.Filter.handle(Filter.java:197)
TCAT: 09-26 05:45:17 at org.restlet.routing.Filter.doHandle(Filter.java:150)
TCAT: 09-26 05:45:17 at org.restlet.routing.Filter.handle(Filter.java:197)
TCAT: 09-26 05:45:17 at org.restlet.engine.CompositeHelper.handle(CompositeHelper.java:202)
TCAT: 09-26 05:45:17 at org.restlet.Component.handle(Component.java:408)
TCAT: 09-26 05:45:17 at com.cisco.api.external.rest.common.APIComponent.handle(APIComponent.java:294)
TCAT: 09-26 05:45:17 at org.restlet.Server.handle(Server.java:507)
TCAT: 09-26 05:45:17 at org.restlet.engine.connector.ServerHelper.handle(ServerHelper.java:63)
TCAT: 09-26 05:45:17 at org.restlet.engine.adapter.HttpServerHelper.handle(HttpServerHelper.java:143)
TCAT: 09-26 05:45:17 at org.restlet.ext.servlet.ServerServlet.service(ServerServlet.java:1117)
TCAT: 09-26 05:45:17 at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
TCAT: 09-26 05:45:17 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
TCAT: 09-26 05:45:17 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
TCAT: 09-26 05:45:17 at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
TCAT: 09-26 05:45:17 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
TCAT: 09-26 05:45:17 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
TCAT: 09-26 05:45:17 at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
TCAT: 09-26 05:45:17 at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
TCAT: 09-26 05:45:17 at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
TCAT: 09-26 05:45:17 at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
TCAT: 09-26 05:45:17 at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
TCAT: 09-26 05:45:17 at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
TCAT: 09-26 05:45:17 at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
TCAT: 09-26 05:45:17 at org.apache.coyote.ajp.AjpProcessor.service(AjpProcessor.java:394)
TCAT: 09-26 05:45:17 at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
TCAT: 09-26 05:45:17 at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:853)
TCAT: 09-26 05:45:17 at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1587)
TCAT: 09-26 05:45:17 at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
TCAT: 09-26 05:45:17 at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
TCAT: 09-26 05:45:17 at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
TCAT: 09-26 05:45:17 at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
TCAT: 09-26 05:45:17 at java.base/java.lang.Thread.run(Unknown Source)
Bulk operations fail due to incorrect url formatting. Update operations require a uuid at the moment, but this is not neccessary for bulk operations where a list of items is passed directly to the api endpoint without specifying the specific uuid of the resource to change
Thanks to Gyorgy Acs for discovering this issue
FMC version 6.6
As title, the job.taskstatus is not declared in the FMC class. Please add it to the FMC class.
Also, this taskstatus API endpoint on FMC doesn't like the query parameters at the back. I realise the code adds "?limit=1000&expanded=True" at the end by default. Please update the resource to not adding any query parameters for taskstatus.
My workaround for this API endpoint at the moment:
taskStatusURL = "https://"+hostname+"/api/fmc_config/v1/domain/"+fmc.domain['id']+"/job/taskstatuses/"+taskId
response = fmc.conn.get(taskStatusURL,None,1)
It might not be perfect, but it works.
requests.exceptions.HTTPError: 404 Client Error: 404 for url: https://fmc.lab.local/api/fmc_platform/v1/updates/upgradepackages/82db7c60-850c-11eb-995a-bdf00d291159/applicabledevices?limit=1000&expanded=True
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "fmc_patching.py", line 69, in
response = fmc.conn.get(applicabledevicesURL)
File "\Python39\site-packages\fireREST\fmc_init_.py", line 159, in get
response = self._request('get', url, params=params)
File "", line 2, in wrapper
File "\Python39\site-packages\retry\api.py", line 73, in retry_decorator
return __retry_internal(partial(f, *args, **kwargs), exceptions, tries, delay, max_delay, backoff, jitter,
File "\Python39\site-packages\retry\api.py", line 33, in __retry_internal
return f()
File "\Python39\site-packages\fireREST\utils.py", line 197, in wrapper
raise_for_status(response)
File "\Python39\site-packages\fireREST\utils.py", line 245, in raise_for_status
raise exceptions.get(status_code, exc.GenericApiError)(
fireREST.exceptions.ResourceNotFoundError: No resource found
API calls are currently poorly logged with not enough details. The implementation should be changed to include a built-in default logger with an additional loglevel (TRACE) to also include exceptions into logs.
log_request should automatically include the action type and all passed params which are being stitched to the url within the respective api calls
Hi there. First, thanks for your time and this helpful tool. Next, I have an issue when I use the get_audit_records method.
FMC 6.5
Python 3.8.3
Source:
from fireREST import Client
client = Client(hostname='fmc ip', username='user', password='pass')
client.get_audit_records()
Debug from ipython:
In [18]: client.get_audit_records()
---------------------------------------------------------------------------
HTTPError Traceback (most recent call last)
~/github/devnet/firepower/fmc_audit/venv/lib/python3.8/site-packages/fireREST/utils.py in wrapper(*args, **kwargs)
151 response = f(*args, **kwargs)
--> 152 response.raise_for_status()
153 except HTTPError:
~/github/devnet/firepower/fmc_audit/venv/lib/python3.8/site-packages/requests/models.py in raise_for_status(self)
940 if http_error_msg:
--> 941 raise HTTPError(http_error_msg, response=self)
942
HTTPError: 404 Client Error: Not Found for url: https://192.168.10.195/api/fmc_platform/v1/audit/auditrecords?limit=1000&expanded=True
During handling of the above exception, another exception occurred:
HTTPError Traceback (most recent call last)
<ipython-input-18-80541365c4d5> in <module>
----> 1 client.get_audit_records()
~/github/devnet/firepower/fmc_audit/venv/lib/python3.8/site-packages/fireREST/utils.py in wrapper(*args, **kwargs)
109 f'{f.__name__} requires fmc software version {minimum_version}. Installed version: {installed_version}',
110 )
--> 111 return f(*args, **kwargs)
112
113 return wrapper
~/github/devnet/firepower/fmc_audit/venv/lib/python3.8/site-packages/fireREST/__init__.py in get_audit_records(self)
390 def get_audit_records(self):
391 url = self._url('platform', '/audit/auditrecords')
--> 392 return self._get(url)
393
394 @utils.minimum_version_required('6.1.0')
~/github/devnet/firepower/fmc_audit/venv/lib/python3.8/site-packages/fireREST/__init__.py in _get(self, url, params, items)
124 params['expanded'] = defaults.API_EXPANSION_MODE
125
--> 126 response = self._request('get', url, params)
127 payload = response.json()
128
~/github/devnet/firepower/fmc_audit/venv/lib/python3.8/site-packages/fireREST/utils.py in wrapper(*args, **kwargs)
156 client._refresh()
157 else:
--> 158 raise_for_status(response)
159 return response
160
~/github/devnet/firepower/fmc_audit/venv/lib/python3.8/site-packages/fireREST/utils.py in raise_for_status(response)
186 if error['msg'] in response.text:
187 raise error['exception']
--> 188 raise exceptions.get(status_code, HTTPError)
HTTPError:
Thanks!
Hello! Any help is greatly appreciated with this issue.
During initialization I'm receiving this error:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python3.8/dist-packages/fireREST/__init__.py", line 42, in __init__
self.conn = Connection(hostname, username, password, protocol, verify_cert, domain, timeout)
File "/usr/local/lib/python3.8/dist-packages/fireREST/fmc/__init__.py", line 69, in __init__
self.login()
File "/usr/local/lib/python3.8/dist-packages/fireREST/fmc/__init__.py", line 203, in login
response = self._request('post', url, auth=self.cred)
File "<decorator-gen-2>", line 2, in wrapper
File "/usr/local/lib/python3.8/dist-packages/retry/api.py", line 73, in retry_decorator
return __retry_internal(partial(f, *args, **kwargs), exceptions, tries, delay, max_delay, backoff, jitter,
File "/usr/local/lib/python3.8/dist-packages/retry/api.py", line 33, in __retry_internal
return f()
File "/usr/local/lib/python3.8/dist-packages/fireREST/utils.py", line 189, in wrapper
response = f(*args, **kwargs)
File "/usr/local/lib/python3.8/dist-packages/fireREST/fmc/__init__.py", line 112, in _request
logger.debug('\n"response": %s', json.dumps(response.json(), sort_keys=True, indent=4))
File "/usr/local/lib/python3.8/dist-packages/requests/models.py", line 900, in json
return complexjson.loads(self.text, **kwargs)
File "/usr/lib/python3/dist-packages/simplejson/__init__.py", line 518, in loads
return _default_decoder.decode(s)
File "/usr/lib/python3/dist-packages/simplejson/decoder.py", line 370, in decode
obj, end = self.raw_decode(s)
File "/usr/lib/python3/dist-packages/simplejson/decoder.py", line 400, in raw_decode
return self.scan_once(s, idx=_w(s, idx).end())
simplejson.errors.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
Step to reproduce:
fmc = FMC(hostname=FMC_HOST, username=FMC_USER, password=FMC_PASS, domain='Global')
Environment:
Additional information:
There are not enough tests in FireREST to make sure new builds do not break the library. Integration tests should be added for all core functionalities
I'm trying to extract the applications from a access rule and if you have a rule that references an app category, the information returned by the API is not helpful unless you make a second call to pull the app category by the ID returned by the first API call. When I use the fmc.object.applicationcategory(uuid={'some_id'}) call, it fails with an HTTP 400 client error. I'll provide the trace below.
For example, I have an inline application filter of type 'categories' in a rule. The rule really references the 'database' category, but the API returns:
{'id': '32', 'name': 'category', 'type': 'ApplicationCategory'}
If I use the API explorer to pull this, it works perfectly. The API explorer uses this as the URL:
https://x.x.x.x/api/fmc_config/v1/domain/{fmc_uuid}/object/applicationcategories/32
When I go to use fireREST, I get this traceback:
fmc.object.applicationcategory.get(uuid='32')
Traceback (most recent call last):
File "C:\Python39\lib\site-packages\fireREST\utils.py", line 188, in wrapper
response.raise_for_status()
File "C:\Users\xxx\AppData\Roaming\Python\Python39\site-packages\requests\models.py", line 953, in raise_for_status
raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 400 Client Error: 400 for url: https://x.x.x.x/api/fmc_config/v1/domain/{fmc_uuid}/object/applicationcategories/32?limit=1000&expanded=True
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python39\lib\site-packages\fireREST\utils.py", line 138, in wrapper
return f(*args, **kwargs)
File "C:\Python39\lib\site-packages\fireREST\utils.py", line 81, in wrapper
return f(*args, **kwargs)
File "C:\Python39\lib\site-packages\fireREST\fmc\__init__.py", line 372, in get
return self.conn.get(url, params)
File "C:\Python39\lib\site-packages\fireREST\fmc\__init__.py", line 165, in get
response = self._request('get', url, params=params)
File "C:\Python39\lib\site-packages\decorator.py", line 232, in fun
return caller(func, *(extras + args), **kw)
File "C:\Python39\lib\site-packages\retry\api.py", line 73, in retry_decorator
return __retry_internal(partial(f, *args, **kwargs), exceptions, tries, delay, max_delay, backoff, jitter,
File "C:\Python39\lib\site-packages\retry\api.py", line 33, in __retry_internal
return f()
File "C:\Python39\lib\site-packages\fireREST\utils.py", line 198, in wrapper
raise_for_status(response)
File "C:\Python39\lib\site-packages\fireREST\utils.py", line 246, in raise_for_status
raise exceptions.get(status_code, exc.GenericApiError)(
fireREST.exceptions.GenericApiError: Invalid query parameter for the GETBYID operation.
Almost seems like it doesn't like the limit=1000&expanded=True
part of the URL.
This was run on 6.7.0 code.
Hi,
to get detail over device status, we need the "expanded" parameter. So I would prefer this way:
def get_devices(self, expanded = False):
request = '/devices/devicerecords'
params = {
'expanded': expanded
}
url = self._url('config', request)
return self._get(url, params)
best regards,
Lars
By the description, I would need to connect to a cdFMC instance but seems that the authentication in this package is not supported, or is it?
Hello,
Thanks for your very nice job here.
I'm stuck on deployement of my policy.
I have the feeling it's an issue on the FMC but I post here in case i'm doing something wrong ...
response = client.update_accesspolicy_rule(policy_id,rule_id,rule)
{"error":{"category":"OTHER","messages":[{"description":"JsonNull"}],"severity":"ERROR"}}
i'm getting the same kind of error with the api/explorer embedded in the FMC.
In fact the /var/log/mojo.log it's seems that the response is prepared & ready but maybe after has been reached a timer elapsed.
I didn't find any timer on the FMC settings regarding the API...
Any clues ?
Oh, and BTW the deployement seems way more touchy :
we need to send that kind of data :
{
"metadata": {
"lastUser": {
"name": "a175552",
"links": {
"parent": "string",
"self": "string"
},
"id": "string",
"type": "string"
},
"task": {
"taskType": "DEVICE_REGISTRATION",
"subTasks": [
{
"message": "string",
"target": {
"metadata": {
"lastUser": {
"name": "string",
"links": {
"parent": "string",
"self": "string"
},
"id": "string",
"type": "string"
},
"domain": {
"name": "string",
"links": {
"parent": "string",
"self": "string"
},
"id": "string",
"type": "string"
},
"readOnly": {
"reason": "RBAC",
"state": true
},
"timestamp": 0
},
"name": "string",
"description": "string",
"links": {
"parent": "string",
"self": "string"
},
"id": "string",
"type": "string",
"version": "string"
},
"status": "string"
}
],
"name": "string",
"description": "string",
"links": {
"parent": "string",
"self": "string"
},
"id": "string",
"type": "string",
"message": "string",
"status": "string"
},
"domain": {
"name": "string",
"links": {
"parent": "string",
"self": "string"
},
"id": "string",
"type": "string"
},
"readOnly": {
"reason": "RBAC",
"state": true
},
"timestamp": 0
},
"forceDeploy": true,
"name": "string",
"deviceList": [
"string"
],
"ignoreWarning": true,
"description": "string",
"links": {
"parent": "string",
"self": "string"
},
"id": "string",
"type": "string",
"version": "string"
}
Python 3.7 on CentOS Linux release 7.7.1908 (Core)
(venv-fmc-obj-maker) [root@devbox firepower-obj-maker]# pip freeze
certifi==2020.4.5.1
chardet==3.0.4
decorator==4.4.2
fireREST==0.1.1
idna==2.9
packaging==20.4
py==1.8.1
pyparsing==2.4.7
requests==2.23.0
retry==0.9.2
six==1.15.0
urllib3==1.25.9
Source:
from fireREST import Client
fmc_hostname = '<ip>'
fmc_username = 'admin'
fmc_password = 'admin'
fmc_client = Client(hostname=fmc_hostname, username=fmc_username, password=fmc_password)
net_obj = {
'name': 'NetObjViaAPI',
'value': '198.18.1.0/24'
}
response = fmc_client.create_object('network', net_obj)
Error:
Traceback (most recent call last):
File "", line 1, in
File "/etc/samba/devbox/firepower-obj-maker/venv-fmc-obj-maker/lib/python3.7/site-packages/fireREST/utils.py", line 137, in wrapper
return f(*args, **kwargs)
File "/etc/samba/devbox/firepower-obj-maker/venv-fmc-obj-maker/lib/python3.7/site-packages/fireREST/utils.py", line 111, in wrapper
return f(*args, **kwargs)
File "/etc/samba/devbox/firepower-obj-maker/venv-fmc-obj-maker/lib/python3.7/site-packages/fireREST/init.py", line 408, in create_object
return self._create(url, data)
File "/etc/samba/devbox/firepower-obj-maker/venv-fmc-obj-maker/lib/python3.7/site-packages/fireREST/init.py", line 185, in _create
return self._request('post', url, params, data)
File "/etc/samba/devbox/firepower-obj-maker/venv-fmc-obj-maker/lib/python3.7/site-packages/fireREST/utils.py", line 151, in wrapper
response = f(*args, **kwargs)
File "/etc/samba/devbox/firepower-obj-maker/venv-fmc-obj-maker/lib/python3.7/site-packages/fireREST/init.py", line 103, in _request
verify=self.verify_cert,
File "/etc/samba/devbox/firepower-obj-maker/venv-fmc-obj-maker/lib/python3.7/site-packages/requests/sessions.py", line 516, in request
prep = self.prepare_request(req)
File "/etc/samba/devbox/firepower-obj-maker/venv-fmc-obj-maker/lib/python3.7/site-packages/requests/sessions.py", line 459, in prepare_request
hooks=merge_hooks(request.hooks, self.hooks),
File "/etc/samba/devbox/firepower-obj-maker/venv-fmc-obj-maker/lib/python3.7/site-packages/requests/models.py", line 318, in prepare
self.prepare_auth(auth, url)
File "/etc/samba/devbox/firepower-obj-maker/venv-fmc-obj-maker/lib/python3.7/site-packages/requests/models.py", line 550, in prepare_auth
r = auth(self)
TypeError: 'dict' object is not callable
Update:
I also get the same behavior running the code in a docker python:3.7.7-buster & python:3.8.3-buster image with packaging & urllib3 downgraded to match what I see in your pipfile document.
Trying to do an fmc.object.continent.get() to get the full list of continents however it fails because the PATH in the Continent object is incorrect. The URL has continent as plural.
fireREST code
from fireREST.fmc import Resource
class Continent(Resource):
PATH = '/object/continent/{uuid}'
MINIMUM_VERSION_REQUIRED_GET = '6.1.0'
Corrected code
from fireREST.fmc import Resource
class Continent(Resource):
PATH = '/object/continents/{uuid}'
MINIMUM_VERSION_REQUIRED_GET = '6.1.0'
I tested this change and it pulled the continents fine.
In the fireREST.fmc.devicehapair constructor the method is named "ftdhapair" while in the directory tree and docs is named "ftddevicehapair".
from fireREST.fmc import Connection
from fireREST.fmc.devicehapair.ftddevicehapair import FtdHAPair
class DeviceHAPair:
def init(self, conn: Connection):
self.ftdhapair = FtdHAPair(conn)
I have found 2 problems and fixed this problems in #62
Thank you for this great library.
I have a NAT policy with 2 rules. I'm able to return a list of both rules with:
fmc.policy.ftdnatpolicy.natrule.get(container_name='Test Threat Defense NAT', data={})
or
fmc.policy.ftdnatpolicy.natrule.get(container_name='Test Threat Defense NAT', data=None)
What I'm not able to do is get a specific rule by id. I've tried:
fmc.policy.ftdnatpolicy.natrule.get(container_name='Test Threat Defense NAT', uuid='005056B9-24B2-0ed3-0000-008589936189', data={})
and
fmc.policy.ftdnatpolicy.natrule.get(container_name='Test Threat Defense NAT', uuid='005056B9-24B2-0ed3-0000-008589936189', data=None)
and the following error is returned:
Traceback (most recent call last):
File "/path/to/.pyenv/versions/venv/lib/python3.7/site-packages/fireREST/utils.py", line 190, in wrapper
response.raise_for_status()
File "/path/to/.pyenv/versions/venv/lib/python3.7/site-packages/requests/models.py", line 941, in raise_for_status
raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 400 Client Error: 400 for url: https://fmc/api/fmc_config/v1/domain/e276abec-e0f2-11e3-8169-6d9ed49b625f/policy/ftdnatpolicies/005056B9-24B2-0ed3-0000-008589936073/natrules/005056B9-24B2-0ed3-0000-008589936189?limit=1000&expanded=True
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/path/to/.pyenv/versions/venv/lib/python3.7/site-packages/fireREST/utils.py", line 170, in wrapper
return f(*args, **kwargs)
File "/path/to/.pyenv/versions/venv/lib/python3.7/site-packages/fireREST/fmc/policy/ftdnatpolicy/natrule/__init__.py", line 50, in get
container_uuid=container_uuid, container_name=container_name, name=name, uuid=uuid, params=params
File "/path/to/.pyenv/versions/venv/lib/python3.7/site-packages/fireREST/utils.py", line 136, in wrapper
return f(*args, **kwargs)
File "/path/to/.pyenv/versions/venv/lib/python3.7/site-packages/fireREST/utils.py", line 78, in wrapper
return f(*args, **kwargs)
File "/path/to/.pyenv/versions/venv/lib/python3.7/site-packages/fireREST/fmc/__init__.py", line 430, in get
return self.conn.get(url, params)
File "/path/to/.pyenv/versions/venv/lib/python3.7/site-packages/fireREST/fmc/__init__.py", line 140, in get
response = self._request('get', url, params=params)
File "<decorator-gen-2>", line 2, in wrapper
File "/path/to/.pyenv/versions/venv/lib/python3.7/site-packages/retry/api.py", line 74, in retry_decorator
logger)
File "/path/to/.pyenv/versions/venv/lib/python3.7/site-packages/retry/api.py", line 33, in __retry_internal
return f()
File "/path/to/.pyenv/versions/venv/lib/python3.7/site-packages/fireREST/utils.py", line 196, in wrapper
raise_for_status(response)
File "/path/to/.pyenv/versions/venv/lib/python3.7/site-packages/fireREST/utils.py", line 239, in raise_for_status
raise exceptions.get(status_code, HTTPError)(msg=response.json()['error']['messages'][0]['description'])
fireREST.exceptions.GenericApiError: Invalid query parameter for the GETBYID operation.
I'm able to get it with a filter:
fmc.policy.ftdnatpolicy.natrule.get(container_name='Test Threat Defense NAT', translated_source='10.117.108.194-32', data=None)
[{'metadata': {'section': 'BEFORE_AUTO', 'index': 1, 'parentType': 'FTDNatRule', 'timestamp': 1612906807140, 'domain': {'name': 'Global', 'id': 'e276abec-e0f2-11e3-8169-6d9ed49b625f', 'type': 'Domain'}}, 'links': {'self': 'https://fmc/api/fmc_config/v1/domain/e276abec-e0f2-11e3-8169-6d9ed49b625f/policy/ftdnatpolicies/005056B9-24B2-0ed3-0000-008589936073/manualnatrules/005056B9-24B2-0ed3-0000-008589936189', 'parent': 'https://fmc/api/fmc_config/v1/domain/e276abec-e0f2-11e3-8169-6d9ed49b625f/policy/ftdnatpolicies/005056B9-24B2-0ed3-0000-008589936073/natrules'}, 'enabled': True, 'unidirectional': False, 'translatedSource': {'type': 'Host', 'overridable': False, 'id': '005056B9-24B2-0ed3-0000-008589936145', 'name': '10.117.108.194-32'}, 'originalSource': {'type': 'Host', 'overridable': False, 'id': '005056B9-24B2-0ed3-0000-008589936145', 'name': '10.117.108.194-32'}, 'interfaceInOriginalDestination': False, 'interfaceInTranslatedSource': False, 'type': 'FTDManualNatRule', 'fallThrough': False, 'dns': True, 'routeLookup': False, 'noProxyArp': False, 'netToNet': False, 'natType': 'STATIC', 'interfaceIpv6': False, 'id': '005056B9-24B2-0ed3-0000-008589936189'}]
2 questions:
/api/fmc_config/v1/domain/{domainUUID}/policy/ftdnatpolicies/{containerUUID}/natrules
and /api/fmc_config/v1/domain/{domainUUID}/policy/ftdnatpolicies/{containerUUID}/natrules/{objectId}
don't support passing a body.Hi Kaisero,
Great work, this helped me out in a time of need!
I needed to update 8000 AC Rules to include Syslog after a migration from ASA.
The current "limit" is set to 50 in fireREST.py on line 70.
The FirePower API Token is only valid for 30 minutes, and the script took a while to get through all 8000 Rules, so i had to increase the "limit" to 1000 (which is the API limit itself). This meant that the script collected the data much quicker.
It may be worth increasing this limit in the production code to prevent this issue occurring going forwards.
Also, it might be worth investigating whether there is a way to utilise the X-authentication-refresh-token if the script runs over 30 minutes.
I have a couple of API scripts myself which ill do a bit of testing with around this and report back if i find anything.
Are there any code examples available for best practice on how to check if changes made to FMC and deployable and to trigger a deployment?
I'm trying to use this on an older FMC to pull data from to build a new FMC on 6.7 code. When I try to create the FMC object, I get a 422 client error, but I can connect to the new FMC just fine. I'm thinking it is an issue with the older FMC version and the API it presents. I did confirm the REST API is enabled on the old server.
Here is the error I get:
Traceback (most recent call last):
File "C:\Python39\lib\site-packages\fireREST\utils.py", line 188, in wrapper
response.raise_for_status()
File "C:\Users\xxx\AppData\Roaming\Python\Python39\site-packages\requests\models.py", line 953, in raise_for_status
raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 422 Client Error: Unprocessable Entity for url: https://10.90.192.38/api/fmc_platform/v1/auth/generatetoken
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python39\lib\site-packages\fireREST\__init__.py", line 43, in __init__
self.conn = Connection(hostname, username, password, protocol, verify_cert, domain, timeout, dry_run)
File "C:\Python39\lib\site-packages\fireREST\fmc\__init__.py", line 74, in __init__
self.login()
File "C:\Python39\lib\site-packages\fireREST\fmc\__init__.py", line 232, in login
response = self._request('post', url, auth=self.cred)
File "C:\Python39\lib\site-packages\decorator.py", line 232, in fun
return caller(func, *(extras + args), **kw)
File "C:\Python39\lib\site-packages\retry\api.py", line 73, in retry_decorator
return __retry_internal(partial(f, *args, **kwargs), exceptions, tries, delay, max_delay, backoff, jitter,
File "C:\Python39\lib\site-packages\retry\api.py", line 33, in __retry_internal
return f()
File "C:\Python39\lib\site-packages\fireREST\utils.py", line 198, in wrapper
raise_for_status(response)
File "C:\Python39\lib\site-packages\fireREST\utils.py", line 246, in raise_for_status
raise exceptions.get(status_code, exc.GenericApiError)(
fireREST.exceptions.UnprocessableEntityError: The Payload size is above:0 Bytes
The update of a Physical Interface doesn't contain the Interface's UUID on the URL formation.
FMC version: 7.0.4
Exception has occurred: GenericApiError
Invalid refresh token
Is there anyway to handle if there is a browser timeout since it looks like the browser timeout also kills off the refresh token along with the access token. Our timeout was required to be set to 10 minutes per our security needs. I have a job that I am pulling all of our ACLs and their related objects and it crashes on this error.
Let me know if any other details are needed.
The current FireREST implementation exposes different functions for some create and get operations that should be merged into a single function which takes a param to indicate if the user wants to receive a specific result or all resources
FMC version 6.6.1
When I tried to retrieve upgradepackages, it returns 404.
response = fmc.update.upgradepackage.get()
requests.exceptions.HTTPError: 404 Client Error: 404 for url: https://fmc.lab.local/api/fmc_config/v1/domain/{domainUUID}/updates/upgradepackages?limit=1000&expanded=True
In API explorer, the updates APIs doesn't have domain and domainUUID in the path
Do you have any overrides support? I did a repo search for "overrid" and found nothing so I am guessing there is no support for it. Can you confirm if you do or do not?
TIA.
It doesn't seem as if the "expanded" flag is permitted for the get_policy method in api 6.2.3. I have been using the following code block instead:
#def get_policy(self, policy_id, policy_type, expanded=False):
def get_policy(self, policy_id, policy_type):
request = '/policy/{0}/{1}'.format(policy_type, policy_id)
# params = {
# 'expanded': expanded
# }
url = self._url('config', request)
return self._get(url)
# return self._get(url, params)
do you have any examples of how to utilize the API wrapper. bit of a newbie looking for some prior work to get ideas off of. thank you in advance.
Currently result caching is achieved using functools lru_cache without cache invalidation for get_id_by_name operations only. The goal is to enable caching by default and add memoization with integrated cache invalidation upon changes performed via create/update procedures.
Great module - thanks.
I've been using it in my script, but when calling "get_objects" I am unable to pass an increased limit beyond the 100. Obviously I could just call "_url" directly, so you may not consider this an issue, but would be good to use the abstraction of "get_objects" and increase the limit as otherwise it takes ages for something like "applications" which has thousands of objects.
I'm not a massive python expert, but don't think I've missed a way to do this using your code (apologies if I have). For now I've just created a child class in my script and overwritten the value that way.
PhysicalInterface class import missing in devicerecord:
diff --git a/fireREST/fmc/device/devicerecord/__init__.py b/fireREST/fmc/device/devicerecord/__init__.py
index dd45828..12b6f56 100644
--- a/fireREST/fmc/device/devicerecord/__init__.py
+++ b/fireREST/fmc/device/devicerecord/__init__.py
@@ -7,6 +7,7 @@ from fireREST.fmc.device.devicerecord.fpphysicalinterface import FpPhysicalInter
from fireREST.fmc.device.devicerecord.inlineset import InlineSet
from fireREST.fmc.device.devicerecord.interfaceevent import InterfaceEvent
from fireREST.fmc.device.devicerecord.operational import Operational
+from fireREST.fmc.device.devicerecord.physicalinterface import PhysicalInterface
from fireREST.fmc.device.devicerecord.redundantinterface import RedundantInterface
from fireREST.fmc.device.devicerecord.routing import Routing
from fireREST.fmc.device.devicerecord.subinterface import SubInterface
@@ -34,6 +35,7 @@ class DeviceRecord(Resource):
self.inlineset = InlineSet(conn)
self.interfaceevent = InterfaceEvent(conn)
self.operational = Operational(conn)
+ self.physicalinterface = PhysicalInterface(conn)
self.redundantinterface = RedundantInterface(conn)
self.routing = Routing(conn)
self.subinterface = SubInterface(conn)
Various enhancements / new APIs for...
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.