mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[SecuritySolution] Fixes for alert ids in the alert flyout (#126490)
* fix: show dns.question.name for network events There are no events with event.category == 'dns'. DNS events are actually 'network' events with dns.network == 'dns'. To simplify the field logic, we'll show the 'dns.question.name' field for all network events. * fix: show threat_match fields For newly-generated events, the threat indicator values can be found under 'kibana.alert.rule.parameters`. This adds a temporary fix for that. * fix: use legacy fields where necessary Threat match and ML alert fields of migrated alerts are not migrated into the alert rule's parameters. We therefore read them by their legacy id. * fix: remove unused import Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
f886a7b532
commit
aa3e20e1f5
4 changed files with 97 additions and 13 deletions
|
@ -62,7 +62,6 @@ export enum EventCategory {
|
|||
PROCESS = 'process',
|
||||
FILE = 'file',
|
||||
NETWORK = 'network',
|
||||
DNS = 'dns',
|
||||
REGISTRY = 'registry',
|
||||
MALWARE = 'malware',
|
||||
}
|
||||
|
|
|
@ -129,7 +129,7 @@ describe('AlertSummaryView', () => {
|
|||
});
|
||||
});
|
||||
|
||||
test('DNS event renders the correct summary rows', () => {
|
||||
test('DNS network event renders the correct summary rows', () => {
|
||||
const renderProps = {
|
||||
...props,
|
||||
data: [
|
||||
|
@ -137,8 +137,8 @@ describe('AlertSummaryView', () => {
|
|||
if (item.category === 'event' && item.field === 'event.category') {
|
||||
return {
|
||||
...item,
|
||||
values: ['dns'],
|
||||
originalValue: ['dns'],
|
||||
values: ['network'],
|
||||
originalValue: ['network'],
|
||||
};
|
||||
}
|
||||
return item;
|
||||
|
@ -324,6 +324,39 @@ describe('AlertSummaryView', () => {
|
|||
});
|
||||
});
|
||||
|
||||
test('[legacy] Machine learning events show correct fields', () => {
|
||||
const enhancedData = [
|
||||
...mockAlertDetailsData.map((item) => {
|
||||
if (item.category === 'kibana' && item.field === 'kibana.alert.rule.type') {
|
||||
return {
|
||||
...item,
|
||||
values: ['machine_learning'],
|
||||
originalValue: ['machine_learning'],
|
||||
};
|
||||
}
|
||||
return item;
|
||||
}),
|
||||
{
|
||||
category: 'signal',
|
||||
field: 'signal.rule.machine_learning_job_id',
|
||||
values: ['i_am_the_ml_job_id'],
|
||||
},
|
||||
{ category: 'signal', field: 'signal.rule.anomaly_threshold', values: [2] },
|
||||
] as TimelineEventsDetailsItem[];
|
||||
const renderProps = {
|
||||
...props,
|
||||
data: enhancedData,
|
||||
};
|
||||
const { getByText } = render(
|
||||
<TestProvidersComponent>
|
||||
<AlertSummaryView {...renderProps} />
|
||||
</TestProvidersComponent>
|
||||
);
|
||||
['i_am_the_ml_job_id', 'signal.rule.anomaly_threshold'].forEach((fieldId) => {
|
||||
expect(getByText(fieldId));
|
||||
});
|
||||
});
|
||||
|
||||
test('Threat match events show correct fields', () => {
|
||||
const enhancedData = [
|
||||
...mockAlertDetailsData.map((item) => {
|
||||
|
@ -338,10 +371,51 @@ describe('AlertSummaryView', () => {
|
|||
}),
|
||||
{
|
||||
category: 'kibana',
|
||||
field: 'kibana.alert.rule.threat_index',
|
||||
field: 'kibana.alert.rule.parameters.threat_index',
|
||||
values: ['threat_index*'],
|
||||
},
|
||||
{ category: 'kibana', field: 'kibana.alert.rule.threat_query', values: ['*query*'] },
|
||||
{
|
||||
category: 'kibana',
|
||||
field: 'kibana.alert.rule.parameters.threat_query',
|
||||
values: ['*query*'],
|
||||
},
|
||||
] as TimelineEventsDetailsItem[];
|
||||
const renderProps = {
|
||||
...props,
|
||||
data: enhancedData,
|
||||
};
|
||||
const { getByText } = render(
|
||||
<TestProvidersComponent>
|
||||
<AlertSummaryView {...renderProps} />
|
||||
</TestProvidersComponent>
|
||||
);
|
||||
['threat_index*', '*query*'].forEach((fieldId) => {
|
||||
expect(getByText(fieldId));
|
||||
});
|
||||
});
|
||||
|
||||
test('[legacy] Threat match events show correct fields', () => {
|
||||
const enhancedData = [
|
||||
...mockAlertDetailsData.map((item) => {
|
||||
if (item.category === 'kibana' && item.field === 'kibana.alert.rule.type') {
|
||||
return {
|
||||
...item,
|
||||
values: ['threat_match'],
|
||||
originalValue: ['threat_match'],
|
||||
};
|
||||
}
|
||||
return item;
|
||||
}),
|
||||
{
|
||||
category: 'signal',
|
||||
field: 'signal.rule.threat_index',
|
||||
values: ['threat_index*'],
|
||||
},
|
||||
{
|
||||
category: 'signal',
|
||||
field: 'signal.rule.threat_query',
|
||||
values: ['*query*'],
|
||||
},
|
||||
] as TimelineEventsDetailsItem[];
|
||||
const renderProps = {
|
||||
...props,
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import { find, isEmpty, uniqBy } from 'lodash/fp';
|
||||
import { ALERT_RULE_NAMESPACE, ALERT_RULE_PARAMETERS, ALERT_RULE_TYPE } from '@kbn/rule-data-utils';
|
||||
import { ALERT_RULE_PARAMETERS, ALERT_RULE_TYPE } from '@kbn/rule-data-utils';
|
||||
|
||||
import * as i18n from './translations';
|
||||
import { BrowserFields } from '../../../../common/search_strategy/index_fields';
|
||||
|
@ -62,10 +62,9 @@ function getFieldsByCategory({
|
|||
{ id: 'destination.port' },
|
||||
{ id: 'source.address' },
|
||||
{ id: 'source.port' },
|
||||
{ id: 'dns.question.name' },
|
||||
{ id: 'process.name' },
|
||||
];
|
||||
case EventCategory.DNS:
|
||||
return [{ id: 'dns.question.name' }, { id: 'process.name' }];
|
||||
case EventCategory.REGISTRY:
|
||||
return [{ id: 'registry.key' }, { id: 'registry.value' }, { id: 'process.name' }];
|
||||
case EventCategory.MALWARE:
|
||||
|
@ -146,18 +145,22 @@ function getFieldsByRuleType(ruleType?: string): EventSummaryField[] {
|
|||
return [
|
||||
{
|
||||
id: `${ALERT_RULE_PARAMETERS}.machine_learning_job_id`,
|
||||
legacyId: 'signal.rule.machine_learning_job_id',
|
||||
},
|
||||
{
|
||||
id: `${ALERT_RULE_PARAMETERS}.anomaly_threshold`,
|
||||
legacyId: 'signal.rule.anomaly_threshold',
|
||||
},
|
||||
];
|
||||
case 'threat_match':
|
||||
return [
|
||||
{
|
||||
id: `${ALERT_RULE_NAMESPACE}.threat_index`,
|
||||
id: `${ALERT_RULE_PARAMETERS}.threat_index`,
|
||||
legacyId: 'signal.rule.threat_index',
|
||||
},
|
||||
{
|
||||
id: `${ALERT_RULE_NAMESPACE}.threat_query`,
|
||||
id: `${ALERT_RULE_PARAMETERS}.threat_query`,
|
||||
legacyId: 'signal.rule.threat_query',
|
||||
},
|
||||
];
|
||||
default:
|
||||
|
@ -251,11 +254,18 @@ export const getSummaryRows = ({
|
|||
|
||||
return data != null
|
||||
? tableFields.reduce<SummaryRow[]>((acc, field) => {
|
||||
const item = data.find((d) => d.field === field.id);
|
||||
if (!item || isEmpty(item?.values)) {
|
||||
const item = data.find(
|
||||
(d) => d.field === field.id || (field.legacyId && d.field === field.legacyId)
|
||||
);
|
||||
if (!item || isEmpty(item.values)) {
|
||||
return acc;
|
||||
}
|
||||
|
||||
// If we found the data by its legacy id we swap the ids to display the correct one
|
||||
if (item.field === field.legacyId) {
|
||||
field.id = field.legacyId;
|
||||
}
|
||||
|
||||
const linkValueField =
|
||||
field.linkField != null && data.find((d) => d.field === field.linkField);
|
||||
const description = {
|
||||
|
|
|
@ -30,6 +30,7 @@ export type EnrichedFieldInfoWithValues = EnrichedFieldInfo & { values: string[]
|
|||
|
||||
export interface EventSummaryField {
|
||||
id: string;
|
||||
legacyId?: string;
|
||||
label?: string;
|
||||
linkField?: string;
|
||||
fieldType?: string;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue