From 117b2ad993c9d0209014cc93ea9d6c037ac913eb Mon Sep 17 00:00:00 2001 From: Kfir Peled Date: Thu, 21 Nov 2024 14:28:22 +0000 Subject: [PATCH] Added timeline investigation, fixed coloring of events. Added node limit, removed unknown targets --- .../server/routes/graph/v1.ts | 2 +- .../components/graph_node_expand_popover.tsx | 18 +++---- .../left/components/graph_visualization.tsx | 53 +++++++++++++++---- .../components/graph_preview_container.tsx | 4 +- .../shared/hooks/use_graph_preview.ts | 6 ++- 5 files changed, 62 insertions(+), 21 deletions(-) diff --git a/x-pack/plugins/cloud_security_posture/server/routes/graph/v1.ts b/x-pack/plugins/cloud_security_posture/server/routes/graph/v1.ts index b14a2ba3e06a9..35232411a50e9 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/graph/v1.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/graph/v1.ts @@ -316,7 +316,7 @@ const determineEntityNodeShape = ( return { shape: 'diamond', icon: 'globe' }; } - return { shape: 'hexagon', icon: 'questionInCircle' }; + return { shape: 'hexagon', icon: '' }; }; const sortNodes = (nodesMap: Record) => { diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/graph_node_expand_popover.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/graph_node_expand_popover.tsx index 7389493ef06df..3432880576f3d 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/graph_node_expand_popover.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/graph_node_expand_popover.tsx @@ -44,15 +44,6 @@ export const GraphNodeExpandPopover: React.FC = mem data-test-subj="graphNodeExpandPopover" > - = mem onClick={onShowActionsOnEntityClick} data-test-subj={GRAPH_NODE_POPOVER_SHOW_ACTIONS_ON_ITEM_ID} /> + ); diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/graph_visualization.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/graph_visualization.tsx index b3ab24cf9588f..c83bbd7c62d56 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/graph_visualization.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/graph_visualization.tsx @@ -19,6 +19,10 @@ import { import type { Filter, Query, TimeRange, BoolQuery, PhraseFilter } from '@kbn/es-query'; import { css } from '@emotion/css'; import { getEsQueryConfig } from '@kbn/data-service'; +import dateMath from '@kbn/datemath'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { normalizeTimeRange } from '../../../../common/utils/normalize_time_range'; +import { InvestigateInTimelineButton } from '../../../../common/components/event_details/investigate_in_timeline_button'; import { useGetScopedSourcererDataView } from '../../../../sourcerer/components/use_get_sourcerer_data_view'; import { SourcererScopeName } from '../../../../sourcerer/store/model'; import { useDocumentDetailsContext } from '../../shared/context'; @@ -47,15 +51,22 @@ const useTimeRange = (timestamp: string) => { return { timeRange, setTimeRange, setPartialTimeRange }; }; -const useGraphData = (eventIds: string[], timeRange: TimeRange, filter: { bool: BoolQuery }) => { +const useGraphData = ( + eventIds: string[], + isAlert: boolean, + timeRange: TimeRange, + filter: { bool: BoolQuery } +) => { const { data, refresh, isFetching } = useFetchGraphData({ req: { query: { - eventIds, + eventIds: isAlert ? eventIds : [], esQuery: filter, start: timeRange.from, end: timeRange.to, }, + nodesLimit: 50, + showUnknownTarget: false, }, options: { refetchOnWindowFocus: false, @@ -169,7 +180,7 @@ export const GraphVisualization: React.FC = memo(() => { }); const [searchFilters, setSearchFilters] = useState(() => []); const { getFieldsData, dataAsNestedObject } = useDocumentDetailsContext(); - const { eventIds, timestamp } = useGraphPreview({ + const { eventIds, isAlert, timestamp } = useGraphPreview({ getFieldsData, ecsData: dataAsNestedObject, }); @@ -183,7 +194,9 @@ export const GraphVisualization: React.FC = memo(() => { buildEsQuery( dataView, [], - [...searchFilters], + isAlert + ? [...searchFilters] + : addFilter(dataView?.id ?? '', searchFilters, 'event.id', eventIds[0]), getEsQueryConfig(uiSettings as Parameters[0]) ) ); @@ -193,11 +206,13 @@ export const GraphVisualization: React.FC = memo(() => { buildEsQuery( dataView, [], - [...searchFilters], + isAlert + ? [...searchFilters] + : addFilter(dataView?.id ?? '', searchFilters, 'event.id', eventIds[0]), getEsQueryConfig(uiSettings as Parameters[0]) ) ); - }, [searchFilters, dataView, uiSettings]); + }, [searchFilters, dataView, uiSettings, isAlert, eventIds]); const { nodeExpandPopover, popoverOpenWrapper } = useGraphPopovers( dataView?.id ?? '', @@ -206,8 +221,15 @@ export const GraphVisualization: React.FC = memo(() => { const expandButtonClickHandler = (...args: unknown[]) => popoverOpenWrapper(nodeExpandPopover.onNodeExpandButtonClick, ...args); const isPopoverOpen = [nodeExpandPopover].some(({ state: { isOpen } }) => isOpen); - const { data, refresh, isFetching } = useGraphData(eventIds, timeRange, query); + const { data, refresh, isFetching } = useGraphData(eventIds, isAlert, timeRange, query); const nodes = useGraphNodes(data?.nodes ?? [], expandButtonClickHandler); + const parsedTimeRange: TimeRange = useMemo(() => { + return { + ...timeRange, + from: dateMath.parse(timeRange.from), + to: dateMath.parse(timeRange.to), + }; + }, [timeRange]); return (
@@ -223,8 +245,8 @@ export const GraphVisualization: React.FC = memo(() => { showQueryInput: false, isLoading: isFetching, isAutoRefreshDisabled: true, - dateRangeFrom: timeRange.from.split('/')[0], - dateRangeTo: timeRange.to.split('/')[0], + dateRangeFrom: timeRange.from, + dateRangeTo: timeRange.to, query: { query: '', language: 'kuery' }, indexPatterns: [dataView], filters: searchFilters, @@ -242,6 +264,19 @@ export const GraphVisualization: React.FC = memo(() => { }} /> )} + + + { eventIds, timestamp = new Date().toISOString(), isAuditLog, + isAlert, } = useGraphPreview({ getFieldsData, ecsData: dataAsNestedObject, @@ -50,9 +51,10 @@ export const GraphPreviewContainer: React.FC = () => { const { isLoading, isError, data } = useFetchGraphData({ req: { query: { - eventIds, + eventIds: isAlert ? eventIds : [], start: `${timestamp}||-30m`, end: `${timestamp}||+30m`, + esQuery: !isAlert ? { bool: { filter: [{ terms: { 'event.id': eventIds } }] } } : undefined, }, }, options: { diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/shared/hooks/use_graph_preview.ts b/x-pack/plugins/security_solution/public/flyout/document_details/shared/hooks/use_graph_preview.ts index d41e905c80703..8f564d2c2438b 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/shared/hooks/use_graph_preview.ts +++ b/x-pack/plugins/security_solution/public/flyout/document_details/shared/hooks/use_graph_preview.ts @@ -6,6 +6,7 @@ */ import type { EcsSecurityExtension as Ecs } from '@kbn/securitysolution-ecs'; +import { ALERT_UUID } from '@kbn/rule-data-utils'; import { get } from 'lodash/fp'; import type { GetFieldsData } from './use_get_fields_data'; import { getField, getFieldArray } from '../utils'; @@ -54,6 +55,8 @@ export interface UseGraphPreviewResult { * Boolean indicating if the event is an audit log (contains event ids, actor ids and action) */ isAuditLog: boolean; + + isAlert: boolean; } /** @@ -77,6 +80,7 @@ export const useGraphPreview = ({ actorIds.length > 0 && eventIds.length > 0 && targetIds.length > 0; + const isAlert = Boolean(getFieldsData(ALERT_UUID)); - return { timestamp, eventIds, actorIds, action, targetIds, isAuditLog }; + return { timestamp, eventIds, actorIds, action, targetIds, isAuditLog, isAlert }; };