diff --git a/x-pack/plugins/security_solution/public/entity_analytics/components/risk_summary_flyout/risk_summary.test.tsx b/x-pack/plugins/security_solution/public/entity_analytics/components/risk_summary_flyout/risk_summary.test.tsx index 5862ac7cd946..81a9159a4f44 100644 --- a/x-pack/plugins/security_solution/public/entity_analytics/components/risk_summary_flyout/risk_summary.test.tsx +++ b/x-pack/plugins/security_solution/public/entity_analytics/components/risk_summary_flyout/risk_summary.test.tsx @@ -5,6 +5,7 @@ * 2.0. */ +import { RiskScoreEntity } from '../../../../common/entity_analytics/risk_engine/types'; import { render } from '@testing-library/react'; import React from 'react'; import { TestProviders } from '../../../common/mock'; @@ -21,6 +22,7 @@ describe('RiskSummary', () => { riskScoreData={mockRiskScoreState} queryId={'testQuery'} openDetailsPanel={() => {}} + entity={RiskScoreEntity.user} /> ); @@ -37,6 +39,7 @@ describe('RiskSummary', () => { riskScoreData={{ ...mockRiskScoreState, data: undefined }} queryId={'testQuery'} openDetailsPanel={() => {}} + entity={RiskScoreEntity.user} /> ); @@ -50,6 +53,7 @@ describe('RiskSummary', () => { riskScoreData={mockRiskScoreState} queryId={'testQuery'} openDetailsPanel={() => {}} + entity={RiskScoreEntity.user} /> ); @@ -64,6 +68,7 @@ describe('RiskSummary', () => { riskScoreData={mockRiskScoreState} queryId={'testQuery'} openDetailsPanel={() => {}} + entity={RiskScoreEntity.user} /> ); diff --git a/x-pack/plugins/security_solution/public/entity_analytics/components/risk_summary_flyout/risk_summary.tsx b/x-pack/plugins/security_solution/public/entity_analytics/components/risk_summary_flyout/risk_summary.tsx index 50259cd6ca13..fdb5b8559f7b 100644 --- a/x-pack/plugins/security_solution/public/entity_analytics/components/risk_summary_flyout/risk_summary.tsx +++ b/x-pack/plugins/security_solution/public/entity_analytics/components/risk_summary_flyout/risk_summary.tsx @@ -21,7 +21,11 @@ import { css } from '@emotion/react'; import { FormattedMessage } from '@kbn/i18n-react'; import { euiThemeVars } from '@kbn/ui-theme'; import { i18n } from '@kbn/i18n'; -import { UserDetailsLeftPanelTab } from '../../../flyout/entity_details/user_details_left/tabs'; +import { EntityDetailsLeftPanelTab } from '../../../flyout/entity_details/shared/components/left_panel/left_panel_header'; +import type { + HostRiskScore, + UserRiskScore, +} from '../../../../common/search_strategy/security_solution/risk_score'; import { InspectButton, InspectButtonContainer } from '../../../common/components/inspect'; import { ONE_WEEK_IN_HOURS } from '../../../timelines/components/side_panel/new_user_detail/constants'; import { FormattedRelativePreferenceDate } from '../../../common/components/formatted_date'; @@ -31,10 +35,11 @@ import { ExpandablePanel } from '../../../flyout/shared/components/expandable_pa import type { RiskScoreState } from '../../api/hooks/use_risk_score'; import { getRiskScoreSummaryAttributes } from '../../lens_attributes/risk_score_summary'; -export interface RiskSummaryProps { - riskScoreData: RiskScoreState; +export interface RiskSummaryProps { + riskScoreData: RiskScoreState; queryId: string; - openDetailsPanel: (tab: UserDetailsLeftPanelTab) => void; + openDetailsPanel: (tab: EntityDetailsLeftPanelTab) => void; + entity: T; } interface TableItem { @@ -44,203 +49,214 @@ interface TableItem { const LENS_VISUALIZATION_HEIGHT = 126; // Static height in pixels specified by design const LAST_30_DAYS = { from: 'now-30d', to: 'now' }; -export const RiskSummary = React.memo( - ({ riskScoreData, queryId, openDetailsPanel }: RiskSummaryProps) => { - const { data: userRisk } = riskScoreData; - const userRiskData = userRisk && userRisk.length > 0 ? userRisk[0] : undefined; - const { euiTheme } = useEuiTheme(); +const RiskSummaryComponent = ({ + riskScoreData, + queryId, + openDetailsPanel, + entity, +}: RiskSummaryProps) => { + const { data } = riskScoreData; + const riskData = data && data.length > 0 ? data[0] : undefined; + const { euiTheme } = useEuiTheme(); - const lensAttributes = useMemo(() => { - return getRiskScoreSummaryAttributes({ - severity: userRiskData?.user?.risk?.calculated_level, - query: `user.name: ${userRiskData?.user?.name}`, - spaceId: 'default', - riskEntity: RiskScoreEntity.user, - }); - }, [userRiskData]); + const entityData = (() => { + if (!riskData) return; + if (entity === RiskScoreEntity.user) return (riskData as UserRiskScore).user; + if (entity === RiskScoreEntity.host) return (riskData as HostRiskScore).host; + })(); - const columns: Array> = useMemo( - () => [ - { - field: 'category', - name: ( + const lensAttributes = useMemo(() => { + return getRiskScoreSummaryAttributes({ + severity: entityData?.risk?.calculated_level, + query: `user.name: ${entityData?.name}`, + spaceId: 'default', + riskEntity: RiskScoreEntity.user, + }); + }, [entityData]); + + const columns: Array> = useMemo( + () => [ + { + field: 'category', + name: ( + + ), + truncateText: false, + mobileOptions: { show: true }, + sortable: true, + }, + { + field: 'count', + name: ( + + ), + truncateText: false, + mobileOptions: { show: true }, + sortable: true, + dataType: 'number', + }, + ], + [] + ); + + const xsFontSize = useEuiFontSize('xxs').fontSize; + + const items: TableItem[] = useMemo( + () => [ + { + category: i18n.translate('xpack.securitySolution.flyout.entityDetails.alertsGroupLabel', { + defaultMessage: 'Alerts', + }), + count: entityData?.risk.inputs?.length ?? 0, + }, + ], + [entityData?.risk.inputs?.length] + ); + + return ( + +

- ), - truncateText: false, - mobileOptions: { show: true }, - sortable: true, - }, - { - field: 'count', - name: ( +

+ + } + extraAction={ + + {riskData && ( + ), + }} /> - ), - truncateText: false, - mobileOptions: { show: true }, - sortable: true, - dataType: 'number', - }, - ], - [] - ); - - const xsFontSize = useEuiFontSize('xxs').fontSize; - - const items: TableItem[] = useMemo( - () => [ - { - category: i18n.translate('xpack.securitySolution.flyout.entityDetails.alertsGroupLabel', { - defaultMessage: 'Alerts', - }), - count: userRiskData?.user.risk.inputs?.length ?? 0, - }, - ], - [userRiskData?.user.risk.inputs?.length] - ); + )} + + } + > + - return ( - -

- -

- - } - extraAction={ - - {userRiskData && ( - - ), - }} - /> - )} - - } - > - - - + ), + link: { + callback: () => openDetailsPanel(EntityDetailsLeftPanelTab.RISK_INPUTS), + tooltip: ( ), - link: { - callback: () => openDetailsPanel(UserDetailsLeftPanelTab.RISK_INPUTS), - tooltip: ( - + + +
+ {riskData && ( + + } /> - ), - }, - iconType: 'arrowStart', - }} - expand={{ - expandable: false, - }} - > - - + )} +
+
+ +
- {userRiskData && ( - - } - /> - )} -
-
- -
-
- - } - /> -
- + } />
-
-
-
-
- -
- ); - } -); + + + + + + + +
+ ); +}; + +export const RiskSummary = React.memo(RiskSummaryComponent); RiskSummary.displayName = 'RiskSummary'; diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/content.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/content.tsx index 4a5ddcb3f181..ac8416ac2518 100644 --- a/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/content.tsx +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/content.tsx @@ -8,13 +8,16 @@ import { EuiHorizontalRule } from '@elastic/eui'; import React from 'react'; +import { RiskSummary } from '../../../entity_analytics/components/risk_summary_flyout/risk_summary'; import type { RiskScoreState } from '../../../entity_analytics/api/hooks/use_risk_score'; -import type { HostItem, RiskScoreEntity } from '../../../../common/search_strategy'; +import { RiskScoreEntity } from '../../../../common/search_strategy'; +import type { HostItem } from '../../../../common/search_strategy'; import { FlyoutBody } from '../../shared/components/flyout_body'; import { ObservedEntity } from '../shared/components/observed_entity'; -import { HOST_PANEL_OBSERVED_HOST_QUERY_ID } from '.'; +import { HOST_PANEL_OBSERVED_HOST_QUERY_ID, HOST_PANEL_RISK_SCORE_QUERY_ID } from '.'; import type { ObservedEntityData } from '../shared/components/observed_entity/types'; import { useObservedHostFields } from './hooks/use_observed_host_fields'; +import type { EntityDetailsLeftPanelTab } from '../shared/components/left_panel/left_panel_header'; interface HostPanelContentProps { observedHost: ObservedEntityData; @@ -22,6 +25,7 @@ interface HostPanelContentProps { contextID: string; scopeId: string; isDraggable: boolean; + openDetailsPanel: (tab: EntityDetailsLeftPanelTab) => void; } export const HostPanelContent = ({ @@ -30,6 +34,7 @@ export const HostPanelContent = ({ contextID, scopeId, isDraggable, + openDetailsPanel, }: HostPanelContentProps) => { const observedFields = useObservedHostFields(observedHost); @@ -37,7 +42,14 @@ export const HostPanelContent = ({ {riskScoreState.isModuleEnabled && riskScoreState.data?.length !== 0 && ( <> - {/* TODO */} + { + + } )} diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/index.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/index.tsx index 9f63328219a4..783a9ce59838 100644 --- a/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/index.tsx +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/index.tsx @@ -8,6 +8,7 @@ import React, { useCallback, useMemo } from 'react'; import type { FlyoutPanelProps } from '@kbn/expandable-flyout'; import { useExpandableFlyoutContext } from '@kbn/expandable-flyout'; + import { hostToCriteria } from '../../../common/components/ml/criteria/host_to_criteria'; import { useRiskScore } from '../../../entity_analytics/api/hooks/use_risk_score'; import { useQueryInspector } from '../../../common/components/page/manage_query'; @@ -23,6 +24,7 @@ import { AnomalyTableProvider } from '../../../common/components/ml/anomaly/anom import type { ObservedEntityData } from '../shared/components/observed_entity/types'; import { useObservedHost } from './hooks/use_observed_host'; import { HostDetailsPanelKey } from '../host_details_left'; +import type { EntityDetailsLeftPanelTab } from '../shared/components/left_panel/left_panel_header'; export interface HostPanelProps extends Record { contextID: string; @@ -72,17 +74,25 @@ export const HostPanel = ({ contextID, scopeId, hostName, isDraggable }: HostPan setQuery, }); - const openPanel = useCallback(() => { - openLeftPanel({ - id: HostDetailsPanelKey, - params: { - riskInputs: { - alertIds: hostRiskData?.host.risk.inputs?.map(({ id }) => id) ?? [], + const openTabPanel = useCallback( + (tab?: EntityDetailsLeftPanelTab) => { + openLeftPanel({ + id: HostDetailsPanelKey, + params: { + riskInputs: { + alertIds: hostRiskData?.host.risk.inputs?.map(({ id }) => id) ?? [], + host: { + name: hostName, + }, + }, + path: tab ? { tab } : undefined, }, - }, - }); - }, [openLeftPanel, hostRiskData?.host.risk.inputs]); + }); + }, + [openLeftPanel, hostRiskData?.host.risk.inputs, hostName] + ); + const openDefaultPanel = useCallback(() => openTabPanel(), [openTabPanel]); const observedHost = useObservedHost(hostName); if (riskScoreState.loading || observedHost.isLoading) { @@ -110,7 +120,7 @@ export const HostPanel = ({ contextID, scopeId, hostName, isDraggable }: HostPan <> ); diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/content.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/content.tsx index f1f7916d3907..7cfff92b0242 100644 --- a/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/content.tsx +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/content.tsx @@ -13,7 +13,8 @@ import { RiskSummary } from '../../../entity_analytics/components/risk_summary_f import type { RiskScoreState } from '../../../entity_analytics/api/hooks/use_risk_score'; import { ManagedUser } from '../../../timelines/components/side_panel/new_user_detail/managed_user'; import type { ManagedUserData } from '../../../timelines/components/side_panel/new_user_detail/types'; -import type { RiskScoreEntity, UserItem } from '../../../../common/search_strategy'; +import { RiskScoreEntity } from '../../../../common/search_strategy'; +import type { UserItem } from '../../../../common/search_strategy'; import { USER_PANEL_RISK_SCORE_QUERY_ID } from '.'; import { FlyoutBody } from '../../shared/components/flyout_body'; import { ObservedEntity } from '../shared/components/observed_entity'; @@ -50,6 +51,7 @@ export const UserPanelContent = ({ riskScoreData={riskScoreState} queryId={USER_PANEL_RISK_SCORE_QUERY_ID} openDetailsPanel={openDetailsPanel} + entity={RiskScoreEntity.user} />