Skip to content

Commit

Permalink
[Cloud Security] Alerts Datagrids for Contextual Flyout (#199573)
Browse files Browse the repository at this point in the history
## Summary

This PR is for Alerts Datagrid component in Contextual Flyout

This PR is for Alerts Datagrid in Contextual Flyout for User name and
Host name
<img width="1480" alt="Screenshot 2024-11-14 at 9 08 26 AM"
src="https://github.com/user-attachments/assets/46a254c8-b7f1-4b63-9637-2b1c281d5502">

---------

Co-authored-by: kibanamachine <[email protected]>
(cherry picked from commit ab965f7)
  • Loading branch information
animehart committed Nov 14, 2024
1 parent 070cbba commit a8396e9
Show file tree
Hide file tree
Showing 18 changed files with 693 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
defaultErrorMessage,
buildMutedRulesFilter,
buildEntityFlyoutPreviewQuery,
buildEntityAlertsQuery,
} from './helpers';

const fallbackMessage = 'thisIsAFallBackMessage';
Expand Down Expand Up @@ -182,4 +183,78 @@ describe('test helper methods', () => {
expect(buildEntityFlyoutPreviewQuery(field)).toEqual(expectedQuery);
});
});

describe('buildEntityAlertsQuery', () => {
const getExpectedAlertsQuery = (size?: number) => {
return {
size: size || 0,
_source: false,
fields: [
'_id',
'_index',
'kibana.alert.rule.uuid',
'kibana.alert.severity',
'kibana.alert.rule.name',
'kibana.alert.workflow_status',
],
query: {
bool: {
filter: [
{
bool: {
must: [],
filter: [
{
match_phrase: {
'host.name': {
query: 'exampleHost',
},
},
},
],
should: [],
must_not: [],
},
},
{
range: {
'@timestamp': {
gte: 'Today',
lte: 'Tomorrow',
},
},
},
{
terms: {
'kibana.alert.workflow_status': ['open', 'acknowledged'],
},
},
],
},
},
};
};

it('should return the correct query when given all params', () => {
const field = 'host.name';
const query = 'exampleHost';
const to = 'Tomorrow';
const from = 'Today';
const size = 100;

expect(buildEntityAlertsQuery(field, to, from, query, size)).toEqual(
getExpectedAlertsQuery(size)
);
});

it('should return the correct query when not given size', () => {
const field = 'host.name';
const query = 'exampleHost';
const to = 'Tomorrow';
const from = 'Today';
const size = undefined;

expect(buildEntityAlertsQuery(field, to, from, query)).toEqual(getExpectedAlertsQuery(size));
});
});
});
57 changes: 57 additions & 0 deletions x-pack/packages/kbn-cloud-security-posture/common/utils/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* 2.0.
*/
import { QueryDslQueryContainer } from '@kbn/data-views-plugin/common/types';

import { i18n } from '@kbn/i18n';
import type { CspBenchmarkRulesStates } from '../schema/rules/latest';

Expand Down Expand Up @@ -62,3 +63,59 @@ export const buildEntityFlyoutPreviewQuery = (field: string, queryValue?: string
},
};
};

export const buildEntityAlertsQuery = (
field: string,
to: string,
from: string,
queryValue?: string,
size?: number
) => {
return {
size: size || 0,
_source: false,
fields: [
'_id',
'_index',
'kibana.alert.rule.uuid',
'kibana.alert.severity',
'kibana.alert.rule.name',
'kibana.alert.workflow_status',
],
query: {
bool: {
filter: [
{
bool: {
must: [],
filter: [
{
match_phrase: {
[field]: {
query: queryValue,
},
},
},
],
should: [],
must_not: [],
},
},
{
range: {
'@timestamp': {
gte: from,
lte: to,
},
},
},
{
terms: {
'kibana.alert.workflow_status': ['open', 'acknowledged'],
},
},
],
},
},
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,11 @@ export const useMisconfigurationFindings = (options: UseCspOptions) => {
params: buildMisconfigurationsFindingsQuery(options, rulesStates!),
})
);
if (!aggregations) throw new Error('expected aggregations to be defined');
if (!aggregations && options.ignore_unavailable === false)
throw new Error('expected aggregations to be defined');

return {
count: getMisconfigurationAggregationCount(aggregations.count.buckets),
count: getMisconfigurationAggregationCount(aggregations?.count.buckets),
rows: hits.hits.map((finding) => ({
result: finding._source?.result,
rule: finding?._source?.rule,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import { AlertsPreview } from './alerts_preview';
import { TestProviders } from '../../../common/mock/test_providers';
import { useExpandableFlyoutApi } from '@kbn/expandable-flyout';
import type { ParsedAlertsData } from '../../../overview/components/detection_response/alerts_by_status/types';
import { useMisconfigurationPreview } from '@kbn/cloud-security-posture/src/hooks/use_misconfiguration_preview';
import { useVulnerabilitiesPreview } from '@kbn/cloud-security-posture/src/hooks/use_vulnerabilities_preview';
import { useRiskScore } from '../../../entity_analytics/api/hooks/use_risk_score';

const mockAlertsData: ParsedAlertsData = {
open: {
Expand All @@ -29,16 +32,24 @@ const mockAlertsData: ParsedAlertsData = {
},
};

jest.mock(
'../../../detections/components/alerts_kpis/alerts_summary_charts_panel/use_summary_chart_data'
);
// Mock hooks
jest.mock('@kbn/cloud-security-posture/src/hooks/use_misconfiguration_preview');
jest.mock('@kbn/cloud-security-posture/src/hooks/use_vulnerabilities_preview');
jest.mock('../../../entity_analytics/api/hooks/use_risk_score');
jest.mock('@kbn/expandable-flyout');

describe('AlertsPreview', () => {
const mockOpenLeftPanel = jest.fn();

beforeEach(() => {
(useExpandableFlyoutApi as jest.Mock).mockReturnValue({ openLeftPanel: mockOpenLeftPanel });
(useVulnerabilitiesPreview as jest.Mock).mockReturnValue({
data: { count: { CRITICAL: 0, HIGH: 1, MEDIUM: 1, LOW: 0, UNKNOWN: 0 } },
});
(useRiskScore as jest.Mock).mockReturnValue({ data: [{ host: { risk: 75 } }] });
(useMisconfigurationPreview as jest.Mock).mockReturnValue({
data: { count: { passed: 1, failed: 1 } },
});
});
afterEach(() => {
jest.clearAllMocks();
Expand All @@ -47,17 +58,17 @@ describe('AlertsPreview', () => {
it('renders', () => {
const { getByTestId } = render(
<TestProviders>
<AlertsPreview alertsData={mockAlertsData} />
<AlertsPreview alertsData={mockAlertsData} name="host1" fieldName="host.name" />
</TestProviders>
);

expect(getByTestId('securitySolutionFlyoutInsightsAlertsTitleText')).toBeInTheDocument();
expect(getByTestId('securitySolutionFlyoutInsightsAlertsTitleLink')).toBeInTheDocument();
});

it('renders correct alerts number', () => {
const { getByTestId } = render(
<TestProviders>
<AlertsPreview alertsData={mockAlertsData} />
<AlertsPreview alertsData={mockAlertsData} name="host1" fieldName="host.name" />
</TestProviders>
);

Expand All @@ -67,7 +78,7 @@ describe('AlertsPreview', () => {
it('should render the correct number of distribution bar section based on the number of severities', () => {
const { queryAllByTestId } = render(
<TestProviders>
<AlertsPreview alertsData={mockAlertsData} />
<AlertsPreview alertsData={mockAlertsData} name="host1" fieldName="host.name" />
</TestProviders>
);

Expand Down
Loading

0 comments on commit a8396e9

Please sign in to comment.