Skip to content

Commit

Permalink
Added timeline investigation, fixed coloring of events. Added node li…
Browse files Browse the repository at this point in the history
…mit, removed unknown targets
  • Loading branch information
kfirpeled committed Nov 21, 2024
1 parent c7fb622 commit 117b2ad
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ const determineEntityNodeShape = (
return { shape: 'diamond', icon: 'globe' };
}

return { shape: 'hexagon', icon: 'questionInCircle' };
return { shape: 'hexagon', icon: '' };
};

const sortNodes = (nodesMap: Record<string, NodeDataModel>) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,6 @@ export const GraphNodeExpandPopover: React.FC<GraphNodeExpandPopoverProps> = mem
data-test-subj="graphNodeExpandPopover"
>
<EuiListGroup gutterSize="none" bordered={false} flush={true}>
<ExpandPopoverListItem
iconType="visTagCloud"
label={i18n.translate(
'xpack.securitySolution.flyout.documentDetails.left.graphNodeExpandPopover.exploreRelatedEntities',
{ defaultMessage: 'Explore related entities' }
)}
onClick={onExploreRelatedEntitiesClick}
data-test-subj={GRAPH_NODE_POPOVER_EXPLORE_RELATED_ITEM_ID}
/>
<ExpandPopoverListItem
iconType="users"
label={i18n.translate(
Expand All @@ -71,6 +62,15 @@ export const GraphNodeExpandPopover: React.FC<GraphNodeExpandPopoverProps> = mem
onClick={onShowActionsOnEntityClick}
data-test-subj={GRAPH_NODE_POPOVER_SHOW_ACTIONS_ON_ITEM_ID}
/>
<ExpandPopoverListItem
iconType="visTagCloud"
label={i18n.translate(
'xpack.securitySolution.flyout.documentDetails.left.graphNodeExpandPopover.exploreRelatedEntities',
{ defaultMessage: 'Explore related entities' }
)}
onClick={onExploreRelatedEntitiesClick}
data-test-subj={GRAPH_NODE_POPOVER_EXPLORE_RELATED_ITEM_ID}
/>
</EuiListGroup>
</GraphPopover>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -169,7 +180,7 @@ export const GraphVisualization: React.FC = memo(() => {
});
const [searchFilters, setSearchFilters] = useState<Filter[]>(() => []);
const { getFieldsData, dataAsNestedObject } = useDocumentDetailsContext();
const { eventIds, timestamp } = useGraphPreview({
const { eventIds, isAlert, timestamp } = useGraphPreview({
getFieldsData,
ecsData: dataAsNestedObject,
});
Expand All @@ -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<typeof getEsQueryConfig>[0])
)
);
Expand All @@ -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<typeof getEsQueryConfig>[0])
)
);
}, [searchFilters, dataView, uiSettings]);
}, [searchFilters, dataView, uiSettings, isAlert, eventIds]);

const { nodeExpandPopover, popoverOpenWrapper } = useGraphPopovers(
dataView?.id ?? '',
Expand All @@ -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 (
<div data-test-subj={GRAPH_VISUALIZATION_TEST_ID}>
Expand All @@ -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,
Expand All @@ -242,6 +264,19 @@ export const GraphVisualization: React.FC = memo(() => {
}}
/>
)}
<InvestigateInTimelineButton
asEmptyButton
dataProviders={[]}
filters={addFilter(dataView?.id ?? '', searchFilters, 'event.id', eventIds[0])}
keepDataView
iconType={'timeline'}
timeRange={{ ...normalizeTimeRange(parsedTimeRange), kind: 'absolute' }}
>
<FormattedMessage
id="xpack.securitySolution.flyout.documentDetails.left.graphVisualization.investigateInTimelineButtonLabel"
defaultMessage="Investigate in Timeline"
/>
</InvestigateInTimelineButton>
<React.Suspense fallback={null}>
<GraphLazy
css={css`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export const GraphPreviewContainer: React.FC = () => {
eventIds,
timestamp = new Date().toISOString(),
isAuditLog,
isAlert,
} = useGraphPreview({
getFieldsData,
ecsData: dataAsNestedObject,
Expand All @@ -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: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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;
}

/**
Expand All @@ -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 };
};

0 comments on commit 117b2ad

Please sign in to comment.