def test_stream_file_by_sha256_when_find_file_version_returns_204_status_code_raises_py42_error( self, mocker, pds_config, ): file_version_list = create_mock_response( mocker, '{"preservationVersions": []}') pds_config.preservation_data_service.get_file_version_list.return_value = ( file_version_list) available_version = create_mock_response(mocker, AVAILABLE_VERSION_RESPONSE, 204) pds_config.preservation_data_service.find_file_version.return_value = ( available_version) security_client = SecurityDataClient( pds_config.file_event_service, pds_config.preservation_data_service, pds_config.saved_search_service, pds_config.storage_service_factory, ) with pytest.raises(Py42Error) as e: security_client.stream_file_by_sha256("shahash") assert e.value.args[0] == PDS_EXCEPTION_MESSAGE.format("shahash")
def test_stream_file_by_md5_when_file_versions_returns_empty_response_gets_version_from_other_location( self, mocker, pds_config, ): file_version_list = create_mock_response( mocker, '{"preservationVersions": []}') pds_config.preservation_data_service.get_file_version_list.return_value = ( file_version_list) available_version = create_mock_response(mocker, AVAILABLE_VERSION_RESPONSE) pds_config.preservation_data_service.find_file_version.return_value = ( available_version) security_client = SecurityDataClient( pds_config.file_event_service, pds_config.preservation_data_service, pds_config.saved_search_service, pds_config.storage_service_factory, ) response = security_client.stream_file_by_md5("mdhash") assert response == b"stream" pds_config.file_event_service.get_file_location_detail_by_sha256.assert_called_once_with( "testsha256-2") expected = ["testmd5-2", "testsha256-2", mocker.ANY] pds_config.preservation_data_service.find_file_version.assert_called_once_with( *expected) # should return version returned by find_file_version expected_download_token_params = ["archiveid-3", "fileid-3", 12346] pds_config.storage_node_client.get_download_token.assert_called_once_with( *expected_download_token_params)
def pds_config( self, mocker, storage_service_factory, file_event_service, preservation_data_service, saved_search_service, ): mock = mocker.MagicMock() file_download = create_mock_response(mocker, "PDSDownloadToken=token") file_event_service.search.return_value = create_mock_response( mocker, FILE_EVENTS_RESPONSE) preservation_data_service.get_file_version_list.return_value = create_mock_response( mocker, PDS_FILE_VERSIONS) file_event_service.get_file_location_detail_by_sha256.return_value = create_mock_response( mocker, FILE_LOCATION_RESPONSE) storage_node_client = mocker.MagicMock( spec=StoragePreservationDataService) storage_node_client.get_download_token.return_value = file_download storage_node_client.get_file.return_value = b"stream" storage_service_factory.create_preservation_data_service.return_value = ( storage_node_client) exfiltration_client = mocker.MagicMock(spec=ExfiltratedDataService) exfiltration_client.get_download_token.return_value = file_download exfiltration_client.get_file.return_value = b"stream" storage_service_factory.create_exfiltrated_data_service.return_value = ( exfiltration_client) mock.storage_service_factory = storage_service_factory mock.file_event_service = file_event_service mock.preservation_data_service = preservation_data_service mock.saved_search_service = saved_search_service mock.storage_node_client = storage_node_client mock.exfiltration_client = exfiltration_client return mock
def mock_audit_log_response(mocker): response1 = create_mock_response( mocker, data={"events": TEST_EVENTS_WITH_SAME_TIMESTAMP}) response2 = create_mock_response( mocker, data={"events": TEST_EVENTS_WITH_DIFFERENT_TIMESTAMPS}) def response_gen(): yield response1 yield response2 return response_gen()
def test_stream_file_by_md5_without_exact_match_response_calls_get_version_list_with_expected_params( self, mocker, pds_config, ): pds_config.file_event_service.search.return_value = create_mock_response( mocker, FILE_EVENTS_RESPONSE.replace("-2", "-6")) security_client = SecurityDataClient( pds_config.file_event_service, pds_config.preservation_data_service, pds_config.saved_search_service, pds_config.storage_service_factory, ) response = security_client.stream_file_by_md5("testmd5-6") expected = [ "testdeviceUid", "testmd5-6", "testsha256-6", "/test/file/path/testfileName", ] pds_config.preservation_data_service.get_file_version_list.assert_called_once_with( *expected) pds_config.storage_service_factory.create_preservation_data_service.assert_called_once_with( "https://host-3.example.com") assert (pds_config.file_event_service. get_file_location_detail_by_sha256.call_count == 0) assert pds_config.preservation_data_service.find_file_version.call_count == 0 # should get version returned with most recent versionTimestamp expected_download_token_params = ["archiveid-3", "fileid-3", 12346] pds_config.storage_node_client.get_download_token.assert_called_once_with( *expected_download_token_params) assert response == b"stream"
def test_stream_to_device_prefers_backup_set_id_of_1( self, mocker, archive_accessor_factory, archive_service, archive_explorer, archive_content_pusher, ): backup_set_text = f'{{"backupSets": [{{"backupSetId": "{TEST_BACKUP_SET_ID}"}}, {{"backupSetId": "1"}}]}}' backup_set_response = create_mock_response(mocker, backup_set_text) archive_service.get_backup_sets.return_value = backup_set_response archive_accessor_factory.create_archive_accessor.return_value = archive_explorer archive_accessor_factory.create_archive_content_pusher.return_value = ( archive_content_pusher) archive = ArchiveClient(archive_accessor_factory, archive_service) archive.stream_to_device( TEST_PATHS, TEST_DEVICE_GUID, TEST_ACCEPTING_GUID, TEST_RESTORE_PATH, destination_guid=TEST_DESTINATION_GUID_1, archive_password=TEST_PASSWORD, encryption_key=TEST_ENCRYPTION_KEY, file_size_calc_timeout=100, show_deleted=True, ) archive_content_pusher.stream_to_device.assert_called_once_with( TEST_RESTORE_PATH, TEST_ACCEPTING_GUID, TEST_FILE_SELECTIONS, "1", True, False, )
def mock_device_service(mocker): service = mocker.MagicMock(spec=DeviceService) response = create_mock_response( mocker, '{"backupUsage": [{"targetComputerGuid": "123"}]}' ) service.get_by_guid.return_value = response return service
def connection(mocker): py_connection = mocker.MagicMock(spec=Connection) py_connection._auth = mocker.MagicMock() py_connection._auth.destination_guid = TEST_DESTINATION_GUID_1 py_connection.post.return_value = create_mock_response( mocker, '{"dataKeyToken": "FAKE_DATA_KEY_TOKEN"}') return py_connection
def create_job(guid, file_id, *args, **kwargs): if file_id == TEST_DOWNLOADS_FILE_ID: text = json.dumps({"jobId": self.DOWNLOADS_JOB}) elif file_id == TEST_DOWNLOADS_DIR_ID: text = json.dumps({"jobId": self.EXT_JOB}) return create_mock_response(mocker, text)
def mock_get_restore_status_responses(mocker, storage_archive_service, json_responses): responses = [] for json_response in json_responses: responses.append(create_mock_response(mocker, json_response)) storage_archive_service.get_restore_status.side_effect = responses
def archive_service(mocker): service = mocker.MagicMock(spec=ArchiveService) data_key_text = f'{{"dataKeyToken": "{TEST_DATA_KEY_TOKEN}"}}' data_key_response = create_mock_response(mocker, data_key_text) service.get_data_key_token.return_value = data_key_response backup_set_text = f'{{"backupSets": [{{"backupSetId": "{TEST_BACKUP_SET_ID}"}}]}}' backup_set_response = create_mock_response(mocker, backup_set_text) service.get_backup_sets.return_value = backup_set_response restore_info_text = f'{{"nodeGuid": "{TEST_NODE_GUID}"}}' restore_info_resp = create_mock_response(mocker, restore_info_text) def get_web_restore_info_side_effect(src_guid, dest_guid): if src_guid == TEST_DEVICE_GUID and dest_guid == TEST_DESTINATION_GUID_1: return restore_info_resp service.get_web_restore_info.side_effect = get_web_restore_info_side_effect return service
def mock_detection_list_user_client( self, mock_connection, user_context, mocker, mock_user_client ): user_client = DetectionListUserService( mock_connection, user_context, mock_user_client ) mock_connection.post.return_value = create_mock_response(mocker, "{}") return user_client
def get_status(job_id, device_guid): if job_id == self.DOWNLOADS_JOB: self.EXTERNAL_DIR_SIZES["status"] = "DONE" text = json.dumps(self.EXTERNAL_DIR_SIZES) elif job_id == self.EXT_JOB: self.DOWNLOADS_DIR_SIZES["status"] = "DONE" text = json.dumps(self.DOWNLOADS_DIR_SIZES) return create_mock_response(mocker, text)
def test_get_by_id_calls_get_with_expected_uri(self, mock_connection, mocker): mock_connection.get.return_value = create_mock_response(mocker, "{}") file_event_service = FileEventService(mock_connection) saved_search_service = SavedSearchService(mock_connection, file_event_service) saved_search_service.get_by_id("test-id") assert (mock_connection.get.call_args[0][0] == "/forensic-search/queryservice/api/v1/saved/test-id")
def mock_audit_log_response_with_10_records(mocker): data = json.dumps({"events": TEST_EVENTS_WITH_SAME_TIMESTAMP}) responses = [] for _ in range(0, 10): responses.append(create_mock_response(mocker, data=data)) def response_gen(): yield from responses return response_gen()
def test_get_query_calls_get_with_expected_uri(self, mock_connection, mocker): response = create_mock_response(mocker, SAVED_SEARCH_GET_RESPONSE) mock_connection.post.return_value = response file_event_service = FileEventService(mock_connection) saved_search_service = SavedSearchService(mock_connection, file_event_service) saved_search_service.get_query("test-id") assert (mock_connection.get.call_args[0][0] == "/forensic-search/queryservice/api/v1/saved/test-id")
def get_file_sizes(job_id, device_id): if job_id == self.DOWNLOADS_JOB: status = desktop_statuses.pop() self.EXTERNAL_DIR_SIZES["status"] = status elif job_id == self.EXT_JOB: self.EXTERNAL_DIR_SIZES["status"] = "DONE" return create_mock_response(mocker, json.dumps(self.EXTERNAL_DIR_SIZES))
def test_get_aggregate_data_creates_alias_for_ffs_url( self, mocker, mock_connection, user_context): # This is to support the method when it once called the v1 api. mock_connection.post.return_value = create_mock_response( mocker, TEST_ALERT_AGGREGATE_RESPONSE) alert_service = AlertService(mock_connection, user_context) response = alert_service.get_aggregate_data("alert-id") assert (response["alert"]["ffsUrl"] == "https://ffs-url-test.example.com" == response["alert"]["ffsUrlEndpoint"])
def test_show_when_alert_has_no_note_excludes_note( mocker, cli_state, runner, full_alert_details_response ): response_data = dict(ALERT_DETAILS_FULL_RESPONSE) response_data["alerts"][0]["note"] = None cli_state.sdk.alerts.get_details.return_value = create_mock_response( mocker, data=response_data ) result = runner.invoke(cli, ["alerts", "show", "TEST-ALERT-ID"], obj=cli_state) # Note is included in `full_alert_details_response` initially. assert "Note" not in result.output
def mock_file_event_response(mocker): data = json.dumps({ "totalCount": 2, "fileEvents": TEST_EVENTS, "nextPgToken": "", "problems": "" }) response = create_mock_response(mocker, data=data) return response
def mock_storage_auth_token_conn(mocker): mock_connection = mocker.MagicMock(spec=Connection) mock_connection.headers = {} mock_connection.post.return_value = create_mock_response( mocker, '["TEST_V1", "TOKEN_VALUE"]' ) mocker.patch( "py42.services.storage._auth._get_new_storage_connection", return_value=mock_connection, ) return mock_connection
def test_get_details_posts_to_expected_url(self, mock_connection, user_context, successful_post, mocker): response = create_mock_response(mocker, TEST_PARSEABLE_ALERT_DETAIL_RESPONSE) mock_connection.post.return_value = response alert_service = AlertService(mock_connection, user_context) alert_ids = ["ALERT_ID_1", "ALERT_ID_2"] alert_service.get_details(alert_ids) assert mock_connection.post.call_args[0][ 0] == "/svc/api/v1/query-details"
def test_get_details_when_given_single_alert_id_posts_expected_data( self, mock_connection, user_context, successful_post, mocker, alert_id): response = create_mock_response(mocker, TEST_PARSEABLE_ALERT_DETAIL_RESPONSE) mock_connection.post.return_value = response alert_service = AlertService(mock_connection, user_context) alert_service.get_details(alert_id) post_data = mock_connection.post.call_args[1]["json"] assert (post_data["tenantId"] == TENANT_ID_FROM_RESPONSE and post_data["alertIds"][0] == "ALERT_ID_1")
def test_stream_file_by_md5_when_get_locations_returns_empty_list_raises_py42_error( self, mocker, pds_config): file_version_list = create_mock_response( mocker, '{"preservationVersions": []}') file_location = create_mock_response(mocker, '{"locations": []}') pds_config.preservation_data_service.get_file_version_list.return_value = ( file_version_list) pds_config.file_event_service.get_file_location_detail_by_sha256.return_value = ( file_location) security_client = SecurityDataClient( pds_config.file_event_service, pds_config.preservation_data_service, pds_config.saved_search_service, pds_config.storage_service_factory, ) with pytest.raises(Py42Error) as e: security_client.stream_file_by_md5("mdhash") assert e.value.args[0] == PDS_EXCEPTION_MESSAGE.format("mdhash")
def mock_detection_list_post_failure_when_invalid_rule_id( mocker, mock_connection): response = mocker.MagicMock(spec=Response) response.status_code = 400 exception = mocker.MagicMock(spec=Py42NotFoundError) exception.response = response mock_connection.post.side_effect = Py42NotFoundError(exception, "") detection_list_user_service = mocker.MagicMock( spec=DetectionListUserService) detection_list_user_service.get_by_id.return_value = create_mock_response( mocker, "{}") return detection_list_user_service
def test_execute_calls_post_with_expected_query(self, mock_connection, mocker): response = create_mock_response(mocker, SAVED_SEARCH_GET_RESPONSE) mock_connection.get.return_value = response file_event_service = FileEventService(mock_connection) saved_search_service = SavedSearchService(mock_connection, file_event_service) saved_search_service.execute("test-id") assert mock_connection.post.call_count == 1 posted_data = mock_connection.post.call_args[1]["json"] assert (posted_data["pgSize"] == 10000 and posted_data["pgNum"] == 1 and posted_data["groups"] == [])
def test_auto_select_destination_guid_when_device_has_no_destination_raises_exception( self, mock_successful_connection, mock_device_service, mock_connection_manager, mocker, ): factory = StorageServiceFactory( mock_successful_connection, mock_device_service, mock_connection_manager ) response = create_mock_response(mocker, '{"backupUsage": []}') mock_device_service.get_by_guid.return_value = response with pytest.raises(Exception): factory.auto_select_destination_guid(TEST_DEVICE_GUID)
def test_stream_file_by_md5_when_search_returns_empty_response_raises_py42_checksum_not_found_error_( self, mocker, pds_config): pds_config.file_event_service.search.return_value = create_mock_response( mocker, '{"fileEvents": []}') security_client = SecurityDataClient( pds_config.file_event_service, pds_config.preservation_data_service, pds_config.saved_search_service, pds_config.storage_service_factory, ) with pytest.raises(Py42ChecksumNotFoundError) as e: security_client.stream_file_by_md5("mdhash") assert "No files found with MD5 checksum" in e.value.args[0]
def test_from_local_account_when_unauthorized_calls_loginConfig_and_returns_config_value_on_raised_exception_text( self, mocker, mock_session, mock_auth, unauthorized_response): login_type = "LOCAL_2FA" mock_session.send.return_value = unauthorized_response mock_session.get.return_value = create_mock_response( mocker, f'{{"loginType": "{login_type}"}}') connection = Connection.from_host_address(HOST_ADDRESS, session=mock_session) client = SDKClient(connection, mock_auth) mocker.patch("py42.sdk.SDKClient.from_local_account", return_value=client) with pytest.raises(Py42UnauthorizedError) as err: from_local_account(HOST_ADDRESS, TEST_USERNAME, TEST_PASSWORD) assert f"User LoginConfig: {login_type}" in str(err)
def test_show_when_alert_does_not_have_observations_and_includes_observations_outputs_no_observations( mocker, cli_state, runner ): response_data = dict(ALERT_DETAILS_FULL_RESPONSE) response_data["alerts"][0]["observations"] = None cli_state.sdk.alerts.get_details.return_value = create_mock_response( mocker, data=response_data ) result = runner.invoke( cli, ["alerts", "show", "TEST-ALERT-ID", "--include-observations"], obj=cli_state, ) assert "No observations found" in result.output assert "Observations:" not in result.output assert "FedEndpointExfiltration" not in result.output