[Cloud Posture] New csp dashboard layout placement (#144209)

This commit is contained in:
Jordan 2022-11-07 15:02:45 +02:00 committed by GitHub
parent a7976e57aa
commit b43c3ddf30
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 247 additions and 5 deletions

View file

@ -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';

View file

@ -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>
);

View file

@ -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>
))}
</>
);
};

View file

@ -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>
);
};