From 629069aff0328a33bb0200e106ef436f50938632 Mon Sep 17 00:00:00 2001 From: Arcuri Davide Date: Thu, 7 May 2020 14:25:07 +0200 Subject: [PATCH 1/2] fix typo --- Usage.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Usage.md b/Usage.md index 5743097..294804c 100644 --- a/Usage.md +++ b/Usage.md @@ -335,7 +335,7 @@ print(key2) # Compare keys print(key1 == key2) -# Revoke the user's API keu +# Revoke the user's API key api.users.revoke_key(user_id) # Lock the user @@ -350,7 +350,7 @@ print(user.hasPassword == True) print(user.status == 'Locked') ``` -## Analyzer Pperations +## Analyzer Operations The `AnalyzersController` class provides a set of methods to handle analyzers. @@ -473,7 +473,7 @@ analyzer = api.analyzers.update(analyzer.id, { }) # Run an analyzer against a domain -job1 = api2.analyzers.run_by_name('Test_1_0', { +job1 = api.analyzers.run_by_name('Test_1_0', { 'data': 'google.com', 'dataType': 'domain', 'tlp': 1, @@ -487,7 +487,7 @@ job1 = api2.analyzers.run_by_name('Test_1_0', { print(json.dumps(job1.json(), indent=2)) # Run an analyzer against a file -job2 = api2.analyzers.run_by_name('File_Info_2_0', { +job2 = api.analyzers.run_by_name('File_Info_2_0', { 'data': '/tmp/sample.txt', 'dataType': 'file', 'tlp': 1 From f8934979c9eb6b5fd81b975b94c34b4e8bf353ee Mon Sep 17 00:00:00 2001 From: Michael Weiser Date: Tue, 20 Oct 2020 10:41:03 +0200 Subject: [PATCH 2/2] Allow for custom requests sessions The requests module internally works with Session objects. These can be customised in behaviour e.g. using retry adapters. This is extremely useful for error handling because the user application doesn't even get to see and need to handle errors until a configurable number of retries with optional backoff has been done. Unfortunately, the module-level API of the requests module does not allow to supply such a customised Session object. Instead it creates a new Session for each request and needs to use it as a context handler to make sure it leaks no sockets - see https://github.com/psf/requests/blob/143150233162d609330941ec2aacde5ed4caa510/requests/api.py#L57 for details. The module-level API is a very thin shim which directly hands all requests to this per-request Session object. This change switches the Cortex API layer to allow usage of a Session object for requests and adds a parameter so users can provide their own customised Session object. To keep default behaviour unchanged, a fresh internal session object is created for each request. This is done so the session does indeed not accumulate state over time. For example this prevents learning of cookies from responses which has been observed to confuse Cortex on subsequent requests. In the case of a user-supplied session it is the responsibility of the user to configure it in such a way that it serves their purpose and does not show behaviour that confuses Cortex. Signed-off-by: Michael Weiser --- cortex4py/api.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/cortex4py/api.py b/cortex4py/api.py index cd55e28..7353984 100644 --- a/cortex4py/api.py +++ b/cortex4py/api.py @@ -29,6 +29,7 @@ def __init__(self, url, api_key, **kwargs): self.__base_url = '{}/api/'.format(url) self.__proxies = kwargs.get('proxies', {}) self.__verify_cert = kwargs.get('verify_cert', kwargs.get('cert', True)) + self.__session = kwargs.get('session', None) self.organizations = OrganizationsController(self) self.users = UsersController(self) @@ -55,13 +56,22 @@ def __recover(exception): else: raise CortexError("Unexpected exception") from exception + @property + def session(self): + # if no custom session object has been provided by the user + if self.__session is None: + # start a fresh session without cookies for each request + return requests.sessions.Session() + + return self.__session + def do_get(self, endpoint, params={}): headers = { 'Authorization': 'Bearer {}'.format(self.__api_key) } try: - response = requests.get('{}{}'.format(self.__base_url, endpoint), + response = self.session.get('{}{}'.format(self.__base_url, endpoint), headers=headers, params=params, proxies=self.__proxies, @@ -78,7 +88,7 @@ def do_file_post(self, endpoint, data, **kwargs): } try: - response = requests.post('{}{}'.format(self.__base_url, endpoint), + response = self.session.post('{}{}'.format(self.__base_url, endpoint), headers=headers, proxies=self.__proxies, data=data, @@ -96,7 +106,7 @@ def do_post(self, endpoint, data, params={}, **kwargs): } try: - response = requests.post('{}{}'.format(self.__base_url, endpoint), + response = self.session.post('{}{}'.format(self.__base_url, endpoint), headers=headers, proxies=self.__proxies, json=data, @@ -115,7 +125,7 @@ def do_patch(self, endpoint, data, params={}): } try: - response = requests.patch('{}{}'.format(self.__base_url, endpoint), + response = self.session.patch('{}{}'.format(self.__base_url, endpoint), headers=headers, proxies=self.__proxies, json=data, @@ -132,7 +142,7 @@ def do_delete(self, endpoint): } try: - response = requests.delete('{}{}'.format(self.__base_url, endpoint), + response = self.session.delete('{}{}'.format(self.__base_url, endpoint), headers=headers, proxies=self.__proxies, verify=self.__verify_cert)