Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Security Solution][Resolver] 2 new functions to DAL #78477

Merged
merged 6 commits into from
Sep 25, 2020
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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