From d841c1a10a8265347f9eae758ca0147ea613150a Mon Sep 17 00:00:00 2001 From: Brent Kimmel Date: Tue, 29 Sep 2020 16:13:22 -0400 Subject: [PATCH 1/2] New mock with cursor --- ...ith_related_events_and_cursor_on_origin.ts | 147 ++++++++++++++++++ .../public/resolver/mocks/resolver_tree.ts | 13 +- 2 files changed, 158 insertions(+), 2 deletions(-) create mode 100644 x-pack/plugins/security_solution/public/resolver/data_access_layer/mocks/no_ancestors_two_children_with_related_events_and_cursor_on_origin.ts diff --git a/x-pack/plugins/security_solution/public/resolver/data_access_layer/mocks/no_ancestors_two_children_with_related_events_and_cursor_on_origin.ts b/x-pack/plugins/security_solution/public/resolver/data_access_layer/mocks/no_ancestors_two_children_with_related_events_and_cursor_on_origin.ts new file mode 100644 index 0000000000000..20054f304b310 --- /dev/null +++ b/x-pack/plugins/security_solution/public/resolver/data_access_layer/mocks/no_ancestors_two_children_with_related_events_and_cursor_on_origin.ts @@ -0,0 +1,147 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { DataAccessLayer } from '../../types'; +import { + mockTreeWithNoAncestorsAndTwoChildrenAndRelatedEventsOnOrigin, + firstRelatedEventID, + secondRelatedEventID, +} from '../../mocks/resolver_tree'; +import { + ResolverRelatedEvents, + ResolverTree, + ResolverEntityIndex, + SafeResolverEvent, +} from '../../../../common/endpoint/types'; +import * as eventModel from '../../../../common/endpoint/models/event'; + +interface Metadata { + /** + * The `_id` of the document being analyzed. + */ + databaseDocumentID: string; + /** + * A record of entityIDs to be used in tests assertions. + */ + entityIDs: { + /** + * The entityID of the node related to the document being analyzed. + */ + origin: 'origin'; + /** + * The entityID of the first child of the origin. + */ + firstChild: 'firstChild'; + /** + * The entityID of the second child of the origin. + */ + secondChild: 'secondChild'; + }; +} + +/** + * See the other mock `noAncestorsTwoChildrenWithRelatedEventsOnOrigin` but this one + * has one of the related events "after" the first (i.e. you have to call with `after` to + * get the second one). + */ +export function noAncestorsTwoChildrenWithRelatedEventsOnOriginWithOneAfterCursor(): { + dataAccessLayer: DataAccessLayer; + metadata: Metadata; +} { + const metadata: Metadata = { + databaseDocumentID: '_id', + entityIDs: { origin: 'origin', firstChild: 'firstChild', secondChild: 'secondChild' }, + }; + const tree = mockTreeWithNoAncestorsAndTwoChildrenAndRelatedEventsOnOrigin({ + originID: metadata.entityIDs.origin, + firstChildID: metadata.entityIDs.firstChild, + secondChildID: metadata.entityIDs.secondChild, + }); + + return { + metadata, + dataAccessLayer: { + /** + * Fetch related events for an entity ID + */ + async relatedEvents(entityID: string): Promise { + /** + * Respond with the mocked related events when the origin's related events are fetched. + **/ + const events = entityID === metadata.entityIDs.origin ? tree.relatedEvents.events : []; + + return { + entityID, + events, + nextEvent: null, + }; + }, + + /** + * Any of the origin's related events by category. + * `entityID` must match the origin node's `process.entity_id`. + * These are split by the `after` cursor: Calling without the cursor will + * return the first event, calling with the cursor set to the id of the first event + * will return the second. + */ + async eventsWithEntityIDAndCategory( + entityID: string, + category: string, + after?: string + ): Promise<{ events: SafeResolverEvent[]; nextEvent: string | null }> { + /** + * For testing: This 'fakes' the behavior of one related event being `after` + * a cursor for an earlier event. + * @param event A `SafeResolverEvent` to filter + */ + function splitOnCursor(event: SafeResolverEvent) { + if (typeof after === 'undefined') { + return eventModel.eventID(event) === firstRelatedEventID; + } + if (after === firstRelatedEventID) { + return eventModel.eventID(event) === secondRelatedEventID; + } + return false; + } + + const events = + entityID === metadata.entityIDs.origin + ? tree.relatedEvents.events.filter( + (event) => + eventModel.eventCategory(event).includes(category) && splitOnCursor(event) + ) + : []; + return { + events, + nextEvent: null, + }; + }, + + /** + * Any of the origin's related events by event.id + */ + async event(eventID: string): Promise { + return ( + tree.relatedEvents.events.find((event) => eventModel.eventID(event) === eventID) ?? null + ); + }, + + /** + * Fetch a ResolverTree for a entityID + */ + async resolverTree(): Promise { + return tree; + }, + + /** + * Get entities matching a document. + */ + async entities(): Promise { + return [{ entity_id: metadata.entityIDs.origin }]; + }, + }, + }; +} diff --git a/x-pack/plugins/security_solution/public/resolver/mocks/resolver_tree.ts b/x-pack/plugins/security_solution/public/resolver/mocks/resolver_tree.ts index 3f7c58efc762b..5b851d588543d 100644 --- a/x-pack/plugins/security_solution/public/resolver/mocks/resolver_tree.ts +++ b/x-pack/plugins/security_solution/public/resolver/mocks/resolver_tree.ts @@ -307,6 +307,15 @@ export function mockTreeWithNoProcessEvents(): ResolverTree { }; } +/** + * first ID (to check in the mock data access layer) + */ +export const firstRelatedEventID = 'id of first related event'; +/** + * second ID (to check in the mock data access layer) + */ +export const secondRelatedEventID = 'id of second related event'; + export function mockTreeWithNoAncestorsAndTwoChildrenAndRelatedEventsOnOrigin({ originID, firstChildID, @@ -326,14 +335,14 @@ export function mockTreeWithNoAncestorsAndTwoChildrenAndRelatedEventsOnOrigin({ mockEndpointEvent({ entityID: originID, parentEntityID, - eventID: 'first related event', + eventID: firstRelatedEventID, eventType: 'access', eventCategory: 'registry', }), mockEndpointEvent({ entityID: originID, parentEntityID, - eventID: 'second related event', + eventID: secondRelatedEventID, eventType: 'access', eventCategory: 'registry', }), From f1591bb9ea4baede5649be1e434dac6802283558 Mon Sep 17 00:00:00 2001 From: Brent Kimmel Date: Wed, 30 Sep 2020 13:49:46 -0400 Subject: [PATCH 2/2] include next cursor --- ...ors_two_children_with_related_events_and_cursor_on_origin.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/public/resolver/data_access_layer/mocks/no_ancestors_two_children_with_related_events_and_cursor_on_origin.ts b/x-pack/plugins/security_solution/public/resolver/data_access_layer/mocks/no_ancestors_two_children_with_related_events_and_cursor_on_origin.ts index 20054f304b310..7682165ac5e94 100644 --- a/x-pack/plugins/security_solution/public/resolver/data_access_layer/mocks/no_ancestors_two_children_with_related_events_and_cursor_on_origin.ts +++ b/x-pack/plugins/security_solution/public/resolver/data_access_layer/mocks/no_ancestors_two_children_with_related_events_and_cursor_on_origin.ts @@ -116,7 +116,7 @@ export function noAncestorsTwoChildrenWithRelatedEventsOnOriginWithOneAfterCurso : []; return { events, - nextEvent: null, + nextEvent: typeof after === 'undefined' ? firstRelatedEventID : null, }; },