Skip to content

Commit

Permalink
[Security Solution] Fixes issues with the Raw events Top N view (redu…
Browse files Browse the repository at this point in the history
…x) (#121590)

## [Security Solution] Fixes issues with the Raw events Top N view (redux)

This PR contains the same fixes described below from #121562 , but doesn't depend on the following constants deleted from `@kbn/rule-data-utils` by #121135

```
ALERT_RULE_RISK_SCORE
ALERT_RULE_RISK_SCORE_MAPPING
ALERT_RULE_SEVERITY
ALERT_RULE_SEVERITY_MAPPING
```
This PR fixes the following issues with the Raw events Top N view:

- Fixes an issue <#121168> where the Sourcerer context included detection alerts in the Raw events view, per the before screenshot below:

### Before

![image](https://user-images.githubusercontent.com/61860752/145980440-0945a01c-d257-434e-8d94-4231feadff5b.png)

_Above: Before - the Raw events view includes detection alerts_

### After

![after_no_detection_alerts_in_raw_events](https://user-images.githubusercontent.com/4459398/146592973-36e51997-86a4-4982-a8c3-fa0c4ee3e99f.png)

_Above: After - The Raw events view does NOT include detection alerts_

- Fixes an issue <#121381> where when inspecting Raw events, `Sorry about that, something went wrong` is displayed when the Sourcerer context does not match the current selection:

### Before

![image](https://user-images.githubusercontent.com/59917825/146342313-7b0afcd5-31c9-4139-9011-cb85af303deb.png)

_Above: Before - When users `Inspect` the Raw events view, `Sorry about that, something went wrong` is displayed_

### After

![after_inspect_raw_events](https://user-images.githubusercontent.com/4459398/146595397-89aa65d0-9055-4511-81bd-670b20449610.png)

_Above: After - When users `Inspect` the raw events view, the expected Index pattern reflects the current Sourcerer selection_

- Fixes an issue where the following filters in the `Security > Alerts` and `Security > Rule > Details` views:
  - `kibana.alert.building_block_type`: an "Additional filters" option on the alerts table
  - `kibana.alert.rule.rule_id`: filters alerts to a single rule on the `Security > Rules > Details` views
  - `kibana.alert.rule.name`: not a built-in view filter, but frequently applied via the `Filter In` and `Filter Out` actions
  - `kibana.alert.rule.threat_mapping`: an "Additional filters" option on the alerts table
  - `kibana.alert.workflow_status`: The `open | acknowledged | closed` status filter

were incorrectly applied to the Raw events view, per the screenshots below:

### Before

Inspecting the Raw events query reveals the alert filters are applied as filter criteria, per the screenshot below:

![before_alert_filters_applied_to_raw_events_query](https://user-images.githubusercontent.com/4459398/146596292-eb2f52a2-adf4-47a3-bb96-3f39019df725.png)

_Above: Before - The alert filters are applied to the Raw events view_

### After

After the fix, the alert filters are NOT applied to the raw events view, per the screenshot below:

![after_alert_filters_NOT_applied_to_raw_events_query](https://user-images.githubusercontent.com/4459398/146596252-d5ec1512-5514-48f5-aff3-e18a69572e6f.png)

_Above: After - The alert filters are NOT applied to the Raw events view_
  • Loading branch information
andrew-goldstein authored Dec 20, 2021
1 parent d68700c commit d25e38d
Show file tree
Hide file tree
Showing 4 changed files with 517 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,155 @@
* 2.0.
*/

import { allEvents, defaultOptions, getOptions, rawEvents, alertEvents } from './helpers';
import type { Filter } from '@kbn/es-query';

import { TimelineId } from '../../../../common/types/timeline';
import {
alertEvents,
allEvents,
defaultOptions,
getOptions,
getSourcererScopeName,
isDetectionsAlertsTable,
rawEvents,
removeIgnoredAlertFilters,
shouldIgnoreAlertFilters,
} from './helpers';
import { SourcererScopeName } from '../../store/sourcerer/model';

/** the following `TimelineId`s are detection alert tables */
const detectionAlertsTimelines = [TimelineId.detectionsPage, TimelineId.detectionsRulesDetailsPage];

/** the following `TimelineId`s are NOT detection alert tables */
const otherTimelines = [
TimelineId.hostsPageEvents,
TimelineId.hostsPageExternalAlerts,
TimelineId.networkPageExternalAlerts,
TimelineId.uebaPageExternalAlerts,
TimelineId.active,
TimelineId.casePage,
TimelineId.test,
TimelineId.alternateTest,
];

const othersWithoutActive = otherTimelines.filter((x) => x !== TimelineId.active);

const hostNameFilter: Filter = {
meta: {
alias: null,
negate: false,
disabled: false,
type: 'phrase',
key: 'host.name',
params: {
query: 'Host-abcd',
},
},
query: {
match_phrase: {
'host.name': {
query: 'Host-abcd',
},
},
},
};

const buildingBlockTypeFilter: Filter = {
meta: {
alias: null,
negate: true,
disabled: false,
type: 'exists',
key: 'signal.rule.building_block_type',
value: 'exists',
},
query: {
exists: {
field: 'signal.rule.building_block_type',
},
},
};

const ruleIdFilter: Filter = {
meta: {
alias: null,
negate: false,
disabled: false,
type: 'phrase',
key: 'kibana.alert.rule.rule_id',
params: {
query: '32a4aefa-80fb-4716-bc0f-3f7bb1f14929',
},
},
query: {
match_phrase: {
'kibana.alert.rule.rule_id': '32a4aefa-80fb-4716-bc0f-3f7bb1f14929',
},
},
};

const ruleNameFilter: Filter = {
meta: {
alias: null,
negate: false,
disabled: false,
type: 'phrase',
key: 'kibana.alert.rule.name',
params: {
query: 'baz',
},
},
query: {
match_phrase: {
'kibana.alert.rule.name': {
query: 'baz',
},
},
},
};

const threatMappingFilter: Filter = {
meta: {
alias: null,
negate: true,
disabled: false,
type: 'exists',
key: 'kibana.alert.rule.threat_mapping',
value: 'exists',
},
query: {
exists: {
field: 'kibana.alert.rule.threat_mapping',
},
},
};

const workflowStatusFilter: Filter = {
meta: {
alias: null,
negate: false,
disabled: false,
type: 'phrase',
key: 'kibana.alert.workflow_status',
params: {
query: 'open',
},
},
query: {
term: {
'kibana.alert.workflow_status': 'open',
},
},
};

const allFilters = [
hostNameFilter,
buildingBlockTypeFilter,
ruleIdFilter,
ruleNameFilter,
threatMappingFilter,
workflowStatusFilter,
];

describe('getOptions', () => {
test(`it returns the default options when 'activeTimelineEventType' is undefined`, () => {
Expand All @@ -24,3 +172,123 @@ describe('getOptions', () => {
expect(getOptions('alert')).toEqual(alertEvents);
});
});

describe('isDetectionsAlertsTable', () => {
detectionAlertsTimelines.forEach((timelineId) =>
test(`it returns true for detections alerts table '${timelineId}'`, () => {
expect(isDetectionsAlertsTable(timelineId)).toEqual(true);
})
);

otherTimelines.forEach((timelineId) =>
test(`it returns false for (NON alert table) timeline '${timelineId}'`, () => {
expect(isDetectionsAlertsTable(timelineId)).toEqual(false);
})
);
});

describe('shouldIgnoreAlertFilters', () => {
detectionAlertsTimelines.forEach((timelineId) => {
test(`it returns true when the view is 'raw' for detections alerts table '${timelineId}'`, () => {
const view = 'raw';
expect(shouldIgnoreAlertFilters({ timelineId, view })).toEqual(true);
});

test(`it returns false when the view is NOT 'raw' for detections alerts table '${timelineId}'`, () => {
const view = 'alert'; // the default selection for detection alert tables
expect(shouldIgnoreAlertFilters({ timelineId, view })).toEqual(false);
});
});

otherTimelines.forEach((timelineId) => {
test(`it returns false when the view is 'raw' for (NON alert table) timeline'${timelineId}'`, () => {
const view = 'raw';
expect(shouldIgnoreAlertFilters({ timelineId, view })).toEqual(false);
});

test(`it returns false when the view is NOT 'raw' for (NON alert table) timeline '${timelineId}'`, () => {
const view = 'alert';
expect(shouldIgnoreAlertFilters({ timelineId, view })).toEqual(false);
});
});
});

describe('removeIgnoredAlertFilters', () => {
detectionAlertsTimelines.forEach((timelineId) => {
test(`it removes the ignored alert filters when the view is 'raw' for detections alerts table '${timelineId}'`, () => {
const view = 'raw';
expect(removeIgnoredAlertFilters({ filters: allFilters, timelineId, view })).toEqual([
hostNameFilter,
]);
});

test(`it does NOT remove any filters when the view is NOT 'raw' for detections alerts table '${timelineId}'`, () => {
const view = 'alert';
expect(removeIgnoredAlertFilters({ filters: allFilters, timelineId, view })).toEqual(
allFilters
);
});
});

otherTimelines.forEach((timelineId) => {
test(`it does NOT remove any filters when the view is 'raw' for (NON alert table) '${timelineId}'`, () => {
const view = 'alert';
expect(removeIgnoredAlertFilters({ filters: allFilters, timelineId, view })).toEqual(
allFilters
);
});

test(`it does NOT remove any filters when the view is NOT 'raw' for (NON alert table '${timelineId}'`, () => {
const view = 'alert';
expect(removeIgnoredAlertFilters({ filters: allFilters, timelineId, view })).toEqual(
allFilters
);
});
});
});

describe('getSourcererScopeName', () => {
detectionAlertsTimelines.forEach((timelineId) => {
test(`it returns the 'default' SourcererScopeName when the view is 'raw' for detections alerts table '${timelineId}'`, () => {
const view = 'raw';
expect(getSourcererScopeName({ timelineId, view })).toEqual(SourcererScopeName.default);
});

test(`it returns the 'detections' SourcererScopeName when the view is NOT 'raw' for detections alerts table '${timelineId}'`, () => {
const view = 'alert';
expect(getSourcererScopeName({ timelineId, view })).toEqual(SourcererScopeName.detections);
});
});

test(`it returns the 'default' SourcererScopeName when timelineId is undefined'`, () => {
const timelineId = undefined;
const view = 'raw';
expect(getSourcererScopeName({ timelineId, view })).toEqual(SourcererScopeName.default);
});

test(`it returns the 'timeline' SourcererScopeName when the view is 'raw' for the active timeline '${TimelineId.active}'`, () => {
const view = 'raw';
expect(getSourcererScopeName({ timelineId: TimelineId.active, view })).toEqual(
SourcererScopeName.timeline
);
});

test(`it returns the 'timeline' SourcererScopeName when the view is NOT 'raw' for the active timeline '${TimelineId.active}'`, () => {
const view = 'all';
expect(getSourcererScopeName({ timelineId: TimelineId.active, view })).toEqual(
SourcererScopeName.timeline
);
});

othersWithoutActive.forEach((timelineId) => {
test(`it returns the 'default' SourcererScopeName when the view is 'raw' for (NON alert table) timeline '${timelineId}'`, () => {
const view = 'raw';
expect(getSourcererScopeName({ timelineId, view })).toEqual(SourcererScopeName.default);
});

test(`it returns the 'default' SourcererScopeName when the view is NOT 'raw' for detections alerts table '${timelineId}'`, () => {
const view = 'alert';
expect(getSourcererScopeName({ timelineId, view })).toEqual(SourcererScopeName.default);
});
});
});
Loading

0 comments on commit d25e38d

Please sign in to comment.