From b6d5998158c830dc4620e18b87fda33224bbf938 Mon Sep 17 00:00:00 2001 From: JudithB <132264628+jbabazadeh@users.noreply.github.com> Date: Thu, 9 Nov 2023 17:44:50 +0200 Subject: [PATCH] change test when state argument is missing (#30773) * change test when state argument is missing * docker image * Update Packs/ProofpointThreatResponse/ReleaseNotes/2_0_15.md Co-authored-by: yuvalbenshalom --------- Co-authored-by: yuvalbenshalom --- .../ProofpointThreatResponse.py | 73 +++++++++---------- .../ProofpointThreatResponse.yml | 52 ++++++------- .../ReleaseNotes/2_0_15.md | 7 ++ .../pack_metadata.json | 2 +- 4 files changed, 70 insertions(+), 64 deletions(-) create mode 100644 Packs/ProofpointThreatResponse/ReleaseNotes/2_0_15.md diff --git a/Packs/ProofpointThreatResponse/Integrations/ProofpointThreatResponse/ProofpointThreatResponse.py b/Packs/ProofpointThreatResponse/Integrations/ProofpointThreatResponse/ProofpointThreatResponse.py index dab2328bfe9f..828fb6bbfa55 100644 --- a/Packs/ProofpointThreatResponse/Integrations/ProofpointThreatResponse/ProofpointThreatResponse.py +++ b/Packs/ProofpointThreatResponse/Integrations/ProofpointThreatResponse/ProofpointThreatResponse.py @@ -25,7 +25,7 @@ def get_list(list_id): - fullurl = BASE_URL + 'api/lists/{}/members.json'.format(list_id) + fullurl = BASE_URL + f'api/lists/{list_id}/members.json' res = requests.get( fullurl, headers={ @@ -36,7 +36,7 @@ def get_list(list_id): ) if res.status_code < 200 or res.status_code >= 300: - return_error('Get list failed. URL: {}, StatusCode: {}'.format(fullurl, res.status_code)) + return_error(f'Get list failed. URL: {fullurl}, StatusCode: {res.status_code}') return res.json() @@ -50,7 +50,7 @@ def get_list_command(): def add_to_list(list_id, indicator, comment, expiration): - fullurl = BASE_URL + 'api/lists/{}/members.json'.format(list_id) + fullurl = BASE_URL + f'api/lists/{list_id}/members.json' indicator = { 'member': indicator @@ -71,7 +71,7 @@ def add_to_list(list_id, indicator, comment, expiration): ) if res.status_code < 200 or res.status_code >= 300: - return_error('Add to list failed. URL: {}, Request Body: {}'.format(fullurl, json.dumps(indicator))) + return_error(f'Add to list failed. URL: {fullurl}, Request Body: {json.dumps(indicator)}') return res.json() @@ -86,7 +86,7 @@ def add_to_list_command(): message = '' for indicator in indicators: add_to_list(list_id, indicator, comment, expiration) - message += '{} added successfully to {}\n'.format(indicator, list_id) + message += f'{indicator} added successfully to {list_id}\n' demisto.results(message) @@ -100,7 +100,7 @@ def block_ip_command(): message = '' for ip in ips: add_to_list(list_id, ip, None, expiration) - message += '{} added successfully to block_ip list\n'.format(ip) + message += f'{ip} added successfully to block_ip list\n' demisto.results(message) @@ -114,7 +114,7 @@ def block_domain_command(): message = '' for domain in domains: add_to_list(list_id, domain, None, expiration) - message += '{} added successfully to block_domain list\n'.format(domain) + message += f'{domain} added successfully to block_domain list\n' demisto.results(message) @@ -128,7 +128,7 @@ def block_url_command(): message = '' for url in urls: add_to_list(list_id, url, None, expiration) - message += '{} added successfully to block_url list\n'.format(url) + message += f'{url} added successfully to block_url list\n' demisto.results(message) @@ -142,7 +142,7 @@ def block_hash_command(): message = '' for h in hashes: add_to_list(list_id, h, None, expiration) - message += '{} added successfully to block_hash list\n'.format(h) + message += f'{h} added successfully to block_hash list\n' demisto.results(message) @@ -170,10 +170,10 @@ def search_indicator_command(): def delete_indicator(list_id, indicator_filter): indicator = search_indicators(list_id, indicator_filter) if len(indicator) == 0: - return_error('{} not exists in {}'.format(indicator_filter, list_id)) + return_error(f'{indicator_filter} not exists in {list_id}') indicator_id = indicator.get('id') # pylint: disable=E1101 - fullurl = BASE_URL + 'api/lists/{}/members/{}.json'.format(list_id, indicator_id) + fullurl = BASE_URL + f'api/lists/{list_id}/members/{indicator_id}.json' res = requests.delete( fullurl, headers={ @@ -182,7 +182,7 @@ def delete_indicator(list_id, indicator_filter): verify=VERIFY_CERTIFICATE ) if res.status_code < 200 or res.status_code >= 300: - return_error('Delete indicator failed. URL: {}, StatusCode: {}'.format(fullurl, res.status_code)) + return_error(f'Delete indicator failed. URL: {fullurl}, StatusCode: {res.status_code}') def delete_indicator_command(): @@ -191,7 +191,7 @@ def delete_indicator_command(): indicator = demisto.args().get('indicator') delete_indicator(list_id, indicator) - demisto.results('{} deleted successfully from list {}'.format(list_id, indicator)) + demisto.results(f'{list_id} deleted successfully from list {indicator}') def test(): @@ -200,7 +200,9 @@ def test(): Returns: 'ok' if test passed, anything else will fail the test. """ - + integration_params = demisto.params() + if integration_params.get('isFetch') and not integration_params.get('states'): + raise DemistoException("Missing argument - You must provide at least one incident state.") get_incidents_request( { 'created_after': date.today(), @@ -220,7 +222,7 @@ def create_incident_field_context(incident): Returns: list. The parsed incident fields list """ - incident_field_values = dict() + incident_field_values = {} for incident_field in incident.get('incident_field_values', []): incident_field_values[incident_field['name'].replace(" ", "_")] = incident_field['value'] @@ -334,7 +336,7 @@ def get_incident_command(): args = demisto.args() incident_id = args.pop('incident_id') expand_events = args.get('expand_events') - fullurl = BASE_URL + 'api/incidents/{}.json'.format(incident_id) + fullurl = BASE_URL + f'api/incidents/{incident_id}.json' incident_data = requests.get( fullurl, headers={ @@ -348,7 +350,7 @@ def get_incident_command(): ) if incident_data.status_code < 200 or incident_data.status_code >= 300: - return_error('Get incident failed. URL: {}, StatusCode: {}'.format(fullurl, incident_data.status_code)) + return_error(f'Get incident failed. URL: {fullurl}, StatusCode: {incident_data.status_code}') incident_data = incident_data.json() human_readable = create_incidents_human_readable('Incident Results:', [incident_data]) @@ -370,11 +372,7 @@ def pass_sources_list_filter(incident, sources_list): if len(sources_list) == 0: return True - for source in sources_list: - if source in incident.get("event_sources"): - return True - - return False + return any(source in incident.get('event_sources') for source in sources_list) def pass_abuse_disposition_filter(incident, abuse_disposition_values): @@ -391,9 +389,8 @@ def pass_abuse_disposition_filter(incident, abuse_disposition_values): return True for incident_field in incident.get('incident_field_values', []): - if incident_field['name'] == 'Abuse Disposition': - if incident_field['value'] in abuse_disposition_values: - return True + if incident_field['name'] == 'Abuse Disposition' and incident_field['value'] in abuse_disposition_values: + return True return False @@ -448,7 +445,7 @@ def get_incidents_request(params): 'You may consider adding a filter argument to the command.\n' 'URL: {}, StatusCode: {}'.format(fullurl, incidents_list.status_code)) else: - return_error('The operation failed. URL: {}, StatusCode: {}'.format(fullurl, incidents_list.status_code)) + return_error(f'The operation failed. URL: {fullurl}, StatusCode: {incidents_list.status_code}') return incidents_list.json() @@ -546,7 +543,7 @@ def get_incidents_batch_by_time_request(params): # updating params according to the new times request_params['created_after'] = created_after.isoformat().split('.')[0] + 'Z' request_params['created_before'] = created_before.isoformat().split('.')[0] + 'Z' - demisto.debug("End of the current batch loop with {} incidents".format(str(len(incidents_list)))) + demisto.debug(f"End of the current batch loop with {str(len(incidents_list))} incidents") # fetching the last batch when created_before is bigger then current time = fetching new incidents if len(incidents_list) < fetch_limit: @@ -597,7 +594,7 @@ def fetch_incidents_command(): for incident in incidents_list: id = incident.get('id') inc = { - 'name': 'ProofPoint_TRAP - ID {}'.format(id), + 'name': f'ProofPoint_TRAP - ID {id}', 'rawJSON': json.dumps(incident), 'occurred': incident['created_at'] } @@ -615,7 +612,7 @@ def fetch_incidents_command(): demisto.setLastRun({'last_fetch': last_fetch}) demisto.setLastRun({'last_fetched_incident_id': last_fetched_id}) - demisto.info('extracted {} incidents'.format(len(incidents))) + demisto.info(f'extracted {len(incidents)} incidents') demisto.incidents(incidents) @@ -640,7 +637,7 @@ def create_add_comment_human_readable(incident): 'Action ID': incident.get('id') }) - return tableToMarkdown('Comments added successfully to incident:{}'.format(incident_id), human_readable, + return tableToMarkdown(f'Comments added successfully to incident:{incident_id}', human_readable, human_readable_headers, removeNull=True) @@ -657,7 +654,7 @@ def add_comment_to_incident_command(): "detail": details } - fullurl = BASE_URL + 'api/incidents/{}/comments.json'.format(incident_id) + fullurl = BASE_URL + f'api/incidents/{incident_id}/comments.json' incident_data = requests.post( fullurl, headers={ @@ -708,7 +705,7 @@ def add_user_to_incident_command(): return_error('Add comment to incident command failed. URL: {}, ' 'StatusCode: {}'.format(fullurl, incident_data.status_code)) - return_outputs('The user was added successfully to incident {}'.format(incident_id), {}, {}) + return_outputs(f'The user was added successfully to incident {incident_id}', {}, {}) def parse_json_argument(argument_string_value, argument_name): @@ -716,9 +713,9 @@ def parse_json_argument(argument_string_value, argument_name): try: parsed_arg = json.loads(argument_string_value) except ValueError as error: - return_error("The '{}' argument is not a valid json. Error: {}".format(argument_name, error)) + return_error(f"The '{argument_name}' argument is not a valid json. Error: {error}") if not parsed_arg.get(argument_name): - return_error("The '{}' json argument should start with a key named '{}'".format(argument_name, argument_name)) + return_error(f"The '{argument_name}' json argument should start with a key named '{argument_name}'") return parsed_arg @@ -726,7 +723,7 @@ def parse_json_argument(argument_string_value, argument_name): def prepare_ingest_alert_request_body(args): json_arguments = ['attacker', 'cnc_host', 'detector', 'email', 'forensics_hosts', 'target', 'threat_info', 'custom_fields'] - request_body = dict() # type: dict + request_body = {} # type: dict for argument_name, argument_value in args.items(): if argument_name in json_arguments: parsed_argument = parse_json_argument(argument_value, argument_name) @@ -749,7 +746,7 @@ def ingest_alert_command(): "either as an argument or as an integration parameter.") request_body = prepare_ingest_alert_request_body(assign_params(**args)) - fullurl = BASE_URL + 'threat/json_event/events/{}'.format(json_source_id) + fullurl = BASE_URL + f'threat/json_event/events/{json_source_id}' alert_data = requests.post( fullurl, headers={ @@ -791,7 +788,7 @@ def close_incident_command(): return_error('Incident closure failed. URL: {}, ' 'StatusCode: {}'.format(fullurl, incident_data.status_code)) - return_outputs('The incident {} was successfully closed'.format(incident_id), {}, {}) + return_outputs(f'The incident {incident_id} was successfully closed', {}, {}) def search_quarantine(): @@ -892,7 +889,7 @@ def search_quarantine(): def main(): handle_proxy(demisto.params().get('proxy')) command = demisto.command() - demisto.info('Command being called is {}'.format(command)) + demisto.info(f'Command being called is {command}') if command == 'test-module': test() diff --git a/Packs/ProofpointThreatResponse/Integrations/ProofpointThreatResponse/ProofpointThreatResponse.yml b/Packs/ProofpointThreatResponse/Integrations/ProofpointThreatResponse/ProofpointThreatResponse.yml index 146a41b93b26..fcb0b029a0f6 100644 --- a/Packs/ProofpointThreatResponse/Integrations/ProofpointThreatResponse/ProofpointThreatResponse.yml +++ b/Packs/ProofpointThreatResponse/Integrations/ProofpointThreatResponse/ProofpointThreatResponse.yml @@ -66,27 +66,29 @@ configuration: additionalinfo: The time range between create_after and created_before that is sent to the API when fetching older incidents. If timeout errors occur, consider changing this value. section: Collect required: false -- display: Fetch incidents with specific event sources. Can be a list of comma separated values. - name: event_sources - type: 0 - section: Collect - advanced: true - required: false -- display: Fetch incidents with specific 'Abuse Disposition' values. Can be a list of comma separated values. - name: abuse_disposition - type: 0 - section: Collect - advanced: true - required: false - display: Fetch incident with specific states. name: states type: 16 + section: Collect + advanced: false + required: false options: - new - open - assigned - closed - ignored + additionalinfo: > + When fetch is enable you must provide this argument. Possible values are: new, open, assigned, closed or ignored. +- display: Fetch incidents with specific event sources. Can be a list of comma separated values. + name: event_sources + type: 0 + section: Collect + advanced: true + required: false +- display: Fetch incidents with specific 'Abuse Disposition' values. Can be a list of comma separated values. + name: abuse_disposition + type: 0 section: Collect advanced: true required: false @@ -128,7 +130,7 @@ script: isArray: true name: ip required: true - - description: 'The date and time the supplied IP addresses should be removed from the block list, in the format YYYY-MM-DDTHH:MM:SSZ. For example: 2020-02-02T19:00:00Z' + - description: 'The date and time the supplied IP addresses should be removed from the block list, in the format YYYY-MM-DDTHH:MM:SSZ. For example: 2020-02-02T19:00:00Z.' name: expiration - description: The ID of the IP block list. name: blacklist_ip @@ -141,7 +143,7 @@ script: isArray: true name: domain required: true - - description: 'The date and time the supplied IP addresses should be removed from the block list, in the format YYYY-MM-DDTHH:MM:SSZ. For example: 2020-02-02T19:00:00Z' + - description: 'The date and time the supplied IP addresses should be removed from the block list, in the format YYYY-MM-DDTHH:MM:SSZ. For example: 2020-02-02T19:00:00Z.' name: expiration - description: The ID of the domain block list. name: blacklist_domain @@ -152,7 +154,7 @@ script: - description: The ID of the list in which to search. name: list-id required: true - - description: The filter for the indicator search. For example, "1.1" will return [1.1.1.1, 22.22.1.1, 1.1.22.22] + - description: The filter for the indicator search. For example, "1.1" will return [1.1.1.1, 22.22.1.1, 1.1.22.22]. name: filter required: true description: Returns indicators from the specified list, according to the defined filter. @@ -171,7 +173,7 @@ script: isArray: true name: url required: true - - description: 'The date and time the supplied URLs should be removed from the block list, in the format YYYY-MM-DDTHH:MM:SSZ. For example: 2020-02-02T19:00:00Z' + - description: 'The date and time the supplied URLs should be removed from the block list, in the format YYYY-MM-DDTHH:MM:SSZ. For example: 2020-02-02T19:00:00Z.' name: expiration - description: The ID of the URL block list. name: blacklist_url @@ -183,9 +185,9 @@ script: isArray: true name: hash required: true - - description: 'The date and time the supplied file hashes should be removed from the block list, in the format YYYY-MM-DDTHH:MM:SSZ. For example: 2020-02-02T19:00:00Z' + - description: 'The date and time the supplied file hashes should be removed from the block list, in the format YYYY-MM-DDTHH:MM:SSZ. For example: 2020-02-02T19:00:00Z.' name: expiration - - description: The ID of the hash block list + - description: The ID of the hash block list. name: blacklist_hash required: true description: Adds the supplied file hashes to the specified file hash block list. @@ -200,13 +202,13 @@ script: - assigned - closed - ignored - - description: 'Retrieve incidents that were created after this date, in ISO 8601 format (UTC). Example: 2020-02-22 or 2020-02-22T00:00:00Z' + - description: 'Retrieve incidents that were created after this date, in ISO 8601 format (UTC). Example: 2020-02-22 or 2020-02-22T00:00:00Z.' name: created_after predefined: - '' - - description: 'Retrieve incidents that were created before this date, in ISO 8601 format (UTC). Example: 2020-02-22 or 2020-02-22T00:00:00Z' + - description: 'Retrieve incidents that were created before this date, in ISO 8601 format (UTC). Example: 2020-02-22 or 2020-02-22T00:00:00Z.' name: created_before - - description: 'Retrieve incidents that were closed after this date, in ISO 8601 format (UTC). Example: 2020-02-22 or 2020-02-22T00:00:00Z' + - description: 'Retrieve incidents that were closed after this date, in ISO 8601 format (UTC). Example: 2020-02-22 or 2020-02-22T00:00:00Z.' name: closed_after - description: 'Retrieve incidents that were closed before this date, in ISO 8601 format (UTC). Example: 2020-02-22 or 2020-02-22T00:00:00Z.' name: closed_before @@ -463,7 +465,7 @@ script: description: The state of the event. type: String - contextPath: ProofPointTRAP.Incident.events.attackDirection - description: The attack direction of the event + description: The attack direction of the event. type: String - contextPath: ProofPointTRAP.Incident.events.received description: The date the incident was received. @@ -616,7 +618,7 @@ script: name: details - description: The incident closure summary. name: summary - description: Close a specified incident + description: Close a specified incident. name: proofpoint-tr-close-incident - arguments: - description: POST URL of the JSON alert source. You can find it by navigating to Sources -> JSON event source -> POST URL. @@ -707,7 +709,7 @@ script: - description: The recipient of the email. name: recipient required: true - - description: 'The reception time of the email in the format YYYY-MM-DDTHH:MM:SSZ. For example: 2020-02-02T19:00:00Z' + - description: 'The reception time of the email in the format YYYY-MM-DDTHH:MM:SSZ. For example: 2020-02-02T19:00:00Z.' name: time required: true outputs: @@ -721,7 +723,7 @@ script: script: '-' subtype: python3 type: python - dockerimage: demisto/python3:3.10.12.63474 + dockerimage: demisto/python3:3.10.13.80014 tests: - No test - beta_integration beta: true diff --git a/Packs/ProofpointThreatResponse/ReleaseNotes/2_0_15.md b/Packs/ProofpointThreatResponse/ReleaseNotes/2_0_15.md new file mode 100644 index 000000000000..2ef6d68af82d --- /dev/null +++ b/Packs/ProofpointThreatResponse/ReleaseNotes/2_0_15.md @@ -0,0 +1,7 @@ + +#### Integrations + +##### Proofpoint Threat Response (Beta) + +- Fixed an issue where Fetch failed on missing parameter. +- Updated the Docker image to: *demisto/python3:3.10.13.80014*. diff --git a/Packs/ProofpointThreatResponse/pack_metadata.json b/Packs/ProofpointThreatResponse/pack_metadata.json index b0d7385886fe..c10fd01cc908 100644 --- a/Packs/ProofpointThreatResponse/pack_metadata.json +++ b/Packs/ProofpointThreatResponse/pack_metadata.json @@ -2,7 +2,7 @@ "name": "Proofpoint Threat Response", "description": "Use the Proofpoint Threat Response integration to orchestrate and automate incident response.", "support": "xsoar", - "currentVersion": "2.0.14", + "currentVersion": "2.0.15", "author": "Cortex XSOAR", "url": "https://www.paloaltonetworks.com/cortex", "email": "",