mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Cloud Posture] Compliance by CIS section table (#145114)
This commit is contained in:
parent
733011b76c
commit
b72a9a3df2
14 changed files with 166 additions and 55 deletions
|
@ -16,10 +16,10 @@ export interface FindingsEvaluation {
|
|||
totalFindings: number;
|
||||
totalPassed: number;
|
||||
totalFailed: number;
|
||||
postureScore: Score;
|
||||
}
|
||||
|
||||
export interface Stats extends FindingsEvaluation {
|
||||
postureScore: Score;
|
||||
resourcesEvaluated?: number;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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';
|
||||
|
@ -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',
|
||||
|
@ -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',
|
||||
|
|
|
@ -12,6 +12,7 @@ const podsAgg = {
|
|||
totalFindings: 2,
|
||||
totalPassed: 1,
|
||||
totalFailed: 1,
|
||||
postureScore: 50.0,
|
||||
};
|
||||
|
||||
const etcdAgg = {
|
||||
|
@ -19,6 +20,7 @@ const etcdAgg = {
|
|||
totalFindings: 5,
|
||||
totalPassed: 0,
|
||||
totalFailed: 5,
|
||||
postureScore: 0,
|
||||
};
|
||||
|
||||
const clusterAgg = {
|
||||
|
@ -26,6 +28,7 @@ const clusterAgg = {
|
|||
totalFindings: 2,
|
||||
totalPassed: 2,
|
||||
totalFailed: 0,
|
||||
postureScore: 100.0,
|
||||
};
|
||||
|
||||
const systemAgg = {
|
||||
|
@ -33,6 +36,7 @@ const systemAgg = {
|
|||
totalFindings: 10,
|
||||
totalPassed: 6,
|
||||
totalFailed: 4,
|
||||
postureScore: 60.0,
|
||||
};
|
||||
|
||||
const apiAgg = {
|
||||
|
@ -40,6 +44,7 @@ const apiAgg = {
|
|||
totalFindings: 19100,
|
||||
totalPassed: 2100,
|
||||
totalFailed: 17000,
|
||||
postureScore: 10.9,
|
||||
};
|
||||
|
||||
const serverAgg = {
|
||||
|
@ -47,6 +52,7 @@ const serverAgg = {
|
|||
totalFindings: 7,
|
||||
totalPassed: 4,
|
||||
totalFailed: 3,
|
||||
postureScore: 57.1,
|
||||
};
|
||||
|
||||
const mockData: RisksTableProps['data'] = [
|
||||
|
@ -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]);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -7,24 +7,26 @@
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -32,19 +34,23 @@ 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(
|
||||
() => [
|
||||
{
|
||||
|
@ -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,
|
||||
}}
|
||||
>
|
||||
<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>
|
||||
|
|
|
@ -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: [
|
||||
|
@ -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: [
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
import React from 'react';
|
||||
import { EuiFlexItem, EuiFlexGroup, useEuiTheme, EuiTitle } from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { CloudPostureScoreChart } from '../compliance_charts/cloud_posture_score_chart';
|
||||
import type { ComplianceDashboardData, Evaluation } from '../../../../common/types';
|
||||
import { RisksTable } from '../compliance_charts/risks_table';
|
||||
|
@ -126,6 +127,10 @@ export const CloudBenchmarksSection = ({
|
|||
onCellClick={(resourceTypeName) =>
|
||||
handleCellClick(cluster.meta.clusterId, resourceTypeName)
|
||||
}
|
||||
viewAllButtonTitle={i18n.translate(
|
||||
'xpack.csp.dashboard.risksTable.clusterCardViewAllButtonTitle',
|
||||
{ defaultMessage: 'View all failed findings for this cluster' }
|
||||
)}
|
||||
onViewAllClick={() => handleViewAllClick(cluster.meta.clusterId)}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -9,6 +9,7 @@ import React, { useMemo } from 'react';
|
|||
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FlexItemGrowSize } from '@elastic/eui/src/components/flex/flex_item';
|
||||
import { statusColors } from '../../../common/constants';
|
||||
import { DASHBOARD_COUNTER_CARDS } from '../test_subjects';
|
||||
import { CspCounterCard, CspCounterCardProps } from '../../../components/csp_counter_card';
|
||||
import { CompactFormattedNumber } from '../../../components/compact_formatted_number';
|
||||
|
@ -79,7 +80,7 @@ export const CloudSummarySection = ({
|
|||
{ defaultMessage: 'Failing Findings' }
|
||||
),
|
||||
title: <CompactFormattedNumber number={complianceData.stats.totalFailed} />,
|
||||
titleColor: complianceData.stats.totalFailed > 0 ? 'danger' : 'text',
|
||||
titleColor: complianceData.stats.totalFailed > 0 ? statusColors.failed : 'text',
|
||||
onClick: () => {
|
||||
navToFindings({ 'result.evaluation': RULE_FAILED });
|
||||
},
|
||||
|
@ -131,6 +132,10 @@ export const CloudSummarySection = ({
|
|||
maxItems={5}
|
||||
onCellClick={handleCellClick}
|
||||
onViewAllClick={handleViewAllClick}
|
||||
viewAllButtonTitle={i18n.translate(
|
||||
'xpack.csp.dashboard.risksTable.viewAllButtonTitle',
|
||||
{ defaultMessage: 'View all failed findings' }
|
||||
)}
|
||||
/>
|
||||
</ChartPanel>
|
||||
</EuiFlexItem>
|
||||
|
|
|
@ -47,6 +47,9 @@ const mockClusterBuckets: ClusterBucket[] = [
|
|||
passed_findings: {
|
||||
doc_count: 3,
|
||||
},
|
||||
score: {
|
||||
value: 0.5,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'boo_type',
|
||||
|
@ -57,6 +60,9 @@ const mockClusterBuckets: ClusterBucket[] = [
|
|||
passed_findings: {
|
||||
doc_count: 3,
|
||||
},
|
||||
score: {
|
||||
value: 0.5,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -87,12 +93,14 @@ describe('getClustersFromAggs', () => {
|
|||
totalFindings: 6,
|
||||
totalFailed: 3,
|
||||
totalPassed: 3,
|
||||
postureScore: 50.0,
|
||||
},
|
||||
{
|
||||
name: 'boo_type',
|
||||
totalFindings: 6,
|
||||
totalFailed: 3,
|
||||
totalPassed: 3,
|
||||
postureScore: 50.0,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
|
@ -17,6 +17,9 @@ const resourceTypeBuckets: FailedFindingsBucket[] = [
|
|||
passed_findings: {
|
||||
doc_count: 11,
|
||||
},
|
||||
score: {
|
||||
value: 0.268,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'boo_type',
|
||||
|
@ -27,6 +30,9 @@ const resourceTypeBuckets: FailedFindingsBucket[] = [
|
|||
passed_findings: {
|
||||
doc_count: 6,
|
||||
},
|
||||
score: {
|
||||
value: 0.545,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
|
@ -39,12 +45,14 @@ describe('getFailedFindingsFromAggs', () => {
|
|||
totalFindings: 41,
|
||||
totalFailed: 30,
|
||||
totalPassed: 11,
|
||||
postureScore: 26.8,
|
||||
},
|
||||
{
|
||||
name: 'boo_type',
|
||||
totalFindings: 11,
|
||||
totalFailed: 5,
|
||||
totalPassed: 6,
|
||||
postureScore: 54.5,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
|
|
@ -11,6 +11,7 @@ import type {
|
|||
QueryDslQueryContainer,
|
||||
SearchRequest,
|
||||
} from '@elastic/elasticsearch/lib/api/types';
|
||||
import { calculatePostureScore } from './get_stats';
|
||||
import type { ComplianceDashboardData } from '../../../common/types';
|
||||
import { KeyDocCount } from './compliance_dashboard';
|
||||
|
||||
|
@ -25,12 +26,14 @@ export interface FailedFindingsBucket extends KeyDocCount {
|
|||
passed_findings: {
|
||||
doc_count: number;
|
||||
};
|
||||
score: { value: number };
|
||||
}
|
||||
|
||||
export const failedFindingsAggQuery = {
|
||||
aggs_by_resource_type: {
|
||||
terms: {
|
||||
field: 'rule.section',
|
||||
size: 5,
|
||||
},
|
||||
aggs: {
|
||||
failed_findings: {
|
||||
|
@ -39,6 +42,22 @@ export const failedFindingsAggQuery = {
|
|||
passed_findings: {
|
||||
filter: { term: { 'result.evaluation': 'passed' } },
|
||||
},
|
||||
score: {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
passed: 'passed_findings>_count',
|
||||
failed: 'failed_findings>_count',
|
||||
},
|
||||
script: 'params.passed / (params.passed + params.failed)',
|
||||
},
|
||||
},
|
||||
sort_by_score: {
|
||||
bucket_sort: {
|
||||
sort: {
|
||||
score: 'asc' as 'asc',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -55,12 +74,18 @@ export const getRisksEsQuery = (query: QueryDslQueryContainer, pitId: string): S
|
|||
export const getFailedFindingsFromAggs = (
|
||||
queryResult: FailedFindingsBucket[]
|
||||
): ComplianceDashboardData['groupedFindingsEvaluation'] =>
|
||||
queryResult.map((bucket) => ({
|
||||
name: bucket.key,
|
||||
totalFindings: bucket.doc_count,
|
||||
totalFailed: bucket.failed_findings.doc_count || 0,
|
||||
totalPassed: bucket.passed_findings.doc_count || 0,
|
||||
}));
|
||||
queryResult.map((bucket) => {
|
||||
const totalPassed = bucket.passed_findings.doc_count || 0;
|
||||
const totalFailed = bucket.failed_findings.doc_count || 0;
|
||||
|
||||
return {
|
||||
name: bucket.key,
|
||||
totalFindings: bucket.doc_count,
|
||||
totalFailed,
|
||||
totalPassed,
|
||||
postureScore: calculatePostureScore(totalPassed, totalFailed),
|
||||
};
|
||||
});
|
||||
|
||||
export const getGroupedFindingsEvaluation = async (
|
||||
esClient: ElasticsearchClient,
|
||||
|
|
|
@ -9855,7 +9855,6 @@
|
|||
"xpack.csp.cspSettings.rules": "Règles de sécurité du CSP - ",
|
||||
"xpack.csp.dashboard.cspPageTemplate.pageTitle": "Niveau du cloud",
|
||||
"xpack.csp.dashboard.risksTable.cisSectionColumnLabel": "Section CIS",
|
||||
"xpack.csp.dashboard.risksTable.findingsColumnLabel": "Résultats",
|
||||
"xpack.csp.dashboard.risksTable.viewAllButtonTitle": "Afficher tous les échecs des résultats",
|
||||
"xpack.csp.dashboard.summarySection.cloudPostureScorePanelTitle": "Score du niveau du cloud",
|
||||
"xpack.csp.expandColumnDescriptionLabel": "Développer",
|
||||
|
|
|
@ -9842,7 +9842,6 @@
|
|||
"xpack.csp.cspSettings.rules": "CSPセキュリティルール - ",
|
||||
"xpack.csp.dashboard.cspPageTemplate.pageTitle": "クラウド態勢",
|
||||
"xpack.csp.dashboard.risksTable.cisSectionColumnLabel": "CISセクション",
|
||||
"xpack.csp.dashboard.risksTable.findingsColumnLabel": "調査結果",
|
||||
"xpack.csp.dashboard.risksTable.viewAllButtonTitle": "すべてのフィールド調査結果を表示",
|
||||
"xpack.csp.dashboard.summarySection.cloudPostureScorePanelTitle": "クラウド態勢スコア",
|
||||
"xpack.csp.expandColumnDescriptionLabel": "拡張",
|
||||
|
|
|
@ -9860,7 +9860,6 @@
|
|||
"xpack.csp.cspSettings.rules": "CSP 安全规则 - ",
|
||||
"xpack.csp.dashboard.cspPageTemplate.pageTitle": "云态势",
|
||||
"xpack.csp.dashboard.risksTable.cisSectionColumnLabel": "CIS 部分",
|
||||
"xpack.csp.dashboard.risksTable.findingsColumnLabel": "结果",
|
||||
"xpack.csp.dashboard.risksTable.viewAllButtonTitle": "查看所有失败的结果",
|
||||
"xpack.csp.dashboard.summarySection.cloudPostureScorePanelTitle": "云态势分数",
|
||||
"xpack.csp.expandColumnDescriptionLabel": "展开",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue