Skip to content

Commit

Permalink
WIP events/all
Browse files Browse the repository at this point in the history
  • Loading branch information
stephmilovic committed Feb 26, 2021
1 parent 75a3a4f commit 46513ac
Show file tree
Hide file tree
Showing 10 changed files with 571 additions and 452 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,40 @@

export const toArray = <T = string>(value: T | T[] | null): T[] =>
Array.isArray(value) ? value : value == null ? [] : [value];

export const toStringArray = <T = string>(value: T | T[] | null): string[] => {
if (Array.isArray(value)) {
return value.reduce<string[]>((acc, v) => {
if (v != null) {
switch (typeof v) {
case 'number':
case 'boolean':
return [...acc, v.toString()];
case 'object':
try {
return [...acc, JSON.stringify(v)];
} catch {
return [...acc, 'Invalid Object'];
}
case 'string':
return [...acc, v];
default:
return [...acc, `${v}`];
}
}
return acc;
}, []);
} else if (value == null) {
return [];
} else if (!Array.isArray(value) && typeof value === 'object') {
try {
return [JSON.stringify(value)];
} catch {
return ['Invalid Object'];
}
} else {
return [`${value}`];
}
};
export const toObjectArrayOfStrings = <T = string>(
value: T | T[] | null
): Array<{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import { EqlSearchStrategyResponse } from '../../../../../data_enhanced/common';
import { DEFAULT_MAX_TABLE_QUERY_SIZE } from '../../../../common/constants';
import { EqlSearchResponse } from '../../../../common/detection_engine/types';
import { EqlSearchResponse, EqlSequence } from '../../../../common/detection_engine/types';
import { EventHit, TimelineEdges } from '../../../../common/search_strategy';
import {
TimelineEqlRequestOptions,
Expand Down Expand Up @@ -56,51 +56,53 @@ export const buildEqlDsl = (options: TimelineEqlRequestOptions): Record<string,
},
};
};
const parseSequences = async (sequences: Array<EqlSequence<unknown>>, fieldRequested: string[]) =>
sequences.reduce<Promise<TimelineEdges[]>>(async (acc, sequence, sequenceIndex) => {
const sequenceParentId = sequence.events[0]?._id ?? null;
const data = await acc;
const allData = await Promise.all(
sequence.events.map(async (event, eventIndex) => {
const item = await formatTimelineData(
fieldRequested,
TIMELINE_EVENTS_FIELDS,
event as EventHit
);
return Promise.resolve({
...item,
node: {
...item.node,
ecs: {
...item.node.ecs,
...(sequenceParentId != null
? {
eql: {
parentId: sequenceParentId,
sequenceNumber: `${sequenceIndex}-${eventIndex}`,
},
}
: {}),
},
},
});
})
);
return Promise.resolve([...data, ...allData]);
}, Promise.resolve([]));

export const parseEqlResponse = (
export const parseEqlResponse = async (
options: TimelineEqlRequestOptions,
response: EqlSearchStrategyResponse<EqlSearchResponse<unknown>>
): Promise<TimelineEqlResponse> => {
const { activePage, querySize } = options.pagination;
// const totalCount = response.rawResponse?.body?.hits?.total?.value ?? 0;
let edges: TimelineEdges[] = [];

if (response.rawResponse.body.hits.sequences !== undefined) {
edges = response.rawResponse.body.hits.sequences.reduce<TimelineEdges[]>(
(data, sequence, sequenceIndex) => {
const sequenceParentId = sequence.events[0]?._id ?? null;
return [
...data,
...sequence.events.map((event, eventIndex) => {
const item = formatTimelineData(
options.fieldRequested,
TIMELINE_EVENTS_FIELDS,
event as EventHit
);
return {
...item,
node: {
...item.node,
ecs: {
...item.node.ecs,
...(sequenceParentId != null
? {
eql: {
parentId: sequenceParentId,
sequenceNumber: `${sequenceIndex}-${eventIndex}`,
},
}
: {}),
},
},
};
}),
];
},
[]
);
edges = await parseSequences(response.rawResponse.body.hits.sequences, options.fieldRequested);
} else if (response.rawResponse.body.hits.events !== undefined) {
edges = response.rawResponse.body.hits.events.map((event) =>
formatTimelineData(options.fieldRequested, TIMELINE_EVENTS_FIELDS, event as EventHit)
edges = await Promise.all(
response.rawResponse.body.hits.events.map(async (event) =>
formatTimelineData(options.fieldRequested, TIMELINE_EVENTS_FIELDS, event as EventHit)
)
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export const securitySolutionTimelineEqlSearchStrategyProvider = (
},
};
}),
mergeMap((esSearchRes) =>
mergeMap(async (esSearchRes) =>
parseEqlResponse(
request,
(esSearchRes as unknown) as EqlSearchStrategyResponse<EqlSearchResponse<unknown>>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,54 +8,23 @@
import { EventHit } from '../../../../../../common/search_strategy';
import { TIMELINE_EVENTS_FIELDS } from './constants';
import { formatTimelineData } from './helpers';
import { eventHit } from '../mocks';

describe('#formatTimelineData', () => {
it('happy path', () => {
const response: EventHit = {
_index: 'auditbeat-7.8.0-2020.11.05-000003',
_id: 'tkCt1nUBaEgqnrVSZ8R_',
_score: 0,
_type: '',
fields: {
'event.category': ['process'],
'process.ppid': [3977],
'user.name': ['jenkins'],
'process.args': ['go', 'vet', './...'],
message: ['Process go (PID: 4313) by user jenkins STARTED'],
'process.pid': [4313],
'process.working_directory': [
'/var/lib/jenkins/workspace/Beats_beats_PR-22624/src/github.com/elastic/beats/libbeat',
],
'process.entity_id': ['Z59cIkAAIw8ZoK0H'],
'host.ip': ['10.224.1.237', 'fe80::4001:aff:fee0:1ed', '172.17.0.1'],
'process.name': ['go'],
'event.action': ['process_started'],
'agent.type': ['auditbeat'],
'@timestamp': ['2020-11-17T14:48:08.922Z'],
'event.module': ['system'],
'event.type': ['start'],
'host.name': ['beats-ci-immutable-ubuntu-1804-1605624279743236239'],
'process.hash.sha1': ['1eac22336a41e0660fb302add9d97daa2bcc7040'],
'host.os.family': ['debian'],
'event.kind': ['event'],
'host.id': ['e59991e835905c65ed3e455b33e13bd6'],
'event.dataset': ['process'],
'process.executable': [
'/var/lib/jenkins/workspace/Beats_beats_PR-22624/.gvm/versions/go1.14.7.linux.amd64/bin/go',
],
},
_source: {},
sort: ['1605624488922', 'beats-ci-immutable-ubuntu-1804-1605624279743236239'],
aggregations: {},
};

expect(
formatTimelineData(
['@timestamp', 'host.name', 'destination.ip', 'source.ip'],
TIMELINE_EVENTS_FIELDS,
response
)
).toEqual({
it('happy path', async () => {
const res = await formatTimelineData(
[
'@timestamp',
'host.name',
'destination.ip',
'source.ip',
'source.geo.location',
'threat.indicator',
],
TIMELINE_EVENTS_FIELDS,
eventHit
);
expect(res).toEqual({
cursor: {
tiebreaker: 'beats-ci-immutable-ubuntu-1804-1605624279743236239',
value: '1605624488922',
Expand All @@ -72,6 +41,50 @@ describe('#formatTimelineData', () => {
field: 'host.name',
value: ['beats-ci-immutable-ubuntu-1804-1605624279743236239'],
},
{
field: 'source.geo.location',
value: [`{"lon":118.7778,"lat":32.0617}`],
},
{
field: 'threat.indicator.matched.field',
value: ['matched_field', 'matched_field_2'],
},
{
field: 'threat.indicator.first_seen',
value: ['2021-02-22T17:29:25.195Z'],
},
{
field: 'threat.indicator.provider',
value: ['yourself', 'other_you'],
},
{
field: 'threat.indicator.type',
value: ['custom'],
},
{
field: 'threat.indicator.matched.atomic',
value: ['matched_atomic', 'matched_atomic_2'],
},
{
field: 'threat.indicator.lazer.great.field',
value: ['grrrrr', 'grrrrr_2'],
},
{
field: 'threat.indicator.lazer.great.field.wowoe.fooooo',
value: ['grrrrr'],
},
{
field: 'threat.indicator.lazer.great.field.astring',
value: ['cool'],
},
{
field: 'threat.indicator.lazer.great.field.aNumber',
value: ['1'],
},
{
field: 'threat.indicator.lazer.great.field.neat',
value: ['true'],
},
],
ecs: {
'@timestamp': ['2020-11-17T14:48:08.922Z'],
Expand Down
Loading

0 comments on commit 46513ac

Please sign in to comment.