mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Cloud Security] refetch status and dashboard data until data is indexed (#163005)
## Summary
This PR enables the Compliance Dashboard page (CSP dashboards) to
self-recover from different "no findings" states so that the user
doesn't need to reload the page to see the changes after they perform
onboarding steps (install integration, deploy agent, index data, etc.)
fixes
- https://github.com/elastic/kibana/issues/156616
### Recording
d0201ebb
-b8f8-4bce-b72e-3fdd85ab79fb
### Checklist
Delete any items that are not applicable to this PR.
- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
---------
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
1696b864a3
commit
9b087e080b
4 changed files with 358 additions and 85 deletions
|
@ -212,3 +212,5 @@ export const cloudPostureIntegrations: CloudPostureIntegrations = {
|
|||
};
|
||||
export const FINDINGS_DOCS_URL = 'https://ela.st/findings';
|
||||
export const MIN_VERSION_GCP_CIS = '1.5.0';
|
||||
|
||||
export const NO_FINDINGS_STATUS_REFRESH_INTERVAL_MS = 10000;
|
||||
|
|
|
@ -31,8 +31,7 @@ import type { IndexDetails, PostureTypes } from '../../common/types';
|
|||
import { cspIntegrationDocsNavigation } from '../common/navigation/constants';
|
||||
import noDataIllustration from '../assets/illustrations/no_data_illustration.svg';
|
||||
import { useCspIntegrationLink } from '../common/navigation/use_csp_integration_link';
|
||||
|
||||
const REFETCH_INTERVAL_MS = 20000;
|
||||
import { NO_FINDINGS_STATUS_REFRESH_INTERVAL_MS } from '../common/constants';
|
||||
|
||||
const NotDeployed = () => {
|
||||
// using an existing hook to get agent id and package policy id
|
||||
|
@ -248,7 +247,7 @@ const ConfigurationFindingsInstalledEmptyPrompt = ({
|
|||
* */
|
||||
export const NoFindingsStates = ({ posturetype }: { posturetype: PostureTypes }) => {
|
||||
const getSetupStatus = useCspSetupStatusApi({
|
||||
refetchInterval: REFETCH_INTERVAL_MS,
|
||||
refetchInterval: NO_FINDINGS_STATUS_REFRESH_INTERVAL_MS,
|
||||
});
|
||||
const statusKspm = getSetupStatus.data?.kspm?.status;
|
||||
const statusCspm = getSetupStatus.data?.cspm?.status;
|
||||
|
|
|
@ -10,7 +10,7 @@ import React from 'react';
|
|||
import { coreMock } from '@kbn/core/public/mocks';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { TestProvider } from '../../test/test_provider';
|
||||
import { ComplianceDashboard } from '.';
|
||||
import { ComplianceDashboard, getDefaultTab } from '.';
|
||||
import { useCspSetupStatusApi } from '../../common/api/use_setup_status_api';
|
||||
import { useLicenseManagementLocatorApi } from '../../common/api/use_license_management_locator_api';
|
||||
import { useSubscriptionStatus } from '../../common/hooks/use_subscription_status';
|
||||
|
@ -21,6 +21,7 @@ import {
|
|||
KUBERNETES_DASHBOARD_CONTAINER,
|
||||
KUBERNETES_DASHBOARD_TAB,
|
||||
CLOUD_DASHBOARD_TAB,
|
||||
CLOUD_POSTURE_DASHBOARD_PAGE_HEADER,
|
||||
} from './test_subjects';
|
||||
import { mockDashboardData } from './mock';
|
||||
import { createReactQueryResponse } from '../../test/fixtures/react_query';
|
||||
|
@ -29,7 +30,9 @@ import { expectIdsInDoc } from '../../test/utils';
|
|||
import {
|
||||
CSPM_INTEGRATION_NOT_INSTALLED_TEST_SUBJECT,
|
||||
KSPM_INTEGRATION_NOT_INSTALLED_TEST_SUBJECT,
|
||||
PACKAGE_NOT_INSTALLED_TEST_SUBJECT,
|
||||
} from '../../components/cloud_posture_page';
|
||||
import { BaseCspSetupStatus, ComplianceDashboardData, CspStatusCode } from '../../../common/types';
|
||||
|
||||
jest.mock('../../common/api/use_setup_status_api');
|
||||
jest.mock('../../common/api/use_stats_api');
|
||||
|
@ -73,10 +76,10 @@ describe('<ComplianceDashboard />', () => {
|
|||
);
|
||||
});
|
||||
|
||||
const renderComplianceDashboardPage = () => {
|
||||
const ComplianceDashboardWithTestProviders = () => {
|
||||
const mockCore = coreMock.createStart();
|
||||
|
||||
render(
|
||||
return (
|
||||
<TestProvider
|
||||
core={{
|
||||
...mockCore,
|
||||
|
@ -95,6 +98,51 @@ describe('<ComplianceDashboard />', () => {
|
|||
);
|
||||
};
|
||||
|
||||
const renderComplianceDashboardPage = () => {
|
||||
return render(<ComplianceDashboardWithTestProviders />);
|
||||
};
|
||||
|
||||
it('shows package not installed page instead of tabs', () => {
|
||||
(useCspSetupStatusApi as jest.Mock).mockImplementation(() =>
|
||||
createReactQueryResponse({
|
||||
status: 'success',
|
||||
data: {
|
||||
kspm: { status: 'not-installed', healthyAgents: 0, installedPackagePolicies: 0 },
|
||||
cspm: { status: 'not-installed', healthyAgents: 0, installedPackagePolicies: 0 },
|
||||
isPluginInitialized: false,
|
||||
indicesDetails: [
|
||||
{ index: 'logs-cloud_security_posture.findings_latest-default', status: 'empty' },
|
||||
{ index: 'logs-cloud_security_posture.findings-default*', status: 'empty' },
|
||||
],
|
||||
},
|
||||
})
|
||||
);
|
||||
(useKspmStatsApi as jest.Mock).mockImplementation(() => ({
|
||||
isSuccess: true,
|
||||
isLoading: false,
|
||||
data: { stats: { totalFindings: 0 } },
|
||||
}));
|
||||
(useCspmStatsApi as jest.Mock).mockImplementation(() => ({
|
||||
isSuccess: true,
|
||||
isLoading: false,
|
||||
data: { stats: { totalFindings: 0 } },
|
||||
}));
|
||||
|
||||
renderComplianceDashboardPage();
|
||||
|
||||
expectIdsInDoc({
|
||||
be: [PACKAGE_NOT_INSTALLED_TEST_SUBJECT, CLOUD_POSTURE_DASHBOARD_PAGE_HEADER],
|
||||
notToBe: [
|
||||
NO_FINDINGS_STATUS_TEST_SUBJ.NO_AGENTS_DEPLOYED,
|
||||
NO_FINDINGS_STATUS_TEST_SUBJ.INDEXING,
|
||||
NO_FINDINGS_STATUS_TEST_SUBJ.INDEX_TIMEOUT,
|
||||
NO_FINDINGS_STATUS_TEST_SUBJ.UNPRIVILEGED,
|
||||
CLOUD_DASHBOARD_CONTAINER,
|
||||
KUBERNETES_DASHBOARD_CONTAINER,
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('no findings state: not-deployed - shows NotDeployed instead of dashboard', () => {
|
||||
(useCspSetupStatusApi as jest.Mock).mockImplementation(() =>
|
||||
createReactQueryResponse({
|
||||
|
@ -124,11 +172,13 @@ describe('<ComplianceDashboard />', () => {
|
|||
renderComplianceDashboardPage();
|
||||
|
||||
expectIdsInDoc({
|
||||
be: [NO_FINDINGS_STATUS_TEST_SUBJ.NO_AGENTS_DEPLOYED],
|
||||
be: [NO_FINDINGS_STATUS_TEST_SUBJ.NO_AGENTS_DEPLOYED, CLOUD_DASHBOARD_TAB],
|
||||
notToBe: [
|
||||
NO_FINDINGS_STATUS_TEST_SUBJ.INDEXING,
|
||||
NO_FINDINGS_STATUS_TEST_SUBJ.INDEX_TIMEOUT,
|
||||
NO_FINDINGS_STATUS_TEST_SUBJ.UNPRIVILEGED,
|
||||
CLOUD_DASHBOARD_CONTAINER,
|
||||
KUBERNETES_DASHBOARD_CONTAINER,
|
||||
],
|
||||
});
|
||||
});
|
||||
|
@ -162,11 +212,53 @@ describe('<ComplianceDashboard />', () => {
|
|||
renderComplianceDashboardPage();
|
||||
|
||||
expectIdsInDoc({
|
||||
be: [NO_FINDINGS_STATUS_TEST_SUBJ.INDEXING],
|
||||
be: [NO_FINDINGS_STATUS_TEST_SUBJ.INDEXING, CLOUD_DASHBOARD_TAB],
|
||||
notToBe: [
|
||||
NO_FINDINGS_STATUS_TEST_SUBJ.NO_AGENTS_DEPLOYED,
|
||||
NO_FINDINGS_STATUS_TEST_SUBJ.INDEX_TIMEOUT,
|
||||
NO_FINDINGS_STATUS_TEST_SUBJ.UNPRIVILEGED,
|
||||
CLOUD_DASHBOARD_CONTAINER,
|
||||
KUBERNETES_DASHBOARD_CONTAINER,
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('no findings state: indexing - shows Indexing instead of dashboard when waiting_for_results', () => {
|
||||
(useCspSetupStatusApi as jest.Mock).mockImplementation(() =>
|
||||
createReactQueryResponse({
|
||||
status: 'success',
|
||||
data: {
|
||||
kspm: { status: 'waiting_for_results', healthyAgents: 1, installedPackagePolicies: 1 },
|
||||
cspm: { status: 'waiting_for_results', healthyAgents: 1, installedPackagePolicies: 1 },
|
||||
installedPackageVersion: '1.2.13',
|
||||
indicesDetails: [
|
||||
{ index: 'logs-cloud_security_posture.findings_latest-default', status: 'empty' },
|
||||
{ index: 'logs-cloud_security_posture.findings-default*', status: 'empty' },
|
||||
],
|
||||
},
|
||||
})
|
||||
);
|
||||
(useKspmStatsApi as jest.Mock).mockImplementation(() => ({
|
||||
isSuccess: true,
|
||||
isLoading: false,
|
||||
data: { stats: { totalFindings: 1 } },
|
||||
}));
|
||||
(useCspmStatsApi as jest.Mock).mockImplementation(() => ({
|
||||
isSuccess: true,
|
||||
isLoading: false,
|
||||
data: { stats: { totalFindings: 1 } },
|
||||
}));
|
||||
|
||||
renderComplianceDashboardPage();
|
||||
|
||||
expectIdsInDoc({
|
||||
be: [NO_FINDINGS_STATUS_TEST_SUBJ.INDEXING, CLOUD_DASHBOARD_TAB],
|
||||
notToBe: [
|
||||
NO_FINDINGS_STATUS_TEST_SUBJ.NO_AGENTS_DEPLOYED,
|
||||
NO_FINDINGS_STATUS_TEST_SUBJ.INDEX_TIMEOUT,
|
||||
NO_FINDINGS_STATUS_TEST_SUBJ.UNPRIVILEGED,
|
||||
CLOUD_DASHBOARD_CONTAINER,
|
||||
KUBERNETES_DASHBOARD_CONTAINER,
|
||||
],
|
||||
});
|
||||
});
|
||||
|
@ -200,11 +292,13 @@ describe('<ComplianceDashboard />', () => {
|
|||
renderComplianceDashboardPage();
|
||||
|
||||
expectIdsInDoc({
|
||||
be: [NO_FINDINGS_STATUS_TEST_SUBJ.INDEX_TIMEOUT],
|
||||
be: [NO_FINDINGS_STATUS_TEST_SUBJ.INDEX_TIMEOUT, CLOUD_DASHBOARD_TAB],
|
||||
notToBe: [
|
||||
NO_FINDINGS_STATUS_TEST_SUBJ.NO_AGENTS_DEPLOYED,
|
||||
NO_FINDINGS_STATUS_TEST_SUBJ.INDEXING,
|
||||
NO_FINDINGS_STATUS_TEST_SUBJ.UNPRIVILEGED,
|
||||
CLOUD_DASHBOARD_CONTAINER,
|
||||
KUBERNETES_DASHBOARD_CONTAINER,
|
||||
],
|
||||
});
|
||||
});
|
||||
|
@ -238,11 +332,13 @@ describe('<ComplianceDashboard />', () => {
|
|||
renderComplianceDashboardPage();
|
||||
|
||||
expectIdsInDoc({
|
||||
be: [NO_FINDINGS_STATUS_TEST_SUBJ.UNPRIVILEGED],
|
||||
be: [NO_FINDINGS_STATUS_TEST_SUBJ.UNPRIVILEGED, CLOUD_DASHBOARD_TAB],
|
||||
notToBe: [
|
||||
NO_FINDINGS_STATUS_TEST_SUBJ.NO_AGENTS_DEPLOYED,
|
||||
NO_FINDINGS_STATUS_TEST_SUBJ.INDEXING,
|
||||
NO_FINDINGS_STATUS_TEST_SUBJ.INDEX_TIMEOUT,
|
||||
CLOUD_DASHBOARD_CONTAINER,
|
||||
KUBERNETES_DASHBOARD_CONTAINER,
|
||||
],
|
||||
});
|
||||
});
|
||||
|
@ -276,7 +372,7 @@ describe('<ComplianceDashboard />', () => {
|
|||
renderComplianceDashboardPage();
|
||||
|
||||
expectIdsInDoc({
|
||||
be: [DASHBOARD_CONTAINER],
|
||||
be: [CLOUD_DASHBOARD_TAB, DASHBOARD_CONTAINER, CLOUD_DASHBOARD_CONTAINER],
|
||||
notToBe: [
|
||||
NO_FINDINGS_STATUS_TEST_SUBJ.INDEX_TIMEOUT,
|
||||
NO_FINDINGS_STATUS_TEST_SUBJ.NO_AGENTS_DEPLOYED,
|
||||
|
@ -315,7 +411,7 @@ describe('<ComplianceDashboard />', () => {
|
|||
renderComplianceDashboardPage();
|
||||
|
||||
expectIdsInDoc({
|
||||
be: [KUBERNETES_DASHBOARD_CONTAINER],
|
||||
be: [KUBERNETES_DASHBOARD_TAB, KUBERNETES_DASHBOARD_CONTAINER],
|
||||
notToBe: [
|
||||
CLOUD_DASHBOARD_CONTAINER,
|
||||
NO_FINDINGS_STATUS_TEST_SUBJ.INDEX_TIMEOUT,
|
||||
|
@ -354,7 +450,7 @@ describe('<ComplianceDashboard />', () => {
|
|||
renderComplianceDashboardPage();
|
||||
|
||||
expectIdsInDoc({
|
||||
be: [CLOUD_DASHBOARD_CONTAINER],
|
||||
be: [CLOUD_DASHBOARD_TAB, CLOUD_DASHBOARD_CONTAINER],
|
||||
notToBe: [
|
||||
KUBERNETES_DASHBOARD_CONTAINER,
|
||||
NO_FINDINGS_STATUS_TEST_SUBJ.INDEX_TIMEOUT,
|
||||
|
@ -550,10 +646,12 @@ describe('<ComplianceDashboard />', () => {
|
|||
data: { stats: { totalFindings: 0 } },
|
||||
}));
|
||||
|
||||
renderComplianceDashboardPage();
|
||||
const { rerender } = renderComplianceDashboardPage();
|
||||
|
||||
screen.getByTestId(CLOUD_DASHBOARD_TAB).click();
|
||||
|
||||
rerender(<ComplianceDashboardWithTestProviders />);
|
||||
|
||||
expectIdsInDoc({
|
||||
be: [CSPM_INTEGRATION_NOT_INSTALLED_TEST_SUBJECT],
|
||||
notToBe: [
|
||||
|
@ -607,4 +705,148 @@ describe('<ComplianceDashboard />', () => {
|
|||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('should not select default tab is user has already selected one themselves', () => {
|
||||
(useCspSetupStatusApi as jest.Mock).mockImplementation(() =>
|
||||
createReactQueryResponse({
|
||||
status: 'success',
|
||||
data: {
|
||||
kspm: { status: 'not-installed' },
|
||||
cspm: { status: 'indexed' },
|
||||
installedPackageVersion: '1.2.13',
|
||||
indicesDetails: [
|
||||
{ index: 'logs-cloud_security_posture.findings_latest-default', status: 'not-empty' },
|
||||
{ index: 'logs-cloud_security_posture.findings-default*', status: 'empty' },
|
||||
],
|
||||
},
|
||||
})
|
||||
);
|
||||
(useKspmStatsApi as jest.Mock).mockImplementation(() => ({
|
||||
isSuccess: true,
|
||||
isLoading: false,
|
||||
data: { stats: { totalFindings: 0 } },
|
||||
}));
|
||||
(useCspmStatsApi as jest.Mock).mockImplementation(() => ({
|
||||
isSuccess: true,
|
||||
isLoading: false,
|
||||
data: mockDashboardData,
|
||||
}));
|
||||
|
||||
const { rerender } = renderComplianceDashboardPage();
|
||||
|
||||
expectIdsInDoc({
|
||||
be: [CLOUD_DASHBOARD_CONTAINER],
|
||||
notToBe: [
|
||||
KUBERNETES_DASHBOARD_CONTAINER,
|
||||
NO_FINDINGS_STATUS_TEST_SUBJ.INDEX_TIMEOUT,
|
||||
NO_FINDINGS_STATUS_TEST_SUBJ.NO_AGENTS_DEPLOYED,
|
||||
NO_FINDINGS_STATUS_TEST_SUBJ.INDEXING,
|
||||
NO_FINDINGS_STATUS_TEST_SUBJ.UNPRIVILEGED,
|
||||
],
|
||||
});
|
||||
|
||||
screen.getByTestId(KUBERNETES_DASHBOARD_TAB).click();
|
||||
|
||||
rerender(<ComplianceDashboardWithTestProviders />);
|
||||
|
||||
expectIdsInDoc({
|
||||
be: [KSPM_INTEGRATION_NOT_INSTALLED_TEST_SUBJECT],
|
||||
notToBe: [
|
||||
CLOUD_DASHBOARD_CONTAINER,
|
||||
NO_FINDINGS_STATUS_TEST_SUBJ.INDEX_TIMEOUT,
|
||||
NO_FINDINGS_STATUS_TEST_SUBJ.NO_AGENTS_DEPLOYED,
|
||||
NO_FINDINGS_STATUS_TEST_SUBJ.INDEXING,
|
||||
NO_FINDINGS_STATUS_TEST_SUBJ.UNPRIVILEGED,
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getDefaultTab', () => {
|
||||
const getPluginStatusMock = (cspmStatus: CspStatusCode, kspmStatus: CspStatusCode) => {
|
||||
return {
|
||||
cspm: { status: cspmStatus },
|
||||
kspm: { status: kspmStatus },
|
||||
};
|
||||
};
|
||||
const getStatsMock = (findings: number) => {
|
||||
return {
|
||||
stats: {
|
||||
totalFindings: findings,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
it('returns CSPM tab if only CSPM has findings', () => {
|
||||
const pluginStatus = getPluginStatusMock('indexed', 'indexed') as BaseCspSetupStatus;
|
||||
const cspmStats = getStatsMock(1) as ComplianceDashboardData;
|
||||
const kspmStats = getStatsMock(0) as ComplianceDashboardData;
|
||||
|
||||
expect(getDefaultTab(pluginStatus, cspmStats, kspmStats)).toEqual('cspm');
|
||||
});
|
||||
|
||||
it('returns CSPM tab if both CSPM and KSPM has findings', () => {
|
||||
const pluginStatus = getPluginStatusMock('indexed', 'indexed') as BaseCspSetupStatus;
|
||||
const cspmStats = getStatsMock(1) as ComplianceDashboardData;
|
||||
const kspmStats = getStatsMock(1) as ComplianceDashboardData;
|
||||
|
||||
expect(getDefaultTab(pluginStatus, cspmStats, kspmStats)).toEqual('cspm');
|
||||
});
|
||||
|
||||
it('returns KSPM tab if only KSPM has findings', () => {
|
||||
const pluginStatus = getPluginStatusMock('indexed', 'indexed') as BaseCspSetupStatus;
|
||||
const cspmStats = getStatsMock(0) as ComplianceDashboardData;
|
||||
const kspmStats = getStatsMock(1) as ComplianceDashboardData;
|
||||
|
||||
expect(getDefaultTab(pluginStatus, cspmStats, kspmStats)).toEqual('kspm');
|
||||
});
|
||||
|
||||
it('when no findings preffers CSPM tab unless not-installed or unprivileged', () => {
|
||||
const cspmStats = getStatsMock(0) as ComplianceDashboardData;
|
||||
const kspmStats = getStatsMock(0) as ComplianceDashboardData;
|
||||
const CspStatusCodeArray: CspStatusCode[] = [
|
||||
'indexed',
|
||||
'indexing',
|
||||
'unprivileged',
|
||||
'index-timeout',
|
||||
'not-deployed',
|
||||
'not-installed',
|
||||
'waiting_for_results',
|
||||
];
|
||||
|
||||
CspStatusCodeArray.forEach((cspmStatus) => {
|
||||
CspStatusCodeArray.forEach((kspmStatus) => {
|
||||
let expectedTab = 'cspm';
|
||||
const pluginStatus = getPluginStatusMock(cspmStatus, kspmStatus) as BaseCspSetupStatus;
|
||||
|
||||
if (
|
||||
(cspmStatus === 'not-installed' || cspmStatus === 'unprivileged') &&
|
||||
kspmStatus !== 'not-installed' &&
|
||||
kspmStatus !== 'unprivileged'
|
||||
) {
|
||||
expectedTab = 'kspm';
|
||||
}
|
||||
|
||||
expect(getDefaultTab(pluginStatus, cspmStats, kspmStats)).toEqual(expectedTab);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('returns CSPM tab is plugin status and kspm status is not provided', () => {
|
||||
const cspmStats = getStatsMock(1) as ComplianceDashboardData;
|
||||
|
||||
expect(getDefaultTab(undefined, cspmStats, undefined)).toEqual('cspm');
|
||||
});
|
||||
|
||||
it('returns KSPM tab is plugin status and csp status is not provided', () => {
|
||||
const kspmStats = getStatsMock(1) as ComplianceDashboardData;
|
||||
|
||||
expect(getDefaultTab(undefined, undefined, kspmStats)).toEqual('kspm');
|
||||
});
|
||||
|
||||
it('returns CSPM tab when only plugins status data is provided', () => {
|
||||
const pluginStatus = getPluginStatusMock('indexed', 'indexed') as BaseCspSetupStatus;
|
||||
|
||||
expect(getDefaultTab(pluginStatus, undefined, undefined)).toEqual('cspm');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import { UseQueryResult } from '@tanstack/react-query';
|
||||
import { EuiEmptyPrompt, EuiIcon, EuiLink, EuiPageHeader, EuiSpacer } from '@elastic/eui';
|
||||
import { css } from '@emotion/react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
@ -40,6 +41,10 @@ import { SummarySection } from './dashboard_sections/summary_section';
|
|||
import { BenchmarksSection } from './dashboard_sections/benchmarks_section';
|
||||
import { CSPM_POLICY_TEMPLATE, KSPM_POLICY_TEMPLATE } from '../../../common/constants';
|
||||
import { cspIntegrationDocsNavigation } from '../../common/navigation/constants';
|
||||
import { NO_FINDINGS_STATUS_REFRESH_INTERVAL_MS } from '../../common/constants';
|
||||
|
||||
const POSTURE_TYPE_CSPM = CSPM_POLICY_TEMPLATE;
|
||||
const POSTURE_TYPE_KSPM = KSPM_POLICY_TEMPLATE;
|
||||
|
||||
const noDataOptions: Record<
|
||||
PosturePolicyTemplate,
|
||||
|
@ -181,7 +186,7 @@ const IntegrationPostureDashboard = ({
|
|||
);
|
||||
};
|
||||
|
||||
const getDefaultTab = (
|
||||
export const getDefaultTab = (
|
||||
pluginStatus?: BaseCspSetupStatus,
|
||||
cspmStats?: ComplianceDashboardData,
|
||||
kspmStats?: ComplianceDashboardData
|
||||
|
@ -190,42 +195,109 @@ const getDefaultTab = (
|
|||
const kspmTotalFindings = kspmStats?.stats.totalFindings;
|
||||
const installedPolicyTemplatesCspm = pluginStatus?.cspm?.status;
|
||||
const installedPolicyTemplatesKspm = pluginStatus?.kspm?.status;
|
||||
let preferredDashboard = CSPM_POLICY_TEMPLATE;
|
||||
let preferredDashboard = POSTURE_TYPE_CSPM;
|
||||
|
||||
// cspm has findings
|
||||
if (!!cspmTotalFindings) {
|
||||
preferredDashboard = CSPM_POLICY_TEMPLATE;
|
||||
preferredDashboard = POSTURE_TYPE_CSPM;
|
||||
}
|
||||
// kspm has findings
|
||||
else if (!!kspmTotalFindings) {
|
||||
preferredDashboard = KSPM_POLICY_TEMPLATE;
|
||||
preferredDashboard = POSTURE_TYPE_KSPM;
|
||||
}
|
||||
// cspm is installed
|
||||
else if (
|
||||
installedPolicyTemplatesCspm !== 'unprivileged' &&
|
||||
installedPolicyTemplatesCspm !== 'not-installed'
|
||||
) {
|
||||
preferredDashboard = CSPM_POLICY_TEMPLATE;
|
||||
preferredDashboard = POSTURE_TYPE_CSPM;
|
||||
}
|
||||
// kspm is installed
|
||||
else if (
|
||||
installedPolicyTemplatesKspm !== 'unprivileged' &&
|
||||
installedPolicyTemplatesKspm !== 'not-installed'
|
||||
) {
|
||||
preferredDashboard = KSPM_POLICY_TEMPLATE;
|
||||
preferredDashboard = POSTURE_TYPE_KSPM;
|
||||
}
|
||||
|
||||
return preferredDashboard;
|
||||
};
|
||||
|
||||
export const ComplianceDashboard = () => {
|
||||
const [selectedTab, setSelectedTab] = useState(CSPM_POLICY_TEMPLATE);
|
||||
const { data: getSetupStatus } = useCspSetupStatusApi();
|
||||
const determineDashboardDataRefetchInterval = (data: ComplianceDashboardData | undefined) => {
|
||||
if (data?.stats.totalFindings === 0) {
|
||||
return NO_FINDINGS_STATUS_REFRESH_INTERVAL_MS;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
const TabContent = ({ posturetype }: { posturetype: PosturePolicyTemplate }) => {
|
||||
const { data: getSetupStatus } = useCspSetupStatusApi({
|
||||
refetchInterval: (data) => {
|
||||
if (data?.[posturetype]?.status === 'indexed') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return NO_FINDINGS_STATUS_REFRESH_INTERVAL_MS;
|
||||
},
|
||||
});
|
||||
const isCloudSecurityPostureInstalled = !!getSetupStatus?.installedPackageVersion;
|
||||
const getCspmDashboardData = useCspmStatsApi({
|
||||
enabled: isCloudSecurityPostureInstalled && posturetype === POSTURE_TYPE_CSPM,
|
||||
refetchInterval: determineDashboardDataRefetchInterval,
|
||||
});
|
||||
const getKspmDashboardData = useKspmStatsApi({
|
||||
enabled: isCloudSecurityPostureInstalled && posturetype === POSTURE_TYPE_KSPM,
|
||||
refetchInterval: determineDashboardDataRefetchInterval,
|
||||
});
|
||||
const setupStatus = getSetupStatus?.[posturetype]?.status;
|
||||
const isStatusManagedInDashboard = setupStatus === 'indexed' || setupStatus === 'not-installed';
|
||||
const shouldRenderNoFindings = !isCloudSecurityPostureInstalled || !isStatusManagedInDashboard;
|
||||
const cspmIntegrationLink = useCspIntegrationLink(CSPM_POLICY_TEMPLATE);
|
||||
const kspmIntegrationLink = useCspIntegrationLink(KSPM_POLICY_TEMPLATE);
|
||||
const isCloudSecurityPostureInstalled = !!getSetupStatus?.installedPackageVersion;
|
||||
let integrationLink;
|
||||
let dataTestSubj;
|
||||
let policyTemplate: PosturePolicyTemplate;
|
||||
let getDashboardData: UseQueryResult<ComplianceDashboardData>;
|
||||
|
||||
switch (posturetype) {
|
||||
case POSTURE_TYPE_CSPM:
|
||||
integrationLink = cspmIntegrationLink;
|
||||
dataTestSubj = CLOUD_DASHBOARD_CONTAINER;
|
||||
policyTemplate = CSPM_POLICY_TEMPLATE;
|
||||
getDashboardData = getCspmDashboardData;
|
||||
break;
|
||||
case POSTURE_TYPE_KSPM:
|
||||
integrationLink = kspmIntegrationLink;
|
||||
dataTestSubj = KUBERNETES_DASHBOARD_CONTAINER;
|
||||
policyTemplate = KSPM_POLICY_TEMPLATE;
|
||||
getDashboardData = getKspmDashboardData;
|
||||
break;
|
||||
}
|
||||
|
||||
if (shouldRenderNoFindings) {
|
||||
return <NoFindingsStates posturetype={posturetype} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<CloudPosturePage query={getDashboardData}>
|
||||
<div data-test-subj={dataTestSubj}>
|
||||
<IntegrationPostureDashboard
|
||||
dashboardType={policyTemplate}
|
||||
complianceData={getDashboardData.data}
|
||||
notInstalledConfig={getNotInstalledConfig(policyTemplate, integrationLink)}
|
||||
isIntegrationInstalled={setupStatus !== 'not-installed'}
|
||||
/>
|
||||
</div>
|
||||
</CloudPosturePage>
|
||||
);
|
||||
};
|
||||
|
||||
export const ComplianceDashboard = () => {
|
||||
const [selectedTab, setSelectedTab] = useState(POSTURE_TYPE_CSPM);
|
||||
const [hasUserSelectedTab, setHasUserSelectedTab] = useState(false);
|
||||
const { data: getSetupStatus } = useCspSetupStatusApi();
|
||||
const isCloudSecurityPostureInstalled = !!getSetupStatus?.installedPackageVersion;
|
||||
const getCspmDashboardData = useCspmStatsApi({
|
||||
enabled: isCloudSecurityPostureInstalled,
|
||||
});
|
||||
|
@ -234,6 +306,10 @@ export const ComplianceDashboard = () => {
|
|||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (hasUserSelectedTab) {
|
||||
return;
|
||||
}
|
||||
|
||||
const preferredDashboard = getDefaultTab(
|
||||
getSetupStatus,
|
||||
getCspmDashboardData.data,
|
||||
|
@ -248,6 +324,7 @@ export const ComplianceDashboard = () => {
|
|||
getSetupStatus,
|
||||
getSetupStatus?.cspm?.status,
|
||||
getSetupStatus?.kspm?.status,
|
||||
hasUserSelectedTab,
|
||||
]);
|
||||
|
||||
const tabs = useMemo(
|
||||
|
@ -259,75 +336,28 @@ export const ComplianceDashboard = () => {
|
|||
defaultMessage: 'Cloud',
|
||||
}),
|
||||
'data-test-subj': CLOUD_DASHBOARD_TAB,
|
||||
isSelected: selectedTab === CSPM_POLICY_TEMPLATE,
|
||||
onClick: () => setSelectedTab(CSPM_POLICY_TEMPLATE),
|
||||
content: (
|
||||
<>
|
||||
{isCloudSecurityPostureInstalled &&
|
||||
(getSetupStatus?.cspm?.status === 'indexed' ||
|
||||
getSetupStatus?.cspm?.status === 'not-installed') ? (
|
||||
<CloudPosturePage query={getCspmDashboardData}>
|
||||
<div data-test-subj={CLOUD_DASHBOARD_CONTAINER}>
|
||||
<IntegrationPostureDashboard
|
||||
dashboardType={CSPM_POLICY_TEMPLATE}
|
||||
complianceData={getCspmDashboardData.data}
|
||||
notInstalledConfig={getNotInstalledConfig(
|
||||
CSPM_POLICY_TEMPLATE,
|
||||
cspmIntegrationLink
|
||||
)}
|
||||
isIntegrationInstalled={getSetupStatus?.cspm?.status !== 'not-installed'}
|
||||
/>
|
||||
</div>
|
||||
</CloudPosturePage>
|
||||
) : (
|
||||
<NoFindingsStates posturetype={'cspm'} />
|
||||
)}
|
||||
</>
|
||||
),
|
||||
isSelected: selectedTab === POSTURE_TYPE_CSPM,
|
||||
onClick: () => {
|
||||
setSelectedTab(POSTURE_TYPE_CSPM);
|
||||
setHasUserSelectedTab(true);
|
||||
},
|
||||
content: <TabContent posturetype={POSTURE_TYPE_CSPM} />,
|
||||
},
|
||||
{
|
||||
label: i18n.translate('xpack.csp.dashboardTabs.kubernetesTab.tabTitle', {
|
||||
defaultMessage: 'Kubernetes',
|
||||
}),
|
||||
'data-test-subj': KUBERNETES_DASHBOARD_TAB,
|
||||
isSelected: selectedTab === KSPM_POLICY_TEMPLATE,
|
||||
onClick: () => setSelectedTab(KSPM_POLICY_TEMPLATE),
|
||||
content: (
|
||||
<>
|
||||
{isCloudSecurityPostureInstalled &&
|
||||
(getSetupStatus?.kspm?.status === 'indexed' ||
|
||||
getSetupStatus?.kspm?.status === 'not-installed') ? (
|
||||
<CloudPosturePage query={getKspmDashboardData}>
|
||||
<div data-test-subj={KUBERNETES_DASHBOARD_CONTAINER}>
|
||||
<IntegrationPostureDashboard
|
||||
dashboardType={KSPM_POLICY_TEMPLATE}
|
||||
complianceData={getKspmDashboardData.data}
|
||||
notInstalledConfig={getNotInstalledConfig(
|
||||
KSPM_POLICY_TEMPLATE,
|
||||
kspmIntegrationLink
|
||||
)}
|
||||
isIntegrationInstalled={getSetupStatus?.kspm?.status !== 'not-installed'}
|
||||
/>
|
||||
</div>
|
||||
</CloudPosturePage>
|
||||
) : (
|
||||
<NoFindingsStates posturetype={'kspm'} />
|
||||
)}
|
||||
</>
|
||||
),
|
||||
isSelected: selectedTab === POSTURE_TYPE_KSPM,
|
||||
onClick: () => {
|
||||
setSelectedTab(POSTURE_TYPE_KSPM);
|
||||
setHasUserSelectedTab(true);
|
||||
},
|
||||
content: <TabContent posturetype={POSTURE_TYPE_KSPM} />,
|
||||
},
|
||||
]
|
||||
: [],
|
||||
[
|
||||
cspmIntegrationLink,
|
||||
getCspmDashboardData,
|
||||
getKspmDashboardData,
|
||||
kspmIntegrationLink,
|
||||
selectedTab,
|
||||
isCloudSecurityPostureInstalled,
|
||||
getSetupStatus?.cspm?.status,
|
||||
getSetupStatus?.kspm?.status,
|
||||
]
|
||||
[selectedTab, isCloudSecurityPostureInstalled]
|
||||
);
|
||||
|
||||
return (
|
||||
|
@ -354,7 +384,7 @@ export const ComplianceDashboard = () => {
|
|||
`}
|
||||
>
|
||||
{tabs.find((t) => t.isSelected)?.content}
|
||||
{!isCloudSecurityPostureInstalled && <NoFindingsStates posturetype={'cspm'} />}
|
||||
{!isCloudSecurityPostureInstalled && <NoFindingsStates posturetype={POSTURE_TYPE_CSPM} />}
|
||||
</div>
|
||||
</CloudPosturePage>
|
||||
);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue