Skip to content

Commit

Permalink
[Security Solution][Resolver] 2 new functions to DAL (#78477) (#78534)
Browse files Browse the repository at this point in the history
* Added 2 new functions to DAL, adjusted old one to use new API

* update mocks to work with interface

* change to optional params

Co-authored-by: oatkiller <robert.austin@elastic.co>
Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
  • Loading branch information
3 people authored Sep 25, 2020
1 parent 6d0257a commit 27ea969
Show file tree
Hide file tree
Showing 7 changed files with 155 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import {
ResolverRelatedEvents,
ResolverTree,
ResolverEntityIndex,
ResolverPaginatedEvents,
SafeResolverEvent,
} from '../../../common/endpoint/types';

/**
Expand All @@ -22,12 +24,54 @@ export function dataAccessLayerFactory(
const dataAccessLayer: DataAccessLayer = {
/**
* Used to get non-process related events for a node.
* @deprecated use the new API (eventsWithEntityIDAndCategory & event) instead
*/
async relatedEvents(entityID: string): Promise<ResolverRelatedEvents> {
return context.services.http.post(`/api/endpoint/resolver/${entityID}/events`, {
query: { events: 100 },
const response: ResolverPaginatedEvents = await context.services.http.post(
'/api/endpoint/resolver/events',
{
query: {},
body: JSON.stringify({
filter: `process.entity_id:"${entityID}" and not event.category:"process"`,
}),
}
);

return { ...response, entityID };
},

/**
* Return events that have `process.entity_id` that includes `entityID` and that have
* a `event.category` that includes `category`.
*/
async eventsWithEntityIDAndCategory(
entityID: string,
category: string,
after?: string
): Promise<ResolverPaginatedEvents> {
return context.services.http.post('/api/endpoint/resolver/events', {
query: { afterEvent: after },
body: JSON.stringify({
filter: `process.entity_id:"${entityID}" and event.category:"${category}"`,
}),
});
},

/**
* Return up to one event that has an `event.id` that includes `eventID`.
*/
async event(eventID: string): Promise<SafeResolverEvent | null> {
const response: ResolverPaginatedEvents = await context.services.http.post(
'/api/endpoint/resolver/events',
{
query: {},
body: JSON.stringify({ filter: `event.id:"${eventID}"` }),
}
);
const [oneEvent] = response.events;
return oneEvent ?? null;
},

/**
* Used to get descendant and ancestor process events for a node.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export function emptifyMock<T>(
return {
metadata,
dataAccessLayer: {
...dataAccessLayer,
/**
* Fetch related events for an entity ID
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import {
ResolverRelatedEvents,
SafeResolverEvent,
ResolverTree,
ResolverEntityIndex,
} from '../../../../common/endpoint/types';
Expand Down Expand Up @@ -58,6 +59,29 @@ export function noAncestorsTwoChildren(): { dataAccessLayer: DataAccessLayer; me
});
},

/**
* Return events that have `process.entity_id` that includes `entityID` and that have
* a `event.category` that includes `category`.
*/
async eventsWithEntityIDAndCategory(
entityID: string,
category: string,
after?: string
): Promise<{
events: SafeResolverEvent[];
nextEvent: string | null;
}> {
const events: SafeResolverEvent[] = [];
return {
events,
nextEvent: null,
};
},

async event(_eventID: string): Promise<SafeResolverEvent | null> {
return null;
},

/**
* Fetch a ResolverTree for a entityID
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
ResolverRelatedEvents,
ResolverTree,
ResolverEntityIndex,
SafeResolverEvent,
} from '../../../../common/endpoint/types';
import { mockEndpointEvent } from '../../mocks/endpoint_event';
import { mockTreeWithNoAncestorsAnd2Children } from '../../mocks/resolver_tree';
Expand Down Expand Up @@ -69,6 +70,32 @@ export function noAncestorsTwoChildenInIndexCalledAwesomeIndex(): {
});
},

async eventsWithEntityIDAndCategory(
entityID: string,
category,
after?: string
): Promise<{
events: SafeResolverEvent[];
nextEvent: string | null;
}> {
return {
events: [
mockEndpointEvent({
entityID,
eventCategory: category,
}),
],
nextEvent: null,
};
},

async event(eventID: string): Promise<SafeResolverEvent | null> {
return mockEndpointEvent({
entityID: metadata.entityIDs.origin,
eventID,
});
},

/**
* Fetch a ResolverTree for a entityID
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import {
ResolverRelatedEvents,
ResolverTree,
ResolverEntityIndex,
SafeResolverEvent,
} from '../../../../common/endpoint/types';
import * as eventModel from '../../../../common/endpoint/models/event';

interface Metadata {
/**
Expand Down Expand Up @@ -56,31 +58,62 @@ export function noAncestorsTwoChildrenWithRelatedEventsOnOrigin(): {
/**
* Fetch related events for an entity ID
*/
relatedEvents(entityID: string): Promise<ResolverRelatedEvents> {
async relatedEvents(entityID: string): Promise<ResolverRelatedEvents> {
/**
* Respond with the mocked related events when the origin's related events are fetched.
**/
const events = entityID === metadata.entityIDs.origin ? tree.relatedEvents.events : [];

return Promise.resolve({
return {
entityID,
events,
nextEvent: null,
});
};
},

/**
* Any of the origin's related events by category.
* `entityID` must match the origin node's `process.entity_id`.
* Does not respect the `_after` parameter.
*/
async eventsWithEntityIDAndCategory(
entityID: string,
category: string,
after?: string
): Promise<{ events: SafeResolverEvent[]; nextEvent: string | null }> {
const events =
entityID === metadata.entityIDs.origin
? tree.relatedEvents.events.filter((event) =>
eventModel.eventCategory(event).includes(category)
)
: [];
return {
events,
nextEvent: null,
};
},

/**
* Any of the origin's related events by event.id
*/
async event(eventID: string): Promise<SafeResolverEvent | null> {
return (
tree.relatedEvents.events.find((event) => eventModel.eventID(event) === eventID) ?? null
);
},

/**
* Fetch a ResolverTree for a entityID
*/
resolverTree(): Promise<ResolverTree> {
return Promise.resolve(tree);
async resolverTree(): Promise<ResolverTree> {
return tree;
},

/**
* Get entities matching a document.
*/
entities(): Promise<ResolverEntityIndex> {
return Promise.resolve([{ entity_id: metadata.entityIDs.origin }]);
async entities(): Promise<ResolverEntityIndex> {
return [{ entity_id: metadata.entityIDs.origin }];
},
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ export function pausifyMock<T>({
}
},
dataAccessLayer: {
...dataAccessLayer,
/**
* Fetch related events for an entity ID
*/
Expand Down
16 changes: 16 additions & 0 deletions x-pack/plugins/security_solution/public/resolver/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
ResolverTree,
ResolverEntityIndex,
SafeResolverEvent,
ResolverPaginatedEvents,
} from '../../common/endpoint/types';

/**
Expand Down Expand Up @@ -503,6 +504,21 @@ export interface DataAccessLayer {
*/
relatedEvents: (entityID: string) => Promise<ResolverRelatedEvents>;

/**
* Return events that have `process.entity_id` that includes `entityID` and that have
* a `event.category` that includes `category`.
*/
eventsWithEntityIDAndCategory: (
entityID: string,
category: string,
after?: string
) => Promise<ResolverPaginatedEvents>;

/**
* Return up to one event that has an `event.id` that includes `eventID`.
*/
event: (eventID: string) => Promise<SafeResolverEvent | null>;

/**
* Fetch a ResolverTree for a entityID
*/
Expand Down

0 comments on commit 27ea969

Please sign in to comment.