[8.x] [Security Solution] Fix alerts table grouping severity stats not showing badge (#216738) (#216846)

# Backport

This will backport the following commits from `main` to `8.x`:
- [[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| ![Screenshot 2025-04-01 at
5
00\n16 PM](https://github.com/user-attachments/assets/c64b8140-4c16-4618-b8b0-0c295e9e35d5)\n|
![Screenshot 2025-04-01 at 5
05\n48 PM](https://github.com/user-attachments/assets/5b06ee16-b6eb-4d33-9510-75a80c569718)\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| ![Screenshot 2025-04-01 at
5
00\n16 PM](https://github.com/user-attachments/assets/c64b8140-4c16-4618-b8b0-0c295e9e35d5)\n|
![Screenshot 2025-04-01 at 5
05\n48 PM](https://github.com/user-attachments/assets/5b06ee16-b6eb-4d33-9510-75a80c569718)\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| ![Screenshot 2025-04-01 at
5
00\n16 PM](https://github.com/user-attachments/assets/c64b8140-4c16-4618-b8b0-0c295e9e35d5)\n|
![Screenshot 2025-04-01 at 5
05\n48 PM](https://github.com/user-attachments/assets/5b06ee16-b6eb-4d33-9510-75a80c569718)\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:
Kibana Machine 2025-04-02 18:03:13 +02:00 committed by GitHub
parent 0dcd49bed0
commit 3dd2138d0f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 156 additions and 41 deletions

View file

@ -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();
});

View file

@ -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,