diff --git a/x-pack/plugins/security_solution/public/cloud_security_posture/components/csp_details/insights_tab_csp.tsx b/x-pack/plugins/security_solution/public/cloud_security_posture/components/csp_details/insights_tab_csp.tsx
index fa91a99c858a8..595aaf5127ca3 100644
--- a/x-pack/plugins/security_solution/public/cloud_security_posture/components/csp_details/insights_tab_csp.tsx
+++ b/x-pack/plugins/security_solution/public/cloud_security_posture/components/csp_details/insights_tab_csp.tsx
@@ -6,55 +6,16 @@
*/
import React, { memo } from 'react';
-import { EuiButtonGroup, EuiSpacer } from '@elastic/eui';
-import type { EuiButtonGroupOptionProps } from '@elastic/eui/src/components/button/button_group/button_group';
-import { i18n } from '@kbn/i18n';
-import { FormattedMessage } from '@kbn/i18n-react';
-import { useExpandableFlyoutState } from '@kbn/expandable-flyout';
+import { EuiSpacer } from '@elastic/eui';
import { MisconfigurationFindingsDetailsTable } from './misconfiguration_findings_details_table';
-enum InsightsTabCspTab {
- MISCONFIGURATION = 'misconfigurationTabId',
-}
-
-const insightsButtons: EuiButtonGroupOptionProps[] = [
- {
- id: InsightsTabCspTab.MISCONFIGURATION,
- label: (
-
- ),
- 'data-test-subj': 'misconfigurationTabDataTestId',
- },
-];
-
/**
* Insights view displayed in the document details expandable flyout left section
*/
export const InsightsTabCsp = memo(
({ name, fieldName }: { name: string; fieldName: 'host.name' | 'user.name' }) => {
- const panels = useExpandableFlyoutState();
- const activeInsightsId = panels.left?.path?.subTab ?? 'misconfigurationTabId';
-
return (
<>
- {}}
- buttonSize="compressed"
- isFullWidth
- data-test-subj={'insightButtonGroupsTestId'}
- />
>
diff --git a/x-pack/plugins/security_solution/public/cloud_security_posture/components/csp_details/misconfiguration_findings_details_table.tsx b/x-pack/plugins/security_solution/public/cloud_security_posture/components/csp_details/misconfiguration_findings_details_table.tsx
index 1362e0e42e6ba..ba413709d6cca 100644
--- a/x-pack/plugins/security_solution/public/cloud_security_posture/components/csp_details/misconfiguration_findings_details_table.tsx
+++ b/x-pack/plugins/security_solution/public/cloud_security_posture/components/csp_details/misconfiguration_findings_details_table.tsx
@@ -102,14 +102,14 @@ export const MisconfigurationFindingsDetailsTable = memo(
const navToFindings = useNavigateFindings();
- const navToFindingsByHostName = (hostName: string) => {
- navToFindings({ 'host.name': hostName }, ['rule.name']);
- };
-
const navToFindingsByRuleAndResourceId = (ruleId: string, resourceId: string) => {
navToFindings({ 'rule.id': ruleId, 'resource.id': resourceId });
};
+ const navToFindingsByName = (name: string, queryField: 'host.name' | 'user.name') => {
+ navToFindings({ [queryField]: name }, ['rule.name']);
+ };
+
const columns: Array> = [
{
field: 'rule',
@@ -154,13 +154,13 @@ export const MisconfigurationFindingsDetailsTable = memo(
{
- navToFindingsByHostName(queryName);
+ navToFindingsByName(queryName, fieldName);
}}
>
{i18n.translate(
'xpack.securitySolution.flyout.left.insights.misconfigurations.tableTitle',
{
- defaultMessage: 'Misconfigurations',
+ defaultMessage: 'Misconfigurations ',
}
)}
diff --git a/x-pack/plugins/security_solution/public/cloud_security_posture/components/index.tsx b/x-pack/plugins/security_solution/public/cloud_security_posture/components/index.tsx
index 3058300036565..6045a8b8c9a5e 100644
--- a/x-pack/plugins/security_solution/public/cloud_security_posture/components/index.tsx
+++ b/x-pack/plugins/security_solution/public/cloud_security_posture/components/index.tsx
@@ -13,7 +13,15 @@ import { FormattedMessage } from '@kbn/i18n-react';
import { useCspSetupStatusApi } from '@kbn/cloud-security-posture/src/hooks/use_csp_setup_status_api';
import { MisconfigurationsPreview } from './misconfiguration/misconfiguration_preview';
-export const EntityInsight = ({ hostName }: { hostName: string }) => {
+export const EntityInsight = ({
+ name,
+ fieldName,
+ isPreviewMode,
+}: {
+ name: string;
+ fieldName: 'host.name' | 'user.name';
+ isPreviewMode?: boolean;
+}) => {
const { euiTheme } = useEuiTheme();
const getSetupStatus = useCspSetupStatusApi();
const hasMisconfigurationFindings = getSetupStatus.data?.hasMisconfigurationsFindings;
@@ -22,7 +30,6 @@ export const EntityInsight = ({ hostName }: { hostName: string }) => {
<>
{hasMisconfigurationFindings && (
<>
-
({ hostName }: { hostName: string }) => {
}
>
-
+
+
>
)}
>
diff --git a/x-pack/plugins/security_solution/public/cloud_security_posture/components/misconfiguration/misconfiguration_preview.test.tsx b/x-pack/plugins/security_solution/public/cloud_security_posture/components/misconfiguration/misconfiguration_preview.test.tsx
index 1c4c2adb60218..2e10d481b9934 100644
--- a/x-pack/plugins/security_solution/public/cloud_security_posture/components/misconfiguration/misconfiguration_preview.test.tsx
+++ b/x-pack/plugins/security_solution/public/cloud_security_posture/components/misconfiguration/misconfiguration_preview.test.tsx
@@ -11,8 +11,9 @@ import { render } from '@testing-library/react';
import React from 'react';
import { MisconfigurationsPreview } from './misconfiguration_preview';
-const mockProps = {
- hostName: 'testContextID',
+const mockProps: { name: string; fieldName: 'host.name' | 'user.name' } = {
+ name: 'testContextID',
+ fieldName: 'host.name',
};
describe('MisconfigurationsPreview', () => {
diff --git a/x-pack/plugins/security_solution/public/cloud_security_posture/components/misconfiguration/misconfiguration_preview.tsx b/x-pack/plugins/security_solution/public/cloud_security_posture/components/misconfiguration/misconfiguration_preview.tsx
index f6ba0389f752a..e6c3950e81583 100644
--- a/x-pack/plugins/security_solution/public/cloud_security_posture/components/misconfiguration/misconfiguration_preview.tsx
+++ b/x-pack/plugins/security_solution/public/cloud_security_posture/components/misconfiguration/misconfiguration_preview.tsx
@@ -17,10 +17,12 @@ import { i18n } from '@kbn/i18n';
import { ExpandablePanel } from '@kbn/security-solution-common';
import { buildEntityFlyoutPreviewQuery } from '@kbn/cloud-security-posture-common';
import { useExpandableFlyoutApi } from '@kbn/expandable-flyout';
+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 { buildHostNamesFilter } from '../../../../common/search_strategy';
+import type { HostRiskScore, UserRiskScore } from '../../../../common/search_strategy';
+import { buildHostNamesFilter, buildUserNamesFilter } from '../../../../common/search_strategy';
const FIRST_RECORD_PAGINATION = {
cursorStart: 0,
@@ -120,46 +122,63 @@ const MisconfigurationPreviewScore = ({
);
};
-export const MisconfigurationsPreview = ({ hostName }: { hostName: string }) => {
+export const MisconfigurationsPreview = ({
+ name,
+ fieldName,
+ isPreviewMode,
+}: {
+ name: string;
+ fieldName: 'host.name' | 'user.name';
+ isPreviewMode?: boolean;
+}) => {
const { data } = useMisconfigurationPreview({
- query: buildEntityFlyoutPreviewQuery('host.name', hostName),
+ query: buildEntityFlyoutPreviewQuery(fieldName, name),
sort: [],
enabled: true,
pageSize: 1,
});
-
+ const isUsingHostName = fieldName === 'host.name';
const passedFindings = data?.count.passed || 0;
const failedFindings = data?.count.failed || 0;
const { euiTheme } = useEuiTheme();
const hasMisconfigurationFindings = passedFindings > 0 || failedFindings > 0;
- const hostNameFilterQuery = useMemo(
- () => (hostName ? buildHostNamesFilter([hostName]) : undefined),
- [hostName]
+
+ const buildFilterQuery = useMemo(
+ () => (isUsingHostName ? buildHostNamesFilter([name]) : buildUserNamesFilter([name])),
+ [isUsingHostName, name]
);
const riskScoreState = useRiskScore({
- riskEntity: RiskScoreEntity.host,
- filterQuery: hostNameFilterQuery,
+ riskEntity: isUsingHostName ? RiskScoreEntity.host : RiskScoreEntity.user,
+ filterQuery: buildFilterQuery,
onlyLatest: false,
pagination: FIRST_RECORD_PAGINATION,
});
const { data: hostRisk } = riskScoreState;
- const hostRiskData = hostRisk && hostRisk.length > 0 ? hostRisk[0] : undefined;
- const isRiskScoreExist = !!hostRiskData?.host.risk;
+ const riskData = hostRisk?.[0];
+ const isRiskScoreExist = isUsingHostName
+ ? !!(riskData as HostRiskScore)?.host.risk
+ : !!(riskData as UserRiskScore)?.user.risk;
const { openLeftPanel } = useExpandableFlyoutApi();
- const isPreviewMode = false;
const goToEntityInsightTab = useCallback(() => {
openLeftPanel({
- id: HostDetailsPanelKey,
- params: {
- name: hostName,
- isRiskScoreExist,
- hasMisconfigurationFindings,
- path: { tab: 'csp_insights' },
- },
+ id: isUsingHostName ? HostDetailsPanelKey : UserDetailsPanelKey,
+ params: isUsingHostName
+ ? {
+ name,
+ isRiskScoreExist,
+ hasMisconfigurationFindings,
+ path: { tab: 'csp_insights' },
+ }
+ : {
+ user: { name },
+ isRiskScoreExist,
+ hasMisconfigurationFindings,
+ path: { tab: 'csp_insights' },
+ },
});
- }, [hasMisconfigurationFindings, hostName, isRiskScoreExist, openLeftPanel]);
+ }, [hasMisconfigurationFindings, isRiskScoreExist, isUsingHostName, name, openLeftPanel]);
const link = useMemo(
() =>
!isPreviewMode
@@ -178,7 +197,7 @@ export const MisconfigurationsPreview = ({ hostName }: { hostName: string }) =>
return (
+
-
);
};
diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/user_details_left/index.test.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/user_details_left/index.test.tsx
index bdff465e0b982..9c4b9938d6daa 100644
--- a/x-pack/plugins/security_solution/public/flyout/entity_details/user_details_left/index.test.tsx
+++ b/x-pack/plugins/security_solution/public/flyout/entity_details/user_details_left/index.test.tsx
@@ -51,4 +51,46 @@ describe('LeftPanel', () => {
expect(tabElement).not.toBeInTheDocument();
});
+
+ it("doesn't render insights panel when there no misconfiguration findings", () => {
+ const { queryByText } = render(
+ ,
+ {
+ wrapper: TestProviders,
+ }
+ );
+
+ const tabElement = queryByText('Insights');
+
+ expect(tabElement).not.toBeInTheDocument();
+ });
+
+ it('render insights panel when there are misconfiguration findings', () => {
+ const { queryByText } = render(
+ ,
+ {
+ wrapper: TestProviders,
+ }
+ );
+
+ const tabElement = queryByText('Insights');
+
+ expect(tabElement).toBeInTheDocument();
+ });
});
diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/user_details_left/index.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/user_details_left/index.tsx
index a04bd739eb299..ae3e99cc17cfe 100644
--- a/x-pack/plugins/security_solution/public/flyout/entity_details/user_details_left/index.tsx
+++ b/x-pack/plugins/security_solution/public/flyout/entity_details/user_details_left/index.tsx
@@ -28,6 +28,7 @@ export interface UserDetailsPanelProps extends Record {
user: UserParam;
path?: PanelPath;
scopeId: string;
+ hasMisconfigurationFindings?: boolean;
}
export interface UserDetailsExpandableFlyoutProps extends FlyoutPanelProps {
key: 'user_details';
@@ -40,10 +41,24 @@ export const UserDetailsPanel = ({
user,
path,
scopeId,
+ hasMisconfigurationFindings,
}: UserDetailsPanelProps) => {
const managedUser = useManagedUser(user.name, user.email);
- const tabs = useTabs(managedUser.data, user.name, isRiskScoreExist, scopeId);
- const { selectedTabId, setSelectedTabId } = useSelectedTab(isRiskScoreExist, user, tabs, path);
+ const tabs = useTabs(
+ managedUser.data,
+ user.name,
+ isRiskScoreExist,
+ scopeId,
+ hasMisconfigurationFindings
+ );
+
+ const { selectedTabId, setSelectedTabId } = useSelectedTab(
+ isRiskScoreExist,
+ user,
+ tabs,
+ path,
+ hasMisconfigurationFindings
+ );
if (managedUser.isLoading) return ;
@@ -67,7 +82,8 @@ const useSelectedTab = (
isRiskScoreExist: boolean,
user: UserParam,
tabs: LeftPanelTabsType,
- path: PanelPath | undefined
+ path: PanelPath | undefined,
+ hasMisconfigurationFindings?: boolean
) => {
const { openLeftPanel } = useExpandableFlyoutApi();
@@ -81,12 +97,13 @@ const useSelectedTab = (
const setSelectedTabId = (tabId: EntityDetailsLeftPanelTab) => {
openLeftPanel({
id: UserDetailsPanelKey,
- path: {
- tab: tabId,
- },
params: {
user,
isRiskScoreExist,
+ hasMisconfigurationFindings,
+ path: {
+ tab: tabId,
+ },
},
});
};
diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/user_details_left/tabs.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/user_details_left/tabs.tsx
index 3a6814a28e62c..6f27b054759f2 100644
--- a/x-pack/plugins/security_solution/public/flyout/entity_details/user_details_left/tabs.tsx
+++ b/x-pack/plugins/security_solution/public/flyout/entity_details/user_details_left/tabs.tsx
@@ -8,7 +8,10 @@
import React, { useMemo } from 'react';
import { FormattedMessage } from '@kbn/i18n-react';
-import { getRiskInputTab } from '../../../entity_analytics/components/entity_details_flyout';
+import {
+ getInsightsInputTab,
+ getRiskInputTab,
+} from '../../../entity_analytics/components/entity_details_flyout';
import { UserAssetTableType } from '../../../explore/users/store/model';
import { ManagedUserDatasetKey } from '../../../../common/search_strategy/security_solution/users/managed_details';
import type {
@@ -26,7 +29,8 @@ export const useTabs = (
managedUser: ManagedUserHits,
name: string,
isRiskScoreExist: boolean,
- scopeId: string
+ scopeId: string,
+ hasMisconfigurationFindings?: boolean
): LeftPanelTabsType =>
useMemo(() => {
const tabs: LeftPanelTabsType = [];
@@ -51,8 +55,12 @@ export const useTabs = (
tabs.push(getEntraTab(entraManagedUser));
}
+ if (hasMisconfigurationFindings) {
+ tabs.push(getInsightsInputTab({ name, fieldName: 'user.name' }));
+ }
+
return tabs;
- }, [isRiskScoreExist, managedUser, name, scopeId]);
+ }, [hasMisconfigurationFindings, isRiskScoreExist, managedUser, name, scopeId]);
const getOktaTab = (oktaManagedUser: ManagedUserHit) => ({
id: EntityDetailsLeftPanelTab.OKTA,
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 26945a12f8bd6..42b281d0c8d2b 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
@@ -23,6 +23,7 @@ import { ObservedEntity } from '../shared/components/observed_entity';
import type { ObservedEntityData } from '../shared/components/observed_entity/types';
import { useObservedUserItems } from './hooks/use_observed_user_items';
import type { EntityDetailsLeftPanelTab } from '../shared/components/left_panel/left_panel_header';
+import { EntityInsight } from '../../../cloud_security_posture/components';
interface UserPanelContentProps {
userName: string;
@@ -72,6 +73,7 @@ export const UserPanelContent = ({
entity={{ name: userName, type: 'user' }}
onChange={onAssetCriticalityChange}
/>
+
0 || failedFindings > 0;
+
useQueryInspector({
deleteQuery,
inspect,
@@ -119,11 +134,20 @@ export const UserPanel = ({
name: userName,
email,
},
+ path: tab ? { tab } : undefined,
+ hasMisconfigurationFindings,
},
- path: tab ? { tab } : undefined,
});
},
- [telemetry, openLeftPanel, userRiskData?.user?.risk, userName, email, scopeId]
+ [
+ telemetry,
+ openLeftPanel,
+ userRiskData?.user?.risk,
+ scopeId,
+ userName,
+ email,
+ hasMisconfigurationFindings,
+ ]
);
const openPanelFirstTab = useCallback(() => openPanelTab(), [openPanelTab]);
@@ -156,7 +180,9 @@ export const UserPanel = ({
return (
<>
(
-
+
),
},
{