def test_search_all_file_events_handles_escaped_quote_chars_in_token( self, connection, preservation_data_service, saved_search_service, storage_service_factory, ): file_event_service = FileEventService(connection) security_client = SecurityDataClient( file_event_service, preservation_data_service, saved_search_service, storage_service_factory, ) escaped_token = r"1234_\"abcde\"" security_client.search_all_file_events(FileEventQuery.all(), escaped_token) expected = { "groupClause": "AND", "groups": [], "srtDir": "asc", "srtKey": "eventId", "pgToken": escaped_token, "pgSize": 10000, } connection.post.assert_called_once_with(FILE_EVENT_URI, json=expected)
def test_stream_file_by_sha256_when_get_locations_returns_empty_list_raises_py42_error( self, mocker, security_service, file_event_service, preservation_data_service, saved_search_service, storage_service_factory, file_event_search, file_version_list, file_location, ): file_version_list.text = '{"versions": []}' file_location.text = '{"locations": []}' preservation_data_service.get_file_version_list.return_value = file_version_list file_event_service.search.return_value = file_event_search file_event_service.get_file_location_detail_by_sha256.return_value = ( file_location) security_client = SecurityDataClient( security_service, file_event_service, preservation_data_service, saved_search_service, 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_get_security_plan_storage_info_two_plans_two_destinations_three_nodes_returns_one_location_per_plan( self, security_service_two_plans_two_destinations_three_nodes, file_event_service, preservation_data_service, saved_search_service, storage_service_factory, ): security_client = SecurityDataClient( security_service_two_plans_two_destinations_three_nodes, file_event_service, preservation_data_service, saved_search_service, storage_service_factory, ) storage_infos = security_client.get_security_plan_storage_info_list( "foo") assert self._storage_info_contains( storage_infos, "111111111111111111", "4", "41") or self._storage_info_contains( storage_infos, "111111111111111111", "5", "51") assert self._storage_info_contains( storage_infos, "222222222222222222", "4", "41") or self._storage_info_contains( storage_infos, "222222222222222222", "5", "52")
def test_search_all_file_events_calls_search_with_expected_params_when_pg_token_is_passed( self, connection, preservation_data_service, saved_search_service, storage_service_factory, ): file_event_service = FileEventService(connection) successful_response = { "totalCount": None, "fileEvents": None, "nextPgToken": "pqr", "problems": None, } connection.post.return_value = successful_response security_client = SecurityDataClient( file_event_service, preservation_data_service, saved_search_service, storage_service_factory, ) query = FileEventQuery.all() response = security_client.search_all_file_events(query, "abc") expected = { "groupClause": "AND", "groups": [], "srtDir": "asc", "srtKey": "eventId", "pgToken": "abc", "pgSize": 10000, } connection.post.assert_called_once_with(FILE_EVENT_URI, json=expected) assert response is successful_response
def test_get_all_user_security_events_calls_security_service_with_expected_params( self, mocker, security_service_one_location, file_event_service, preservation_data_service, saved_search_service, storage_service_factory, ): mock_storage_security_service = mocker.MagicMock( spec=StorageSecurityDataService) response = mocker.MagicMock(spec=Py42Response) response.text = "{}" response.data = {} mock_storage_security_service.get_plan_security_events.return_value = response storage_service_factory.create_security_data_service.return_value = ( mock_storage_security_service) security_client = SecurityDataClient( security_service_one_location, file_event_service, preservation_data_service, saved_search_service, storage_service_factory, ) for _, _ in security_client.get_all_user_security_events("foo"): pass mock_storage_security_service.get_plan_security_events.assert_called_once_with( "111111111111111111", cursor=None, event_types=None, include_files=True, max_timestamp=None, min_timestamp=None, )
def test_get_all_plan_security_events_when_multiple_plans_returned_calls_security_service_expected_number_of_times( self, mocker, security_service, file_event_service, preservation_data_service, saved_search_service, storage_service_factory, ): mock_storage_security_service = mocker.MagicMock( spec=StorageSecurityDataService) response = mocker.MagicMock(spec=Py42Response) response.text = "{}" response.data = {} mock_storage_security_service.get_plan_security_events.return_value = response storage_service_factory.create_security_data_service.return_value = ( mock_storage_security_service) security_client = SecurityDataClient( security_service, file_event_service, preservation_data_service, saved_search_service, storage_service_factory, ) plans = [ PlanStorageInfo("111111111111111111", "41", "4"), PlanStorageInfo("222222222222222222", "41", "4"), ] for _, _ in security_client.get_all_plan_security_events(plans): pass assert mock_storage_security_service.get_plan_security_events.call_count == 2
def test_get_all_plan_security_events_when_cursors_returned_calls_security_service_expected_number_of_times( self, mocker, security_service, file_event_service, preservation_data_service, saved_search_service, storage_service_factory, ): mock_storage_security_service = mocker.MagicMock( spec=StorageSecurityDataService) response1 = mocker.MagicMock(spec=Py42Response) cursor_json = '{"cursor": "1:1"}' response1.text = cursor_json response1.data = json.loads(cursor_json) response2 = mocker.MagicMock(spec=Py42Response) response2.text = "{}" response2.data = {} mock_storage_security_service.get_plan_security_events.side_effect = [ response1, response2, ] storage_service_factory.create_security_data_service.return_value = ( mock_storage_security_service) security_client = SecurityDataClient( security_service, file_event_service, preservation_data_service, saved_search_service, storage_service_factory, ) for _, _ in security_client.get_all_plan_security_events( PlanStorageInfo("111111111111111111", "41", "4")): pass assert mock_storage_security_service.get_plan_security_events.call_count == 2
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_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 test_stream_file_by_md5_with_exact_match_response_calls_get_version_list_with_expected_params( self, pds_config, ): 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-2") version_list_params = [ "testdeviceUid", "testmd5-2", "testsha256-2", "/test/file/path/testfileName", ] pds_config.preservation_data_service.get_file_version_list.assert_called_once_with( *version_list_params) pds_config.storage_service_factory.create_preservation_data_service.assert_called_once_with( "https://host-2.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 expected_download_token_params = ["archiveid-2", "fileid-2", 12344] pds_config.storage_node_client.get_download_token.assert_called_once_with( *expected_download_token_params) assert response == b"stream"
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_find_file_version_returns_204_status_code_raises_py42_error( self, security_service, file_event_service, preservation_data_service, saved_search_service, storage_service_factory, file_event_search, file_location, file_version_list, available_version, ): file_version_list.text = '{"versions": []}' preservation_data_service.get_file_version_list.return_value = file_version_list file_event_service.search.return_value = file_event_search file_event_service.get_file_location_detail_by_sha256.return_value = ( file_location) available_version.status_code = 204 preservation_data_service.find_file_version.return_value = available_version security_client = SecurityDataClient( security_service, file_event_service, preservation_data_service, saved_search_service, 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 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_search_with_only_query_calls_through_to_client( self, file_event_service, preservation_data_service, saved_search_service, storage_service_factory, ): security_client = SecurityDataClient( file_event_service, preservation_data_service, saved_search_service, storage_service_factory, ) security_client.search_file_events(RAW_QUERY) file_event_service.search.assert_called_once_with(RAW_QUERY)
def test_search_all_file_events_when_token_is_none_succeeds( self, connection, preservation_data_service, saved_search_service, storage_service_factory, ): file_event_service = FileEventService(connection) security_client = SecurityDataClient( file_event_service, preservation_data_service, saved_search_service, storage_service_factory, ) security_client.search_all_file_events(FileEventQuery.all(), page_token=None)
def test_stream_file_by_sha256_without_exact_match_response_calls_get_version_list_with_expected_params( self, mocker, security_service, file_event_service, preservation_data_service, saved_search_service, storage_service_factory, file_event_search, file_version_list, file_download, ): file_event_search.text = file_event_search.text.replace("-2", "-6") file_event_service.search.return_value = file_event_search preservation_data_service.get_file_version_list.return_value = file_version_list 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) security_client = SecurityDataClient( security_service, file_event_service, preservation_data_service, saved_search_service, storage_service_factory, ) response = security_client.stream_file_by_sha256("testsha256-6") expected = [ "testdeviceUid", "testmd5-6", "testsha256-6", "/test/file/path/testfileName", ] preservation_data_service.get_file_version_list.assert_called_once_with( *expected) storage_service_factory.create_preservation_data_service.assert_called_once_with( "https://host-3.com") assert file_event_service.get_file_location_detail_by_sha256.call_count == 0 assert preservation_data_service.find_file_version.call_count == 0 # should get version with most recent versionTimestamp download_token_params = ["archiveid-3", "fileid-3", 12346] storage_node_client.get_download_token.assert_called_once_with( *download_token_params) assert response == b"stream"
def _init_clients(services, connection): # clients are imported within function to prevent circular imports when a client # imports anything from py42.sdk.queries from py42.clients import Clients from py42.clients._archiveaccess.accessorfactory import ArchiveAccessorFactory from py42.clients.alertrules import AlertRulesClient from py42.clients.alerts import AlertsClient from py42.clients.archive import ArchiveClient from py42.clients.auditlogs import AuditLogsClient from py42.clients.authority import AuthorityClient from py42.clients.cases import CasesClient from py42.clients.detectionlists import DetectionListsClient from py42.clients.loginconfig import LoginConfigurationClient from py42.clients.securitydata import SecurityDataClient from py42.clients.trustedactivities import TrustedActivitiesClient from py42.services.storage._service_factory import ConnectionManager from py42.services.storage._service_factory import StorageServiceFactory authority = AuthorityClient( administration=services.administration, archive=services.archive, devices=services.devices, legalhold=services.legalhold, orgs=services.orgs, users=services.users, ) detectionlists = DetectionListsClient(services.userprofile, services.departingemployee, services.highriskemployee) storage_service_factory = StorageServiceFactory(connection, services.devices, ConnectionManager()) alertrules = AlertRulesClient(services.alerts, services.alertrules) securitydata = SecurityDataClient( services.fileevents, services.preservationdata, services.savedsearch, storage_service_factory, ) alerts = AlertsClient(services.alerts, alertrules) archive_accessor_factory = ArchiveAccessorFactory(services.archive, storage_service_factory) archive = ArchiveClient(archive_accessor_factory, services.archive) auditlogs = AuditLogsClient(services.auditlogs) loginconfig = LoginConfigurationClient(connection) trustedactivities = TrustedActivitiesClient(services.trustedactivities) clients = Clients( authority=authority, detectionlists=detectionlists, alerts=alerts, securitydata=securitydata, archive=archive, auditlogs=auditlogs, cases=CasesClient(services.cases, services.casesfileevents), loginconfig=loginconfig, trustedactivities=trustedactivities, ) return clients
def test_stream_file_by_sha256_when_file_versions_returns_empty_response_gets_version_from_other_location( self, mocker, security_service, file_event_service, preservation_data_service, saved_search_service, storage_service_factory, file_event_search, file_version_list, file_location, file_download, available_version, ): file_version_list.text = '{"versions": []}' preservation_data_service.get_file_version_list.return_value = file_version_list preservation_data_service.find_file_version.return_value = available_version file_event_service.search.return_value = file_event_search file_event_service.get_file_location_detail_by_sha256.return_value = ( file_location) 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) security_client = SecurityDataClient( security_service, file_event_service, preservation_data_service, saved_search_service, storage_service_factory, ) response = security_client.stream_file_by_sha256("shahash") assert response == b"stream" file_event_service.get_file_location_detail_by_sha256.assert_called_once_with( "testsha256-2") expected = ["testmd5-2", "testsha256-2", mocker.ANY] preservation_data_service.find_file_version.assert_called_once_with( *expected) # should return version returned by find_file_version download_token_params = ["archiveid-3", "fileid-3", 12346] storage_node_client.get_download_token.assert_called_once_with( *download_token_params)
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 test_get_security_plan_storage_info_one_location_returns_location_info( self, security_service_one_location, file_event_service, preservation_data_service, saved_search_service, storage_service_factory, ): security_client = SecurityDataClient( security_service_one_location, file_event_service, preservation_data_service, saved_search_service, storage_service_factory, ) storage_infos = security_client.get_security_plan_storage_info_list( "foo") assert len(storage_infos) == 1 assert self._storage_info_contains(storage_infos, "111111111111111111", "4", "41")
def test_stream_file_by_sha256_when_search_returns_empty_response_raises_py42_checksum_not_found_error_( self, security_service, file_event_service, preservation_data_service, saved_search_service, storage_service_factory, file_event_search, ): file_event_search.text = '{"fileEvents": []}' file_event_service.search.return_value = file_event_search security_client = SecurityDataClient( security_service, file_event_service, preservation_data_service, saved_search_service, storage_service_factory, ) with pytest.raises(Py42ChecksumNotFoundError) as e: security_client.stream_file_by_sha256("shahash") assert u"No files found with SHA256 checksum" in e.value.args[0]
def test_stream_file_by_sha256_when_has_path_match_calls_get_token_with_expected_params_and_streams_successfully( self, mocker, pds_config): file_version_list = create_mock_response(mocker, XFC_MATCHED_FILE_VERSIONS) pds_config.preservation_data_service.get_file_version_list.return_value = ( file_version_list) 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_sha256("testsha256-2") assert response == b"stream" expected_download_token_params = [ "eventid-3", "deviceuid-3", "/test/file/path-3/", 12346, ] pds_config.exfiltration_client.get_download_token.assert_called_once_with( *expected_download_token_params)
def test_saved_searches_returns_saved_search_client( self, file_event_service, preservation_data_service, saved_search_service, storage_service_factory, ): security_client = SecurityDataClient( file_event_service, preservation_data_service, saved_search_service, storage_service_factory, ) assert security_client.savedsearches
def _init_clients(services, connection): authority = AuthorityClient( administration=services.administration, archive=services.archive, devices=services.devices, legalhold=services.legalhold, orgs=services.orgs, securitydata=services.securitydata, users=services.users, ) detectionlists = DetectionListsClient(services.userprofile, services.departingemployee, services.highriskemployee) storage_service_factory = StorageServiceFactory(connection, services.devices, ConnectionManager()) alertrules = AlertRulesClient(services.alerts, services.alertrules) securitydata = SecurityDataClient( services.securitydata, services.fileevents, services.preservationdata, services.savedsearch, storage_service_factory, ) alerts = AlertsClient(services.alerts, alertrules) archive_accessor_mgr = ArchiveAccessorManager(services.archive, storage_service_factory) archive = ArchiveClient(archive_accessor_mgr, services.archive) auditlogs = AuditLogsClient(services.auditlogs) clients = Clients( authority=authority, detectionlists=detectionlists, alerts=alerts, securitydata=securitydata, archive=archive, auditlogs=auditlogs, ) return clients