From 468f2781727c05f99f87c7b33d75663bc2bcafab Mon Sep 17 00:00:00 2001 From: Juliya Smith Date: Thu, 9 Jul 2020 16:54:16 +0000 Subject: [PATCH 1/5] Address PR Feedback --- ...tfield-Code42_SecurityAlert_Timestamp.json | 2 +- .../incidentfield-Code42_Username.json | 2 +- Packs/Code42/Integrations/Code42/Code42.py | 48 ++++++++++----- .../Code42/Integrations/Code42/Code42_test.py | 60 +++++++++++++++---- Packs/Code42/Integrations/Code42/README.md | 1 - .../Integrations/Code42/command_examples.txt | 4 +- 6 files changed, 86 insertions(+), 31 deletions(-) diff --git a/Packs/Code42/IncidentFields/incidentfield-Code42_SecurityAlert_Timestamp.json b/Packs/Code42/IncidentFields/incidentfield-Code42_SecurityAlert_Timestamp.json index b0e5558f2162..cf39367d357c 100644 --- a/Packs/Code42/IncidentFields/incidentfield-Code42_SecurityAlert_Timestamp.json +++ b/Packs/Code42/IncidentFields/incidentfield-Code42_SecurityAlert_Timestamp.json @@ -31,7 +31,7 @@ "system": false, "systemAssociatedTypes": null, "threshold": 72, - "type": "shortText", + "type": "date", "unmapped": false, "unsearchable": false, "useAsKpi": false, diff --git a/Packs/Code42/IncidentFields/incidentfield-Code42_Username.json b/Packs/Code42/IncidentFields/incidentfield-Code42_Username.json index 16292af7b787..e9eb4acb4b47 100644 --- a/Packs/Code42/IncidentFields/incidentfield-Code42_Username.json +++ b/Packs/Code42/IncidentFields/incidentfield-Code42_Username.json @@ -1,5 +1,5 @@ { - "associatedToAll": true, + "associatedToAll": false, "associatedTypes": null, "breachScript": "", "caseInsensitive": true, diff --git a/Packs/Code42/Integrations/Code42/Code42.py b/Packs/Code42/Integrations/Code42/Code42.py index 45b93d331387..1d1ff5f28bfc 100644 --- a/Packs/Code42/Integrations/Code42/Code42.py +++ b/Packs/Code42/Integrations/Code42/Code42.py @@ -136,8 +136,7 @@ def _create_alert_query(event_severity_filter, start_time): def _get_all_high_risk_employees_from_page(page, risk_tags): res = [] - # Note: page is a `Py42Response` and has no `get()` method. - employees = page["items"] + employees = page.get("items") or [] for employee in employees: if not risk_tags: res.append(employee) @@ -198,8 +197,8 @@ def get_all_departing_employees(self, results): results = int(results) if results else None pages = self._get_sdk().detectionlists.departing_employee.get_all() for page in pages: - # Note: page is a `Py42Response` and has no `get()` method. - employees = page["items"] + page_json = json.loads(page.text) + employees = page_json.get("items") or [] for employee in employees: res.append(employee) if results and len(res) == results: @@ -236,7 +235,8 @@ def get_all_high_risk_employees(self, risk_tags, results): res = [] pages = self._get_sdk().detectionlists.high_risk_employee.get_all() for page in pages: - employees = _get_all_high_risk_employees_from_page(page, risk_tags) + page_json = json.loads(page.text) + employees = _get_all_high_risk_employees_from_page(page_json, risk_tags) for employee in employees: res.append(employee) if results and len(res) == results: @@ -246,10 +246,11 @@ def get_all_high_risk_employees(self, risk_tags, results): def fetch_alerts(self, start_time, event_severity_filter): query = _create_alert_query(event_severity_filter, start_time) res = self._get_sdk().alerts.search(query) - return res["alerts"] + return json.loads(res.text).get("alerts") def get_alert_details(self, alert_id): - res = self._get_sdk().alerts.get_details(alert_id)["alerts"] + py42_res = self._get_sdk().alerts.get_details(alert_id) + res = json.loads(py42_res.text).get("alerts") if not res: raise Code42AlertNotFoundError(alert_id) return res[0] @@ -263,7 +264,8 @@ def get_current_user(self): return res def get_user(self, username): - res = self._get_sdk().users.get_by_username(username)["users"] + py42_res = self._get_sdk().users.get_by_username(username) + res = json.loads(py42_res.text).get("users") if not res: raise Code42UserNotFoundError(username) return res[0] @@ -296,15 +298,16 @@ def reactivate_user(self, username): def get_org(self, org_name): org_pages = self._get_sdk().orgs.get_all() for org_page in org_pages: - orgs = org_page["orgs"] + page_json = json.loads(org_page.text) + orgs = page_json.get("orgs") for org in orgs: if org.get("orgName") == org_name: return org raise Code42OrgNotFoundError(org_name) def search_file_events(self, payload): - res = self._get_sdk().securitydata.search_file_events(payload) - return res["fileEvents"] + py42_res = self._get_sdk().securitydata.search_file_events(payload) + return json.loads(py42_res.text).get("fileEvents") def download_file(self, hash_arg): security_module = self._get_sdk().securitydata @@ -313,7 +316,7 @@ def download_file(self, hash_arg): elif _hash_is_sha256(hash_arg): return security_module.stream_file_by_sha256(hash_arg) else: - raise Exception("Unsupported hash. Must be SHA256 or MD5.") + raise Code42UnsupportedHashError() def _get_user_id(self, username): user_id = self.get_user(username).get("userUid") @@ -355,6 +358,20 @@ def __init__(self, org_name): ) +class Code42UnsupportedHashError(Exception): + def __init__(self): + super(Code42UnsupportedHashError, self).__init__( + "Unsupported hash. Must be SHA256 or MD5." + ) + + +class Code42MissingSearchArgumentsError(Exception): + def __init__(self): + super(Code42MissingSearchArgumentsError, self).__init__( + "No query args provided for searching Code42 security events." + ) + + class Code42SearchFilters(object): def __init__(self): self._filters = [] @@ -417,6 +434,9 @@ def build_query_payload(args): username = args.get("username") exposure = args.get("exposure") + if not _hash and not hostname and not username and not exposure: + raise Code42MissingSearchArgumentsError() + search_args = FileEventQueryFilters(pg_size) search_args.append_result(_hash, _create_hash_filter) search_args.append_result(hostname, OSHostname.eq) @@ -1042,7 +1062,7 @@ def _fetch_alerts(self, start_query_time): return self._client.fetch_alerts(start_query_time, self._event_severity_filter) def _create_incident_from_alert(self, alert): - details = self._client.get_alert_details(alert["id"]) + details = self._client.get_alert_details(alert.get("id")) incident = _create_incident_from_alert_details(details) if self._include_files: details = self._relate_files_to_alert(details) @@ -1060,7 +1080,7 @@ def _relate_files_to_alert(self, alert_details): return alert_details def _get_file_events_from_alert_details(self, observation, alert_details): - security_data_query = map_observation_to_security_query(observation, alert_details["actor"]) + security_data_query = map_observation_to_security_query(observation, alert_details.get("actor")) return self._client.search_file_events(security_data_query) diff --git a/Packs/Code42/Integrations/Code42/Code42_test.py b/Packs/Code42/Integrations/Code42/Code42_test.py index 99b8ded2c230..7dfe3a515ed1 100644 --- a/Packs/Code42/Integrations/Code42/Code42_test.py +++ b/Packs/Code42/Integrations/Code42/Code42_test.py @@ -28,6 +28,10 @@ user_reactivate_command, download_file_command, fetch_incidents, + Code42AlertNotFoundError, + Code42UserNotFoundError, + Code42OrgNotFoundError, + Code42MissingSearchArgumentsError, ) import time @@ -1193,8 +1197,13 @@ def assert_detection_list_outputs_match_response_items(outputs_list, response_it """TESTS""" -def test_client_lazily_inits_sdk(mocker): - mocker.patch("py42.sdk.from_local_account") +def test_client_lazily_inits_sdk(mocker, code42_sdk_mock): + sdk_factory_mock = mocker.patch("py42.sdk.from_local_account") + response_json_mock = """{"total": 1, "users": [{"username": "Test"}]}""" + code42_sdk_mock.users.get_by_username.return_value = create_mock_code42_sdk_response( + mocker, response_json_mock + ) + sdk_factory_mock.return_value = code42_sdk_mock # test that sdk does not init during ctor client = Code42Client(sdk=None, base_url=MOCK_URL, auth=MOCK_AUTH, verify=False, proxy=False) @@ -1205,19 +1214,23 @@ def test_client_lazily_inits_sdk(mocker): assert client._sdk is not None -def test_client_when_no_alert_found_raises_exception(code42_sdk_mock): - code42_sdk_mock.alerts.get_details.return_value = ( - """{'type$': 'ALERT_DETAILS_RESPONSE', 'alerts': []}""" +def test_client_when_no_alert_found_raises_Code42AlertNotFoundError(mocker, code42_sdk_mock): + response_json = """{"alerts": []}""" + code42_sdk_mock.alerts.get_details.return_value = create_mock_code42_sdk_response( + mocker, response_json ) client = create_client(code42_sdk_mock) - with pytest.raises(Exception): + with pytest.raises(Code42AlertNotFoundError): client.get_alert_details("mock-id") -def test_client_when_no_user_found_raises_exception(code42_sdk_mock): - code42_sdk_mock.users.get_by_username.return_value = """{'totalCount': 0, 'users': []}""" +def test_client_when_no_user_found_raises_Code42UserNotFoundError(mocker, code42_sdk_mock): + response_json = """{"totalCount": 0, "users": []}""" + code42_sdk_mock.users.get_by_username.return_value = create_mock_code42_sdk_response( + mocker, response_json + ) client = create_client(code42_sdk_mock) - with pytest.raises(Exception): + with pytest.raises(Code42UserNotFoundError): client.get_user("test@example.com") @@ -1554,6 +1567,23 @@ def test_user_create_command(code42_users_mock): assert cmd_res.outputs["Email"] == "new.user@example.com" +def test_user_create_command_when_org_not_found_raises_Code42OrgNotFoundError(mocker, code42_users_mock): + response_json = """{"total": 0, "orgs": []}""" + code42_users_mock.orgs.get_all.return_value = create_mock_code42_sdk_response_generator( + mocker, [response_json] + ) + client = create_client(code42_users_mock) + with pytest.raises(Code42OrgNotFoundError): + user_create_command( + client, + { + "orgname": _TEST_ORG_NAME, + "username": "new.user@example.com", + "email": "new.user@example.com", + } + ) + + def test_user_block_command(code42_users_mock): client = create_client(code42_users_mock) cmd_res = user_block_command(client, {"username": "new.user@example.com"}) @@ -1627,6 +1657,12 @@ def test_security_data_search_command(code42_file_events_mock): assert output_item == mapped_event +def test_securitydata_search_command_when_not_given_any_queryable_args_raises_error(code42_file_events_mock): + client = create_client(code42_file_events_mock) + with pytest.raises(Code42MissingSearchArgumentsError): + securitydata_search_command(client, {}) + + def test_download_file_command_when_given_md5(code42_sdk_mock, mocker): fr = mocker.patch("Code42.fileResult") client = create_client(code42_sdk_mock) @@ -1669,8 +1705,8 @@ def test_fetch_when_no_significant_file_categories_ignores_filter( assert "IMAGE" not in actual_query -def test_fetch_incidents_handles_single_severity(code42_sdk_mock): - client = create_client(code42_sdk_mock) +def test_fetch_incidents_handles_single_severity(code42_fetch_incidents_mock): + client = create_client(code42_fetch_incidents_mock) fetch_incidents( client=client, last_run={"last_fetch": None}, @@ -1680,7 +1716,7 @@ def test_fetch_incidents_handles_single_severity(code42_sdk_mock): include_files=True, integration_context=None, ) - assert "HIGH" in str(code42_sdk_mock.alerts.search.call_args[0][0]) + assert "HIGH" in str(code42_fetch_incidents_mock.alerts.search.call_args[0][0]) def test_fetch_incidents_handles_multi_severity(code42_fetch_incidents_mock): diff --git a/Packs/Code42/Integrations/Code42/README.md b/Packs/Code42/Integrations/Code42/README.md index d9f6ed54fcb5..6da6fc70562c 100644 --- a/Packs/Code42/Integrations/Code42/README.md +++ b/Packs/Code42/Integrations/Code42/README.md @@ -1,5 +1,4 @@ Use the Code42 integration to identify potential data exfiltration from insider threats while speeding investigation and response by providing fast access to file events and metadata across physical and cloud environments. -This integration was integrated and tested with version xx of Code42 ## Configure Code42 on Cortex XSOAR 1. Navigate to **Settings** > **Integrations** > **Servers & Services**. diff --git a/Packs/Code42/Integrations/Code42/command_examples.txt b/Packs/Code42/Integrations/Code42/command_examples.txt index d7bb4697e6ae..e3e8f8372c5c 100644 --- a/Packs/Code42/Integrations/Code42/command_examples.txt +++ b/Packs/Code42/Integrations/Code42/command_examples.txt @@ -3,8 +3,8 @@ !code42-departingemployee-add username="partner.demisto@example.com" departuredate="2020-010-28" note="Leaving for competitor" !code42-departingemployee-remove username="partner.demisto@example.com" !code42-departingemployee-get-all -!code42-highriskemployee-add username="partner.demisto@example.com" note="Risky activity" -!code42-highriskemployee-remove username="partner.demisto@example.com" note="Risky activity" +!code42-highriskemployee-add username="partner.demisto@example.com" note="Approved activity" +!code42-highriskemployee-remove username="partner.demisto@example.com" note="Approved activity" !code42-highriskemployee-get-all !code42-highriskemployee-add-risk-tags username="partner.demisto@example.com" note="PERFORMANCE_CONCERN" !code42-highriskemployee-remove-risk-tags username="partner.demisto@example.com" risktags="PERFORMANCE_CONCERNS" From 1acd858d221746ce903b9a6592be33ba585b4ba2 Mon Sep 17 00:00:00 2001 From: Juliya Smith Date: Thu, 9 Jul 2020 16:58:30 +0000 Subject: [PATCH 2/5] Missing test --- Packs/Code42/Integrations/Code42/Code42_test.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Packs/Code42/Integrations/Code42/Code42_test.py b/Packs/Code42/Integrations/Code42/Code42_test.py index 7dfe3a515ed1..348651bbf579 100644 --- a/Packs/Code42/Integrations/Code42/Code42_test.py +++ b/Packs/Code42/Integrations/Code42/Code42_test.py @@ -31,6 +31,7 @@ Code42AlertNotFoundError, Code42UserNotFoundError, Code42OrgNotFoundError, + Code42UnsupportedHashError, Code42MissingSearchArgumentsError, ) import time @@ -1682,6 +1683,15 @@ def test_download_file_command_when_given_sha256(code42_sdk_mock, mocker): assert fr.call_count == 1 +def test_download_file_when_given_other_hash_raises_Code42UnsupportedHashError(code42_sdk_mock, mocker): + fr = mocker.patch("Code42.fileResult") + _hash = "41966f10cc59ab466444add08974fde4cd37f88d79321d42da8e4c79b51c214941966f10cc59ab466444add08974fde4cd37" \ + "f88d79321d42da8e4c79b51c2149" + client = create_client(code42_sdk_mock) + with pytest.raises(Code42UnsupportedHashError): + _ = download_file_command(client, {"hash": _hash}) + + def test_fetch_when_no_significant_file_categories_ignores_filter( code42_fetch_incidents_mock, mocker ): From 68a7d612d99c8c3b384bcfe67e80f1e459fc2148 Mon Sep 17 00:00:00 2001 From: Juliya Smith Date: Thu, 9 Jul 2020 18:08:07 +0000 Subject: [PATCH 3/5] Resolve conflicts --- Packs/Code42/Integrations/Code42/Code42.py | 1 + .../Code42/Integrations/Code42/Code42_test.py | 27 ++++++++++++------- Packs/Code42/ReleaseNotes/2_0_0.md | 3 +++ 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/Packs/Code42/Integrations/Code42/Code42.py b/Packs/Code42/Integrations/Code42/Code42.py index da1a62e5aab0..7ef575d8733d 100644 --- a/Packs/Code42/Integrations/Code42/Code42.py +++ b/Packs/Code42/Integrations/Code42/Code42.py @@ -405,6 +405,7 @@ class Code42MissingSearchArgumentsError(Exception): def __init__(self): super(Code42MissingSearchArgumentsError, self).__init__( "No query args provided for searching Code42 security events." + ) class Code42LegalHoldMatterNotFoundError(Exception): diff --git a/Packs/Code42/Integrations/Code42/Code42_test.py b/Packs/Code42/Integrations/Code42/Code42_test.py index 84738e9885b8..8c5c0e19e107 100644 --- a/Packs/Code42/Integrations/Code42/Code42_test.py +++ b/Packs/Code42/Integrations/Code42/Code42_test.py @@ -1315,23 +1315,28 @@ def test_client_lazily_inits_sdk(mocker, code42_sdk_mock): assert client._sdk is not None -def test_client_when_no_alert_found_raises_alert_not_found(code42_sdk_mock): - code42_sdk_mock.alerts.get_details.return_value = ( - json.loads('{"type$": "ALERT_DETAILS_RESPONSE", "alerts": []}') +def test_client_when_no_alert_found_raises_alert_not_found(mocker, code42_sdk_mock): + response_json = """{"alerts": []}""" + code42_sdk_mock.alerts.get_details.return_value = create_mock_code42_sdk_response( + mocker, response_json ) client = create_client(code42_sdk_mock) with pytest.raises(Code42AlertNotFoundError): client.get_alert_details("mock-id") -def test_client_when_no_user_found_raises_user_not_found(code42_sdk_mock): - code42_sdk_mock.users.get_by_username.return_value = json.loads('{"totalCount":0, "users":[]}') +def test_client_when_no_user_found_raises_user_not_found(mocker, code42_sdk_mock): + response_json = """{"totalCount": 0, "users": []}""" + code42_sdk_mock.users.get_by_username.return_value = create_mock_code42_sdk_response( + mocker, response_json + ) client = create_client(code42_sdk_mock) with pytest.raises(Code42UserNotFoundError): client.get_user("test@example.com") def test_client_add_to_matter_when_no_legal_hold_matter_found_raises_matter_not_found(code42_sdk_mock, mocker): + code42_sdk_mock.legalhold.get_all_matters.return_value = ( get_empty_legalhold_matters_response(mocker, MOCK_GET_ALL_MATTERS_RESPONSE) ) @@ -1341,8 +1346,9 @@ def test_client_add_to_matter_when_no_legal_hold_matter_found_raises_matter_not_ client.add_user_to_legal_hold_matter("TESTUSERNAME", "TESTMATTERNAME") -def test_client_add_to_matter_when_no_user_found_raises_user_not_found(code42_sdk_mock): - code42_sdk_mock.users.get_by_username.return_value = json.loads('{"totalCount":0, "users":[]}') +def test_client_add_to_matter_when_no_user_found_raises_user_not_found(mocker, code42_sdk_mock): + response_json = '{"totalCount":0, "users":[]}' + code42_sdk_mock.users.get_by_username.return_value = create_mock_code42_sdk_response(mocker, response_json) client = create_client(code42_sdk_mock) with pytest.raises(Code42UserNotFoundError): client.add_user_to_legal_hold_matter("TESTUSERNAME", "TESTMATTERNAME") @@ -1358,8 +1364,9 @@ def test_client_remove_from_matter_when_no_legal_hold_matter_found_raises_except client.remove_user_from_legal_hold_matter("TESTUSERNAME", "TESTMATTERNAME") -def test_client_remove_from_matter_when_no_user_found_raises_user_not_found(code42_sdk_mock): - code42_sdk_mock.users.get_by_username.return_value = json.loads('{"totalCount":0, "users":[]}') +def test_client_remove_from_matter_when_no_user_found_raises_user_not_found(mocker, code42_sdk_mock): + response_json = '{"totalCount":0, "users":[]}' + code42_sdk_mock.users.get_by_username.return_value = create_mock_code42_sdk_response(mocker, response_json) client = create_client(code42_sdk_mock) with pytest.raises(Code42UserNotFoundError): client.remove_user_from_legal_hold_matter("TESTUSERNAME", "TESTMATTERNAME") @@ -1851,7 +1858,7 @@ def test_download_file_command_when_given_sha256(code42_sdk_mock, mocker): def test_download_file_when_given_other_hash_raises_Code42UnsupportedHashError(code42_sdk_mock, mocker): - mocker.patch("Code42.fileResult") + fr = mocker.patch("Code42.fileResult") _hash = "41966f10cc59ab466444add08974fde4cd37f88d79321d42da8e4c79b51c214941966f10cc59ab466444add08974fde4cd37" \ "f88d79321d42da8e4c79b51c2149" client = create_client(code42_sdk_mock) diff --git a/Packs/Code42/ReleaseNotes/2_0_0.md b/Packs/Code42/ReleaseNotes/2_0_0.md index 8b2b76d3b58b..b8100e9092bd 100644 --- a/Packs/Code42/ReleaseNotes/2_0_0.md +++ b/Packs/Code42/ReleaseNotes/2_0_0.md @@ -1,6 +1,7 @@ #### Integrations ##### Code42 +## [Unreleased] - Internal code improvements. - Added new commands: - **code42-departingemployee-get-all** @@ -14,6 +15,8 @@ - **code42-user-block** - **code42-user-unblock** - **code42-user-create** + - **code42-legalhold-add-user** + - **code42-legalhold-remove-user** - **code42-file-download** - Improve error messages for all Commands to include exception detail. - **Code42 Exfiltration Playbook** now downloads the file in replace of a manual step for retrieving file contents. From 7689a5824e279011e7d06b965c213a0b808436d2 Mon Sep 17 00:00:00 2001 From: Juliya Smith Date: Thu, 9 Jul 2020 18:09:32 +0000 Subject: [PATCH 4/5] Flake8 --- Packs/Code42/Integrations/Code42/Code42.py | 1 + Packs/Code42/Integrations/Code42/Code42_test.py | 4 +--- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Packs/Code42/Integrations/Code42/Code42.py b/Packs/Code42/Integrations/Code42/Code42.py index 7ef575d8733d..910a47fce21a 100644 --- a/Packs/Code42/Integrations/Code42/Code42.py +++ b/Packs/Code42/Integrations/Code42/Code42.py @@ -945,6 +945,7 @@ def securitydata_search_command(client, args): raw_response={}, ) + @logger def user_create_command(client, args): org_name = args.get("orgname") diff --git a/Packs/Code42/Integrations/Code42/Code42_test.py b/Packs/Code42/Integrations/Code42/Code42_test.py index 8c5c0e19e107..80fb948d0dd0 100644 --- a/Packs/Code42/Integrations/Code42/Code42_test.py +++ b/Packs/Code42/Integrations/Code42/Code42_test.py @@ -5,8 +5,6 @@ from py42.response import Py42Response from Code42 import ( Code42Client, - Code42AlertNotFoundError, - Code42UserNotFoundError, Code42LegalHoldMatterNotFoundError, Code42InvalidLegalHoldMembershipError, build_query_payload, @@ -1858,7 +1856,7 @@ def test_download_file_command_when_given_sha256(code42_sdk_mock, mocker): def test_download_file_when_given_other_hash_raises_Code42UnsupportedHashError(code42_sdk_mock, mocker): - fr = mocker.patch("Code42.fileResult") + mocker.patch("Code42.fileResult") _hash = "41966f10cc59ab466444add08974fde4cd37f88d79321d42da8e4c79b51c214941966f10cc59ab466444add08974fde4cd37" \ "f88d79321d42da8e4c79b51c2149" client = create_client(code42_sdk_mock) From 283e02d0f3c8e39c3bdf92beaac380ab2cf03867 Mon Sep 17 00:00:00 2001 From: Juliya Smith Date: Thu, 9 Jul 2020 18:12:45 +0000 Subject: [PATCH 5/5] Case conform --- Packs/Code42/Integrations/Code42/Code42_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Packs/Code42/Integrations/Code42/Code42_test.py b/Packs/Code42/Integrations/Code42/Code42_test.py index 80fb948d0dd0..8bfa6b9289ed 100644 --- a/Packs/Code42/Integrations/Code42/Code42_test.py +++ b/Packs/Code42/Integrations/Code42/Code42_test.py @@ -1740,7 +1740,7 @@ def test_user_create_command(code42_users_mock): assert cmd_res.outputs["Email"] == "new.user@example.com" -def test_user_create_command_when_org_not_found_raises_Code42OrgNotFoundError(mocker, code42_users_mock): +def test_user_create_command_when_org_not_found_raises_org_not_found(mocker, code42_users_mock): response_json = """{"total": 0, "orgs": []}""" code42_users_mock.orgs.get_all.return_value = create_mock_code42_sdk_response_generator( mocker, [response_json] @@ -1855,7 +1855,7 @@ def test_download_file_command_when_given_sha256(code42_sdk_mock, mocker): assert fr.call_count == 1 -def test_download_file_when_given_other_hash_raises_Code42UnsupportedHashError(code42_sdk_mock, mocker): +def test_download_file_when_given_other_hash_raises_unsupported_hash(code42_sdk_mock, mocker): mocker.patch("Code42.fileResult") _hash = "41966f10cc59ab466444add08974fde4cd37f88d79321d42da8e4c79b51c214941966f10cc59ab466444add08974fde4cd37" \ "f88d79321d42da8e4c79b51c2149"