Skip to content

Commit

Permalink
[Security Solution][Investigations][Timeline] - Update getExceptions …
Browse files Browse the repository at this point in the history
…to use parameters (#145889)

## Summary

Fixes: #136772

The issue was introduced by a couple of changes:

First:
https://github.com/elastic/kibana/pull/136163/files#diff-02d33a1ed6679f7775dc01941ca21b085d7c008ecffe5e029f5967407a5e5b13L23
in 8.4.

The bug: A filter on the timeline UI relied on the `exceptions_list`
field provided on `_source` to auto-generate a filter when investigating
in timeline labelled `Not Exceptions` which would filter out the
exceptions from the timeline. This PR resolves that issue by pulling the
`exceptions_list` field from `kibana.alert.rule.parameters`.

Second:
https://github.com/elastic/kibana/pull/133254/files#diff-0f69b69fd9cefef6ed04a048d7df86b7e385e816bdf17309212437dc3f69726cL74

The filter actually stopped being passed to timeline entirely because of
the above change.

With the fixes in place:


https://user-images.githubusercontent.com/17211684/203111748-7a0c2eb5-a46f-4f88-9d77-3628204625ac.mov
  • Loading branch information
michaelolo24 authored Nov 28, 2022
1 parent 7198faf commit b32c8b9
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { useDispatch } from 'react-redux';
import { EuiContextMenuItem } from '@elastic/eui';

import { i18n } from '@kbn/i18n';
import { ALERT_RULE_EXCEPTIONS_LIST } from '@kbn/rule-data-utils';
import { ALERT_RULE_EXCEPTIONS_LIST, ALERT_RULE_PARAMETERS } from '@kbn/rule-data-utils';
import type { ExceptionListId } from '@kbn/securitysolution-io-ts-list-types';
import { useApi } from '@kbn/securitysolution-list-hooks';

Expand Down Expand Up @@ -52,9 +52,27 @@ export const useInvestigateInTimeline = ({

const getExceptionFilter = useCallback(
async (ecsData: Ecs): Promise<Filter | undefined> => {
const exceptionsLists = (getField(ecsData, ALERT_RULE_EXCEPTIONS_LIST) ?? []).reduce(
(acc: ExceptionListId[], next: string) => {
const parsedList = JSON.parse(next);
// This pulls exceptions list information from `_source`
// This primarily matters for the old `signal` alerts a user may be viewing
// as new exception lists are pulled from kibana.alert.rule.parameters[0].exception_lists;
// Source was removed in favour of the fields api which passes the exceptions_list via `kibana.alert.rule.parameters`
let exceptionsList = getField(ecsData, ALERT_RULE_EXCEPTIONS_LIST) ?? [];

if (exceptionsList.length === 0) {
try {
const ruleParameters = getField(ecsData, ALERT_RULE_PARAMETERS) ?? {};
if (ruleParameters.length > 0) {
const parametersObject = JSON.parse(ruleParameters[0]);
exceptionsList = parametersObject?.exceptions_list ?? [];
}
} catch (error) {
// do nothing, just fail silently as parametersObject is initialized
}
}
const detectionExceptionsLists = exceptionsList.reduce(
(acc: ExceptionListId[], next: string | object) => {
// parsed rule.parameters returns an object else use the default string representation
const parsedList = typeof next === 'string' ? JSON.parse(next) : next;
if (parsedList.type === 'detection') {
const formattedList = {
exception_list_id: parsedList.list_id,
Expand All @@ -67,14 +85,15 @@ export const useInvestigateInTimeline = ({
[]
);

if (exceptionsLists.length > 0) {
let exceptionFilter;
if (detectionExceptionsLists.length > 0) {
await getExceptionFilterFromIds({
exceptionListIds: exceptionsLists,
exceptionListIds: detectionExceptionsLists,
excludeExceptions: true,
chunkSize: 20,
alias: 'Exceptions',
onSuccess: (filter) => {
return filter;
exceptionFilter = filter;
},
onError: (err: string[]) => {
addError(err, {
Expand All @@ -86,7 +105,7 @@ export const useInvestigateInTimeline = ({
},
});
}
return undefined;
return exceptionFilter;
},
[addError, getExceptionFilterFromIds]
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@
* 2.0.
*/

import { ALERT_RULE_CONSUMER, ALERT_RISK_SCORE, ALERT_SEVERITY } from '@kbn/rule-data-utils';
import {
ALERT_RULE_CONSUMER,
ALERT_RISK_SCORE,
ALERT_SEVERITY,
ALERT_RULE_PARAMETERS,
} from '@kbn/rule-data-utils';
import { ENRICHMENT_DESTINATION_PATH } from '../../../../../common/constants';

export const MATCHED_ATOMIC = 'matched.atomic';
Expand Down Expand Up @@ -40,6 +45,7 @@ export const CTI_ROW_RENDERER_FIELDS = [
FEED_NAME_REFERENCE,
];

// TODO: update all of these fields to use the constants from technical field names
export const TIMELINE_EVENTS_FIELDS = [
ALERT_RULE_CONSUMER,
'@timestamp',
Expand All @@ -58,6 +64,7 @@ export const TIMELINE_EVENTS_FIELDS = [
'kibana.alert.rule.version',
ALERT_SEVERITY,
ALERT_RISK_SCORE,
ALERT_RULE_PARAMETERS,
'kibana.alert.threshold_result',
'kibana.alert.building_block_type',
'kibana.alert.suppression.docs_count',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,50 @@ describe('formatTimelineData', () => {
field: 'kibana.alert.rule.uuid',
value: ['15d82f10-0926-11ed-bece-6b0c033d0075'],
},
{
field: 'kibana.alert.rule.parameters.sourceId',
value: ['default'],
},
{
field: 'kibana.alert.rule.parameters.nodeType',
value: ['host'],
},
{
field: 'kibana.alert.rule.parameters.criteria.comparator',
value: ['>'],
},
{
field: 'kibana.alert.rule.parameters.criteria.timeSize',
value: ['1'],
},
{
field: 'kibana.alert.rule.parameters.criteria.metric',
value: ['cpu'],
},
{
field: 'kibana.alert.rule.parameters.criteria.threshold',
value: ['10'],
},
{
field: 'kibana.alert.rule.parameters.criteria.customMetric.aggregation',
value: ['avg'],
},
{
field: 'kibana.alert.rule.parameters.criteria.customMetric.id',
value: ['alert-custom-metric'],
},
{
field: 'kibana.alert.rule.parameters.criteria.customMetric.field',
value: [''],
},
{
field: 'kibana.alert.rule.parameters.criteria.customMetric.type',
value: ['custom'],
},
{
field: 'kibana.alert.rule.parameters.criteria.timeUnit',
value: ['d'],
},
{
field: 'event.action',
value: ['active'],
Expand Down Expand Up @@ -466,50 +510,6 @@ describe('formatTimelineData', () => {
field: 'kibana.version',
value: ['8.4.0'],
},
{
field: 'kibana.alert.rule.parameters.sourceId',
value: ['default'],
},
{
field: 'kibana.alert.rule.parameters.nodeType',
value: ['host'],
},
{
field: 'kibana.alert.rule.parameters.criteria.comparator',
value: ['>'],
},
{
field: 'kibana.alert.rule.parameters.criteria.timeSize',
value: ['1'],
},
{
field: 'kibana.alert.rule.parameters.criteria.metric',
value: ['cpu'],
},
{
field: 'kibana.alert.rule.parameters.criteria.threshold',
value: ['10'],
},
{
field: 'kibana.alert.rule.parameters.criteria.customMetric.aggregation',
value: ['avg'],
},
{
field: 'kibana.alert.rule.parameters.criteria.customMetric.id',
value: ['alert-custom-metric'],
},
{
field: 'kibana.alert.rule.parameters.criteria.customMetric.field',
value: [''],
},
{
field: 'kibana.alert.rule.parameters.criteria.customMetric.type',
value: ['custom'],
},
{
field: 'kibana.alert.rule.parameters.criteria.timeUnit',
value: ['d'],
},
],
ecs: {
'@timestamp': ['2022-07-21T22:38:57.888Z'],
Expand All @@ -528,6 +528,9 @@ describe('formatTimelineData', () => {
consumer: ['infrastructure'],
name: ['test 1212'],
uuid: ['15d82f10-0926-11ed-bece-6b0c033d0075'],
parameters: [
'{"sourceId":"default","nodeType":"host","criteria":[{"comparator":">","timeSize":1,"metric":"cpu","threshold":[10],"customMetric":{"aggregation":"avg","id":"alert-custom-metric","field":"","type":"custom"},"timeUnit":"d"}]}',
],
},
workflow_status: ['open'],
},
Expand Down

0 comments on commit b32c8b9

Please sign in to comment.