Hi all,
I am facing a very core problem with Resilient platform's Python SDK. I have a rule which gets triggered when a new artifact of type "DNS Name" is created. The rule invokes a workflow which has my function that connects to an external API, gets the screenshot of the latest URL under that "DNS Name" artifact and uploads it to the incident as an attachment. Everything works fine when a single artifact is created in the incident.
The problem occurs when I create multiple artifacts of type "DNS Name" simultaneously from a script. The rule is triggered for each artifact and two separate workflows are launched. When both of these workflows try to upload the attachment, one of them fails and my function in that workflow raises the exception below:
Traceback (most recent call last):
File "/home/integration/fn_slashnext/fn_slashnext/components/funct_slashnext_host_report.py", line 76, in _slashnext_host_report_function
attachment_utils.attach_screenshot(response_list[2], scan_id)
File "/home/integration/fn_slashnext/fn_slashnext/util/attachment_utils.py", line 17, in attach_screenshot
self._attach_file(json_response.get('scData').get('scBase64'), file_name, 'image/jpeg', self.incident_id)
File "/home/integration/fn_slashnext/fn_slashnext/util/attachment_utils.py", line 39, in _attach_file
incident_id, content_type=content_type)
File "/home/integration/ibm/lib/python2.7/site-packages/resilient_lib/components/resilient_common.py", line 277, in write_file_attachment
mimetype=content_type)
File "/home/integration/ibm/lib/python2.7/site-packages/resilient/co3.py", line 505, in post_attachment
_raise_if_error(ex.get_response())
File "/home/integration/ibm/lib/python2.7/site-packages/resilient/co3.py", line 211, in _raise_if_error
raise SimpleHTTPException(response)
SimpleHTTPException: Conflict: {"error_code":"generic","hints":[],"message":"Conflict","success":false,"title":null}
I am using the write_file_attachment function available in resilient_lib package. The class that I have implemented for this is given below (file: attachment_utils.py):
from io import BytesIO
import base64
from resilient_lib import write_file_attachment
class ResilientAttachments:
def __init__(self, incident_id, rest_client, logger):
self.incident_id = incident_id
self.rest_client = rest_client
self.logger = logger
def attach_screenshot(self, json_response, name):
if json_response.get('errorNo') == 0:
file_name = name + '.jpeg'
self.logger.info('Uploading Screenshot Attachment')
self._attach_file(json_response.get('scData').get('scBase64'), file_name, 'image/jpeg', self.incident_id)
self.logger.info('Uploading Screenshot Attachment Complete')
def _attach_file(self, base64_data, file_name, content_type, incident_id):
datastream = BytesIO(base64.b64decode(base64_data))
new_attachment = write_file_attachment(self.rest_client, file_name, datastream,
incident_id, content_type=content_type)
and then in my function, I use this class in my function code as (only relevant code shown):
from attachment_utils import ResilientAttachments
attachment_utils = ResilientAttachments(incident_id, self.rest_client(), self.logger)
attachment_utils.attach_screenshot(response_list[2], scan_id)
My guess is that the Resilient REST API, that the resilient_lib is using at back-end is not thread-safe and when two workflows simultaneously try to upload an attachment, one of them faces a conflict and has to abort. Can someone please point out any workaround for this issue as it is disturbing the core-functionality of Resilient and there is no way I can create my playbook without multiple workflows running simultaneously on different artifacts. Any help will be highly appreciated.
Thanks!
------------------------------
Umair Ahmed
------------------------------