From f7d994c3135d81ab8a110be7648a90b539ebd5d0 Mon Sep 17 00:00:00 2001 From: christineweng <18648970+christineweng@users.noreply.github.com> Date: Tue, 16 Jan 2024 15:30:32 -0600 Subject: [PATCH] [Security Solution] Alert flyout - update document id in analyzer preview and same ancestry (#174651) ## Summary Address: https://github.com/elastic/kibana/issues/169373 This PR updates the use of `kibana.alert.ancestor.id` to `_id` (available in flyout context as `eventId`) in analyzer preview and alerts by ancestry. This change allows upgrade from 7.x kibana to 8.10+ to utilize analyzer preview. No UI change introduced. **How to test** - Analyzer preview should match that of prior to the change - Alert by ancestry in correlations overview (right section) and correlations tab (left section -> Insights) should match that of prior to the change - Analyzer preview should match the analyzer viewer in alerts table ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios (cherry picked from commit f288919b144dbfc2e99a3ff689ddfc0707c89379) --- .../components/correlations_details.test.tsx | 4 +-- .../left/components/correlations_details.tsx | 15 ++-------- .../related_alerts_by_ancestry.test.tsx | 8 +----- .../components/related_alerts_by_ancestry.tsx | 9 ++---- .../components/analyzer_preview.test.tsx | 6 ++-- .../right/components/analyzer_preview.tsx | 12 +++----- .../components/correlations_overview.test.tsx | 4 +-- .../components/correlations_overview.tsx | 10 ++----- .../components/related_alerts_by_ancestry.tsx | 2 +- .../use_fetch_related_alerts_by_ancestry.ts | 2 +- ...e_show_related_alerts_by_ancestry.test.tsx | 28 ++++--------------- .../use_show_related_alerts_by_ancestry.ts | 11 +------- 12 files changed, 29 insertions(+), 82 deletions(-) diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/correlations_details.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/correlations_details.test.tsx index 21214670241aa..2c1a6c27a52d3 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/correlations_details.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/correlations_details.test.tsx @@ -67,7 +67,7 @@ describe('CorrelationsDetails', () => { it('renders all sections', () => { jest .mocked(useShowRelatedAlertsByAncestry) - .mockReturnValue({ show: true, documentId: 'documentId', indices: ['index1'] }); + .mockReturnValue({ show: true, indices: ['index1'] }); jest .mocked(useShowRelatedAlertsBySameSourceEvent) .mockReturnValue({ show: true, originalEventId: 'originalEventId' }); @@ -115,7 +115,7 @@ describe('CorrelationsDetails', () => { it('should render no section and show error message if show values are false', () => { jest .mocked(useShowRelatedAlertsByAncestry) - .mockReturnValue({ show: false, documentId: 'documentId', indices: ['index1'] }); + .mockReturnValue({ show: false, indices: ['index1'] }); jest .mocked(useShowRelatedAlertsBySameSourceEvent) .mockReturnValue({ show: false, originalEventId: 'originalEventId' }); diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/correlations_details.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/correlations_details.tsx index 0302083236532..739a17b7699a8 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/correlations_details.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/correlations_details.tsx @@ -30,11 +30,7 @@ export const CorrelationsDetails: React.FC = () => { const { dataAsNestedObject, dataFormattedForFieldBrowser, eventId, getFieldsData, scopeId } = useLeftPanelContext(); - const { - show: showAlertsByAncestry, - documentId, - indices, - } = useShowRelatedAlertsByAncestry({ + const { show: showAlertsByAncestry, indices } = useShowRelatedAlertsByAncestry({ getFieldsData, dataAsNestedObject, dataFormattedForFieldBrowser, @@ -86,14 +82,9 @@ export const CorrelationsDetails: React.FC = () => { )} - {showAlertsByAncestry && documentId && indices && ( + {showAlertsByAncestry && indices && ( - + )} diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/related_alerts_by_ancestry.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/related_alerts_by_ancestry.test.tsx index d7f4a35fd11c5..063ebce7354aa 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/related_alerts_by_ancestry.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/related_alerts_by_ancestry.test.tsx @@ -27,7 +27,6 @@ jest.mock('../hooks/use_paginated_alerts'); const documentId = 'documentId'; const indices = ['index1']; const scopeId = 'scopeId'; -const eventId = 'eventId'; const TOGGLE_ICON = EXPANDABLE_PANEL_TOGGLE_ICON_TEST_ID( CORRELATIONS_DETAILS_BY_ANCESTRY_SECTION_TEST_ID @@ -42,12 +41,7 @@ const TITLE_TEXT = EXPANDABLE_PANEL_HEADER_TITLE_TEXT_TEST_ID( const renderRelatedAlertsByAncestry = () => render( - + ); diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/related_alerts_by_ancestry.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/related_alerts_by_ancestry.tsx index 050d2b4ae1966..b8bb13fd1bd9f 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/related_alerts_by_ancestry.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/related_alerts_by_ancestry.tsx @@ -13,7 +13,7 @@ import { CORRELATIONS_DETAILS_BY_ANCESTRY_SECTION_TEST_ID } from './test_ids'; export interface RelatedAlertsByAncestryProps { /** - * Value of the kibana.alert.ancestors.id field + * Id of the document */ documentId: string; /** @@ -24,10 +24,6 @@ export interface RelatedAlertsByAncestryProps { * Maintain backwards compatibility // TODO remove when possible */ scopeId: string; - /** - * Id of the document - */ - eventId: string; } /** @@ -37,7 +33,6 @@ export const RelatedAlertsByAncestry: React.VFC = documentId, indices, scopeId, - eventId, }) => { const { loading, error, data, dataCount } = useFetchRelatedAlertsByAncestry({ documentId, @@ -61,7 +56,7 @@ export const RelatedAlertsByAncestry: React.VFC = loading={loading} alertIds={data} scopeId={scopeId} - eventId={eventId} + eventId={documentId} noItemsMessage={ ', () => { expect(mockUseAlertPrevalenceFromProcessTree).toHaveBeenCalledWith({ isActiveTimeline: false, - documentId: 'ancestors-id', + documentId: 'eventId', indices: ['rule-indices'], }); expect(wrapper.getByTestId(ANALYZER_PREVIEW_TEST_ID)).toBeInTheDocument(); }); - it('shows error message when documentid and index are not present', () => { + it('shows error message when index is not present', () => { mockUseAlertPrevalenceFromProcessTree.mockReturnValue({ loading: false, error: false, @@ -82,7 +82,7 @@ describe('', () => { expect(mockUseAlertPrevalenceFromProcessTree).toHaveBeenCalledWith({ isActiveTimeline: false, - documentId: '', + documentId: 'eventId', indices: [], }); diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/analyzer_preview.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/analyzer_preview.tsx index e8f23bc4638bd..0beb237f17cf2 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/analyzer_preview.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/analyzer_preview.tsx @@ -11,7 +11,7 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import { ANALYZER_PREVIEW_TEST_ID, ANALYZER_PREVIEW_LOADING_TEST_ID } from './test_ids'; import { getTreeNodes } from '../utils/analyzer_helpers'; -import { ANCESTOR_ID, RULE_INDICES } from '../../shared/constants/field_names'; +import { RULE_INDICES } from '../../shared/constants/field_names'; import { useRightPanelContext } from '../context'; import { useAlertPrevalenceFromProcessTree } from '../../../../common/containers/alerts/use_alert_prevalence_from_process_tree'; import type { StatsNode } from '../../../../common/containers/alerts/use_alert_prevalence_from_process_tree'; @@ -33,18 +33,14 @@ interface Cache { */ export const AnalyzerPreview: React.FC = () => { const [cache, setCache] = useState>({}); - const { dataFormattedForFieldBrowser: data, scopeId } = useRightPanelContext(); - - const documentId = find({ category: 'kibana', field: ANCESTOR_ID }, data); - const processDocumentId = - documentId && Array.isArray(documentId.values) ? documentId.values[0] : ''; + const { dataFormattedForFieldBrowser: data, scopeId, eventId } = useRightPanelContext(); const index = find({ category: 'kibana', field: RULE_INDICES }, data); const indices = index?.values ?? []; const { statsNodes, loading, error } = useAlertPrevalenceFromProcessTree({ isActiveTimeline: isActiveTimeline(scopeId), - documentId: processDocumentId, + documentId: eventId, indices, }); @@ -59,7 +55,7 @@ export const AnalyzerPreview: React.FC = () => { [cache.statsNodes] ); - const showAnalyzerTree = documentId && index && items && items.length > 0 && !error; + const showAnalyzerTree = eventId && index && items && items.length > 0 && !error; return loading ? ( ', () => { it('should show component with all rows in expandable panel', () => { jest .mocked(useShowRelatedAlertsByAncestry) - .mockReturnValue({ show: true, documentId: 'documentId', indices: ['index1'] }); + .mockReturnValue({ show: true, indices: ['index1'] }); jest .mocked(useShowRelatedAlertsBySameSourceEvent) .mockReturnValue({ show: true, originalEventId: 'originalEventId' }); @@ -145,7 +145,7 @@ describe('', () => { it('should hide rows and show error message if show values are false', () => { jest .mocked(useShowRelatedAlertsByAncestry) - .mockReturnValue({ show: false, documentId: 'documentId', indices: ['index1'] }); + .mockReturnValue({ show: false, indices: ['index1'] }); jest .mocked(useShowRelatedAlertsBySameSourceEvent) .mockReturnValue({ show: false, originalEventId: 'originalEventId' }); diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/correlations_overview.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/correlations_overview.tsx index 52e66fed55b5d..44689eaed616d 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/correlations_overview.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/correlations_overview.tsx @@ -56,11 +56,7 @@ export const CorrelationsOverview: React.FC = () => { }); }, [eventId, openLeftPanel, indexName, scopeId]); - const { - show: showAlertsByAncestry, - documentId, - indices, - } = useShowRelatedAlertsByAncestry({ + const { show: showAlertsByAncestry, indices } = useShowRelatedAlertsByAncestry({ getFieldsData, dataAsNestedObject, dataFormattedForFieldBrowser, @@ -115,8 +111,8 @@ export const CorrelationsOverview: React.FC = () => { {showAlertsBySession && entityId && ( )} - {showAlertsByAncestry && documentId && indices && ( - + {showAlertsByAncestry && indices && ( + )} ) : ( diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/related_alerts_by_ancestry.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/related_alerts_by_ancestry.tsx index 1c41fbe0969b3..2e628ba61a7be 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/related_alerts_by_ancestry.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/related_alerts_by_ancestry.tsx @@ -15,7 +15,7 @@ const ICON = 'warning'; export interface RelatedAlertsByAncestryProps { /** - * Value of the kibana.alert.ancestors.id field + * Id of the document */ documentId: string; /** diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/shared/hooks/use_fetch_related_alerts_by_ancestry.ts b/x-pack/plugins/security_solution/public/flyout/document_details/shared/hooks/use_fetch_related_alerts_by_ancestry.ts index 73415c880a3c1..b44349a06eec9 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/shared/hooks/use_fetch_related_alerts_by_ancestry.ts +++ b/x-pack/plugins/security_solution/public/flyout/document_details/shared/hooks/use_fetch_related_alerts_by_ancestry.ts @@ -11,7 +11,7 @@ import { isActiveTimeline } from '../../../../helpers'; export interface UseFetchRelatedAlertsByAncestryParams { /** - * Value of the kibana.alert.ancestors.id field + * Id of the document */ documentId: string; /** diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/shared/hooks/use_show_related_alerts_by_ancestry.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/shared/hooks/use_show_related_alerts_by_ancestry.test.tsx index a452e0e3a1686..8b70fcebdefb7 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/shared/hooks/use_show_related_alerts_by_ancestry.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/shared/hooks/use_show_related_alerts_by_ancestry.test.tsx @@ -16,6 +16,7 @@ import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_ex import { licenseService } from '../../../../common/hooks/use_license'; import { mockDataFormattedForFieldBrowser } from '../mocks/mock_data_formatted_for_field_browser'; import { mockDataAsNestedObject } from '../mocks/mock_data_as_nested_object'; +import { useIsInvestigateInResolverActionEnabled } from '../../../../detections/components/alerts_table/timeline_actions/investigate_in_resolver'; jest.mock('../../../../common/hooks/use_experimental_features'); jest.mock('../../../../common/hooks/use_license', () => { @@ -29,6 +30,9 @@ jest.mock('../../../../common/hooks/use_license', () => { }, }; }); +jest.mock( + '../../../../detections/components/alerts_table/timeline_actions/investigate_in_resolver' +); const licenseServiceMock = licenseService as jest.Mocked; const dataAsNestedObject = mockDataAsNestedObject; @@ -40,8 +44,9 @@ describe('useShowRelatedAlertsByAncestry', () => { UseShowRelatedAlertsByAncestryResult >; - it('should return false if getFieldsData returns null', () => { + it('should return false if Process Entity Info is not available', () => { (useIsExperimentalFeatureEnabled as jest.Mock).mockReturnValue(true); + (useIsInvestigateInResolverActionEnabled as jest.Mock).mockReturnValue(false); licenseServiceMock.isPlatinumPlus.mockReturnValue(true); const getFieldsData = () => null; hookResult = renderHook(() => @@ -69,7 +74,6 @@ describe('useShowRelatedAlertsByAncestry', () => { expect(hookResult.result.current).toEqual({ show: false, - documentId: 'value', indices: ['rule-parameters-index'], }); }); @@ -88,26 +92,6 @@ describe('useShowRelatedAlertsByAncestry', () => { expect(hookResult.result.current).toEqual({ show: false, - documentId: 'value', - indices: ['rule-parameters-index'], - }); - }); - - it('should return true if getFieldsData has the correct fields', () => { - (useIsExperimentalFeatureEnabled as jest.Mock).mockReturnValue(true); - licenseServiceMock.isPlatinumPlus.mockReturnValue(true); - const getFieldsData = () => 'value'; - hookResult = renderHook(() => - useShowRelatedAlertsByAncestry({ - getFieldsData, - dataAsNestedObject, - dataFormattedForFieldBrowser, - }) - ); - - expect(hookResult.result.current).toEqual({ - show: true, - documentId: 'value', indices: ['rule-parameters-index'], }); }); diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/shared/hooks/use_show_related_alerts_by_ancestry.ts b/x-pack/plugins/security_solution/public/flyout/document_details/shared/hooks/use_show_related_alerts_by_ancestry.ts index 53a1b336ff456..f1627b749bfe1 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/shared/hooks/use_show_related_alerts_by_ancestry.ts +++ b/x-pack/plugins/security_solution/public/flyout/document_details/shared/hooks/use_show_related_alerts_by_ancestry.ts @@ -13,8 +13,7 @@ import type { GetFieldsData } from '../../../../common/hooks/use_get_fields_data import { useIsInvestigateInResolverActionEnabled } from '../../../../detections/components/alerts_table/timeline_actions/investigate_in_resolver'; import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features'; import { useLicense } from '../../../../common/hooks/use_license'; -import { getField } from '../utils'; -import { ANCESTOR_ID, RULE_PARAMETERS_INDEX } from '../constants/field_names'; +import { RULE_PARAMETERS_INDEX } from '../constants/field_names'; export interface UseShowRelatedAlertsByAncestryParams { /** @@ -36,10 +35,6 @@ export interface UseShowRelatedAlertsByAncestryResult { * Returns true if the user has at least platinum privilege, and if the document has ancestry data */ show: boolean; - /** - * Value of the kibana.alert.ancestors.id field - */ - documentId?: string; /** * Values of the kibana.alert.rule.parameters.index field */ @@ -59,8 +54,6 @@ export const useShowRelatedAlertsByAncestry = ({ ); const hasProcessEntityInfo = useIsInvestigateInResolverActionEnabled(dataAsNestedObject); - const originalDocumentId = getField(getFieldsData(ANCESTOR_ID)); - // can't use getFieldsData here as the kibana.alert.rule.parameters is different and can be nested const originalDocumentIndex = useMemo( () => find({ category: 'kibana', field: RULE_PARAMETERS_INDEX }, dataFormattedForFieldBrowser), @@ -72,13 +65,11 @@ export const useShowRelatedAlertsByAncestry = ({ const show = isRelatedAlertsByProcessAncestryEnabled && hasProcessEntityInfo && - originalDocumentId != null && originalDocumentIndex != null && hasAtLeastPlatinum; return { show, - ...(originalDocumentId && { documentId: originalDocumentId }), ...(originalDocumentIndex && originalDocumentIndex.values && { indices: originalDocumentIndex.values }), };