Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Cloud Posture] Compliance by CIS section table #145114

Merged
merged 37 commits into from
Nov 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
4892f6f
init
JordanSh Oct 30, 2022
17aafaf
layout done
JordanSh Oct 30, 2022
cd404f4
layout fine tuning
JordanSh Oct 30, 2022
2ea6c1a
Merge branch 'main' of https://github.com/elastic/kibana into new-csp…
JordanSh Oct 31, 2022
1be7828
base component created
JordanSh Oct 31, 2022
ed8605f
working on number abbv
JordanSh Nov 2, 2022
322a336
ui progress
JordanSh Nov 2, 2022
cbe7151
ui progress
JordanSh Nov 3, 2022
80787e7
added query
JordanSh Nov 3, 2022
8f05630
added tests
JordanSh Nov 7, 2022
e23bca1
merge
JordanSh Nov 7, 2022
99177fa
minor changes
JordanSh Nov 7, 2022
602cf74
added empty state test
JordanSh Nov 7, 2022
506e009
init
JordanSh Nov 8, 2022
6c612d9
init
JordanSh Nov 8, 2022
351a5db
progress on layout
JordanSh Nov 8, 2022
4c3e3c6
working on compact versions of components
JordanSh Nov 9, 2022
bad5f3d
merge
JordanSh Nov 9, 2022
9f2cc87
progress on layout
JordanSh Nov 10, 2022
ea7ffde
progress on layout
JordanSh Nov 10, 2022
3e6a698
progress
JordanSh Nov 13, 2022
4b5cc0b
fixed tests errors
JordanSh Nov 13, 2022
20953a5
added counter tooltips
JordanSh Nov 13, 2022
280a000
cleanups
JordanSh Nov 13, 2022
9dc250d
cleanups and i18n fix
JordanSh Nov 13, 2022
d306a6f
using progress element
JordanSh Nov 14, 2022
0ac1d48
using flex items to draw the progress bar
JordanSh Nov 14, 2022
2d7343e
cleanups
JordanSh Nov 14, 2022
9cdd8df
merge
JordanSh Nov 14, 2022
44d8529
typo
JordanSh Nov 14, 2022
70a0d76
i18n
JordanSh Nov 14, 2022
ba1cc45
fixed tests that broke cause of changes
JordanSh Nov 14, 2022
7eaf563
added ts ignore
JordanSh Nov 14, 2022
a7601de
ignore
JordanSh Nov 14, 2022
6ceea02
Merge branch 'main' of https://github.com/elastic/kibana into cis-sec…
JordanSh Nov 14, 2022
cd1fb8f
removed eui vars from table component
JordanSh Nov 14, 2022
8b2c48b
fix type
JordanSh Nov 14, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion x-pack/plugins/cloud_security_posture/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ export interface FindingsEvaluation {
totalFindings: number;
totalPassed: number;
totalFailed: number;
postureScore: Score;
}

export interface Stats extends FindingsEvaluation {
postureScore: Score;
resourcesEvaluated?: number;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
* 2.0.
*/

import { euiPaletteForStatus } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { euiThemeVars } from '@kbn/ui-theme';
import { CLOUDBEAT_EKS, CLOUDBEAT_VANILLA } from '../../common/constants';

const [success, warning, danger] = euiPaletteForStatus(3);
export const statusColors = {
passed: euiThemeVars.euiColorVis0,
failed: euiThemeVars.euiColorVis9,
};

export const statusColors = { success, warning, danger };
export const CSP_MOMENT_FORMAT = 'MMMM D, YYYY @ HH:mm:ss.SSS';

export type CloudPostureIntegrations = typeof cloudPostureIntegrations;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
import { FormattedDate, FormattedTime } from '@kbn/i18n-react';
import moment from 'moment';
import { i18n } from '@kbn/i18n';
import { statusColors } from '../../../common/constants';
import { RULE_FAILED, RULE_PASSED } from '../../../../common/constants';
import { CompactFormattedNumber } from '../../../components/compact_formatted_number';
import type { Evaluation, PostureTrend, Stats } from '../../../../common/types';
Expand Down Expand Up @@ -163,7 +164,7 @@ export const CloudPostureScoreChart = ({
<CounterLink
text="passed"
count={data.totalPassed}
color="success"
color={statusColors.passed}
onClick={() => onEvalCounterClick(RULE_PASSED)}
tooltipContent={i18n.translate(
'xpack.csp.cloudPostureScoreChart.counterLink.passedFindingsTooltip',
Expand All @@ -174,7 +175,7 @@ export const CloudPostureScoreChart = ({
<CounterLink
text="failed"
count={data.totalFailed}
color="danger"
color={statusColors.failed}
onClick={() => onEvalCounterClick(RULE_FAILED)}
tooltipContent={i18n.translate(
'xpack.csp.cloudPostureScoreChart.counterLink.failedFindingsTooltip',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,41 +12,47 @@ const podsAgg = {
totalFindings: 2,
totalPassed: 1,
totalFailed: 1,
postureScore: 50.0,
};

const etcdAgg = {
name: 'etcd',
totalFindings: 5,
totalPassed: 0,
totalFailed: 5,
postureScore: 0,
};

const clusterAgg = {
name: 'cluster',
totalFindings: 2,
totalPassed: 2,
totalFailed: 0,
postureScore: 100.0,
};

const systemAgg = {
name: 'system',
totalFindings: 10,
totalPassed: 6,
totalFailed: 4,
postureScore: 60.0,
};

const apiAgg = {
name: 'api',
totalFindings: 19100,
totalPassed: 2100,
totalFailed: 17000,
postureScore: 10.9,
};

const serverAgg = {
name: 'server',
totalFindings: 7,
totalPassed: 4,
totalFailed: 3,
postureScore: 57.1,
};

const mockData: RisksTableProps['data'] = [
Expand All @@ -59,15 +65,11 @@ const mockData: RisksTableProps['data'] = [
];

describe('getTopRisks', () => {
it('returns sorted by failed findings', () => {
expect(getTopRisks([systemAgg, etcdAgg, apiAgg], 3)).toEqual([apiAgg, etcdAgg, systemAgg]);
it('returns sorted by posture score', () => {
expect(getTopRisks([systemAgg, etcdAgg, apiAgg], 3)).toEqual([etcdAgg, apiAgg, systemAgg]);
});

it('return array filtered with failed findings only', () => {
expect(getTopRisks([systemAgg, clusterAgg, apiAgg], 3)).toEqual([apiAgg, systemAgg]);
});

it('return sorted and filtered array with the correct number of elements', () => {
expect(getTopRisks(mockData, 5)).toEqual([apiAgg, etcdAgg, systemAgg, serverAgg, podsAgg]);
it('return sorted array with the correct number of elements', () => {
expect(getTopRisks(mockData, 5)).toEqual([etcdAgg, apiAgg, podsAgg, serverAgg, systemAgg]);
Comment on lines +72 to +73
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think this is tested in previous case too

});
});
Original file line number Diff line number Diff line change
Expand Up @@ -7,44 +7,50 @@

import React, { useMemo } from 'react';
import {
EuiBasicTable,
EuiBasicTableColumn,
EuiButtonEmpty,
EuiFlexGroup,
EuiFlexItem,
EuiInMemoryTable,
EuiLink,
EuiText,
EuiToolTip,
useEuiTheme,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import { statusColors } from '../../../common/constants';
import { ComplianceDashboardData, GroupedFindingsEvaluation } from '../../../../common/types';
import { CompactFormattedNumber } from '../../../components/compact_formatted_number';

export interface RisksTableProps {
data: ComplianceDashboardData['groupedFindingsEvaluation'];
maxItems: number;
onCellClick: (name: string) => void;
onViewAllClick: () => void;
viewAllButtonTitle: string;
compact?: boolean;
}

export const getTopRisks = (
groupedFindingsEvaluation: ComplianceDashboardData['groupedFindingsEvaluation'],
maxItems: number
) => {
const filtered = groupedFindingsEvaluation.filter((x) => x.totalFailed > 0);
const sorted = filtered.slice().sort((first, second) => second.totalFailed - first.totalFailed);
const sorted = groupedFindingsEvaluation
.slice()
.sort((first, second) => first.postureScore - second.postureScore);

return sorted.slice(0, maxItems);
};

export const RisksTable = ({
data: resourcesTypes,
data: cisSectionsEvaluations,
maxItems,
onCellClick,
onViewAllClick,
viewAllButtonTitle,
compact,
}: RisksTableProps) => {
const { euiTheme } = useEuiTheme();

const columns: Array<EuiBasicTableColumn<GroupedFindingsEvaluation>> = useMemo(
() => [
{
Expand All @@ -62,49 +68,87 @@ export const RisksTable = ({
),
},
{
field: 'totalFailed',
field: 'postureScore',
width: '115px',
name: compact
? ''
: i18n.translate('xpack.csp.dashboard.risksTable.findingsColumnLabel', {
defaultMessage: 'Findings',
: i18n.translate('xpack.csp.dashboard.risksTable.complianceColumnLabel', {
defaultMessage: 'Compliance',
}),
render: (
totalFailed: GroupedFindingsEvaluation['totalFailed'],
resource: GroupedFindingsEvaluation
) => (
<>
<EuiText size="s" color="danger">
<CompactFormattedNumber number={resource.totalFailed} />
</EuiText>
<EuiText size="s">
{'/'}
<CompactFormattedNumber number={resource.totalFindings} />
</EuiText>
</>
render: (postureScore: GroupedFindingsEvaluation['postureScore'], data) => (
<EuiFlexGroup
gutterSize="none"
alignItems="center"
justifyContent="flexEnd"
style={{ gap: euiTheme.size.s }}
>
<EuiFlexItem>
<EuiToolTip
content={i18n.translate(
'xpack.csp.complianceDashboard.complianceByCisSection.complianceColumnTooltip',
{
defaultMessage: '{passed}/{total}',
values: { passed: data.totalPassed, total: data.totalFindings },
}
)}
>
<EuiFlexGroup
gutterSize="none"
style={{
height: euiTheme.size.xs,
borderRadius: euiTheme.border.radius.medium,
overflow: 'hidden',
gap: 1,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gap takes a <length> value, so 1 shouldn't be valid

}}
>
<EuiFlexItem
style={{
flex: data.totalFailed,
background: statusColors.failed,
}}
/>
<EuiFlexItem
style={{
flex: data.totalPassed,
background: statusColors.passed,
}}
/>
</EuiFlexGroup>
</EuiToolTip>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiText size="xs" style={{ fontWeight: euiTheme.font.weight.bold }}>{`${
postureScore?.toFixed(0) || 0
}%`}</EuiText>
</EuiFlexItem>
</EuiFlexGroup>
),
},
],
[compact, onCellClick]
[
compact,
euiTheme.border.radius.medium,
euiTheme.font.weight.bold,
euiTheme.size.s,
euiTheme.size.xs,
onCellClick,
]
);

const items = useMemo(() => getTopRisks(resourcesTypes, maxItems), [resourcesTypes, maxItems]);
const sortedByComplianceScore = getTopRisks(cisSectionsEvaluations, maxItems);

return (
<EuiFlexGroup direction="column" justifyContent="spaceBetween" gutterSize="none">
<EuiFlexItem>
<EuiBasicTable<GroupedFindingsEvaluation>
rowHeader="name"
items={items}
<EuiInMemoryTable<GroupedFindingsEvaluation>
items={sortedByComplianceScore}
columns={columns}
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<div>
<EuiButtonEmpty onClick={onViewAllClick} iconType="search">
<FormattedMessage
id="xpack.csp.dashboard.risksTable.viewAllButtonTitle"
defaultMessage="View all failed findings"
/>
{viewAllButtonTitle}
</EuiButtonEmpty>
</div>
</EuiFlexItem>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,42 +43,49 @@ export const mockDashboardData: ComplianceDashboardData = {
totalFindings: 104,
totalFailed: 0,
totalPassed: 104,
postureScore: 100,
},
{
name: 'API Server',
totalFindings: 27,
totalFailed: 11,
totalPassed: 16,
postureScore: 59.2,
},
{
name: 'Master Node Configuration Files',
totalFindings: 17,
totalFailed: 1,
totalPassed: 16,
postureScore: 94.1,
},
{
name: 'Kubelet',
totalFindings: 11,
totalFailed: 4,
totalPassed: 7,
postureScore: 63.6,
},
{
name: 'etcd',
totalFindings: 6,
totalFailed: 0,
totalPassed: 6,
postureScore: 100,
},
{
name: 'Worker Node Configuration Files',
totalFindings: 5,
totalFailed: 0,
totalPassed: 5,
postureScore: 100,
},
{
name: 'Scheduler',
totalFindings: 2,
totalFailed: 1,
totalPassed: 1,
postureScore: 50.0,
},
],
clusters: [
Expand All @@ -101,42 +108,49 @@ export const mockDashboardData: ComplianceDashboardData = {
totalFindings: 104,
totalFailed: 0,
totalPassed: 104,
postureScore: 100,
},
{
name: 'API Server',
totalFindings: 27,
totalFailed: 11,
totalPassed: 16,
postureScore: 59.2,
},
{
name: 'Master Node Configuration Files',
totalFindings: 17,
totalFailed: 1,
totalPassed: 16,
postureScore: 94.1,
},
{
name: 'Kubelet',
totalFindings: 11,
totalFailed: 4,
totalPassed: 7,
postureScore: 63.6,
},
{
name: 'etcd',
totalFindings: 6,
totalFailed: 0,
totalPassed: 6,
postureScore: 100,
},
{
name: 'Worker Node Configuration Files',
totalFindings: 5,
totalFailed: 0,
totalPassed: 5,
postureScore: 100,
},
{
name: 'Scheduler',
totalFindings: 2,
totalFailed: 1,
totalPassed: 1,
postureScore: 50.0,
},
],
trend: [
Expand Down
Loading