mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[Cloud Posture] New csp dashboard layout placement (#144209)
This commit is contained in:
parent
a7976e57aa
commit
b43c3ddf30
4 changed files with 247 additions and 5 deletions
|
@ -42,6 +42,7 @@ export const INTERNAL_FEATURE_FLAGS = {
|
|||
showManageRulesMock: false,
|
||||
showFindingFlyoutEvidence: false,
|
||||
showFindingsGroupBy: true,
|
||||
showNewDashboard: false,
|
||||
} as const;
|
||||
|
||||
export const CSP_RULE_SAVED_OBJECT_TYPE = 'csp_rule';
|
||||
|
|
|
@ -9,6 +9,8 @@ import React from 'react';
|
|||
import { EuiSpacer, EuiPageHeader } from '@elastic/eui';
|
||||
import { css } from '@emotion/react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { INTERNAL_FEATURE_FLAGS } from '../../../common/constants';
|
||||
import { CloudSummarySection } from './dashboard_sections/cloud_summary_section';
|
||||
import { CloudPosturePageTitle } from '../../components/cloud_posture_page_title';
|
||||
import { CloudPosturePage } from '../../components/cloud_posture_page';
|
||||
import { DASHBOARD_CONTAINER } from './test_subjects';
|
||||
|
@ -17,6 +19,7 @@ import { BenchmarksSection } from './dashboard_sections/benchmarks_section';
|
|||
import { useComplianceDashboardDataApi } from '../../common/api';
|
||||
import { useCspSetupStatusApi } from '../../common/api/use_setup_status_api';
|
||||
import { NoFindingsStates } from '../../components/no_findings_states';
|
||||
import { CloudBenchmarksSection } from './dashboard_sections/cloud_benchmarks_section';
|
||||
|
||||
export const ComplianceDashboard = () => {
|
||||
const getSetupStatus = useCspSetupStatusApi();
|
||||
|
@ -43,15 +46,26 @@ export const ComplianceDashboard = () => {
|
|||
<div
|
||||
data-test-subj={DASHBOARD_CONTAINER}
|
||||
css={css`
|
||||
max-width: 1600px;
|
||||
max-width: 1440px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
`}
|
||||
>
|
||||
<SummarySection complianceData={getDashboardData.data!} />
|
||||
<EuiSpacer />
|
||||
<BenchmarksSection complianceData={getDashboardData.data!} />
|
||||
<EuiSpacer />
|
||||
{INTERNAL_FEATURE_FLAGS.showNewDashboard ? (
|
||||
<>
|
||||
<CloudSummarySection complianceData={getDashboardData.data!} />
|
||||
<EuiSpacer />
|
||||
<CloudBenchmarksSection complianceData={getDashboardData.data!} />
|
||||
<EuiSpacer />
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<SummarySection complianceData={getDashboardData.data!} />
|
||||
<EuiSpacer />
|
||||
<BenchmarksSection complianceData={getDashboardData.data!} />
|
||||
<EuiSpacer />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</CloudPosturePage>
|
||||
);
|
||||
|
|
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* 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 React from 'react';
|
||||
import { EuiFlexItem, EuiFlexGroup, useEuiTheme, EuiTitle } from '@elastic/eui';
|
||||
import { PartitionElementEvent } from '@elastic/charts';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { ChartPanel } from '../../../components/chart_panel';
|
||||
import { CloudPostureScoreChart } from '../compliance_charts/cloud_posture_score_chart';
|
||||
import type { ComplianceDashboardData, Evaluation } from '../../../../common/types';
|
||||
import { RisksTable } from '../compliance_charts/risks_table';
|
||||
import { RULE_FAILED } from '../../../../common/constants';
|
||||
import { useNavigateFindings } from '../../../common/hooks/use_navigate_findings';
|
||||
import { ClusterDetailsBox } from './cluster_details_box';
|
||||
import { dashboardColumnsGrow } from './cloud_summary_section';
|
||||
|
||||
export const CloudBenchmarksSection = ({
|
||||
complianceData,
|
||||
}: {
|
||||
complianceData: ComplianceDashboardData;
|
||||
}) => {
|
||||
const { euiTheme } = useEuiTheme();
|
||||
const navToFindings = useNavigateFindings();
|
||||
|
||||
const handleElementClick = (clusterId: string, elements: PartitionElementEvent[]) => {
|
||||
const [element] = elements;
|
||||
const [layerValue] = element;
|
||||
const evaluation = layerValue[0].groupByRollup as Evaluation;
|
||||
|
||||
navToFindings({ cluster_id: clusterId, 'result.evaluation': evaluation });
|
||||
};
|
||||
|
||||
const handleCellClick = (clusterId: string, ruleSection: string) => {
|
||||
navToFindings({
|
||||
cluster_id: clusterId,
|
||||
'rule.section': ruleSection,
|
||||
'result.evaluation': RULE_FAILED,
|
||||
});
|
||||
};
|
||||
|
||||
const handleViewAllClick = (clusterId: string) => {
|
||||
navToFindings({ cluster_id: clusterId, 'result.evaluation': RULE_FAILED });
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<EuiFlexGroup
|
||||
alignItems="flexStart"
|
||||
gutterSize="none"
|
||||
style={{
|
||||
borderBottom: euiTheme.border.thick,
|
||||
borderBottomColor: euiTheme.colors.text,
|
||||
marginBottom: euiTheme.size.l,
|
||||
paddingBottom: euiTheme.size.s,
|
||||
}}
|
||||
>
|
||||
<EuiFlexItem grow={dashboardColumnsGrow.first}>
|
||||
<EuiTitle size="xxs" css={{ fontWeight: euiTheme.font.weight.semiBold }}>
|
||||
<h5>
|
||||
<FormattedMessage
|
||||
id="xpack.csp.dashboard.cloudBenchmarkSection.columnsHeader.clusterNameTitle"
|
||||
defaultMessage="Cluster Name"
|
||||
/>
|
||||
</h5>
|
||||
</EuiTitle>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={dashboardColumnsGrow.second}>
|
||||
<EuiTitle
|
||||
size="xxs"
|
||||
css={{ fontWeight: euiTheme.font.weight.semiBold, paddingLeft: euiTheme.size.xl }}
|
||||
>
|
||||
<h5>
|
||||
<FormattedMessage
|
||||
id="xpack.csp.dashboard.cloudBenchmarkSection.columnsHeader.complianceScoreTitle"
|
||||
defaultMessage="Compliance Score"
|
||||
/>
|
||||
</h5>
|
||||
</EuiTitle>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={dashboardColumnsGrow.third}>
|
||||
<EuiTitle
|
||||
size="xxs"
|
||||
css={{ fontWeight: euiTheme.font.weight.semiBold, paddingLeft: euiTheme.size.xl }}
|
||||
>
|
||||
<h5>
|
||||
<FormattedMessage
|
||||
id="xpack.csp.dashboard.cloudBenchmarkSection.columnsHeader.complianceByCisSectionTitle"
|
||||
defaultMessage="Compliance by CIS Section"
|
||||
/>
|
||||
</h5>
|
||||
</EuiTitle>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
{complianceData.clusters.map((cluster) => (
|
||||
<EuiFlexGroup
|
||||
key={cluster.meta.clusterId}
|
||||
gutterSize="l"
|
||||
style={{ borderBottom: euiTheme.border.thin }}
|
||||
>
|
||||
<EuiFlexItem grow={dashboardColumnsGrow.first}>
|
||||
<ClusterDetailsBox cluster={cluster} />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={dashboardColumnsGrow.second}>
|
||||
<ChartPanel hasBorder={false}>
|
||||
<CloudPostureScoreChart
|
||||
id={`${cluster.meta.clusterId}_score_chart`}
|
||||
data={cluster.stats}
|
||||
trend={cluster.trend}
|
||||
partitionOnElementClick={(elements) =>
|
||||
handleElementClick(cluster.meta.clusterId, elements)
|
||||
}
|
||||
/>
|
||||
</ChartPanel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={dashboardColumnsGrow.third}>
|
||||
<ChartPanel hasBorder={false}>
|
||||
<RisksTable
|
||||
data={cluster.groupedFindingsEvaluation}
|
||||
maxItems={3}
|
||||
onCellClick={(resourceTypeName) =>
|
||||
handleCellClick(cluster.meta.clusterId, resourceTypeName)
|
||||
}
|
||||
onViewAllClick={() => handleViewAllClick(cluster.meta.clusterId)}
|
||||
/>
|
||||
</ChartPanel>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* 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 React from 'react';
|
||||
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
import { PartitionElementEvent } from '@elastic/charts';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FlexItemGrowSize } from '@elastic/eui/src/components/flex/flex_item';
|
||||
import { ChartPanel } from '../../../components/chart_panel';
|
||||
import { CloudPostureScoreChart } from '../compliance_charts/cloud_posture_score_chart';
|
||||
import type { ComplianceDashboardData, Evaluation } from '../../../../common/types';
|
||||
import { RisksTable } from '../compliance_charts/risks_table';
|
||||
import { useNavigateFindings } from '../../../common/hooks/use_navigate_findings';
|
||||
import { RULE_FAILED } from '../../../../common/constants';
|
||||
|
||||
const defaultHeight = 360;
|
||||
|
||||
// TODO: limit this to desktop media queries only
|
||||
const summarySectionWrapperStyle = {
|
||||
height: defaultHeight,
|
||||
};
|
||||
|
||||
export const dashboardColumnsGrow: Record<string, FlexItemGrowSize> = {
|
||||
first: 3,
|
||||
second: 8,
|
||||
third: 8,
|
||||
};
|
||||
|
||||
export const CloudSummarySection = ({
|
||||
complianceData,
|
||||
}: {
|
||||
complianceData: ComplianceDashboardData;
|
||||
}) => {
|
||||
const navToFindings = useNavigateFindings();
|
||||
|
||||
const handleElementClick = (elements: PartitionElementEvent[]) => {
|
||||
const [element] = elements;
|
||||
const [layerValue] = element;
|
||||
const evaluation = layerValue[0].groupByRollup as Evaluation;
|
||||
|
||||
navToFindings({ 'result.evaluation': evaluation });
|
||||
};
|
||||
|
||||
const handleCellClick = (ruleSection: string) => {
|
||||
navToFindings({
|
||||
'rule.section': ruleSection,
|
||||
'result.evaluation': RULE_FAILED,
|
||||
});
|
||||
};
|
||||
|
||||
const handleViewAllClick = () => {
|
||||
navToFindings({ 'result.evaluation': RULE_FAILED });
|
||||
};
|
||||
|
||||
return (
|
||||
<EuiFlexGroup gutterSize="l" style={summarySectionWrapperStyle}>
|
||||
<EuiFlexItem grow={dashboardColumnsGrow.first} />
|
||||
<EuiFlexItem grow={dashboardColumnsGrow.second}>
|
||||
<ChartPanel
|
||||
title={i18n.translate('xpack.csp.dashboard.summarySection.cloudPostureScorePanelTitle', {
|
||||
defaultMessage: 'Cloud Posture Score',
|
||||
})}
|
||||
>
|
||||
<CloudPostureScoreChart
|
||||
id="cloud_posture_score_chart"
|
||||
data={complianceData.stats}
|
||||
trend={complianceData.trend}
|
||||
partitionOnElementClick={handleElementClick}
|
||||
/>
|
||||
</ChartPanel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={dashboardColumnsGrow.third}>
|
||||
<ChartPanel
|
||||
title={i18n.translate('xpack.csp.dashboard.summarySection.failedFindingsPanelTitle', {
|
||||
defaultMessage: 'Failed Findings',
|
||||
})}
|
||||
>
|
||||
<RisksTable
|
||||
data={complianceData.groupedFindingsEvaluation}
|
||||
maxItems={5}
|
||||
onCellClick={handleCellClick}
|
||||
onViewAllClick={handleViewAllClick}
|
||||
/>
|
||||
</ChartPanel>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue