-
Notifications
You must be signed in to change notification settings - Fork 8.5k
Pin individual entities in graph #251299
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Pin individual entities in graph #251299
Changes from 1 commit
a420be2
3dd196b
88fb679
02d0607
22c50a4
9a635bb
073c9b2
f957495
c15f8ec
daaaf90
dc28d49
506c58c
bf53bcf
fba883f
4849924
1bd8bc0
502894d
104c2f7
b24b6da
6bb04bc
0550c0b
00bf4a7
f4af09c
a269bbe
c7fbe32
abe1c09
90fd0f4
652f449
2f51c5a
e0c0bdd
5a4f749
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,6 +17,10 @@ import { Panel } from '@xyflow/react'; | |
| import { getEsQueryConfig } from '@kbn/data-service'; | ||
| import { EuiFlexGroup, EuiFlexItem, EuiProgress } from '@elastic/eui'; | ||
| import useSessionStorage from 'react-use/lib/useSessionStorage'; | ||
| import { | ||
| GRAPH_ACTOR_ENTITY_FIELDS, | ||
| GRAPH_TARGET_ENTITY_FIELDS, | ||
| } from '@kbn/cloud-security-posture-common/constants'; | ||
| import { Graph, isEntityNode, type NodeProps } from '../../..'; | ||
| import { Callout } from '../callout/callout'; | ||
| import { type UseFetchGraphDataParams, useFetchGraphData } from '../../hooks/use_fetch_graph_data'; | ||
|
|
@@ -30,7 +34,11 @@ import { analyzeDocuments } from '../node/label_node/analyze_documents'; | |
| import { EVENT_ID, GRAPH_NODES_LIMIT, TOGGLE_SEARCH_BAR_STORAGE_KEY } from '../../common/constants'; | ||
| import { Actions } from '../controls/actions'; | ||
| import { AnimatedSearchBarContainer, useBorder } from './styles'; | ||
| import { CONTROLLED_BY_GRAPH_INVESTIGATION_FILTER, addFilter } from './search_filters'; | ||
| import { | ||
| CONTROLLED_BY_GRAPH_INVESTIGATION_FILTER, | ||
| addFilter, | ||
| getFilterValues, | ||
| } from './search_filters'; | ||
| import { useEntityNodeExpandPopover } from '../popovers/node_expand/use_entity_node_expand_popover'; | ||
| import { useLabelNodeExpandPopover } from '../popovers/node_expand/use_label_node_expand_popover'; | ||
| import type { NodeViewModel } from '../types'; | ||
|
|
@@ -284,6 +292,13 @@ export const GraphInvestigation = memo<GraphInvestigationProps>( | |
| return lastValidEsQuery.current; | ||
| }, [dataView, kquery, notifications, searchFilters, uiSettings]); | ||
|
|
||
| const pinnedEntities = useMemo(() => { | ||
| return getFilterValues(searchFilters, [ | ||
| ...GRAPH_ACTOR_ENTITY_FIELDS, | ||
| ...GRAPH_TARGET_ENTITY_FIELDS, | ||
| ]).map(String); | ||
|
Comment on lines
+296
to
+299
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Reads all kinds of entity IDs from applied filters (
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Changed to
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is a nice workaround, but it is a workaround. Since we don't have design yet for pinning an event. From your work here, I assume that if we had the ability to pin an event/alert we will add a filter of _id: eventDocId/alertDocId That filter is really adds anything to the graph, except for pinning the node. So that's why it is a workaround for a missing pinning capability. Just be aware that we haven't discussed it yet, to add a filter in order to pin a node. While it is true for actors and targets, it is not true for alert and event. We previously did it for POC purposes, but it wasn't a requirement |
||
| }, [searchFilters]); | ||
|
|
||
| const { data, refresh, isFetching, isError, error } = useFetchGraphData({ | ||
| req: { | ||
| query: { | ||
|
|
@@ -294,6 +309,7 @@ export const GraphInvestigation = memo<GraphInvestigationProps>( | |
| end: timeRange.to, | ||
| }, | ||
| nodesLimit: GRAPH_NODES_LIMIT, | ||
| pinnedEntityIds: pinnedEntities, | ||
| }, | ||
| options: { | ||
| refetchOnWindowFocus: false, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -39,6 +39,7 @@ interface BuildEsqlQueryParams { | |
| isEnrichPolicyExists: boolean; | ||
| spaceId: string; | ||
| alertsMappingsIncluded: boolean; | ||
| pinnedEntityIds?: string[]; | ||
| } | ||
|
|
||
| export const fetchGraph = async ({ | ||
|
|
@@ -51,6 +52,7 @@ export const fetchGraph = async ({ | |
| indexPatterns, | ||
| spaceId, | ||
| esQuery, | ||
| pinnedEntityIds, | ||
| }: { | ||
| esClient: IScopedClusterClient; | ||
| logger: Logger; | ||
|
|
@@ -61,6 +63,7 @@ export const fetchGraph = async ({ | |
| indexPatterns: string[]; | ||
| spaceId: string; | ||
| esQuery?: EsQuery; | ||
| pinnedEntityIds?: string[]; | ||
| }): Promise<EsqlToRecords<GraphEdge>> => { | ||
| const originAlertIds = originEventIds.filter((originEventId) => originEventId.isAlert); | ||
|
|
||
|
|
@@ -93,6 +96,7 @@ export const fetchGraph = async ({ | |
| isEnrichPolicyExists, | ||
| spaceId, | ||
| alertsMappingsIncluded, | ||
| pinnedEntityIds, | ||
| }); | ||
|
|
||
| logger.trace(`Executing query [${query}]`); | ||
|
|
@@ -109,6 +113,7 @@ export const fetchGraph = async ({ | |
| ...originEventIds | ||
| .filter((originEventId) => originEventId.isAlert) | ||
| .map((originEventId, idx) => ({ [`og_alrt_id${idx}`]: originEventId.id })), | ||
| ...(pinnedEntityIds ?? []).map((id, idx) => ({ [`pinned_id${idx}`]: id })), | ||
| ], | ||
| }) | ||
| .toRecords<GraphEdge>(); | ||
|
|
@@ -282,6 +287,7 @@ const buildEsqlQuery = ({ | |
| isEnrichPolicyExists, | ||
| spaceId, | ||
| alertsMappingsIncluded, | ||
| pinnedEntityIds, | ||
| }: BuildEsqlQueryParams): string => { | ||
| const SECURITY_ALERTS_PARTIAL_IDENTIFIER = '.alerts-security.alerts-'; | ||
| const enrichPolicyName = getEnrichPolicyId(spaceId); | ||
|
|
@@ -312,6 +318,21 @@ const buildEsqlQuery = ({ | |
| const actorFieldHintCases = generateFieldHintCases(GRAPH_ACTOR_ENTITY_FIELDS, 'actorEntityId'); | ||
| const targetFieldHintCases = generateFieldHintCases(GRAPH_TARGET_ENTITY_FIELDS, 'targetEntityId'); | ||
|
|
||
| // Generate pinned entity evaluation | ||
| // This checks if the current actor or target entity ID matches any of the pinned entity IDs | ||
| const pinnedEntityEval = | ||
| pinnedEntityIds && pinnedEntityIds.length > 0 | ||
| ? `| EVAL pinned = CASE( | ||
albertoblaz marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| actorEntityId IN (${pinnedEntityIds | ||
| .map((_id, idx) => `?pinned_id${idx}`) | ||
| .join(', ')}), actorEntityId, | ||
| targetEntityId IN (${pinnedEntityIds | ||
| .map((_id, idx) => `?pinned_id${idx}`) | ||
| .join(', ')}), targetEntityId, | ||
| null | ||
| )` | ||
| : '| EVAL pinned = TO_STRING(null)'; | ||
|
||
|
|
||
albertoblaz marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| const query = `FROM ${indexPatterns | ||
| .filter((indexPattern) => indexPattern.length > 0) | ||
| .join(',')} METADATA _id, _index | ||
|
|
@@ -325,6 +346,7 @@ const buildEsqlQuery = ({ | |
| ${targetEntityIdEvals} | ||
| | MV_EXPAND actorEntityId | ||
| | MV_EXPAND targetEntityId | ||
| ${pinnedEntityEval} | ||
| | EVAL actorEntityFieldHint = CASE( | ||
| ${actorFieldHintCases}, | ||
| "" | ||
|
|
@@ -452,7 +474,8 @@ ${buildEnrichedEntityFieldsEsql()} | |
| targetEntityType, | ||
| targetEntitySubType, | ||
| isOrigin, | ||
| isOriginAlert | ||
| isOriginAlert, | ||
| pinned | ||
albertoblaz marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| | LIMIT 1000 | ||
| | SORT action DESC, isOrigin`; | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.