mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[8.16] [Security Solution] Fix alerts table grouping severity stats not showing badge (#216738) (#216841)
# Backport This will backport the following commits from `main` to `8.16`: - [[Security Solution] Fix alerts table grouping severity stats not showing badge (#216738)](https://github.com/elastic/kibana/pull/216738) <!--- Backport version: 9.6.6 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport) <!--BACKPORT [{"author":{"name":"Philippe Oberti","email":"philippe.oberti@elastic.co"},"sourceCommit":{"committedDate":"2025-04-02T13:42:46Z","message":"[Security Solution] Fix alerts table grouping severity stats not showing badge (#216738)\n\n## Summary\n\nThis PR fixes an issue introduced by [this\nPR](https://github.com/elastic/kibana/pull/184635) back in `8.16`. I\ndon't think anyone noticed the problem until now...\n\nIn the PR linked above, the name of the property responsible to render\ncustom components in the group stats section of the alerts table\ngrouping was changed from `renderer` to `component` but there was (at\nleast) one usage that had not been updated. Because that usage wasn't\ncorrectly typed and there was no unit tests to verify the behavior, the\nissue went unnoticed...\n\n### Notes\n\nThis whole code should be refactored eventually. This is not the purpose\nof this PR. This only focuses on fixing the issue, adding proper types\nand unit tests.\n\n| Before | After |\n| ------------- | ------------- |\n| \n| \n|\n\n### Checklist\n\n- [x] [Unit or functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere updated or added to match the most common scenarios","sha":"c1939bb6478bc1f64046680bf77346549517921f","branchLabelMapping":{"^v9.1.0$":"main","^v8.19.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team:Threat Hunting:Investigations","Team:Security Generative AI","backport:version","v9.1.0","v8.19.0","v8.18.1","v9.0.1","v8.17.5","v8.16.7"],"title":"[Security Solution] Fix alerts table grouping severity stats not showing badge","number":216738,"url":"https://github.com/elastic/kibana/pull/216738","mergeCommit":{"message":"[Security Solution] Fix alerts table grouping severity stats not showing badge (#216738)\n\n## Summary\n\nThis PR fixes an issue introduced by [this\nPR](https://github.com/elastic/kibana/pull/184635) back in `8.16`. I\ndon't think anyone noticed the problem until now...\n\nIn the PR linked above, the name of the property responsible to render\ncustom components in the group stats section of the alerts table\ngrouping was changed from `renderer` to `component` but there was (at\nleast) one usage that had not been updated. Because that usage wasn't\ncorrectly typed and there was no unit tests to verify the behavior, the\nissue went unnoticed...\n\n### Notes\n\nThis whole code should be refactored eventually. This is not the purpose\nof this PR. This only focuses on fixing the issue, adding proper types\nand unit tests.\n\n| Before | After |\n| ------------- | ------------- |\n| \n| \n|\n\n### Checklist\n\n- [x] [Unit or functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere updated or added to match the most common scenarios","sha":"c1939bb6478bc1f64046680bf77346549517921f"}},"sourceBranch":"main","suggestedTargetBranches":["8.x","8.18","9.0","8.17","8.16"],"targetPullRequestStates":[{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/216738","number":216738,"mergeCommit":{"message":"[Security Solution] Fix alerts table grouping severity stats not showing badge (#216738)\n\n## Summary\n\nThis PR fixes an issue introduced by [this\nPR](https://github.com/elastic/kibana/pull/184635) back in `8.16`. I\ndon't think anyone noticed the problem until now...\n\nIn the PR linked above, the name of the property responsible to render\ncustom components in the group stats section of the alerts table\ngrouping was changed from `renderer` to `component` but there was (at\nleast) one usage that had not been updated. Because that usage wasn't\ncorrectly typed and there was no unit tests to verify the behavior, the\nissue went unnoticed...\n\n### Notes\n\nThis whole code should be refactored eventually. This is not the purpose\nof this PR. This only focuses on fixing the issue, adding proper types\nand unit tests.\n\n| Before | After |\n| ------------- | ------------- |\n| \n| \n|\n\n### Checklist\n\n- [x] [Unit or functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere updated or added to match the most common scenarios","sha":"c1939bb6478bc1f64046680bf77346549517921f"}},{"branch":"8.x","label":"v8.19.0","branchLabelMappingKey":"^v8.19.0$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"8.18","label":"v8.18.1","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"9.0","label":"v9.0.1","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"8.17","label":"v8.17.5","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"8.16","label":"v8.16.7","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"}]}] BACKPORT--> Co-authored-by: Philippe Oberti <philippe.oberti@elastic.co>
This commit is contained in:
parent
643553661f
commit
a6113352d7
2 changed files with 156 additions and 41 deletions
|
@ -10,70 +10,201 @@ import { getStats } from '.';
|
|||
describe('getStats', () => {
|
||||
it('returns array of badges which corresponds to the field name', () => {
|
||||
const badgesRuleName = getStats('kibana.alert.rule.name', {
|
||||
key: ['Rule name test', 'Some description'],
|
||||
usersCountAggregation: {
|
||||
value: 10,
|
||||
},
|
||||
key: [],
|
||||
severitiesSubAggregation: { buckets: [{ key: 'medium', doc_count: 10 }] },
|
||||
countSeveritySubAggregation: { value: 1 },
|
||||
usersCountAggregation: { value: 3 },
|
||||
hostsCountAggregation: { value: 5 },
|
||||
doc_count: 10,
|
||||
});
|
||||
|
||||
expect(badgesRuleName.length).toBe(4);
|
||||
expect(
|
||||
badgesRuleName.find(
|
||||
(badge) => badge.badge != null && badge.title === 'Users:' && badge.badge.value === 10
|
||||
(badge) => badge.title === 'Severity:' && badge.component != null && badge.badge == null
|
||||
)
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
badgesRuleName.find(
|
||||
(badge) => badge.badge != null && badge.title === 'Alerts:' && badge.badge.value === 10
|
||||
(badge) =>
|
||||
badge.title === 'Users:' &&
|
||||
badge.component == null &&
|
||||
badge.badge != null &&
|
||||
badge.badge.value === 3
|
||||
)
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
badgesRuleName.find(
|
||||
(badge) =>
|
||||
badge.title === 'Hosts:' &&
|
||||
badge.component == null &&
|
||||
badge.badge != null &&
|
||||
badge.badge.value === 5
|
||||
)
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
badgesRuleName.find(
|
||||
(badge) =>
|
||||
badge.title === 'Alerts:' &&
|
||||
badge.component == null &&
|
||||
badge.badge != null &&
|
||||
badge.badge.value === 10
|
||||
)
|
||||
).toBeTruthy();
|
||||
|
||||
const badgesHostName = getStats('host.name', {
|
||||
key: 'Host',
|
||||
rulesCountAggregation: {
|
||||
value: 3,
|
||||
},
|
||||
severitiesSubAggregation: { buckets: [{ key: 'medium', doc_count: 10 }] },
|
||||
countSeveritySubAggregation: { value: 1 },
|
||||
usersCountAggregation: { value: 5 },
|
||||
rulesCountAggregation: { value: 3 },
|
||||
doc_count: 2,
|
||||
});
|
||||
|
||||
expect(badgesHostName.length).toBe(4);
|
||||
expect(
|
||||
badgesHostName.find(
|
||||
(badge) => badge.badge != null && badge.title === 'Rules:' && badge.badge.value === 3
|
||||
(badge) => badge.title === 'Severity:' && badge.component != null && badge.badge == null
|
||||
)
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
badgesHostName.find(
|
||||
(badge) =>
|
||||
badge.title === 'Users:' &&
|
||||
badge.component == null &&
|
||||
badge.badge != null &&
|
||||
badge.badge.value === 5
|
||||
)
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
badgesHostName.find(
|
||||
(badge) =>
|
||||
badge.title === 'Rules:' &&
|
||||
badge.component == null &&
|
||||
badge.badge != null &&
|
||||
badge.badge.value === 3
|
||||
)
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
badgesHostName.find(
|
||||
(badge) =>
|
||||
badge.title === 'Alerts:' &&
|
||||
badge.component == null &&
|
||||
badge.badge != null &&
|
||||
badge.badge.value === 2
|
||||
)
|
||||
).toBeTruthy();
|
||||
|
||||
const badgesUserName = getStats('user.name', {
|
||||
key: 'User test',
|
||||
hostsCountAggregation: {
|
||||
value: 1,
|
||||
},
|
||||
severitiesSubAggregation: { buckets: [{ key: 'medium', doc_count: 10 }] },
|
||||
countSeveritySubAggregation: { value: 1 },
|
||||
rulesCountAggregation: { value: 2 },
|
||||
hostsCountAggregation: { value: 1 },
|
||||
doc_count: 1,
|
||||
});
|
||||
|
||||
expect(badgesUserName.length).toBe(4);
|
||||
expect(
|
||||
badgesUserName.find(
|
||||
(badge) => badge.badge != null && badge.title === `Hosts:` && badge.badge.value === 1
|
||||
(badge) => badge.title === 'Severity:' && badge.component != null && badge.badge == null
|
||||
)
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
badgesUserName.find(
|
||||
(badge) =>
|
||||
badge.title === 'Hosts:' &&
|
||||
badge.component == null &&
|
||||
badge.badge != null &&
|
||||
badge.badge.value === 1
|
||||
)
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
badgesUserName.find(
|
||||
(badge) =>
|
||||
badge.title === 'Rules:' &&
|
||||
badge.component == null &&
|
||||
badge.badge != null &&
|
||||
badge.badge.value === 2
|
||||
)
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
badgesUserName.find(
|
||||
(badge) =>
|
||||
badge.title === 'Alerts:' &&
|
||||
badge.component == null &&
|
||||
badge.badge != null &&
|
||||
badge.badge.value === 1
|
||||
)
|
||||
).toBeTruthy();
|
||||
|
||||
const badgesSourceIp = getStats('source.ip', {
|
||||
key: 'User test',
|
||||
severitiesSubAggregation: { buckets: [{ key: 'medium', doc_count: 10 }] },
|
||||
countSeveritySubAggregation: { value: 1 },
|
||||
rulesCountAggregation: { value: 16 },
|
||||
hostsCountAggregation: { value: 17 },
|
||||
doc_count: 18,
|
||||
});
|
||||
|
||||
expect(badgesSourceIp.length).toBe(4);
|
||||
expect(
|
||||
badgesSourceIp.find(
|
||||
(badge) => badge.title === 'Severity:' && badge.component != null && badge.badge == null
|
||||
)
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
badgesSourceIp.find(
|
||||
(badge) =>
|
||||
badge.title === 'Hosts:' &&
|
||||
badge.component == null &&
|
||||
badge.badge != null &&
|
||||
badge.badge.value === 17
|
||||
)
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
badgesSourceIp.find(
|
||||
(badge) =>
|
||||
badge.title === 'Rules:' &&
|
||||
badge.component == null &&
|
||||
badge.badge != null &&
|
||||
badge.badge.value === 16
|
||||
)
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
badgesSourceIp.find(
|
||||
(badge) =>
|
||||
badge.title === 'Alerts:' &&
|
||||
badge.component == null &&
|
||||
badge.badge != null &&
|
||||
badge.badge.value === 18
|
||||
)
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
it('returns default badges if the field specific does not exist', () => {
|
||||
it('should return default badges if the field specific does not exist', () => {
|
||||
const badges = getStats('process.name', {
|
||||
key: 'process',
|
||||
rulesCountAggregation: {
|
||||
value: 3,
|
||||
},
|
||||
severitiesSubAggregation: { buckets: [{ key: 'medium', doc_count: 10 }] },
|
||||
countSeveritySubAggregation: { value: 1 },
|
||||
rulesCountAggregation: { value: 3 },
|
||||
doc_count: 10,
|
||||
});
|
||||
|
||||
expect(badges.length).toBe(2);
|
||||
expect(badges.length).toBe(3);
|
||||
expect(
|
||||
badges.find(
|
||||
(badge) => badge.badge != null && badge.title === 'Rules:' && badge.badge.value === 3
|
||||
(badge) => badge.title === 'Severity:' && badge.component != null && badge.badge == null
|
||||
)
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
badges.find(
|
||||
(badge) => badge.badge != null && badge.title === 'Alerts:' && badge.badge.value === 10
|
||||
(badge) => badge.title === 'Rules:' && badge.component == null && badge.badge?.value === 3
|
||||
)
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
badges.find(
|
||||
(badge) => badge.title === 'Alerts:' && badge.component == null && badge.badge?.value === 10
|
||||
)
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import { EuiIcon } from '@elastic/eui';
|
||||
import React from 'react';
|
||||
import type { RawBucket, GroupStatsItem } from '@kbn/grouping';
|
||||
import type { GroupStatsItem, RawBucket } from '@kbn/grouping';
|
||||
import type { AlertsGroupingAggregation } from './types';
|
||||
import * as i18n from '../translations';
|
||||
|
||||
|
@ -77,16 +77,16 @@ export const getStats = (
|
|||
? multiSeverity
|
||||
: singleSeverityComponent;
|
||||
|
||||
const severityStat = !severityComponent
|
||||
const severityStat: GroupStatsItem[] = !severityComponent
|
||||
? []
|
||||
: [
|
||||
{
|
||||
title: i18n.STATS_GROUP_SEVERITY,
|
||||
renderer: severityComponent,
|
||||
component: severityComponent,
|
||||
},
|
||||
];
|
||||
|
||||
const defaultBadges = [
|
||||
const defaultBadges: GroupStatsItem[] = [
|
||||
{
|
||||
title: i18n.STATS_GROUP_ALERTS,
|
||||
badge: {
|
||||
|
@ -133,22 +133,6 @@ export const getStats = (
|
|||
...defaultBadges,
|
||||
];
|
||||
case 'user.name':
|
||||
return [
|
||||
...severityStat,
|
||||
{
|
||||
title: i18n.STATS_GROUP_HOSTS,
|
||||
badge: {
|
||||
value: bucket.hostsCountAggregation?.value ?? 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18n.STATS_GROUP_RULES,
|
||||
badge: {
|
||||
value: bucket.rulesCountAggregation?.value ?? 0,
|
||||
},
|
||||
},
|
||||
...defaultBadges,
|
||||
];
|
||||
case 'source.ip':
|
||||
return [
|
||||
...severityStat,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue