def test_update_state_posts_to_expected_url( self, mock_connection, user_context, successful_post ): alert_service = AlertService(mock_connection, user_context) alert_ids = ["ALERT_ID_1", "ALERT_ID_2"] alert_service.update_state("RESOLVED", alert_ids, "some-tenant-id") assert mock_connection.post.call_args[0][0] == "/svc/api/v1/update-state"
def test_get_rule_by_observer_id_posts_expected_data( self, mock_connection, user_context, successful_post ): alert_service = AlertService(mock_connection, user_context) for _ in alert_service.get_rule_by_observer_id("testid"): break assert mock_connection.post.call_count == 1 posted_data = mock_connection.post.call_args[1]["json"] filter_group = posted_data["groups"][0]["filters"][0] assert filter_group["term"] == "ObserverRuleId" assert filter_group["operator"] == "IS" assert filter_group["value"] == "testid" assert ( mock_connection.post.call_args[0][0] == "/svc/api/v1/rules/query-rule-metadata" ) assert ( posted_data["tenantId"] == user_context.get_current_tenant_id() and posted_data["groupClause"] == "AND" and posted_data["pgNum"] == 0 and posted_data["pgSize"] == 500 and posted_data["srtKey"] == "CreatedAt" and posted_data["srtDirection"] == "DESC" )
def test_get_aggregate_data_calls_post_with_expected_url_and_data( self, mock_connection, user_context): alert_service = AlertService(mock_connection, user_context) alert_service.get_aggregate_data("alert-id") assert (mock_connection.post.call_args[0][0] == "/svc/api/v2/query-details-aggregate") post_data = mock_connection.post.call_args[1]["json"] assert post_data["alertId"] == "alert-id"
def test_search_posts_to_expected_url( self, mock_connection, user_context, successful_post ): alert_service = AlertService(mock_connection, user_context) _filter = AlertState.eq("OPEN") query = AlertQuery(_filter) alert_service.search(query) assert mock_connection.post.call_args[0][0] == u"/svc/api/v1/query-alerts"
def test_update_state_when_given_single_alert_id_posts_expected_data( self, mock_connection, user_context, successful_post, alert_id): alert_service = AlertService(mock_connection, user_context) alert_service.update_state("PENDING", 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" and post_data["state"] == "PENDING" and post_data["note"] == "")
def test_update_note_calls_post_with_expected_url_and_data( self, mock_connection, user_context): alert_service = AlertService(mock_connection, user_context) alert_service.update_note("alert-id", note="Test Note") assert mock_connection.post.call_args[0][0] == "/svc/api/v1/add-note" post_data = mock_connection.post.call_args[1]["json"] assert (post_data["tenantId"] == TENANT_ID_FROM_RESPONSE and post_data["alertId"] == "alert-id" and post_data["note"] == "Test Note")
def test_get_details_posts_to_expected_url( self, mock_connection, user_context, successful_post, py42_response ): py42_response.text = TEST_PARSEABLE_ALERT_DETAIL_RESPONSE mock_connection.post.return_value = py42_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, py42_response, alert_id): py42_response.text = TEST_PARSEABLE_ALERT_DETAIL_RESPONSE mock_connection.post.return_value = py42_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_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_update_state_posts_expected_data(self, mock_connection, user_context, successful_post): alert_service = AlertService(mock_connection, user_context) alert_ids = ["ALERT_ID_1", "ALERT_ID_2"] alert_service.update_state("OPEN", alert_ids, "some-tenant-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" and post_data["alertIds"][1] == "ALERT_ID_2" and post_data["state"] == "OPEN" and post_data["note"] == "some-tenant-id")
def test_get_details_when_observation_data_not_parseable_remains_unchanged( self, mocker, mock_connection, user_context): requests_response = mocker.MagicMock(spec=Response) requests_response.text = TEST_NON_PARSEABLE_ALERT_DETAIL_RESPONSE py42_response = Py42Response(requests_response) mock_connection.post.return_value = py42_response alert_service = AlertService(mock_connection, user_context) response = alert_service.get_details("alert_id") observation_data = response["alerts"][0]["observations"][0]["data"] expected_observation_data = '{"invalid_json": ][ }' assert observation_data == expected_observation_data
def test_get_details_converts_json_observation_strings_to_objects( self, mocker, mock_connection, user_context): requests_response = mocker.MagicMock(spec=Response) requests_response.text = TEST_PARSEABLE_ALERT_DETAIL_RESPONSE py42_response = Py42Response(requests_response) mock_connection.post.return_value = py42_response alert_service = AlertService(mock_connection, user_context) response = alert_service.get_details("alert_id") observation_data = response["alerts"][0]["observations"][0]["data"] assert observation_data["example_key"] == "example_string_value" assert type(observation_data["example_list"]) is list
def test_get_details_when_given_tenant_id_posts_expected_data( 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) 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" and post_data["alertIds"][1] == "ALERT_ID_2")
def test_update_state_when_note_passed_none_posts_expected_data( self, mock_connection, user_context, successful_post): alert_service = AlertService(mock_connection, user_context) alert_ids = ["ALERT_ID_1", "ALERT_ID_2"] alert_service.update_state("RESOLVED", alert_ids, note=None) assert mock_connection.post.call_args[0][ 0] == "/svc/api/v1/update-state" 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" and post_data["alertIds"][1] == "ALERT_ID_2" and post_data["state"] == "RESOLVED" and post_data["note"] == "")
def _init_services(main_connection, main_auth): alert_rules_key = u"FedObserver-API_URL" alerts_key = u"AlertService-API_URL" file_events_key = u"FORENSIC_SEARCH-API_URL" preservation_data_key = u"PRESERVATION-DATA-SERVICE_API-URL" employee_case_mgmt_key = u"employeecasemanagement-API_URL" kv_prefix = u"simple-key-value-store" audit_logs_key = u"AUDIT-LOG_API-URL" kv_connection = Connection.from_microservice_prefix( main_connection, kv_prefix) kv_service = KeyValueStoreService(kv_connection) alert_rules_conn = Connection.from_microservice_key(kv_service, alert_rules_key, auth=main_auth) alerts_conn = Connection.from_microservice_key(kv_service, alerts_key, auth=main_auth) file_events_conn = Connection.from_microservice_key(kv_service, file_events_key, auth=main_auth) pds_conn = Connection.from_microservice_key(kv_service, preservation_data_key, auth=main_auth) ecm_conn = Connection.from_microservice_key(kv_service, employee_case_mgmt_key, auth=main_auth) audit_logs_conn = Connection.from_microservice_key(kv_service, audit_logs_key, auth=main_auth) user_svc = UserService(main_connection) administration_svc = AdministrationService(main_connection) file_event_svc = FileEventService(file_events_conn) user_ctx = UserContext(administration_svc) user_profile_svc = DetectionListUserService(ecm_conn, user_ctx, user_svc) services = Services( administration=administration_svc, archive=ArchiveService(main_connection), devices=DeviceService(main_connection), legalhold=LegalHoldService(main_connection), orgs=OrgService(main_connection), securitydata=SecurityDataService(main_connection), users=UserService(main_connection), alertrules=AlertRulesService(alert_rules_conn, user_ctx, user_profile_svc), alerts=AlertService(alerts_conn, user_ctx), fileevents=file_event_svc, savedsearch=SavedSearchService(file_events_conn, file_event_svc), preservationdata=PreservationDataService(pds_conn), departingemployee=DepartingEmployeeService(ecm_conn, user_ctx, user_profile_svc), highriskemployee=HighRiskEmployeeService(ecm_conn, user_ctx, user_profile_svc), userprofile=user_profile_svc, auditlogs=AuditLogsService(audit_logs_conn), ) return services, user_ctx
def test_search_posts_expected_data(self, mock_connection, user_context, successful_post): alert_service = AlertService(mock_connection, user_context) _filter = AlertState.eq("OPEN") query = AlertQuery(_filter) alert_service.search(query) post_data = json.loads(mock_connection.post.call_args[1]["data"]) assert (post_data["tenantId"] == TENANT_ID_FROM_RESPONSE and post_data["groupClause"] == "AND" and post_data["srtKey"] == "CreatedAt" and post_data["srtDirection"] == "desc" and post_data["pgSize"] == 500 and post_data["pgNum"] == 0 and post_data["groups"][0]["filterClause"] == "AND" and post_data["groups"][0]["filters"][0]["operator"] == "IS" and post_data["groups"][0]["filters"][0]["term"] == "state" and post_data["groups"][0]["filters"][0]["value"] == "OPEN")
def test_get_all_rules_posts_expected_data(self, mock_connection, user_context): alert_service = AlertService(mock_connection, user_context) for _ in alert_service.get_all_rules(sort_key="key", sort_direction="ASC"): break assert mock_connection.post.call_count == 1 posted_data = mock_connection.post.call_args[1]["json"] assert (mock_connection.post.call_args[0][0] == "/svc/api/v1/rules/query-rule-metadata") assert (posted_data["tenantId"] == user_context.get_current_tenant_id() and posted_data["groups"] == [] and posted_data["groupClause"] == "AND" and posted_data["pgNum"] == 0 and posted_data["pgSize"] == 500 and posted_data["srtKey"] == "key" and posted_data["srtDirection"] == "ASC")
def test_search_posts_expected_data_overwrites_default_option_when_passed_page_num_and_page_size( self, mock_connection, user_context): alert_service = AlertService(mock_connection, user_context) _filter = AlertState.eq("OPEN") query = AlertQuery(_filter) alert_service.search(query, 10, 20) assert mock_connection.post.call_count == 1 assert mock_connection.post.call_args[0][ 0] == "/svc/api/v1/query-alerts" post_data = mock_connection.post.call_args[1]["json"] assert (post_data["tenantId"] == TENANT_ID_FROM_RESPONSE and post_data["groupClause"] == "AND" and post_data["srtKey"] == "CreatedAt" and post_data["srtDirection"] == "desc" and post_data["pgSize"] == 20 and post_data["pgNum"] == 9 and post_data["groups"][0]["filterClause"] == "AND" and post_data["groups"][0]["filters"][0]["operator"] == "IS" and post_data["groups"][0]["filters"][0]["term"] == "state" and post_data["groups"][0]["filters"][0]["value"] == "OPEN")
def test_search_all_pages_posts_expected_data(self, mock_connection, user_context): alert_service = AlertService(mock_connection, user_context) _filter = AlertState.eq("OPEN") query = AlertQuery(_filter) for _ in alert_service.search_all_pages(query): break assert mock_connection.post.call_count == 1 assert mock_connection.post.call_args[0][ 0] == "/svc/api/v1/query-alerts" post_data = mock_connection.post.call_args[1]["json"] assert (post_data["tenantId"] == TENANT_ID_FROM_RESPONSE and post_data["groupClause"] == "AND" and post_data["srtKey"] == "CreatedAt" and post_data["srtDirection"] == "desc" and post_data["pgSize"] == 500 and post_data["pgNum"] == 0 and post_data["groups"][0]["filterClause"] == "AND" and post_data["groups"][0]["filters"][0]["operator"] == "IS" and post_data["groups"][0]["filters"][0]["term"] == "state" and post_data["groups"][0]["filters"][0]["value"] == "OPEN")
def test_get_rules_page_calls_post_with_expected_url_and_data( self, mock_connection, user_context, successful_post): alert_service = AlertService(mock_connection, user_context) alert_service.get_rules_page( groups=["groups"], page_num=1, page_size=100, sort_key="sort key", sort_direction="direction", ) # Note that pgNum is -1 from what is given because of that API data = { "tenantId": TENANT_ID_FROM_RESPONSE, "groups": ["groups"], "groupClause": "AND", "pgNum": 0, "pgSize": 100, "srtKey": "sort key", "srtDirection": "direction", } mock_connection.post.assert_called_once_with( "/svc/api/v1/rules/query-rule-metadata", json=data)
def _init_services(main_connection, main_auth): # services are imported within function to prevent circular imports when a service # imports anything from py42.sdk.queries from py42.services import Services from py42.services._keyvaluestore import KeyValueStoreService from py42.services.administration import AdministrationService from py42.services.alertrules import AlertRulesService from py42.services.alerts import AlertService from py42.services.archive import ArchiveService from py42.services.auditlogs import AuditLogsService from py42.services.cases import CasesService from py42.services.casesfileevents import CasesFileEventsService from py42.services.detectionlists.departing_employee import DepartingEmployeeService from py42.services.detectionlists.high_risk_employee import HighRiskEmployeeService from py42.services.detectionlists.user_profile import DetectionListUserService from py42.services.devices import DeviceService from py42.services.fileevent import FileEventService from py42.services.legalhold import LegalHoldService from py42.services.orgs import OrgService from py42.services.preservationdata import PreservationDataService from py42.services.savedsearch import SavedSearchService from py42.services.trustedactivities import TrustedActivitiesService from py42.services.users import UserService alert_rules_key = "FedObserver-API_URL" alerts_key = "AlertService-API_URL" file_events_key = "FORENSIC_SEARCH-API_URL" preservation_data_key = "PRESERVATION-DATA-SERVICE_API-URL" employee_case_mgmt_key = "employeecasemanagementV2-API_URL" kv_prefix = "simple-key-value-store" audit_logs_key = "AUDIT-LOG_API-URL" cases_key = "CASES_API-URL" trusted_activities_key = "TRUSTED-DOMAINS_API-URL" kv_connection = Connection.from_microservice_prefix( main_connection, kv_prefix) kv_service = KeyValueStoreService(kv_connection) alert_rules_conn = Connection.from_microservice_key(kv_service, alert_rules_key, auth=main_auth) alerts_conn = Connection.from_microservice_key(kv_service, alerts_key, auth=main_auth) file_events_conn = Connection.from_microservice_key(kv_service, file_events_key, auth=main_auth) pds_conn = Connection.from_microservice_key(kv_service, preservation_data_key, auth=main_auth) ecm_conn = Connection.from_microservice_key(kv_service, employee_case_mgmt_key, auth=main_auth) audit_logs_conn = Connection.from_microservice_key(kv_service, audit_logs_key, auth=main_auth) user_svc = UserService(main_connection) administration_svc = AdministrationService(main_connection) file_event_svc = FileEventService(file_events_conn) user_ctx = UserContext(administration_svc) user_profile_svc = DetectionListUserService(ecm_conn, user_ctx, user_svc) cases_conn = Connection.from_microservice_key(kv_service, cases_key, auth=main_auth) trusted_activities_conn = Connection.from_microservice_key( kv_service, trusted_activities_key, auth=main_auth) services = Services( administration=administration_svc, archive=ArchiveService(main_connection), devices=DeviceService(main_connection), legalhold=LegalHoldService(main_connection), orgs=OrgService(main_connection), users=UserService(main_connection), alertrules=AlertRulesService(alert_rules_conn, user_ctx, user_profile_svc), alerts=AlertService(alerts_conn, user_ctx), fileevents=file_event_svc, savedsearch=SavedSearchService(file_events_conn, file_event_svc), preservationdata=PreservationDataService(pds_conn), departingemployee=DepartingEmployeeService(ecm_conn, user_ctx, user_profile_svc), highriskemployee=HighRiskEmployeeService(ecm_conn, user_ctx, user_profile_svc), userprofile=user_profile_svc, auditlogs=AuditLogsService(audit_logs_conn), cases=CasesService(cases_conn), casesfileevents=CasesFileEventsService(cases_conn), trustedactivities=TrustedActivitiesService(trusted_activities_conn), ) return services, user_ctx