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 SOLUTIONS] Bugs overview page + investigate eql in timeline #81550

Merged
merged 10 commits into from
Oct 27, 2020
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ describe('alert actions', () => {
searchStrategyClient = {
aggs: {} as ISearchStart['aggs'],
showError: jest.fn(),
search: jest.fn().mockResolvedValue({ data: mockTimelineDetails }),
search: jest
.fn()
.mockImplementation(() => ({ toPromise: () => ({ data: mockTimelineDetails }) })),
searchSource: {} as ISearchStart['searchSource'],
session: dataPluginMock.createStartContract().search.session,
};
Expand Down Expand Up @@ -400,6 +402,78 @@ describe('alert actions', () => {
expect(createTimeline).toHaveBeenCalledWith(defaultTimelineProps);
});
});

describe('Eql', () => {
test(' with signal.group.id', async () => {
const ecsDataMock: Ecs = {
...mockEcsDataWithAlert,
signal: {
rule: {
...mockEcsDataWithAlert.signal?.rule!,
type: ['eql'],
timeline_id: [''],
},
group: {
id: ['my-group-id'],
},
},
};

await sendAlertToTimelineAction({
createTimeline,
ecsData: ecsDataMock,
nonEcsData: [],
updateTimelineIsLoading,
searchStrategyClient,
});

expect(updateTimelineIsLoading).not.toHaveBeenCalled();
expect(createTimeline).toHaveBeenCalledTimes(1);
expect(createTimeline).toHaveBeenCalledWith({
...defaultTimelineProps,
timeline: {
...defaultTimelineProps.timeline,
dataProviders: [
{
and: [],
enabled: true,
excluded: false,
id:
'send-alert-to-timeline-action-default-draggable-event-details-value-formatted-field-value-timeline-1-alert-id-my-group-id',
kqlQuery: '',
name: '1',
queryMatch: { field: 'signal.group.id', operator: ':', value: 'my-group-id' },
},
],
},
});
});

test(' with NO signal.group.id', async () => {
const ecsDataMock: Ecs = {
...mockEcsDataWithAlert,
signal: {
rule: {
...mockEcsDataWithAlert.signal?.rule!,
type: ['eql'],
timeline_id: [''],
},
},
};

await sendAlertToTimelineAction({
createTimeline,
ecsData: ecsDataMock,
nonEcsData: [],
updateTimelineIsLoading,
searchStrategyClient,
});

expect(updateTimelineIsLoading).not.toHaveBeenCalled();
expect(createTimeline).toHaveBeenCalledTimes(1);
expect(createTimeline).toHaveBeenCalledWith(defaultTimelineProps);
});
});
});

describe('determineToAndFrom', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,10 @@ export const getThresholdAggregationDataProvider = (
];
};

export const isEqlRule = (ecsData: Ecs) =>
ecsData.signal?.rule?.type?.length && ecsData.signal?.rule?.type[0] === 'eql';
export const isEqlRuleWithGroupId = (ecsData: Ecs) =>
ecsData.signal?.rule?.type?.length &&
ecsData.signal?.rule?.type[0] === 'eql' &&
Comment on lines +154 to +155
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Could consolidate to the following using array item access with optional chaining if you'd like:

Suggested change
ecsData.signal?.rule?.type?.length &&
ecsData.signal?.rule?.type[0] === 'eql' &&
ecsData.signal?.rule?.type?.[0] === 'eql' &&

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've also got those rule type helpers that could be leveraged here!

ecsData.signal?.group?.id?.length;

export const isThresholdRule = (ecsData: Ecs) =>
ecsData.signal?.rule?.type?.length && ecsData.signal?.rule?.type[0] === 'threshold';
Expand Down Expand Up @@ -181,24 +183,23 @@ export const sendAlertToTimelineAction = async ({
timelineType: TimelineType.template,
},
}),
searchStrategyClient.search<
TimelineEventsDetailsRequestOptions,
TimelineEventsDetailsStrategyResponse
>(
{
defaultIndex: [],
docValueFields: [],
indexName: ecsData._index ?? '',
eventId: ecsData._id,
factoryQueryType: TimelineEventsQueries.details,
},
{
strategy: 'securitySolutionTimelineSearchStrategy',
}
),
searchStrategyClient
.search<TimelineEventsDetailsRequestOptions, TimelineEventsDetailsStrategyResponse>(
{
defaultIndex: [],
docValueFields: [],
indexName: ecsData._index ?? '',
eventId: ecsData._id,
factoryQueryType: TimelineEventsQueries.details,
},
{
strategy: 'securitySolutionTimelineSearchStrategy',
}
)
.toPromise(),
]);
const resultingTimeline: TimelineResult = getOr({}, 'data.getOneTimeline', responseTimeline);
const eventData: TimelineEventsDetailsItem[] = getOr([], 'data', eventDataResp);
const eventData: TimelineEventsDetailsItem[] = eventDataResp.data ?? [];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for cleaning up more getOr's! 🙇‍♂️

if (!isEmpty(resultingTimeline)) {
const timelineTemplate: TimelineResult = omitTypenameInTimeline(resultingTimeline);
const { timeline, notes } = formatTimelineResultToModel(
Expand Down Expand Up @@ -327,7 +328,7 @@ export const sendAlertToTimelineAction = async ({
},
},
];
if (isEqlRule(ecsData)) {
if (isEqlRuleWithGroupId(ecsData)) {
const signalGroupId = ecsData.signal?.group?.id?.length
? ecsData.signal?.group?.id[0]
: 'unknown-signal-group-id';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ const OverviewComponent: React.FC<PropsFromRedux> = ({
<EventCounts
filters={filters}
from={from}
indexNames={[]}
indexNames={selectedPatterns}
indexPattern={indexPattern}
query={query}
setQuery={setQuery}
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/security_solution/public/plugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ export class Plugin implements IPlugin<PluginSetup, PluginStart, SetupPlugins, S
this.subPlugins(),
startPlugins.data.search
.search<IndexFieldsStrategyRequest, IndexFieldsStrategyResponse>(
{ indices: defaultIndicesName, onlyCheckIfIndicesExist: false },
{ indices: defaultIndicesName, onlyCheckIfIndicesExist: true },
{
strategy: 'securitySolutionIndexFields',
}
Expand Down