Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

deduplication code #5

Closed
wants to merge 26 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
2175971
deduplication code
sudhanshu-metron Sep 5, 2024
be78c85
fetchfile-progress
sudhanshu-metron Oct 11, 2024
73e6752
malop-processes command date filter changes
sudhanshu-metron Oct 15, 2024
189d7c2
Test file changes
sudhanshu-metron Oct 21, 2024
070bd36
Integration script changes
sudhanshu-metron Oct 21, 2024
851f78e
integration test file changes
sudhanshu-metron Oct 21, 2024
3c4fae2
removing demisto.log from the integration script
sudhanshu-metron Oct 21, 2024
1f6dddf
mapping changes
sudhanshu-metron Oct 29, 2024
eb9c29c
pre-commit resolution
sudhanshu-metron Oct 29, 2024
1d9628f
precommit resolution
sudhanshu-metron Oct 29, 2024
01f5715
test file update
sudhanshu-metron Oct 29, 2024
99892b5
cybereason_test file fix
sudhanshu-metron Oct 29, 2024
071bfc1
malop to incident test case update
sudhanshu-metron Oct 29, 2024
61899f5
adding test cases to complete the checks
sudhanshu-metron Oct 29, 2024
657f04c
adding test case coverage
sudhanshu-metron Oct 29, 2024
e6ee17f
adding more test coverage
sudhanshu-metron Oct 29, 2024
0becdd3
fixing error in test file
sudhanshu-metron Oct 29, 2024
1db6001
adding test cases
sudhanshu-metron Oct 29, 2024
f121781
Test Case for pre commit hooks
sudhanshu-metron Oct 29, 2024
2dfebf4
More Test Cases for pre commit test criteria
sudhanshu-metron Oct 29, 2024
50454d0
error fix in for the test cases
sudhanshu-metron Oct 30, 2024
db5486c
test case improvement
sudhanshu-metron Oct 30, 2024
53a8606
Increasing test case to complete the pre-commit check
sudhanshu-metron Oct 30, 2024
1c4599f
autopep8 error resolution
sudhanshu-metron Oct 30, 2024
097c188
readme file
sudhanshu-metron Nov 4, 2024
ae9668f
metadata file
sudhanshu-metron Nov 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 112 additions & 11 deletions Packs/Cybereason/Integrations/Cybereason/Cybereason.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ def cybereason_api_call(
error_msg = 'Authentication failed, verify the credentials are correct.'
raise ValueError(
f'Failed to process the API response. {str(error_msg)} {str(error_content)} - {str(e)}')
return None

def error_handler(self, res: requests.Response):
# Handle error responses gracefully
Expand Down Expand Up @@ -416,6 +417,7 @@ def query_connections_command(client: Client, args: dict):
outputs_prefix='Cybereason.Connection',
outputs_key_field='Name',
outputs=context)
return None


def query_connections(client: Client, machine: str, ip: str, filter_input: str) -> dict:
Expand Down Expand Up @@ -666,13 +668,16 @@ def malop_processes_command(client: Client, args: dict):
machine_name = str(args.get('machineName'))
date_time = str(args.get('dateTime'))

milliseconds = 0
filter_input = []

if date_time != 'None':
date_time_parser = dateparser.parse(date_time)
if not date_time_parser:
raise DemistoException("dateTime could not be parsed. Please enter a valid time parameter.")
date_time_parser = date_time_parser.timestamp()
milliseconds = int(date_time_parser * 1000)
demisto.info("Returning all the processes since the entered date is not valid.")
if date_time_parser:
epoch_time = date_time_parser.timestamp()
milliseconds = int(epoch_time) * 1000
filter_input = [{"facetName": "creationTime", "filterType": "GreaterThan", "values": [milliseconds], "isResult": True}]

if isinstance(malop_guids, str):
Expand Down Expand Up @@ -722,7 +727,8 @@ def malop_processes_command(client: Client, args: dict):
for output in outputs:
# Remove whitespaces from dictionary keys
context.append({key.translate({32: None}): value for key, value in output.items()})

demisto.info(f"context, {context}")
demisto.info(f"outputs, {outputs}")
return CommandResults(
readable_output=tableToMarkdown('Cybereason Malop Processes', outputs, headers=PROCESS_HEADERS, removeNull=True),
outputs_prefix='Cybereason.Process',
Expand Down Expand Up @@ -754,7 +760,6 @@ def malop_processes(client: Client, malop_guids: list, filter_value: list) -> di
'templateContext': 'MALOP',
'queryTimeout': None
}

return client.cybereason_api_call('POST', '/rest/visualsearch/query/simple', json_body=json_body)


Expand Down Expand Up @@ -916,6 +921,7 @@ def kill_process_command(client: Client, args: dict):
action_status, ['Remediation status'])} \n Reason: {dict_safe_get(
action_status, ['Reason'])} \n Remediation ID: {dict_safe_get(action_status, ['Remediation ID'])}'''
raise DemistoException(failure_response)
return None
else:
raise DemistoException('Machine must be connected to Cybereason in order to perform this action.')

Expand All @@ -940,6 +946,7 @@ def quarantine_file_command(client: Client, args: dict):
action_status, ['Remediation status'])} \n Reason: {dict_safe_get(
action_status, ['Reason'])} \n Remediation ID: {dict_safe_get(action_status, ['Remediation ID'])}'''
raise DemistoException(failure_response)
return None
else:
raise DemistoException('Machine must be connected to Cybereason in order to perform this action.')

Expand All @@ -964,6 +971,7 @@ def unquarantine_file_command(client: Client, args: dict):
action_status, ['Remediation status'])} \n Reason: {dict_safe_get(
action_status, ['Reason'])} \n Remediation ID: {dict_safe_get(action_status, ['Remediation ID'])}'''
raise DemistoException(failure_response)
return None
else:
raise DemistoException('Machine must be connected to Cybereason in order to perform this action.')

Expand All @@ -988,6 +996,7 @@ def block_file_command(client: Client, args: dict):
action_status, ['Remediation status'])} \n Reason: {dict_safe_get(
action_status, ['Reason'])} \n Remediation ID: {dict_safe_get(action_status, ['Remediation ID'])}'''
raise DemistoException(failure_response)
return None
else:
raise DemistoException('Machine must be connected to Cybereason in order to perform this action.')

Expand All @@ -1012,6 +1021,7 @@ def delete_registry_key_command(client: Client, args: dict):
action_status, ['Remediation status'])} \n Reason: {dict_safe_get(
action_status, ['Reason'])} \n Remediation ID: {dict_safe_get(action_status, ['Remediation ID'])}'''
raise DemistoException(failure_response)
return None
else:
raise DemistoException('Machine must be connected to Cybereason in order to perform this action.')

Expand All @@ -1036,6 +1046,7 @@ def kill_prevent_unsuspend_command(client: Client, args: dict):
action_status, ['Remediation status'])} \n" Reason: {dict_safe_get(
action_status, ['Reason'])} \n Remediation ID: {dict_safe_get(action_status, ['Remediation ID'])}'''
raise DemistoException(failure_response)
return None
else:
raise DemistoException('Machine must be connected to Cybereason in order to perform this action.')

Expand All @@ -1060,6 +1071,7 @@ def unsuspend_process_command(client: Client, args: dict):
action_status, ['Remediation status'])} \n Reason: {dict_safe_get(
action_status, ['Reason'])} \n Remediation ID: {dict_safe_get(action_status, ['Remediation ID'])}'''
raise DemistoException(failure_response)
return None
else:
raise DemistoException('Machine must be connected to Cybereason in order to perform this action.')

Expand Down Expand Up @@ -1213,6 +1225,7 @@ def query_file_command(client: Client, args: dict) -> Any:
outputs=cybereason_outputs)
else:
raise DemistoException('No results found.')
return None


def query_file(client: Client, filters: list) -> dict:
Expand Down Expand Up @@ -1303,6 +1316,7 @@ def query_domain_command(client: Client, args: dict) -> Any:
outputs=cybereason_outputs)
else:
raise DemistoException('No results found.')
return None


def query_domain(client: Client, filters: list) -> dict:
Expand Down Expand Up @@ -1364,6 +1378,7 @@ def query_user_command(client: Client, args: dict):
outputs=cybereason_outputs)
else:
raise DemistoException('No results found.')
return None


def query_user(client: Client, filters: list) -> dict:
Expand Down Expand Up @@ -1477,13 +1492,78 @@ def malop_to_incident(malop: str) -> dict:
if not isinstance(malop, dict):
raise ValueError("Cybereason raw response is not valid, malop is not dict")

status = 0
malopStatus = ""
if malop.get('status', ''):
malopStatus = (malop.get('status', 'UNREAD'))
elif malop.get('simpleValues', ''):
malopStatus = (malop.get('simpleValues', {}).get('managementStatus', {}).get('values', ['UNREAD'])[0])
if (malopStatus == "Active") or (malopStatus == "UNREAD"):
status = 0
elif (malopStatus == "Remediated") or (malopStatus == "TODO"):
status = 1
elif (malopStatus == "Closed") or (malopStatus == "RESOLVED"):
status = 2
else:
status = 0

guid_string = malop.get('guidString', '')
if not guid_string:
guid_string = malop.get('guid', '')

if malop.get("isEdr", '') or malop.get("edr", '') or malop.get('simpleValues', ''):
link = SERVER + '/#/malop/' + guid_string
isEdr = True
else:
link = SERVER + '/#/detection-malop/' + guid_string
isEdr = False

if malop.get('simpleValues'):
malopCreationTime = malop.get('simpleValues', {}).get('creationTime', {}).get('values', ['2010-01-01'])[0]
malopUpdateTime = malop.get('simpleValues', {}).get('malopLastUpdateTime', {}).get('values', ['2010-01-01'])[0]
else:
malopCreationTime = str(malop.get('creationTime', '2010-01-01'))
malopUpdateTime = str(malop.get('lastUpdateTime', '2010-01-01'))

if malop.get('elementValues'):
if malop.get('elementValues', {}).get('rootCauseElements', {}).get('elementValues', ''):
rootCauseElementName = (malop.get('elementValues', {}).get('rootCauseElements', {}).get('elementValues',
'')[0]).get('name', '')
rootCauseElementType = (malop.get('elementValues', {}).get('rootCauseElements', {}).get('elementValues', '')[0]
).get('elementType', '')
else:
rootCauseElementName = ''
rootCauseElementType = ''
else:
rootCauseElementName = malop.get('primaryRootCauseName', '')
rootCauseElementType = malop.get('rootCauseElementType', '')

if malop.get('malopDetectionType'):
detectionType = malop.get('malopDetectionType', '')
else:
detectionType = (malop.get('simpleValues', {}).get('detectionType', {}).get('values', [''])[0])

malopGroup = malop.get('group', '')

severity = malop.get('severity', '')

incident = {
'rawJSON': json.dumps(malop),
'rawjson': json.dumps(malop),
'name': 'Cybereason Malop ' + guid_string,
'labels': [{'type': 'GUID', 'value': guid_string}]}
'dbotmirrorid': guid_string,
'CustomFields': {
'malopcreationtime': malopCreationTime,
'malopupdatetime': malopUpdateTime,
'maloprootcauseelementname': rootCauseElementName,
'maloprootcauseelementtype': rootCauseElementType,
'malopseverity': severity,
'malopdetectiontype': detectionType,
'malopedr': isEdr,
'malopurl': link,
'malopgroup': malopGroup
},
'labels': [{'type': 'GUID', 'value': guid_string}],
'status': status}

return incident

Expand Down Expand Up @@ -1530,7 +1610,15 @@ def fetch_incidents(client: Client):
if int(malop_update_time) > int(max_update_time):
max_update_time = malop_update_time

incident = malop_to_incident(malop)
guid_string = malop.get('guidString', '')
if not guid_string:
guid_string = malop.get('guid', '')

try:
incident = malop_to_incident(malop)
except Exception:
demisto.debug(f"edr malop got failed to convert into incident : {guid_string} and malop : {malop}")
continue
incidents.append(incident)

# Enable Polling for Cybereason EPP Malops
Expand All @@ -1543,7 +1631,15 @@ def fetch_incidents(client: Client):
if malop_update_time > max_update_time:
max_update_time = malop_update_time

incident = malop_to_incident(non_edr_malops)
guid_string = malop.get('guidString', '')
if not guid_string:
guid_string = malop.get('guid', '')

try:
incident = malop_to_incident(non_edr_malops)
except Exception:
demisto.debug(f"non edr malop got failed to convert into incident : {guid_string} and malop : {non_edr_malops}")
continue
incidents.append(incident)
demisto.debug(f"Fetching the length of incidents list if epp in enabled : {len(incidents)}")

Expand Down Expand Up @@ -1724,6 +1820,7 @@ def start_fetchfile_command(client: Client, args: dict):
return CommandResults(readable_output="Successfully started fetching file for the given malop")
except Exception:
raise Exception("Failed to start fetch file process")
return None


def start_fetchfile(client: Client, element_id: str, user_name: str) -> dict:
Expand Down Expand Up @@ -1775,9 +1872,12 @@ def get_batch_id(client: Client, suspect_files_guids: dict) -> list:
del suspect_files_guids[file_status['fileName']]
for suspect_file in list(suspect_files_guids.keys()):
malop_comment = f'Could not download the file {suspect_file} from source machine, even after waiting for 80 seconds.'
raise DemistoException(malop_comment)
demisto.info(malop_comment)

return new_malop_comments
if new_malop_comments == []:
raise DemistoException(malop_comment)
else:
return new_malop_comments


def fetchfile_progress(client: Client):
Expand Down Expand Up @@ -1826,6 +1926,7 @@ def malware_query_command(client: Client, args: dict):
if limit_range > 0:
filter_response = malware_query_filter(client, needs_attention, malware_type, malware_status, time_stamp, limit_range)
return CommandResults(raw_response=filter_response)
return None
else:
raise DemistoException("Limit cannot be zero or a negative number.")

Expand Down
Loading
Loading