diff --git a/Packs/CommonScripts/ReleaseNotes/1_7_65.md b/Packs/CommonScripts/ReleaseNotes/1_7_65.md new file mode 100644 index 000000000000..0cf029cff683 --- /dev/null +++ b/Packs/CommonScripts/ReleaseNotes/1_7_65.md @@ -0,0 +1,17 @@ + +#### Scripts +##### MaliciousRatioReputation +- Updated the Docker image to: *demisto/python3:3.10.7.33922*. + +##### DisplayHTML +- Updated the Docker image to: *demisto/python3:3.10.7.33922*. + +##### SendEmailOnSLABreach +- Updated the Docker image to: *demisto/python3:3.10.7.33922*. + +##### ResolveShortenedURL +- Updated the Docker image to: *demisto/python3:3.10.7.33922*. +- Added support for the *insecure* argument. + +##### FileToBase64List +- Updated the Docker image to: *demisto/python3:3.10.7.33922*. \ No newline at end of file diff --git a/Packs/CommonScripts/Scripts/DisplayHTML/DisplayHTML.py b/Packs/CommonScripts/Scripts/DisplayHTML/DisplayHTML.py new file mode 100644 index 000000000000..6f6668c176b7 --- /dev/null +++ b/Packs/CommonScripts/Scripts/DisplayHTML/DisplayHTML.py @@ -0,0 +1,23 @@ +import demistomock as demisto # noqa: F401 +from CommonServerPython import * # noqa: F401 + + +def main(): + html = demisto.args().get("html") + note = demisto.args().get("markAsNote") + header = demisto.args().get("header") + + note = True if note and note.lower() == "true" else False + if header: + html = "

{0}


{1}".format(header, html) + + demisto.results({ + 'ContentsFormat': formats['html'], + 'Type': entryTypes['note'], + 'Contents': html, + 'Note': note + }) + + +if __name__ == "__builtin__" or __name__ == "builtins": + main() diff --git a/Packs/CommonScripts/Scripts/DisplayHTML/DisplayHTML.yml b/Packs/CommonScripts/Scripts/DisplayHTML/DisplayHTML.yml new file mode 100644 index 000000000000..63c7fa4f4eba --- /dev/null +++ b/Packs/CommonScripts/Scripts/DisplayHTML/DisplayHTML.yml @@ -0,0 +1,28 @@ +commonfields: + id: DisplayHTML + version: -1 +name: DisplayHTML +script: '' +type: python +subtype: python3 +tags: [] +comment: Display HTML in the War Room. +system: true +args: +- name: html + required: true + description: The HTML to display +- name: markAsNote + auto: PREDEFINED + predefined: + - "true" + - "false" + description: Should the entry be marked as a note? +- name: header + description: Add a header text to the output +scripttarget: 0 +runonce: false +fromversion: 6.5.0 +dockerimage: demisto/python3:3.10.7.33922 +tests: +- No tests (auto formatted) diff --git a/Packs/CommonScripts/Scripts/DisplayHTML/DisplayHTML_test.py b/Packs/CommonScripts/Scripts/DisplayHTML/DisplayHTML_test.py new file mode 100644 index 000000000000..323cdd0d245e --- /dev/null +++ b/Packs/CommonScripts/Scripts/DisplayHTML/DisplayHTML_test.py @@ -0,0 +1,23 @@ +import demistomock as demisto +from CommonServerPython import * + + +def test_DisplayHTML(mocker): + """ + Given: + - The script args. + When: + - Running the DisplayHTML script. + Then: + - Validating the results after manipulating the given data. + """ + from DisplayHTML import main + mocker.patch.object(demisto, 'args', return_value={'html': 'html', 'markAsNote': 'True', "header": "header"}) + results_mock = mocker.patch.object(demisto, 'results') + main() + results_mock.assert_called_once() + results = results_mock.call_args[0][0] + assert results == {'Contents': '

header


html', + 'ContentsFormat': 'html', + 'Note': True, + 'Type': EntryType.NOTE} diff --git a/Packs/CommonScripts/Scripts/script-DisplayHTML_README.md b/Packs/CommonScripts/Scripts/DisplayHTML/README.md similarity index 100% rename from Packs/CommonScripts/Scripts/script-DisplayHTML_README.md rename to Packs/CommonScripts/Scripts/DisplayHTML/README.md diff --git a/Packs/CommonScripts/Scripts/FileToBase64List/FileToBase64List.py b/Packs/CommonScripts/Scripts/FileToBase64List/FileToBase64List.py index 5b7287aa8303..653326549b26 100644 --- a/Packs/CommonScripts/Scripts/FileToBase64List/FileToBase64List.py +++ b/Packs/CommonScripts/Scripts/FileToBase64List/FileToBase64List.py @@ -11,7 +11,7 @@ def get_file_data(file_path, zip=False): if zip: data = zlib.compress(data) - return base64.b64encode(data) + return base64.b64encode(data).decode('utf-8') def main(): @@ -42,5 +42,5 @@ def main(): } -if __name__ == "__builtin__" or __name__ == '__main__': +if __name__ in ('__main__', '__builtin__', 'builtins'): demisto.results(main()) diff --git a/Packs/CommonScripts/Scripts/FileToBase64List/FileToBase64List.yml b/Packs/CommonScripts/Scripts/FileToBase64List/FileToBase64List.yml index 926aa6bc474c..9436c18bd806 100644 --- a/Packs/CommonScripts/Scripts/FileToBase64List/FileToBase64List.yml +++ b/Packs/CommonScripts/Scripts/FileToBase64List/FileToBase64List.yml @@ -36,10 +36,10 @@ tags: - list timeout: '0' type: python -subtype: python2 +subtype: python3 runas: DBotWeakRole runonce: true tests: - No Test fromversion: 5.0.0 -dockerimage: demisto/python:2.7.18.27799 +dockerimage: demisto/python3:3.10.7.33922 diff --git a/Packs/CommonScripts/Scripts/FileToBase64List/file_to_base64_list_test.py b/Packs/CommonScripts/Scripts/FileToBase64List/file_to_base64_list_test.py index c495d448e37f..425392bedf8d 100644 --- a/Packs/CommonScripts/Scripts/FileToBase64List/file_to_base64_list_test.py +++ b/Packs/CommonScripts/Scripts/FileToBase64List/file_to_base64_list_test.py @@ -38,6 +38,6 @@ def test_file_to_base64_list(mocker): def test_get_file_data(mocker): data = get_file_data(TEST_FILE_PATH) - assert base64.b64decode(data).strip() == "this is a test file" + assert base64.b64decode(data).strip() == b"this is a test file" data = get_file_data(TEST_FILE_PATH, True) - assert zlib.decompress(base64.b64decode(data)).strip() == "this is a test file" + assert zlib.decompress(base64.b64decode(data)).strip() == b"this is a test file" diff --git a/Packs/CommonScripts/Scripts/MaliciousRatioReputation/MaliciousRatioReputation.py b/Packs/CommonScripts/Scripts/MaliciousRatioReputation/MaliciousRatioReputation.py new file mode 100644 index 000000000000..7a128e880700 --- /dev/null +++ b/Packs/CommonScripts/Scripts/MaliciousRatioReputation/MaliciousRatioReputation.py @@ -0,0 +1,48 @@ +import demistomock as demisto # noqa: F401 +from CommonServerPython import * # noqa: F401 + + +def get_indicator_from_value(indicator_value): + try: + res = demisto.executeCommand("findIndicators", {'value': indicator_value}) + indicator = res[0]['Contents'][0] + return indicator + except Exception: + pass + + +def get_indicator_result(indicator): + res = demisto.executeCommand("maliciousRatio", {'value': indicator['value']}) + + mr_score = res[0]['Contents'][0]['maliciousRatio'] + if mr_score > float(demisto.args()['threshold']): + ec = {} + ec['DBotScore'] = { + 'Type': indicator['indicator_type'].lower(), + 'Score': 2, # suspicious + 'Vendor': 'DBot-MaliciousRatio', + 'Indicator': indicator['value'] + } + entry = { + 'Type': entryTypes['note'], + 'EntryContext': ec, + 'Contents': ec['DBotScore']['Score'], + 'ContentsFormat': formats['text'], + 'HumanReadable': 'Malicious ratio for %s is %.2f' % (indicator['value'], mr_score), + 'ReadableContentsFormat': formats['markdown'] + } + return entry + + +def main(): + indicator_value = demisto.args().get('input') + indicator = get_indicator_from_value(indicator_value) + if indicator: + try: + demisto.results(get_indicator_result(indicator)) + except Exception: + pass + + +if __name__ == "__builtin__" or __name__ == "builtins": + main() diff --git a/Packs/CommonScripts/Scripts/MaliciousRatioReputation/MaliciousRatioReputation.yml b/Packs/CommonScripts/Scripts/MaliciousRatioReputation/MaliciousRatioReputation.yml new file mode 100644 index 000000000000..f19e6b588467 --- /dev/null +++ b/Packs/CommonScripts/Scripts/MaliciousRatioReputation/MaliciousRatioReputation.yml @@ -0,0 +1,25 @@ +commonfields: + id: MaliciousRatioReputation + version: -1 +name: MaliciousRatioReputation +fromversion: "6.5.0" +script: '' +type: python +subtype: python3 +tags: +- reputation +comment: |- + Set indicator reputation to "suspicious" when malicious ratio is above threshold. + Malicious ratio is the ration between number of "bad" incidents to total number of incidents the indicator appears in. +enabled: true +args: +- name: input + description: Value of the indicator. +- name: threshold + description: 'Malicious ratio threshold to set indicator as suspicious. ' + defaultValue: "0.3" +scripttarget: 0 +runonce: false +dockerimage: demisto/python3:3.10.7.33922 +tests: +- No tests (auto formatted) diff --git a/Packs/CommonScripts/Scripts/MaliciousRatioReputation/MaliciousRatioReputation_test.py b/Packs/CommonScripts/Scripts/MaliciousRatioReputation/MaliciousRatioReputation_test.py new file mode 100644 index 000000000000..ba6f1d6605b4 --- /dev/null +++ b/Packs/CommonScripts/Scripts/MaliciousRatioReputation/MaliciousRatioReputation_test.py @@ -0,0 +1,87 @@ +import demistomock as demisto + + +def test_main_malicious_ratio_reputation(mocker): + """ + Given: + - The script args. + When: + - Running the main with valid indicator. + Then: + - Validating after calling the helper functions the results is as expected. + """ + import MaliciousRatioReputation + args = {'input': 'value_a', 'threshold': '-2'} + mocker.patch.object(demisto, 'args', return_value=args) + mocker.patch.object(MaliciousRatioReputation, 'get_indicator_from_value', + return_value={'value': 'value_a', 'indicator_type': 'IP'}) + res_get_indicator_result = {'Type': 1, 'EntryContext': {'DBotScore': {'Type': 'ip', + 'Score': 2, 'Vendor': 'DBot-MaliciousRatio', + 'Indicator': 'value_a'}}, + 'Contents': 2, + 'ContentsFormat': 'text', + 'HumanReadable': 'Malicious ratio for value_a is -1.00', + 'ReadableContentsFormat': 'markdown'} + mocker.patch.object(MaliciousRatioReputation, 'get_indicator_result', + return_value=res_get_indicator_result) + res_mock = mocker.patch.object(demisto, 'results') + MaliciousRatioReputation.main() + assert res_mock.call_count == 1 + assert res_mock.call_args[0][0] == res_get_indicator_result + + +def test_get_indicator_result(mocker): + """ + Given: + - The script args and indicator with mr_score > given threshold. + When: + - Running the get_indicator_result function. + Then: + - Validating that the function returns entry to the context. + """ + from MaliciousRatioReputation import get_indicator_result + args = {'input': '8.8.8.8', 'threshold': '-2'} + mocker.patch.object(demisto, 'args', return_value=args) + indicator = {'value': '8.8.8.8', 'indicator_type': 'IP'} + execute_command_res = [{'Contents': [{'maliciousRatio': -1}]}] + execute_mock = mocker.patch.object(demisto, 'executeCommand', return_value=execute_command_res) + entry = get_indicator_result(indicator) + assert execute_mock.call_count == 1 + assert len(entry['EntryContext']) > 0 + + +def test_get_indicator_result_with_smaller_mr_score(mocker): + """ + Given: + - The script args and indicator with mr_score < given threshold. + When: + - Running the get_indicator_result function. + Then: + - Validating that the function doesn't return entry. + """ + from MaliciousRatioReputation import get_indicator_result + mocker.patch.object(demisto, 'args', return_value={'input': '8.8.8.8', 'threshold': '0.3'}) + indicator = {'value': '8.8.8.8', 'indicator_type': 'IP'} + execute_command_res = [{'Contents': [{'maliciousRatio': -1}]}] + execute_mock = mocker.patch.object(demisto, 'executeCommand', return_value=execute_command_res) + assert get_indicator_result(indicator) is None + assert execute_mock.call_count == 1 + + +def test_get_indicator_from_value(mocker): + """ + Given: + - The function args. + When: + - Running the get_indicator_from_value function. + Then: + - Validating that the return value after calling to "findIndicators" command is as expected. + """ + from MaliciousRatioReputation import get_indicator_from_value + + execute_command_res = [{'Contents': [{'id': 'a', 'investigationIDs': ['1', '2', '10'], 'value': 'value_a', + 'indicator_type': 'File'}], 'Type': 'note'}] + execute_mock = mocker.patch.object(demisto, 'executeCommand', return_value=execute_command_res) + indicator = get_indicator_from_value('value_a') + assert execute_mock.call_count == 1 + assert indicator == execute_command_res[0]['Contents'][0] diff --git a/Packs/CommonScripts/Scripts/script-MaliciousRatioReputation_README.md b/Packs/CommonScripts/Scripts/MaliciousRatioReputation/README.md similarity index 100% rename from Packs/CommonScripts/Scripts/script-MaliciousRatioReputation_README.md rename to Packs/CommonScripts/Scripts/MaliciousRatioReputation/README.md diff --git a/Packs/CommonScripts/Scripts/script-ResolveShortenedURL_README.md b/Packs/CommonScripts/Scripts/ResolveShortenedURL/README.md similarity index 62% rename from Packs/CommonScripts/Scripts/script-ResolveShortenedURL_README.md rename to Packs/CommonScripts/Scripts/ResolveShortenedURL/README.md index 1ec4f28b1445..eda5672139e5 100644 --- a/Packs/CommonScripts/Scripts/script-ResolveShortenedURL_README.md +++ b/Packs/CommonScripts/Scripts/ResolveShortenedURL/README.md @@ -11,9 +11,10 @@ Resolves the original URL from the given shortened URL and places it in both, as ## Inputs --- -| **Argument Name** | **Description** | -| --- | --- | -| url | The URL to resolve. | +| **Argument Name** | **Description** | +| --- |---------------------------------------------------------| +| url | The URL to resolve. | +| insecure | Trust any certificate (not secure) | ## Outputs --- diff --git a/Packs/CommonScripts/Scripts/ResolveShortenedURL/ResolveShortenedURL.py b/Packs/CommonScripts/Scripts/ResolveShortenedURL/ResolveShortenedURL.py new file mode 100644 index 000000000000..8ecf4ec31a2a --- /dev/null +++ b/Packs/CommonScripts/Scripts/ResolveShortenedURL/ResolveShortenedURL.py @@ -0,0 +1,44 @@ +import demistomock as demisto # noqa: F401 +from CommonServerPython import * # noqa: F401 +import requests +# disable insecure warnings +requests.packages.urllib3.disable_warnings() + +headers = { + 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11', + 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', + 'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.3', + 'Accept-Encoding': 'none', + 'Accept-Language': 'en-US,en;q=0.8', + 'Connection': 'keep-alive' +} + + +def main(): + url = demisto.args().get('url') + verify = not argToBoolean(demisto.args().get('insecure', False)) + req = requests.get('https://unshorten.me/json/' + url, headers=headers, verify=verify) + content = req.json() + if content['success']: + resolvedUrl = content['resolved_url'] + shortenedUrl = content['requested_url'] + usageCount = content['usage_count'] + ec = {} + ec['URL.Data'] = [resolvedUrl] + demisto.results({ + 'Type': entryTypes['note'], + 'Contents': [resolvedUrl], + 'ContentsFormat': formats['json'], + 'HumanReadable': tableToMarkdown('Shorten URL results', [{ + 'Shortened URL': shortenedUrl, + 'Resolved URL': resolvedUrl, + 'Usage count': usageCount + }]), + 'EntryContext': ec + }) + else: + demisto.results('Provided URL could not be un-shortened') + + +if __name__ == "__builtin__" or __name__ == "builtins": + main() diff --git a/Packs/CommonScripts/Scripts/ResolveShortenedURL/ResolveShortenedURL.yml b/Packs/CommonScripts/Scripts/ResolveShortenedURL/ResolveShortenedURL.yml new file mode 100644 index 000000000000..8c5d505e3893 --- /dev/null +++ b/Packs/CommonScripts/Scripts/ResolveShortenedURL/ResolveShortenedURL.yml @@ -0,0 +1,29 @@ +commonfields: + id: ResolveShortenedURL + version: -1 +name: ResolveShortenedURL +script: '' +type: python +subtype: python3 +tags: +- Utility +comment: Resolve the original URL from the given shortened URL and place it in both as output and in the context of a playbook. (https://unshorten.me/api) +enabled: true +args: +- name: url + required: true + default: true + description: URL to resolve +- name: insecure + required: false + type: Boolean + defaultValue: "false" + description: Trust any certificate (not secure) +outputs: +- contextPath: URL.Data + description: Shortened URL +scripttarget: 0 +tests: +- "No test" +fromversion: 6.5.0 +dockerimage: demisto/python3:3.10.7.33922 diff --git a/Packs/CommonScripts/Scripts/ResolveShortenedURL/ResolveShortenedURL_test.py b/Packs/CommonScripts/Scripts/ResolveShortenedURL/ResolveShortenedURL_test.py new file mode 100644 index 000000000000..fda5b32e4e2a --- /dev/null +++ b/Packs/CommonScripts/Scripts/ResolveShortenedURL/ResolveShortenedURL_test.py @@ -0,0 +1,43 @@ +import demistomock as demisto +import ResolveShortenedURL + + +def test_resolve_un_shortened_url(mocker, requests_mock): + """ + Given: + - The script args. + When: + - Running the main with a URL that can be unshortened. + Then: + - Validating calling to 'demisto.results' once with the right arguments. + """ + args = {'url': 'https://test/example'} + mocker.patch.object(demisto, 'args', return_value=args) + content = {'success': True, 'resolved_url': 'test', 'requested_url': 'test', 'usage_count': 'test'} + excepted_args = {'Type': 1, 'Contents': ['test'], 'ContentsFormat': 'json', + 'HumanReadable': '### Shorten URL results\n|Resolved URL|Shortened URL|Usage count|\n' + '|---|---|---|\n| test | test | test |\n', 'EntryContext': {'URL.Data': ['test']}} + requests_mock.get('https://unshorten.me/json/' + args['url'], json=content) + execute_mock = mocker.patch.object(demisto, 'results') + ResolveShortenedURL.main() + assert execute_mock.call_count == 1 + assert execute_mock.call_args[0][0] == excepted_args + + +def test_resolve_shortened_url(mocker, requests_mock): + """ + Given: + - The script args. + When: + - Running the main with a URL that cannot be unshortened. + Then: + - Validating calling to 'demisto.results' once with the relevant massage. + """ + args = {'url': 'https://test.com'} + mocker.patch.object(demisto, 'args', return_value=args) + content = {'success': False} + requests_mock.get('https://unshorten.me/json/' + args['url'], json=content) + execute_mock = mocker.patch.object(demisto, 'results') + ResolveShortenedURL.main() + assert execute_mock.call_count == 1 + assert execute_mock.call_args[0][0] == 'Provided URL could not be un-shortened' diff --git a/Packs/CommonScripts/Scripts/script-SendEmailOnSLABreach_README.md b/Packs/CommonScripts/Scripts/SendEmailOnSLABreach/README.md similarity index 100% rename from Packs/CommonScripts/Scripts/script-SendEmailOnSLABreach_README.md rename to Packs/CommonScripts/Scripts/SendEmailOnSLABreach/README.md diff --git a/Packs/CommonScripts/Scripts/SendEmailOnSLABreach/SendEmailOnSLABreach.py b/Packs/CommonScripts/Scripts/SendEmailOnSLABreach/SendEmailOnSLABreach.py new file mode 100644 index 000000000000..15c5d9bc0918 --- /dev/null +++ b/Packs/CommonScripts/Scripts/SendEmailOnSLABreach/SendEmailOnSLABreach.py @@ -0,0 +1,67 @@ +import demistomock as demisto # noqa: F401 +from CommonServerPython import * # noqa: F401 + +""" +This script is used to send an email about a breached SLA. The script, by default, sends the email to the assignee of the +incident. The email is sent using the send-email command, using all enabled integrations that support the command. +""" + + +def get_owner_email(): + owner_username = demisto.incidents()[0].get("owner") + if owner_username: + try: + owner_info = demisto.executeCommand('getUserByUsername', {"username": owner_username})[0] + owner_email = owner_info.get("EntryContext").get("UserByUsername").get("email") + return owner_email + except Exception as ex: + demisto.results({ + "Type": entryTypes["error"], + "ContentsFormat": formats["text"], + "Contents": "Could not retrieve user email. Maybe the user has no associated email to it.\ + Error: {}".format(ex) + + }) + return + else: + demisto.results({ + "Type": entryTypes["error"], + "ContentsFormat": formats["text"], + "Contents": "An email can't be sent to the owner of the incident, because no owner was assigned." + }) + + +def get_subject(): + incident_name = demisto.incidents()[0].get("name") + incident_id = demisto.incidents()[0].get("id") + subject = "SLA Breached in incident \"{}\" #{}".format(incident_name, incident_id) + return subject + + +def send_email(to, subject, body): + demisto.results(demisto.executeCommand('send-mail', { + "to": to, + "subject": subject, + "body": body})) + + +def get_body(): + field_name = demisto.args().get("field").get("cliName") + sla = demisto.args().get("fieldValue").get("sla") + start_date = demisto.args().get("fieldValue").get("startDate") + body = "We have detected a breach in your SLA \"{}\".\nThe SLA was set to {} minute and was started on {}.".format( + field_name, sla, start_date.split(".")[0]) + return body + + +def main(): + email_to = get_owner_email() + email_subject = get_subject() + email_body = get_body() + + if email_to: + send_email(email_to, email_subject, email_body) + + +if __name__ == "__builtin__" or __name__ == "builtins": + main() diff --git a/Packs/CommonScripts/Scripts/SendEmailOnSLABreach/SendEmailOnSLABreach.yml b/Packs/CommonScripts/Scripts/SendEmailOnSLABreach/SendEmailOnSLABreach.yml new file mode 100644 index 000000000000..57f13c8241ab --- /dev/null +++ b/Packs/CommonScripts/Scripts/SendEmailOnSLABreach/SendEmailOnSLABreach.yml @@ -0,0 +1,21 @@ +commonfields: + id: SendEmailOnSLABreach + version: -1 +name: SendEmailOnSLABreach +script: '' +type: python +subtype: python3 +tags: +- sla +- example +comment: |- + Sends an email informing the user of an SLA breach. The email is sent to the user who is assigned to the incident. It includes the incident name, ID, name of the SLA field that was breached, duration of that SLA field, and the date and time when that SLA was started. + In order to run successfully, the script should be configured to trigger on SLA breach, through field edit mode. +enabled: true +scripttarget: 0 +runonce: false +runas: DBotWeakRole +tests: +- No test - Can't test script that triggers on SLA breach. Need a field to trigger it and need a configured mail sender. Also errors aren't accounted. +fromversion: 6.5.0 +dockerimage: demisto/python3:3.10.7.33922 diff --git a/Packs/CommonScripts/Scripts/SendEmailOnSLABreach/SendEmailOnSLABreach_test.py b/Packs/CommonScripts/Scripts/SendEmailOnSLABreach/SendEmailOnSLABreach_test.py new file mode 100644 index 000000000000..e853ba95d167 --- /dev/null +++ b/Packs/CommonScripts/Scripts/SendEmailOnSLABreach/SendEmailOnSLABreach_test.py @@ -0,0 +1,107 @@ +import demistomock as demisto + +incident_with_owner = { + 'id': 1, + 'name': 'incident1', + 'owner': 'admin' +} +incident_without_owner = { + 'id': 2, + 'name': 'incident2', + 'owner': "" +} + + +def test_get_owner_email(mocker): + """ + Given: + - Incident with owner. + When: + - Running get_owner_email function. + Then: + - Validating the return value as expected. + """ + from SendEmailOnSLABreach import get_owner_email + + mocker.patch.object(demisto, 'incidents', return_value=[incident_with_owner]) + mocker.patch.object(demisto, "executeCommand", return_value=[{'EntryContext': + {'UserByUsername': {'email': "test@gmail.com"}}, + 'Type': ''}]) + results_mock = mocker.patch.object(demisto, 'results') + assert get_owner_email() == "test@gmail.com" + results_mock.assert_not_called() + + +def test_get_no_email_owner(mocker): + """ + Given: + - Incident without owner. + When: + - Running get_owner_email function. + Then: + - Validating calling to 'demisto.results' once with the right arguments. + """ + from SendEmailOnSLABreach import get_owner_email + + mocker.patch.object(demisto, 'incidents', return_value=[incident_without_owner]) + demisto_results_mocker = mocker.patch.object(demisto, 'results') + get_owner_email() + demisto_results_mocker.assert_called_once() + results = demisto_results_mocker.call_args[0][0] + assert results == {"Type": 4, + "ContentsFormat": "text", + "Contents": "An email can't be sent to the owner of the incident," + " because no owner was assigned."} + + +def test_get_subject(mocker): + """ + Given: + - Incident + When: + - Running get_subject function. + Then: + - Validating the return value as expected. + """ + from SendEmailOnSLABreach import get_subject + + mocker.patch.object(demisto, 'incidents', return_value=[incident_with_owner]) + excepted_subject = "SLA Breached in incident \"{}\" #{}".format(incident_with_owner['name'], + incident_with_owner['id']) + assert get_subject() == excepted_subject + + +def test_send_email(mocker): + """ + Given: + - The function's arguments + When: + - Running send_email function. + Then: + - Validating calling to 'demisto.results' once with the right arguments. + """ + from SendEmailOnSLABreach import send_email + mocker.patch.object(demisto, "executeCommand", return_value="send-mail") + results_mock = mocker.patch.object(demisto, 'results') + send_email(to="to_mail_test", subject="subject_test", body="body_test") + results_mock.assert_called_once() + assert results_mock.call_args[0][0] == "send-mail" + + +def test_get_body(mocker): + """ + Given: + - The function's arguments + When: + - Running get_body function. + Then: + - Validating the return value as expected. + """ + from SendEmailOnSLABreach import get_body + field_name, sla, start_date = "cliNameTest", "slaTest", "2022-09-07T15:10:04.000Z" + args = {'field': {'cliName': "cliNameTest"}, 'fieldValue': {"sla": "slaTest", + "startDate": "2022-09-07T15:10:04.000Z"}} + mocker.patch.object(demisto, 'args', return_value=args) + excepted_body = "We have detected a breach in your SLA \"{}\".\nThe SLA was set to {} minute and was started on {}." \ + .format(field_name, sla, start_date.split(".")[0]) + assert get_body() == excepted_body diff --git a/Packs/CommonScripts/Scripts/script-DisplayHTML.yml b/Packs/CommonScripts/Scripts/script-DisplayHTML.yml deleted file mode 100644 index 5890a0220546..000000000000 --- a/Packs/CommonScripts/Scripts/script-DisplayHTML.yml +++ /dev/null @@ -1,46 +0,0 @@ -commonfields: - id: DisplayHTML - version: -1 -name: DisplayHTML -script: > - html = demisto.args().get("html") - - note = demisto.args().get("markAsNote") - - header = demisto.args().get("header") - - - note = True if note and note.lower() == "true" else False - - if header: - html = "

{0}


{1}".format(header,html) - - demisto.results( { - 'ContentsFormat': formats['html'], - 'Type': entryTypes['note'], - 'Contents': html, - 'Note': note - } ) -type: python -subtype: python2 -tags: [] -comment: Display HTML in the War Room. -system: true -args: -- name: html - required: true - description: The HTML to display -- name: markAsNote - auto: PREDEFINED - predefined: - - "true" - - "false" - description: Should the entry be marked as a note? -- name: header - description: Add a header text to the output -scripttarget: 0 -runonce: false -fromversion: 5.0.0 -dockerimage: demisto/python:2.7.18.27799 -tests: -- No tests (auto formatted) diff --git a/Packs/CommonScripts/Scripts/script-MaliciousRatioReputation.yml b/Packs/CommonScripts/Scripts/script-MaliciousRatioReputation.yml deleted file mode 100644 index c49e8ed35674..000000000000 --- a/Packs/CommonScripts/Scripts/script-MaliciousRatioReputation.yml +++ /dev/null @@ -1,60 +0,0 @@ -commonfields: - id: MaliciousRatioReputation - version: -1 -name: MaliciousRatioReputation -fromversion: "5.0.0" -script: >- - def get_indicator_from_value(indicator_value): - try: - res = demisto.executeCommand("findIndicators", {'value': indicator_value}) - indicator = res[0]['Contents'][0] - return indicator - except: - pass - - indicator_value = demisto.args()['input'] - - indicator = get_indicator_from_value(indicator_value) - - if indicator: - res = demisto.executeCommand("maliciousRatio", {'value': indicator['value']}) - try: - mr_score = res[0]['Contents'][0]['maliciousRatio'] - if mr_score > float(demisto.args()['threshold']): - ec = {} - ec['DBotScore'] = { - 'Type': indicator['indicator_type'].lower(), - 'Score': 2, #suspicious - 'Vendor': 'DBot-MaliciousRatio', - 'Indicator': indicator['value'] - } - entry = { - 'Type': entryTypes['note'], - 'EntryContext': ec, - 'Contents': ec['DBotScore']['Score'], - 'ContentsFormat': formats['text'], - 'HumanReadable': 'Malicious ratio for %s is %.2f' % (indicator['value'], mr_score), - 'ReadableContentsFormat': formats['markdown'] - } - demisto.results(entry) - except: - pass -type: python -subtype: python2 -tags: -- reputation -comment: |- - Set indicator reputation to "suspicious" when malicious ratio is above threshold. - Malicious ratio is the ration between number of "bad" incidents to total number of incidents the indicator appears in. -enabled: true -args: -- name: input - description: Value of the indicator. -- name: threshold - description: 'Malicious ratio threshold to set indicator as suspicious. ' - defaultValue: "0.3" -scripttarget: 0 -runonce: false -dockerimage: demisto/python:2.7.18.24398 -tests: -- No tests (auto formatted) diff --git a/Packs/CommonScripts/Scripts/script-ResolveShortenedURL.yml b/Packs/CommonScripts/Scripts/script-ResolveShortenedURL.yml deleted file mode 100644 index a7ab4a25929c..000000000000 --- a/Packs/CommonScripts/Scripts/script-ResolveShortenedURL.yml +++ /dev/null @@ -1,68 +0,0 @@ -commonfields: - id: ResolveShortenedURL - version: -1 -name: ResolveShortenedURL -script: > - import urllib2 - - import re - - - headers = { - 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11', - 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', - 'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.3', - 'Accept-Encoding': 'none', - 'Accept-Language': 'en-US,en;q=0.8', - 'Connection': 'keep-alive' - } - - - url = demisto.args()['url'] - - - req = urllib2.Request('https://unshorten.me/json/'+url, headers=headers) - - page = urllib2.urlopen(req) - - content = json.loads(page.read()) - - if content['success'] == True: - resolvedUrl = content['resolved_url'] - shortenedUrl = content['requested_url'] - usageCount = content['usage_count'] - ec = {}; - ec['URL.Data'] = [resolvedUrl] - demisto.results({ - 'Type': entryTypes['note'], - 'Contents': [resolvedUrl], - 'ContentsFormat': formats['json'], - 'HumanReadable': tableToMarkdown('Shorten URL results', [{ - 'Shortened URL': shortenedUrl, - 'Resolved URL': resolvedUrl, - 'Usage count': usageCount - }]), - 'EntryContext': ec - }) - else: - demisto.results('Provided URL could not be un-shortened') - -type: python -subtype: python2 -tags: -- Utility -comment: Resolve the original URL from the given shortened URL and place it in both as output and in the context of a playbook. (https://unshorten.me/api) -enabled: true -args: -- name: url - required: true - default: true - description: URL to resolve -outputs: -- contextPath: URL.Data - description: Shortened URL -scripttarget: 0 -tests: -- "No test" -fromversion: 5.0.0 -dockerimage: demisto/python:2.7.18.24398 diff --git a/Packs/CommonScripts/Scripts/script-SendEmailOnSLABreach.yml b/Packs/CommonScripts/Scripts/script-SendEmailOnSLABreach.yml deleted file mode 100644 index cbfaec7880a9..000000000000 --- a/Packs/CommonScripts/Scripts/script-SendEmailOnSLABreach.yml +++ /dev/null @@ -1,85 +0,0 @@ -commonfields: - id: SendEmailOnSLABreach - version: -1 -name: SendEmailOnSLABreach -script: >- - """ - - This script is used to send an email about a breached SLA. The script, by default, sends the email to the assignee of the - - incident. The email is sent using the send-email command, using all enabled integrations that support the command. - - """ - - - def get_owner_email(): - owner_username = demisto.incidents()[0].get("owner") - if owner_username: - try: - owner_info = demisto.executeCommand('getUserByUsername', {"username":owner_username})[0] - owner_email = owner_info.get("EntryContext").get("UserByUsername").get("email") - return owner_email - except Exception, ex: - demisto.results - ({ - "Type" : entryTypes["error"], - "ContentsFormat" : formats["text"], - "Contents" : "Could not retrieve user email. Maybe the user has no associated email to it.\ - Error: {}".format(ex) - - }) - return - else: - demisto.results - ({ - "Type" : entryTypes["error"], - "ContentsFormat" : formats["text"], - "Contents" : "An email can't be sent to the owner of the incident, because no owner was assigned." - - }) - - def get_subject(): - incident_name = demisto.incidents()[0].get("name") - incident_id = demisto.incidents()[0].get("id") - subject = "SLA Breached in incident \"{}\" #{}".format(incident_name, incident_id) - return subject - - def send_email(to, subject, body): - demisto.results(demisto.executeCommand('send-mail', { - "to": to, - "subject": subject, - "body": body})) - - def get_body(): - field_name = demisto.args().get("field").get("cliName") - sla = demisto.args().get("fieldValue").get("sla") - start_date = demisto.args().get("fieldValue").get("startDate") - body = "We have detected a breach in your SLA \"{}\".\nThe SLA was set to {} minute and was started on {}.".format( - field_name, sla, start_date.split(".")[0]) - return body - - email_to = get_owner_email() - - email_subject = get_subject() - - email_body = get_body() - - - if email_to: - send_email(email_to, email_subject, email_body) -type: python -subtype: python2 -tags: -- sla -- example -comment: |- - Sends an email informing the user of an SLA breach. The email is sent to the user who is assigned to the incident. It includes the incident name, ID, name of the SLA field that was breached, duration of that SLA field, and the date and time when that SLA was started. - In order to run successfully, the script should be configured to trigger on SLA breach, through field edit mode. -enabled: true -scripttarget: 0 -runonce: false -runas: DBotWeakRole -tests: -- No test - Can't test script that triggers on SLA breach. Need a field to trigger it and need a configured mail sender. Also errors aren't accounted. -fromversion: 5.0.0 -dockerimage: demisto/python:2.7.18.24398 diff --git a/Packs/CommonScripts/pack_metadata.json b/Packs/CommonScripts/pack_metadata.json index a9afac3643d8..1314e5e5b3ed 100644 --- a/Packs/CommonScripts/pack_metadata.json +++ b/Packs/CommonScripts/pack_metadata.json @@ -2,7 +2,7 @@ "name": "Common Scripts", "description": "Frequently used scripts pack.", "support": "xsoar", - "currentVersion": "1.7.64", + "currentVersion": "1.7.65", "author": "Cortex XSOAR", "url": "https://www.paloaltonetworks.com/cortex", "email": "",