mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[Cloud Security] Refactor Contextual Flyout (#200291)
## Summary This PR is for reducing code duplication by Encapsulating Hooks, Functions, constants that are used multiple times in a same manner accross multiple files --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Maxim Kholod <maxim.kholod@elastic.co>
This commit is contained in:
parent
1fea109ecc
commit
c842db549a
21 changed files with 360 additions and 463 deletions
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { buildEntityFlyoutPreviewQuery } from '@kbn/cloud-security-posture-common';
|
||||
import { useMisconfigurationPreview } from './use_misconfiguration_preview';
|
||||
|
||||
export const useHasMisconfigurations = (field: 'host.name' | 'user.name', value: string) => {
|
||||
const { data } = useMisconfigurationPreview({
|
||||
query: buildEntityFlyoutPreviewQuery(field, value),
|
||||
sort: [],
|
||||
enabled: true,
|
||||
pageSize: 1,
|
||||
});
|
||||
|
||||
const passedFindings = data?.count.passed || 0;
|
||||
const failedFindings = data?.count.failed || 0;
|
||||
|
||||
const hasMisconfigurationFindings = passedFindings > 0 || failedFindings > 0;
|
||||
|
||||
return {
|
||||
passedFindings,
|
||||
failedFindings,
|
||||
hasMisconfigurationFindings,
|
||||
};
|
||||
};
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { buildEntityFlyoutPreviewQuery } from '@kbn/cloud-security-posture-common';
|
||||
import { useVulnerabilitiesPreview } from './use_vulnerabilities_preview';
|
||||
import { hasVulnerabilitiesData } from '../utils/vulnerability_helpers';
|
||||
|
||||
export const useHasVulnerabilities = (field: 'host.name' | 'user.name', value: string) => {
|
||||
const { data: vulnerabilitiesData } = useVulnerabilitiesPreview({
|
||||
query: buildEntityFlyoutPreviewQuery(field, value),
|
||||
sort: [],
|
||||
enabled: true,
|
||||
pageSize: 1,
|
||||
});
|
||||
|
||||
const {
|
||||
CRITICAL = 0,
|
||||
HIGH = 0,
|
||||
MEDIUM = 0,
|
||||
LOW = 0,
|
||||
NONE = 0,
|
||||
} = vulnerabilitiesData?.count || {};
|
||||
|
||||
const counts = {
|
||||
critical: CRITICAL,
|
||||
high: HIGH,
|
||||
medium: MEDIUM,
|
||||
low: LOW,
|
||||
none: NONE,
|
||||
};
|
||||
|
||||
const hasVulnerabilitiesFindings = hasVulnerabilitiesData(counts);
|
||||
|
||||
return { counts, hasVulnerabilitiesFindings };
|
||||
};
|
|
@ -58,7 +58,7 @@ describe('AlertsPreview', () => {
|
|||
it('renders', () => {
|
||||
const { getByTestId } = render(
|
||||
<TestProviders>
|
||||
<AlertsPreview alertsData={mockAlertsData} name="host1" fieldName="host.name" />
|
||||
<AlertsPreview alertsData={mockAlertsData} value="host1" field="host.name" />
|
||||
</TestProviders>
|
||||
);
|
||||
|
||||
|
@ -68,7 +68,7 @@ describe('AlertsPreview', () => {
|
|||
it('renders correct alerts number', () => {
|
||||
const { getByTestId } = render(
|
||||
<TestProviders>
|
||||
<AlertsPreview alertsData={mockAlertsData} name="host1" fieldName="host.name" />
|
||||
<AlertsPreview alertsData={mockAlertsData} value="host1" field="host.name" />
|
||||
</TestProviders>
|
||||
);
|
||||
|
||||
|
@ -78,7 +78,7 @@ describe('AlertsPreview', () => {
|
|||
it('should render the correct number of distribution bar section based on the number of severities', () => {
|
||||
const { queryAllByTestId } = render(
|
||||
<TestProviders>
|
||||
<AlertsPreview alertsData={mockAlertsData} name="host1" fieldName="host.name" />
|
||||
<AlertsPreview alertsData={mockAlertsData} value="host1" field="host.name" />
|
||||
</TestProviders>
|
||||
);
|
||||
|
||||
|
|
|
@ -5,40 +5,21 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import React, { useMemo } from 'react';
|
||||
import { capitalize } from 'lodash';
|
||||
import type { EuiThemeComputed } from '@elastic/eui';
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText, EuiTitle, useEuiTheme } from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { DistributionBar } from '@kbn/security-solution-distribution-bar';
|
||||
import {
|
||||
buildEntityFlyoutPreviewQuery,
|
||||
getAbbreviatedNumber,
|
||||
} from '@kbn/cloud-security-posture-common';
|
||||
import { hasVulnerabilitiesData } from '@kbn/cloud-security-posture';
|
||||
import { useMisconfigurationPreview } from '@kbn/cloud-security-posture/src/hooks/use_misconfiguration_preview';
|
||||
import { useVulnerabilitiesPreview } from '@kbn/cloud-security-posture/src/hooks/use_vulnerabilities_preview';
|
||||
import { useExpandableFlyoutApi } from '@kbn/expandable-flyout';
|
||||
import { getAbbreviatedNumber } from '@kbn/cloud-security-posture-common';
|
||||
import type {
|
||||
AlertsByStatus,
|
||||
ParsedAlertsData,
|
||||
} from '../../../overview/components/detection_response/alerts_by_status/types';
|
||||
import { ExpandablePanel } from '../../../flyout/shared/components/expandable_panel';
|
||||
import { getSeverityColor } from '../../../detections/components/alerts_kpis/severity_level_panel/helpers';
|
||||
import type { HostRiskScore, UserRiskScore } from '../../../../common/search_strategy';
|
||||
import {
|
||||
buildHostNamesFilter,
|
||||
buildUserNamesFilter,
|
||||
RiskScoreEntity,
|
||||
} from '../../../../common/search_strategy';
|
||||
import { useRiskScore } from '../../../entity_analytics/api/hooks/use_risk_score';
|
||||
import { FIRST_RECORD_PAGINATION } from '../../../entity_analytics/common';
|
||||
import { HostDetailsPanelKey } from '../../../flyout/entity_details/host_details_left';
|
||||
import {
|
||||
EntityDetailsLeftPanelTab,
|
||||
CspInsightLeftPanelSubTab,
|
||||
} from '../../../flyout/entity_details/shared/components/left_panel/left_panel_header';
|
||||
import { UserDetailsPanelKey } from '../../../flyout/entity_details/user_details_left';
|
||||
import { CspInsightLeftPanelSubTab } from '../../../flyout/entity_details/shared/components/left_panel/left_panel_header';
|
||||
import { useNavigateEntityInsight } from '../../hooks/use_entity_insight';
|
||||
|
||||
const AlertsCount = ({
|
||||
alertsTotal,
|
||||
|
@ -77,13 +58,13 @@ const AlertsCount = ({
|
|||
|
||||
export const AlertsPreview = ({
|
||||
alertsData,
|
||||
fieldName,
|
||||
name,
|
||||
field,
|
||||
value,
|
||||
isPreviewMode,
|
||||
}: {
|
||||
alertsData: ParsedAlertsData;
|
||||
fieldName: string;
|
||||
name: string;
|
||||
field: 'host.name' | 'user.name';
|
||||
value: string;
|
||||
isPreviewMode?: boolean;
|
||||
}) => {
|
||||
const { euiTheme } = useEuiTheme();
|
||||
|
@ -107,101 +88,14 @@ export const AlertsPreview = ({
|
|||
|
||||
const totalAlertsCount = alertStats.reduce((total, item) => total + item.count, 0);
|
||||
|
||||
const { data } = useMisconfigurationPreview({
|
||||
query: buildEntityFlyoutPreviewQuery(fieldName, name),
|
||||
sort: [],
|
||||
enabled: true,
|
||||
pageSize: 1,
|
||||
ignore_unavailable: true,
|
||||
});
|
||||
const isUsingHostName = fieldName === 'host.name';
|
||||
const passedFindings = data?.count.passed || 0;
|
||||
const failedFindings = data?.count.failed || 0;
|
||||
|
||||
const hasMisconfigurationFindings = passedFindings > 0 || failedFindings > 0;
|
||||
|
||||
const { data: vulnerabilitiesData } = useVulnerabilitiesPreview({
|
||||
query: buildEntityFlyoutPreviewQuery('host.name', name),
|
||||
sort: [],
|
||||
enabled: true,
|
||||
pageSize: 1,
|
||||
});
|
||||
|
||||
const {
|
||||
CRITICAL = 0,
|
||||
HIGH = 0,
|
||||
MEDIUM = 0,
|
||||
LOW = 0,
|
||||
NONE = 0,
|
||||
} = vulnerabilitiesData?.count || {};
|
||||
|
||||
const hasVulnerabilitiesFindings = hasVulnerabilitiesData({
|
||||
critical: CRITICAL,
|
||||
high: HIGH,
|
||||
medium: MEDIUM,
|
||||
low: LOW,
|
||||
none: NONE,
|
||||
});
|
||||
|
||||
const buildFilterQuery = useMemo(
|
||||
() => (isUsingHostName ? buildHostNamesFilter([name]) : buildUserNamesFilter([name])),
|
||||
[isUsingHostName, name]
|
||||
);
|
||||
|
||||
const riskScoreState = useRiskScore({
|
||||
riskEntity: isUsingHostName ? RiskScoreEntity.host : RiskScoreEntity.user,
|
||||
filterQuery: buildFilterQuery,
|
||||
onlyLatest: false,
|
||||
pagination: FIRST_RECORD_PAGINATION,
|
||||
});
|
||||
|
||||
const { data: hostRisk } = riskScoreState;
|
||||
|
||||
const riskData = hostRisk?.[0];
|
||||
|
||||
const isRiskScoreExist = isUsingHostName
|
||||
? !!(riskData as HostRiskScore)?.host.risk
|
||||
: !!(riskData as UserRiskScore)?.user.risk;
|
||||
|
||||
const hasNonClosedAlerts = totalAlertsCount > 0;
|
||||
|
||||
const { openLeftPanel } = useExpandableFlyoutApi();
|
||||
|
||||
const goToEntityInsightTab = useCallback(() => {
|
||||
openLeftPanel({
|
||||
id: isUsingHostName ? HostDetailsPanelKey : UserDetailsPanelKey,
|
||||
params: isUsingHostName
|
||||
? {
|
||||
name,
|
||||
isRiskScoreExist,
|
||||
hasMisconfigurationFindings,
|
||||
hasVulnerabilitiesFindings,
|
||||
hasNonClosedAlerts,
|
||||
path: {
|
||||
tab: EntityDetailsLeftPanelTab.CSP_INSIGHTS,
|
||||
subTab: CspInsightLeftPanelSubTab.ALERTS,
|
||||
},
|
||||
}
|
||||
: {
|
||||
user: { name },
|
||||
isRiskScoreExist,
|
||||
hasMisconfigurationFindings,
|
||||
hasNonClosedAlerts,
|
||||
path: {
|
||||
tab: EntityDetailsLeftPanelTab.CSP_INSIGHTS,
|
||||
subTab: CspInsightLeftPanelSubTab.ALERTS,
|
||||
},
|
||||
},
|
||||
});
|
||||
}, [
|
||||
hasMisconfigurationFindings,
|
||||
hasNonClosedAlerts,
|
||||
hasVulnerabilitiesFindings,
|
||||
isRiskScoreExist,
|
||||
isUsingHostName,
|
||||
name,
|
||||
openLeftPanel,
|
||||
]);
|
||||
const { goToEntityInsightTab } = useNavigateEntityInsight({
|
||||
field,
|
||||
value,
|
||||
queryIdExtension: 'ALERTS_PREVIEW',
|
||||
subTab: CspInsightLeftPanelSubTab.ALERTS,
|
||||
});
|
||||
const link = useMemo(
|
||||
() =>
|
||||
!isPreviewMode
|
||||
|
|
|
@ -60,7 +60,7 @@ interface AlertsDetailsFields {
|
|||
}
|
||||
|
||||
export const AlertsDetailsTable = memo(
|
||||
({ fieldName, queryName }: { fieldName: 'host.name' | 'user.name'; queryName: string }) => {
|
||||
({ field, value }: { field: 'host.name' | 'user.name'; value: string }) => {
|
||||
useEffect(() => {
|
||||
uiMetricService.trackUiMetric(
|
||||
METRIC_TYPE.COUNT,
|
||||
|
@ -90,7 +90,7 @@ export const AlertsDetailsTable = memo(
|
|||
const { to, from } = useGlobalTime();
|
||||
const { signalIndexName } = useSignalIndex();
|
||||
const { data } = useQueryAlerts({
|
||||
query: buildEntityAlertsQuery(fieldName, to, from, queryName, 500),
|
||||
query: buildEntityAlertsQuery(field, to, from, value, 500),
|
||||
queryName: ALERTS_QUERY_NAMES.BY_RULE_BY_STATUS,
|
||||
indexName: signalIndexName,
|
||||
});
|
||||
|
@ -216,11 +216,11 @@ export const AlertsDetailsTable = memo(
|
|||
[
|
||||
{
|
||||
title:
|
||||
fieldName === 'host.name'
|
||||
field === 'host.name'
|
||||
? OPEN_IN_ALERTS_TITLE_HOSTNAME
|
||||
: OPEN_IN_ALERTS_TITLE_USERNAME,
|
||||
selectedOptions: [queryName],
|
||||
fieldName,
|
||||
selectedOptions: [value],
|
||||
fieldName: field,
|
||||
},
|
||||
{
|
||||
title: OPEN_IN_ALERTS_TITLE_STATUS,
|
||||
|
@ -230,7 +230,7 @@ export const AlertsDetailsTable = memo(
|
|||
],
|
||||
true
|
||||
),
|
||||
[fieldName, openAlertsPageWithFilters, queryName]
|
||||
[field, openAlertsPageWithFilters, value]
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
|
@ -42,7 +42,7 @@ function isCspFlyoutPanelProps(
|
|||
}
|
||||
|
||||
export const InsightsTabCsp = memo(
|
||||
({ name, fieldName }: { name: string; fieldName: 'host.name' | 'user.name' }) => {
|
||||
({ value, field }: { value: string; field: 'host.name' | 'user.name' }) => {
|
||||
const panels = useExpandableFlyoutState();
|
||||
|
||||
let hasMisconfigurationFindings = false;
|
||||
|
@ -150,11 +150,11 @@ export const InsightsTabCsp = memo(
|
|||
/>
|
||||
<EuiSpacer size="xl" />
|
||||
{activeInsightsId === CspInsightLeftPanelSubTab.MISCONFIGURATIONS ? (
|
||||
<MisconfigurationFindingsDetailsTable fieldName={fieldName} queryName={name} />
|
||||
<MisconfigurationFindingsDetailsTable field={field} value={value} />
|
||||
) : activeInsightsId === CspInsightLeftPanelSubTab.VULNERABILITIES ? (
|
||||
<VulnerabilitiesFindingsDetailsTable queryName={name} />
|
||||
<VulnerabilitiesFindingsDetailsTable value={value} />
|
||||
) : (
|
||||
<AlertsDetailsTable fieldName={fieldName} queryName={name} />
|
||||
<AlertsDetailsTable field={field} value={value} />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -59,7 +59,7 @@ const getFindingsStats = (passedFindingsStats: number, failedFindingsStats: numb
|
|||
* Insights view displayed in the document details expandable flyout left section
|
||||
*/
|
||||
export const MisconfigurationFindingsDetailsTable = memo(
|
||||
({ fieldName, queryName }: { fieldName: 'host.name' | 'user.name'; queryName: string }) => {
|
||||
({ field, value }: { field: 'host.name' | 'user.name'; value: string }) => {
|
||||
useEffect(() => {
|
||||
uiMetricService.trackUiMetric(
|
||||
METRIC_TYPE.COUNT,
|
||||
|
@ -68,7 +68,7 @@ export const MisconfigurationFindingsDetailsTable = memo(
|
|||
}, []);
|
||||
|
||||
const { data } = useMisconfigurationFindings({
|
||||
query: buildEntityFlyoutPreviewQuery(fieldName, queryName),
|
||||
query: buildEntityFlyoutPreviewQuery(field, value),
|
||||
sort: [],
|
||||
enabled: true,
|
||||
pageSize: 1,
|
||||
|
@ -183,7 +183,7 @@ export const MisconfigurationFindingsDetailsTable = memo(
|
|||
<EuiPanel hasShadow={false}>
|
||||
<SecuritySolutionLinkAnchor
|
||||
deepLinkId={SecurityPageName.cloudSecurityPostureFindings}
|
||||
path={`${getFindingsPageUrl(queryName, fieldName)}`}
|
||||
path={`${getFindingsPageUrl(value, field)}`}
|
||||
target={'_blank'}
|
||||
external={false}
|
||||
onClick={() => {
|
||||
|
|
|
@ -44,7 +44,7 @@ interface VulnerabilitiesPackage extends Vulnerability {
|
|||
};
|
||||
}
|
||||
|
||||
export const VulnerabilitiesFindingsDetailsTable = memo(({ queryName }: { queryName: string }) => {
|
||||
export const VulnerabilitiesFindingsDetailsTable = memo(({ value }: { value: string }) => {
|
||||
useEffect(() => {
|
||||
uiMetricService.trackUiMetric(
|
||||
METRIC_TYPE.COUNT,
|
||||
|
@ -53,7 +53,7 @@ export const VulnerabilitiesFindingsDetailsTable = memo(({ queryName }: { queryN
|
|||
}, []);
|
||||
|
||||
const { data } = useVulnerabilitiesFindings({
|
||||
query: buildEntityFlyoutPreviewQuery('host.name', queryName),
|
||||
query: buildEntityFlyoutPreviewQuery('host.name', value),
|
||||
sort: [],
|
||||
enabled: true,
|
||||
pageSize: 1,
|
||||
|
@ -204,7 +204,7 @@ export const VulnerabilitiesFindingsDetailsTable = memo(({ queryName }: { queryN
|
|||
<EuiPanel hasShadow={false}>
|
||||
<SecuritySolutionLinkAnchor
|
||||
deepLinkId={SecurityPageName.cloudSecurityPostureFindings}
|
||||
path={`${getVulnerabilityUrl(queryName, 'host.name')}`}
|
||||
path={`${getVulnerabilityUrl(value, 'host.name')}`}
|
||||
target={'_blank'}
|
||||
external={false}
|
||||
onClick={() => {
|
||||
|
|
|
@ -7,97 +7,56 @@
|
|||
|
||||
import { EuiAccordion, EuiHorizontalRule, EuiSpacer, EuiTitle, useEuiTheme } from '@elastic/eui';
|
||||
|
||||
import React, { useMemo } from 'react';
|
||||
import React from 'react';
|
||||
import { css } from '@emotion/react';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { useMisconfigurationPreview } from '@kbn/cloud-security-posture/src/hooks/use_misconfiguration_preview';
|
||||
import { buildEntityFlyoutPreviewQuery } from '@kbn/cloud-security-posture-common';
|
||||
import { useVulnerabilitiesPreview } from '@kbn/cloud-security-posture/src/hooks/use_vulnerabilities_preview';
|
||||
import { hasVulnerabilitiesData } from '@kbn/cloud-security-posture';
|
||||
import { FILTER_CLOSED } from '../../../common/types';
|
||||
import { useHasVulnerabilities } from '@kbn/cloud-security-posture/src/hooks/use_has_vulnerabilities';
|
||||
import { useHasMisconfigurations } from '@kbn/cloud-security-posture/src/hooks/use_has_misconfigurations';
|
||||
import { MisconfigurationsPreview } from './misconfiguration/misconfiguration_preview';
|
||||
import { VulnerabilitiesPreview } from './vulnerabilities/vulnerabilities_preview';
|
||||
import { AlertsPreview } from './alerts/alerts_preview';
|
||||
import { useGlobalTime } from '../../common/containers/use_global_time';
|
||||
import type { ParsedAlertsData } from '../../overview/components/detection_response/alerts_by_status/types';
|
||||
import { DETECTION_RESPONSE_ALERTS_BY_STATUS_ID } from '../../overview/components/detection_response/alerts_by_status/types';
|
||||
import { useAlertsByStatus } from '../../overview/components/detection_response/alerts_by_status/use_alerts_by_status';
|
||||
import { useSignalIndex } from '../../detections/containers/detection_engine/alerts/use_signal_index';
|
||||
import { useNonClosedAlerts } from '../hooks/use_non_closed_alerts';
|
||||
|
||||
export const EntityInsight = <T,>({
|
||||
name,
|
||||
fieldName,
|
||||
value,
|
||||
field,
|
||||
isPreviewMode,
|
||||
}: {
|
||||
name: string;
|
||||
fieldName: 'host.name' | 'user.name';
|
||||
value: string;
|
||||
field: 'host.name' | 'user.name';
|
||||
isPreviewMode?: boolean;
|
||||
}) => {
|
||||
const { euiTheme } = useEuiTheme();
|
||||
const insightContent: React.ReactElement[] = [];
|
||||
|
||||
const { data: dataMisconfiguration } = useMisconfigurationPreview({
|
||||
query: buildEntityFlyoutPreviewQuery(fieldName, name),
|
||||
sort: [],
|
||||
enabled: true,
|
||||
pageSize: 1,
|
||||
});
|
||||
const { hasMisconfigurationFindings: showMisconfigurationsPreview } = useHasMisconfigurations(
|
||||
field,
|
||||
value
|
||||
);
|
||||
|
||||
const passedFindings = dataMisconfiguration?.count.passed || 0;
|
||||
const failedFindings = dataMisconfiguration?.count.failed || 0;
|
||||
const { hasVulnerabilitiesFindings } = useHasVulnerabilities(field, value);
|
||||
|
||||
const hasMisconfigurationFindings = passedFindings > 0 || failedFindings > 0;
|
||||
|
||||
const { data } = useVulnerabilitiesPreview({
|
||||
query: buildEntityFlyoutPreviewQuery(fieldName, name),
|
||||
sort: [],
|
||||
enabled: true,
|
||||
pageSize: 1,
|
||||
});
|
||||
|
||||
const { CRITICAL = 0, HIGH = 0, MEDIUM = 0, LOW = 0, NONE = 0 } = data?.count || {};
|
||||
|
||||
const hasVulnerabilitiesFindings = hasVulnerabilitiesData({
|
||||
critical: CRITICAL,
|
||||
high: HIGH,
|
||||
medium: MEDIUM,
|
||||
low: LOW,
|
||||
none: NONE,
|
||||
});
|
||||
|
||||
const isVulnerabilitiesFindingForHost = hasVulnerabilitiesFindings && fieldName === 'host.name';
|
||||
|
||||
const { signalIndexName } = useSignalIndex();
|
||||
|
||||
const entityFilter = useMemo(() => ({ field: fieldName, value: name }), [fieldName, name]);
|
||||
const showVulnerabilitiesPreview = hasVulnerabilitiesFindings && field === 'host.name';
|
||||
|
||||
const { to, from } = useGlobalTime();
|
||||
|
||||
const { items: alertsData } = useAlertsByStatus({
|
||||
entityFilter,
|
||||
signalIndexName,
|
||||
queryId: DETECTION_RESPONSE_ALERTS_BY_STATUS_ID,
|
||||
const { hasNonClosedAlerts: showAlertsPreview, filteredAlertsData } = useNonClosedAlerts({
|
||||
field,
|
||||
value,
|
||||
to,
|
||||
from,
|
||||
queryId: DETECTION_RESPONSE_ALERTS_BY_STATUS_ID,
|
||||
});
|
||||
|
||||
const filteredAlertsData: ParsedAlertsData = alertsData
|
||||
? Object.fromEntries(Object.entries(alertsData).filter(([key]) => key !== FILTER_CLOSED))
|
||||
: {};
|
||||
|
||||
const alertsOpenCount = filteredAlertsData?.open?.total || 0;
|
||||
|
||||
const alertsAcknowledgedCount = filteredAlertsData?.acknowledged?.total || 0;
|
||||
|
||||
const alertsCount = alertsOpenCount + alertsAcknowledgedCount;
|
||||
|
||||
if (alertsCount > 0) {
|
||||
if (showAlertsPreview) {
|
||||
insightContent.push(
|
||||
<>
|
||||
<AlertsPreview
|
||||
alertsData={filteredAlertsData}
|
||||
fieldName={fieldName}
|
||||
name={name}
|
||||
field={field}
|
||||
value={value}
|
||||
isPreviewMode={isPreviewMode}
|
||||
/>
|
||||
<EuiSpacer size="s" />
|
||||
|
@ -105,34 +64,23 @@ export const EntityInsight = <T,>({
|
|||
);
|
||||
}
|
||||
|
||||
if (hasMisconfigurationFindings)
|
||||
if (showMisconfigurationsPreview)
|
||||
insightContent.push(
|
||||
<>
|
||||
<MisconfigurationsPreview
|
||||
name={name}
|
||||
fieldName={fieldName}
|
||||
hasNonClosedAlerts={alertsCount > 0}
|
||||
isPreviewMode={isPreviewMode}
|
||||
/>
|
||||
<MisconfigurationsPreview value={value} field={field} isPreviewMode={isPreviewMode} />
|
||||
<EuiSpacer size="s" />
|
||||
</>
|
||||
);
|
||||
if (isVulnerabilitiesFindingForHost && hasVulnerabilitiesFindings)
|
||||
if (showVulnerabilitiesPreview)
|
||||
insightContent.push(
|
||||
<>
|
||||
<VulnerabilitiesPreview
|
||||
name={name}
|
||||
isPreviewMode={isPreviewMode}
|
||||
hasNonClosedAlerts={alertsCount > 0}
|
||||
/>
|
||||
<VulnerabilitiesPreview value={value} field={field} isPreviewMode={isPreviewMode} />
|
||||
<EuiSpacer size="s" />
|
||||
</>
|
||||
);
|
||||
return (
|
||||
<>
|
||||
{(insightContent.length > 0 ||
|
||||
hasMisconfigurationFindings ||
|
||||
(isVulnerabilitiesFindingForHost && hasVulnerabilitiesFindings)) && (
|
||||
{insightContent.length > 0 && (
|
||||
<>
|
||||
<EuiAccordion
|
||||
initialIsOpen={true}
|
||||
|
|
|
@ -37,7 +37,7 @@ describe('MisconfigurationsPreview', () => {
|
|||
it('renders', () => {
|
||||
const { getByTestId } = render(
|
||||
<TestProviders>
|
||||
<MisconfigurationsPreview name="host1" fieldName="host.name" />
|
||||
<MisconfigurationsPreview value="host1" field="host.name" />
|
||||
</TestProviders>
|
||||
);
|
||||
|
||||
|
|
|
@ -5,39 +5,23 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import React, { useCallback, useEffect, useMemo } from 'react';
|
||||
import React, { useEffect, useMemo } from 'react';
|
||||
import { css } from '@emotion/react';
|
||||
import type { EuiThemeComputed } from '@elastic/eui';
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText, useEuiTheme, EuiTitle } from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { DistributionBar } from '@kbn/security-solution-distribution-bar';
|
||||
import { useMisconfigurationPreview } from '@kbn/cloud-security-posture/src/hooks/use_misconfiguration_preview';
|
||||
import { useHasMisconfigurations } from '@kbn/cloud-security-posture/src/hooks/use_has_misconfigurations';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { buildEntityFlyoutPreviewQuery } from '@kbn/cloud-security-posture-common';
|
||||
import { useExpandableFlyoutApi } from '@kbn/expandable-flyout';
|
||||
import { useVulnerabilitiesPreview } from '@kbn/cloud-security-posture/src/hooks/use_vulnerabilities_preview';
|
||||
import { hasVulnerabilitiesData, statusColors } from '@kbn/cloud-security-posture';
|
||||
import { statusColors } from '@kbn/cloud-security-posture';
|
||||
import { METRIC_TYPE } from '@kbn/analytics';
|
||||
import {
|
||||
ENTITY_FLYOUT_WITH_MISCONFIGURATION_VISIT,
|
||||
uiMetricService,
|
||||
} from '@kbn/cloud-security-posture-common/utils/ui_metrics';
|
||||
import { ExpandablePanel } from '../../../flyout/shared/components/expandable_panel';
|
||||
import {
|
||||
CspInsightLeftPanelSubTab,
|
||||
EntityDetailsLeftPanelTab,
|
||||
} from '../../../flyout/entity_details/shared/components/left_panel/left_panel_header';
|
||||
import { UserDetailsPanelKey } from '../../../flyout/entity_details/user_details_left';
|
||||
import { HostDetailsPanelKey } from '../../../flyout/entity_details/host_details_left';
|
||||
import { useRiskScore } from '../../../entity_analytics/api/hooks/use_risk_score';
|
||||
import { RiskScoreEntity } from '../../../../common/entity_analytics/risk_engine';
|
||||
import type { HostRiskScore, UserRiskScore } from '../../../../common/search_strategy';
|
||||
import { buildHostNamesFilter, buildUserNamesFilter } from '../../../../common/search_strategy';
|
||||
|
||||
const FIRST_RECORD_PAGINATION = {
|
||||
cursorStart: 0,
|
||||
querySize: 1,
|
||||
};
|
||||
import { CspInsightLeftPanelSubTab } from '../../../flyout/entity_details/shared/components/left_panel/left_panel_header';
|
||||
import { useNavigateEntityInsight } from '../../hooks/use_entity_insight';
|
||||
|
||||
export const getFindingsStats = (passedFindingsStats: number, failedFindingsStats: number) => {
|
||||
if (passedFindingsStats === 0 && failedFindingsStats === 0) return [];
|
||||
|
@ -101,113 +85,30 @@ const MisconfigurationPreviewScore = ({
|
|||
};
|
||||
|
||||
export const MisconfigurationsPreview = ({
|
||||
name,
|
||||
fieldName,
|
||||
hasNonClosedAlerts = false,
|
||||
value,
|
||||
field,
|
||||
isPreviewMode,
|
||||
}: {
|
||||
name: string;
|
||||
fieldName: 'host.name' | 'user.name';
|
||||
hasNonClosedAlerts?: boolean;
|
||||
value: string;
|
||||
field: 'host.name' | 'user.name';
|
||||
isPreviewMode?: boolean;
|
||||
}) => {
|
||||
const { data } = useMisconfigurationPreview({
|
||||
query: buildEntityFlyoutPreviewQuery(fieldName, name),
|
||||
sort: [],
|
||||
enabled: true,
|
||||
pageSize: 1,
|
||||
ignore_unavailable: true,
|
||||
});
|
||||
const isUsingHostName = fieldName === 'host.name';
|
||||
const passedFindings = data?.count.passed || 0;
|
||||
const failedFindings = data?.count.failed || 0;
|
||||
const { hasMisconfigurationFindings, passedFindings, failedFindings } = useHasMisconfigurations(
|
||||
field,
|
||||
value
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, ENTITY_FLYOUT_WITH_MISCONFIGURATION_VISIT);
|
||||
}, []);
|
||||
const { euiTheme } = useEuiTheme();
|
||||
const hasMisconfigurationFindings = passedFindings > 0 || failedFindings > 0;
|
||||
|
||||
const { data: vulnerabilitiesData } = useVulnerabilitiesPreview({
|
||||
query: buildEntityFlyoutPreviewQuery('host.name', name),
|
||||
sort: [],
|
||||
enabled: true,
|
||||
pageSize: 1,
|
||||
const { goToEntityInsightTab } = useNavigateEntityInsight({
|
||||
field,
|
||||
value,
|
||||
queryIdExtension: 'MISCONFIGURATION_PREVIEW',
|
||||
subTab: CspInsightLeftPanelSubTab.MISCONFIGURATIONS,
|
||||
});
|
||||
|
||||
const {
|
||||
CRITICAL = 0,
|
||||
HIGH = 0,
|
||||
MEDIUM = 0,
|
||||
LOW = 0,
|
||||
NONE = 0,
|
||||
} = vulnerabilitiesData?.count || {};
|
||||
|
||||
const hasVulnerabilitiesFindings = hasVulnerabilitiesData({
|
||||
critical: CRITICAL,
|
||||
high: HIGH,
|
||||
medium: MEDIUM,
|
||||
low: LOW,
|
||||
none: NONE,
|
||||
});
|
||||
|
||||
const buildFilterQuery = useMemo(
|
||||
() => (isUsingHostName ? buildHostNamesFilter([name]) : buildUserNamesFilter([name])),
|
||||
[isUsingHostName, name]
|
||||
);
|
||||
|
||||
const riskScoreState = useRiskScore({
|
||||
riskEntity: isUsingHostName ? RiskScoreEntity.host : RiskScoreEntity.user,
|
||||
filterQuery: buildFilterQuery,
|
||||
onlyLatest: false,
|
||||
pagination: FIRST_RECORD_PAGINATION,
|
||||
});
|
||||
|
||||
const { data: hostRisk } = riskScoreState;
|
||||
|
||||
const riskData = hostRisk?.[0];
|
||||
|
||||
const isRiskScoreExist = isUsingHostName
|
||||
? !!(riskData as HostRiskScore)?.host.risk
|
||||
: !!(riskData as UserRiskScore)?.user.risk;
|
||||
|
||||
const { openLeftPanel } = useExpandableFlyoutApi();
|
||||
|
||||
const goToEntityInsightTab = useCallback(() => {
|
||||
openLeftPanel({
|
||||
id: isUsingHostName ? HostDetailsPanelKey : UserDetailsPanelKey,
|
||||
params: isUsingHostName
|
||||
? {
|
||||
name,
|
||||
isRiskScoreExist,
|
||||
hasMisconfigurationFindings,
|
||||
hasVulnerabilitiesFindings,
|
||||
hasNonClosedAlerts,
|
||||
path: {
|
||||
tab: EntityDetailsLeftPanelTab.CSP_INSIGHTS,
|
||||
subTab: CspInsightLeftPanelSubTab.MISCONFIGURATIONS,
|
||||
},
|
||||
}
|
||||
: {
|
||||
user: { name },
|
||||
isRiskScoreExist,
|
||||
hasMisconfigurationFindings,
|
||||
hasNonClosedAlerts,
|
||||
path: {
|
||||
tab: EntityDetailsLeftPanelTab.CSP_INSIGHTS,
|
||||
subTab: CspInsightLeftPanelSubTab.MISCONFIGURATIONS,
|
||||
},
|
||||
},
|
||||
});
|
||||
}, [
|
||||
hasMisconfigurationFindings,
|
||||
hasNonClosedAlerts,
|
||||
hasVulnerabilitiesFindings,
|
||||
isRiskScoreExist,
|
||||
isUsingHostName,
|
||||
name,
|
||||
openLeftPanel,
|
||||
]);
|
||||
const link = useMemo(
|
||||
() =>
|
||||
!isPreviewMode
|
||||
|
|
|
@ -37,7 +37,7 @@ describe('VulnerabilitiesPreview', () => {
|
|||
it('renders', () => {
|
||||
const { getByTestId } = render(
|
||||
<TestProviders>
|
||||
<VulnerabilitiesPreview name="host1" />
|
||||
<VulnerabilitiesPreview value="host1" field="host.name" />
|
||||
</TestProviders>
|
||||
);
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import React, { useCallback, useEffect, useMemo } from 'react';
|
||||
import React, { useEffect, useMemo } from 'react';
|
||||
import { css } from '@emotion/react';
|
||||
import type { EuiThemeComputed } from '@elastic/eui';
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText, useEuiTheme, EuiTitle } from '@elastic/eui';
|
||||
|
@ -17,24 +17,14 @@ import {
|
|||
getAbbreviatedNumber,
|
||||
} from '@kbn/cloud-security-posture-common';
|
||||
import { getVulnerabilityStats, hasVulnerabilitiesData } from '@kbn/cloud-security-posture';
|
||||
import { useExpandableFlyoutApi } from '@kbn/expandable-flyout';
|
||||
import { useMisconfigurationPreview } from '@kbn/cloud-security-posture/src/hooks/use_misconfiguration_preview';
|
||||
import {
|
||||
ENTITY_FLYOUT_WITH_VULNERABILITY_PREVIEW,
|
||||
uiMetricService,
|
||||
} from '@kbn/cloud-security-posture-common/utils/ui_metrics';
|
||||
import { METRIC_TYPE } from '@kbn/analytics';
|
||||
import { ExpandablePanel } from '../../../flyout/shared/components/expandable_panel';
|
||||
import { EntityDetailsLeftPanelTab } from '../../../flyout/entity_details/shared/components/left_panel/left_panel_header';
|
||||
import { HostDetailsPanelKey } from '../../../flyout/entity_details/host_details_left';
|
||||
import { useRiskScore } from '../../../entity_analytics/api/hooks/use_risk_score';
|
||||
import { RiskScoreEntity } from '../../../../common/entity_analytics/risk_engine';
|
||||
import { buildHostNamesFilter } from '../../../../common/search_strategy';
|
||||
|
||||
const FIRST_RECORD_PAGINATION = {
|
||||
cursorStart: 0,
|
||||
querySize: 1,
|
||||
};
|
||||
import { CspInsightLeftPanelSubTab } from '../../../flyout/entity_details/shared/components/left_panel/left_panel_header';
|
||||
import { useNavigateEntityInsight } from '../../hooks/use_entity_insight';
|
||||
|
||||
const VulnerabilitiesCount = ({
|
||||
vulnerabilitiesTotal,
|
||||
|
@ -70,20 +60,20 @@ const VulnerabilitiesCount = ({
|
|||
};
|
||||
|
||||
export const VulnerabilitiesPreview = ({
|
||||
name,
|
||||
value,
|
||||
field,
|
||||
isPreviewMode,
|
||||
hasNonClosedAlerts = false,
|
||||
}: {
|
||||
name: string;
|
||||
value: string;
|
||||
field: 'host.name' | 'user.name';
|
||||
isPreviewMode?: boolean;
|
||||
hasNonClosedAlerts?: boolean;
|
||||
}) => {
|
||||
useEffect(() => {
|
||||
uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, ENTITY_FLYOUT_WITH_VULNERABILITY_PREVIEW);
|
||||
}, []);
|
||||
|
||||
const { data } = useVulnerabilitiesPreview({
|
||||
query: buildEntityFlyoutPreviewQuery('host.name', name),
|
||||
query: buildEntityFlyoutPreviewQuery(field, value),
|
||||
sort: [],
|
||||
enabled: true,
|
||||
pageSize: 1,
|
||||
|
@ -103,49 +93,12 @@ export const VulnerabilitiesPreview = ({
|
|||
|
||||
const { euiTheme } = useEuiTheme();
|
||||
|
||||
const { data: dataMisconfiguration } = useMisconfigurationPreview({
|
||||
query: buildEntityFlyoutPreviewQuery('host.name', name),
|
||||
sort: [],
|
||||
enabled: true,
|
||||
pageSize: 1,
|
||||
const { goToEntityInsightTab } = useNavigateEntityInsight({
|
||||
field,
|
||||
value,
|
||||
queryIdExtension: 'VULNERABILITIES_PREVIEW',
|
||||
subTab: CspInsightLeftPanelSubTab.VULNERABILITIES,
|
||||
});
|
||||
|
||||
const passedFindings = dataMisconfiguration?.count.passed || 0;
|
||||
const failedFindings = dataMisconfiguration?.count.failed || 0;
|
||||
|
||||
const hasMisconfigurationFindings = passedFindings > 0 || failedFindings > 0;
|
||||
|
||||
const buildFilterQuery = useMemo(() => buildHostNamesFilter([name]), [name]);
|
||||
const riskScoreState = useRiskScore({
|
||||
riskEntity: RiskScoreEntity.host,
|
||||
filterQuery: buildFilterQuery,
|
||||
onlyLatest: false,
|
||||
pagination: FIRST_RECORD_PAGINATION,
|
||||
});
|
||||
const { data: hostRisk } = riskScoreState;
|
||||
const riskData = hostRisk?.[0];
|
||||
const isRiskScoreExist = riskData?.host.risk;
|
||||
const { openLeftPanel } = useExpandableFlyoutApi();
|
||||
const goToEntityInsightTab = useCallback(() => {
|
||||
openLeftPanel({
|
||||
id: HostDetailsPanelKey,
|
||||
params: {
|
||||
name,
|
||||
isRiskScoreExist,
|
||||
hasMisconfigurationFindings,
|
||||
hasVulnerabilitiesFindings,
|
||||
hasNonClosedAlerts,
|
||||
path: { tab: EntityDetailsLeftPanelTab.CSP_INSIGHTS, subTab: 'vulnerabilitiesTabId' },
|
||||
},
|
||||
});
|
||||
}, [
|
||||
hasMisconfigurationFindings,
|
||||
hasNonClosedAlerts,
|
||||
hasVulnerabilitiesFindings,
|
||||
isRiskScoreExist,
|
||||
name,
|
||||
openLeftPanel,
|
||||
]);
|
||||
const link = useMemo(
|
||||
() =>
|
||||
!isPreviewMode
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { useExpandableFlyoutApi } from '@kbn/expandable-flyout';
|
||||
import { useCallback } from 'react';
|
||||
import { useHasVulnerabilities } from '@kbn/cloud-security-posture/src/hooks/use_has_vulnerabilities';
|
||||
import { useHasMisconfigurations } from '@kbn/cloud-security-posture/src/hooks/use_has_misconfigurations';
|
||||
import { UserDetailsPanelKey } from '../../flyout/entity_details/user_details_left';
|
||||
import { HostDetailsPanelKey } from '../../flyout/entity_details/host_details_left';
|
||||
import { EntityDetailsLeftPanelTab } from '../../flyout/entity_details/shared/components/left_panel/left_panel_header';
|
||||
import { useGlobalTime } from '../../common/containers/use_global_time';
|
||||
import { DETECTION_RESPONSE_ALERTS_BY_STATUS_ID } from '../../overview/components/detection_response/alerts_by_status/types';
|
||||
import { useNonClosedAlerts } from './use_non_closed_alerts';
|
||||
import { useHasRiskScore } from './use_risk_score_data';
|
||||
|
||||
export const useNavigateEntityInsight = ({
|
||||
field,
|
||||
value,
|
||||
subTab,
|
||||
queryIdExtension,
|
||||
}: {
|
||||
field: 'host.name' | 'user.name';
|
||||
value: string;
|
||||
subTab: string;
|
||||
queryIdExtension: string;
|
||||
}) => {
|
||||
const isHostNameField = field === 'host.name';
|
||||
const { to, from } = useGlobalTime();
|
||||
|
||||
const { hasNonClosedAlerts } = useNonClosedAlerts({
|
||||
field,
|
||||
value,
|
||||
to,
|
||||
from,
|
||||
queryId: `${DETECTION_RESPONSE_ALERTS_BY_STATUS_ID}${queryIdExtension}`,
|
||||
});
|
||||
|
||||
const { hasVulnerabilitiesFindings } = useHasVulnerabilities(field, value);
|
||||
|
||||
const { hasRiskScore } = useHasRiskScore({
|
||||
field,
|
||||
value,
|
||||
});
|
||||
const { hasMisconfigurationFindings } = useHasMisconfigurations(field, value);
|
||||
const { openLeftPanel } = useExpandableFlyoutApi();
|
||||
|
||||
const goToEntityInsightTab = useCallback(() => {
|
||||
openLeftPanel({
|
||||
id: isHostNameField ? HostDetailsPanelKey : UserDetailsPanelKey,
|
||||
params: isHostNameField
|
||||
? {
|
||||
name: value,
|
||||
isRiskScoreExist: hasRiskScore,
|
||||
hasMisconfigurationFindings,
|
||||
hasVulnerabilitiesFindings,
|
||||
hasNonClosedAlerts,
|
||||
path: {
|
||||
tab: EntityDetailsLeftPanelTab.CSP_INSIGHTS,
|
||||
subTab,
|
||||
},
|
||||
}
|
||||
: {
|
||||
user: { name: value },
|
||||
isRiskScoreExist: hasRiskScore,
|
||||
hasMisconfigurationFindings,
|
||||
hasNonClosedAlerts,
|
||||
path: {
|
||||
tab: EntityDetailsLeftPanelTab.CSP_INSIGHTS,
|
||||
subTab,
|
||||
},
|
||||
},
|
||||
});
|
||||
}, [
|
||||
openLeftPanel,
|
||||
isHostNameField,
|
||||
value,
|
||||
hasRiskScore,
|
||||
hasMisconfigurationFindings,
|
||||
hasVulnerabilitiesFindings,
|
||||
hasNonClosedAlerts,
|
||||
subTab,
|
||||
]);
|
||||
|
||||
return { goToEntityInsightTab };
|
||||
};
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { useMemo } from 'react';
|
||||
import { FILTER_CLOSED } from '@kbn/securitysolution-data-table/common/types';
|
||||
import { useSignalIndex } from '../../detections/containers/detection_engine/alerts/use_signal_index';
|
||||
import { useAlertsByStatus } from '../../overview/components/detection_response/alerts_by_status/use_alerts_by_status';
|
||||
import type { ParsedAlertsData } from '../../overview/components/detection_response/alerts_by_status/types';
|
||||
|
||||
export const useNonClosedAlerts = ({
|
||||
field,
|
||||
value,
|
||||
to,
|
||||
from,
|
||||
queryId,
|
||||
}: {
|
||||
field: 'host.name' | 'user.name';
|
||||
value: string;
|
||||
to: string;
|
||||
from: string;
|
||||
queryId: string;
|
||||
}) => {
|
||||
const { signalIndexName } = useSignalIndex();
|
||||
|
||||
const entityFilter = useMemo(() => ({ field, value }), [field, value]);
|
||||
|
||||
const { items: alertsData } = useAlertsByStatus({
|
||||
entityFilter,
|
||||
signalIndexName,
|
||||
queryId,
|
||||
to,
|
||||
from,
|
||||
});
|
||||
|
||||
const filteredAlertsData: ParsedAlertsData = alertsData
|
||||
? Object.fromEntries(Object.entries(alertsData).filter(([key]) => key !== FILTER_CLOSED))
|
||||
: {};
|
||||
|
||||
const hasNonClosedAlerts =
|
||||
(filteredAlertsData?.acknowledged?.total || 0) + (filteredAlertsData?.open?.total || 0) > 0;
|
||||
|
||||
return { hasNonClosedAlerts, filteredAlertsData };
|
||||
};
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { useMemo } from 'react';
|
||||
import {
|
||||
RiskScoreEntity,
|
||||
type HostRiskScore,
|
||||
type UserRiskScore,
|
||||
buildHostNamesFilter,
|
||||
buildUserNamesFilter,
|
||||
} from '../../../common/search_strategy';
|
||||
import { useRiskScore } from '../../entity_analytics/api/hooks/use_risk_score';
|
||||
import { FIRST_RECORD_PAGINATION } from '../../entity_analytics/common';
|
||||
|
||||
export const useHasRiskScore = ({
|
||||
field,
|
||||
value,
|
||||
}: {
|
||||
field: 'host.name' | 'user.name';
|
||||
value: string;
|
||||
}) => {
|
||||
const isHostNameField = field === 'host.name';
|
||||
const buildFilterQuery = useMemo(
|
||||
() => (isHostNameField ? buildHostNamesFilter([value]) : buildUserNamesFilter([value])),
|
||||
[isHostNameField, value]
|
||||
);
|
||||
const { data } = useRiskScore({
|
||||
riskEntity: isHostNameField ? RiskScoreEntity.host : RiskScoreEntity.user,
|
||||
filterQuery: buildFilterQuery,
|
||||
onlyLatest: false,
|
||||
pagination: FIRST_RECORD_PAGINATION,
|
||||
});
|
||||
|
||||
const riskData = data?.[0];
|
||||
|
||||
const hasRiskScore = isHostNameField
|
||||
? !!(riskData as HostRiskScore)?.host.risk
|
||||
: !!(riskData as UserRiskScore)?.user.risk;
|
||||
|
||||
return { hasRiskScore };
|
||||
};
|
|
@ -44,6 +44,6 @@ export const getInsightsInputTab = ({
|
|||
defaultMessage="Insights"
|
||||
/>
|
||||
),
|
||||
content: <InsightsTabCsp name={name} fieldName={fieldName} />,
|
||||
content: <InsightsTabCsp value={name} field={fieldName} />,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -64,7 +64,7 @@ export const HostPanelContent = ({
|
|||
entity={{ name: hostName, type: 'host' }}
|
||||
onChange={onAssetCriticalityChange}
|
||||
/>
|
||||
<EntityInsight name={hostName} fieldName={'host.name'} isPreviewMode={isPreviewMode} />
|
||||
<EntityInsight value={hostName} field={'host.name'} isPreviewMode={isPreviewMode} />
|
||||
<ObservedEntity
|
||||
observedData={observedHost}
|
||||
contextID={contextID}
|
||||
|
|
|
@ -9,12 +9,10 @@ import React, { useCallback, useMemo } from 'react';
|
|||
import type { FlyoutPanelProps } from '@kbn/expandable-flyout';
|
||||
import { useExpandableFlyoutApi } from '@kbn/expandable-flyout';
|
||||
|
||||
import { buildEntityFlyoutPreviewQuery } from '@kbn/cloud-security-posture-common';
|
||||
import { useMisconfigurationPreview } from '@kbn/cloud-security-posture/src/hooks/use_misconfiguration_preview';
|
||||
import { useVulnerabilitiesPreview } from '@kbn/cloud-security-posture/src/hooks/use_vulnerabilities_preview';
|
||||
import { sum } from 'lodash';
|
||||
import { useHasMisconfigurations } from '@kbn/cloud-security-posture/src/hooks/use_has_misconfigurations';
|
||||
import { useHasVulnerabilities } from '@kbn/cloud-security-posture/src/hooks/use_has_vulnerabilities';
|
||||
import { useNonClosedAlerts } from '../../../cloud_security_posture/hooks/use_non_closed_alerts';
|
||||
import { DETECTION_RESPONSE_ALERTS_BY_STATUS_ID } from '../../../overview/components/detection_response/alerts_by_status/types';
|
||||
import { useAlertsByStatus } from '../../../overview/components/detection_response/alerts_by_status/use_alerts_by_status';
|
||||
import { useRefetchQueryById } from '../../../entity_analytics/api/hooks/use_refetch_query_by_id';
|
||||
import { RISK_INPUTS_TAB_QUERY_ID } from '../../../entity_analytics/components/entity_details_flyout/tabs/risk_inputs/risk_inputs_tab';
|
||||
import type { Refetch } from '../../../common/types';
|
||||
|
@ -37,7 +35,6 @@ import { useObservedHost } from './hooks/use_observed_host';
|
|||
import { HostDetailsPanelKey } from '../host_details_left';
|
||||
import { EntityDetailsLeftPanelTab } from '../shared/components/left_panel/left_panel_header';
|
||||
import { HostPreviewPanelFooter } from '../host_preview/footer';
|
||||
import { useSignalIndex } from '../../../detections/containers/detection_engine/alerts/use_signal_index';
|
||||
import { EntityEventTypes } from '../../../common/lib/telemetry';
|
||||
|
||||
export interface HostPanelProps extends Record<string, unknown> {
|
||||
|
@ -101,43 +98,18 @@ export const HostPanel = ({
|
|||
{ onSuccess: refetchRiskScore }
|
||||
);
|
||||
|
||||
const { data } = useMisconfigurationPreview({
|
||||
query: buildEntityFlyoutPreviewQuery('host.name', hostName),
|
||||
sort: [],
|
||||
enabled: true,
|
||||
pageSize: 1,
|
||||
ignore_unavailable: true,
|
||||
});
|
||||
const { hasMisconfigurationFindings } = useHasMisconfigurations('host.name', hostName);
|
||||
|
||||
const passedFindings = data?.count.passed || 0;
|
||||
const failedFindings = data?.count.failed || 0;
|
||||
const { hasVulnerabilitiesFindings } = useHasVulnerabilities('host.name', hostName);
|
||||
|
||||
const hasMisconfigurationFindings = passedFindings > 0 || failedFindings > 0;
|
||||
|
||||
const { data: vulnerabilitiesData } = useVulnerabilitiesPreview({
|
||||
query: buildEntityFlyoutPreviewQuery('host.name', hostName),
|
||||
sort: [],
|
||||
enabled: true,
|
||||
pageSize: 1,
|
||||
});
|
||||
|
||||
const hasVulnerabilitiesFindings = sum(Object.values(vulnerabilitiesData?.count || {})) > 0;
|
||||
|
||||
const { signalIndexName } = useSignalIndex();
|
||||
|
||||
const entityFilter = useMemo(() => ({ field: 'host.name', value: hostName }), [hostName]);
|
||||
|
||||
const { items: alertsData } = useAlertsByStatus({
|
||||
entityFilter,
|
||||
signalIndexName,
|
||||
queryId: `${DETECTION_RESPONSE_ALERTS_BY_STATUS_ID}HOST_NAME_RIGHT`,
|
||||
const { hasNonClosedAlerts } = useNonClosedAlerts({
|
||||
field: 'host.name',
|
||||
value: hostName,
|
||||
to,
|
||||
from,
|
||||
queryId: `${DETECTION_RESPONSE_ALERTS_BY_STATUS_ID}HOST_NAME_RIGHT`,
|
||||
});
|
||||
|
||||
const hasNonClosedAlerts =
|
||||
(alertsData?.acknowledged?.total || 0) + (alertsData?.open?.total || 0) > 0;
|
||||
|
||||
useQueryInspector({
|
||||
deleteQuery,
|
||||
inspect: inspectRiskScore,
|
||||
|
|
|
@ -73,7 +73,7 @@ export const UserPanelContent = ({
|
|||
entity={{ name: userName, type: 'user' }}
|
||||
onChange={onAssetCriticalityChange}
|
||||
/>
|
||||
<EntityInsight name={userName} fieldName={'user.name'} isPreviewMode={isPreviewMode} />
|
||||
<EntityInsight value={userName} field={'user.name'} isPreviewMode={isPreviewMode} />
|
||||
<ObservedEntity
|
||||
observedData={observedUser}
|
||||
contextID={contextID}
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
import React, { useCallback, useMemo } from 'react';
|
||||
import type { FlyoutPanelProps } from '@kbn/expandable-flyout';
|
||||
import { useExpandableFlyoutApi } from '@kbn/expandable-flyout';
|
||||
import { useMisconfigurationPreview } from '@kbn/cloud-security-posture/src/hooks/use_misconfiguration_preview';
|
||||
import { buildEntityFlyoutPreviewQuery } from '@kbn/cloud-security-posture-common';
|
||||
import { useHasMisconfigurations } from '@kbn/cloud-security-posture/src/hooks/use_has_misconfigurations';
|
||||
import { useNonClosedAlerts } from '../../../cloud_security_posture/hooks/use_non_closed_alerts';
|
||||
import { useRefetchQueryById } from '../../../entity_analytics/api/hooks/use_refetch_query_by_id';
|
||||
import type { Refetch } from '../../../common/types';
|
||||
import { RISK_INPUTS_TAB_QUERY_ID } from '../../../entity_analytics/components/entity_details_flyout/tabs/risk_inputs/risk_inputs_tab';
|
||||
|
@ -33,8 +33,6 @@ import { UserDetailsPanelKey } from '../user_details_left';
|
|||
import { useObservedUser } from './hooks/use_observed_user';
|
||||
import { EntityDetailsLeftPanelTab } from '../shared/components/left_panel/left_panel_header';
|
||||
import { UserPreviewPanelFooter } from '../user_preview/footer';
|
||||
import { useSignalIndex } from '../../../detections/containers/detection_engine/alerts/use_signal_index';
|
||||
import { useAlertsByStatus } from '../../../overview/components/detection_response/alerts_by_status/use_alerts_by_status';
|
||||
import { DETECTION_RESPONSE_ALERTS_BY_STATUS_ID } from '../../../overview/components/detection_response/alerts_by_status/types';
|
||||
import { EntityEventTypes } from '../../../common/lib/telemetry';
|
||||
|
||||
|
@ -102,34 +100,16 @@ export const UserPanel = ({
|
|||
{ onSuccess: refetchRiskScore }
|
||||
);
|
||||
|
||||
const { data } = useMisconfigurationPreview({
|
||||
query: buildEntityFlyoutPreviewQuery('user.name', userName),
|
||||
sort: [],
|
||||
enabled: true,
|
||||
pageSize: 1,
|
||||
ignore_unavailable: true,
|
||||
});
|
||||
const { hasMisconfigurationFindings } = useHasMisconfigurations('user.name', userName);
|
||||
|
||||
const passedFindings = data?.count.passed || 0;
|
||||
const failedFindings = data?.count.failed || 0;
|
||||
|
||||
const hasMisconfigurationFindings = passedFindings > 0 || failedFindings > 0;
|
||||
|
||||
const { signalIndexName } = useSignalIndex();
|
||||
|
||||
const entityFilter = useMemo(() => ({ field: 'user.name', value: userName }), [userName]);
|
||||
|
||||
const { items: alertsData } = useAlertsByStatus({
|
||||
entityFilter,
|
||||
signalIndexName,
|
||||
queryId: `${DETECTION_RESPONSE_ALERTS_BY_STATUS_ID}USER_NAME_RIGHT`,
|
||||
const { hasNonClosedAlerts } = useNonClosedAlerts({
|
||||
field: 'user.name',
|
||||
value: userName,
|
||||
to,
|
||||
from,
|
||||
queryId: `${DETECTION_RESPONSE_ALERTS_BY_STATUS_ID}USER_NAME_RIGHT`,
|
||||
});
|
||||
|
||||
const hasNonClosedAlerts =
|
||||
(alertsData?.acknowledged?.total || 0) + (alertsData?.open?.total || 0) > 0;
|
||||
|
||||
useQueryInspector({
|
||||
deleteQuery,
|
||||
inspect,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue