[8.7] [Cloud Security] change Belongs To column to use runtime field (#151038) (#151420)

# Backport

This will backport the following commits from `main` to `8.7`:
- [[Cloud Security] change `Belongs To` column to use runtime field
(#151038)](https://github.com/elastic/kibana/pull/151038)

<!--- Backport version: 8.9.7 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT
[{"author":{"name":"Jordan","email":"51442161+JordanSh@users.noreply.github.com"},"sourceCommit":{"committedDate":"2023-02-16T10:43:17Z","message":"[Cloud
Security] change `Belongs To` column to use runtime field
(#151038)","sha":"e974e53b3206031b101de4a843b713bdb349bcdf","branchLabelMapping":{"^v8.8.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team:Cloud
Security","v8.7.0","v8.8.0"],"number":151038,"url":"https://github.com/elastic/kibana/pull/151038","mergeCommit":{"message":"[Cloud
Security] change `Belongs To` column to use runtime field
(#151038)","sha":"e974e53b3206031b101de4a843b713bdb349bcdf"}},"sourceBranch":"main","suggestedTargetBranches":["8.7"],"targetPullRequestStates":[{"branch":"8.7","label":"v8.7.0","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.8.0","labelRegex":"^v8.8.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/151038","number":151038,"mergeCommit":{"message":"[Cloud
Security] change `Belongs To` column to use runtime field
(#151038)","sha":"e974e53b3206031b101de4a843b713bdb349bcdf"}}]}]
BACKPORT-->

Co-authored-by: Jordan <51442161+JordanSh@users.noreply.github.com>
This commit is contained in:
Kibana Machine 2023-02-16 06:53:03 -05:00 committed by GitHub
parent f53f245f7b
commit cb1cb236cf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 86 additions and 36 deletions

View file

@ -0,0 +1,52 @@
/*
* 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 { MappingRuntimeFields } from '@elastic/elasticsearch/lib/api/types';
/**
* Creates the `belongs_to` runtime field with the value of either
* `account.cloud.name` or `cluster.id` based on the value of `rule.benchmark.posture_type`
*/
export const getBelongsToRuntimeMapping = (): MappingRuntimeFields => ({
belongs_to: {
type: 'keyword',
script: {
source: `
if (!doc.containsKey('rule.benchmark.posture_type'))
{
def identifier = doc["cluster_id"].value;
emit(identifier);
return
}
else
{
if(doc["rule.benchmark.posture_type"].size() > 0)
{
def policy_template_type = doc["rule.benchmark.posture_type"].value;
if (policy_template_type == "cspm")
{
def identifier = doc["cloud.account.name"].value;
emit(identifier);
return
}
if (policy_template_type == "kspm")
{
def identifier = doc["cluster_id"].value;
emit(identifier);
return
}
}
def identifier = doc["cluster_id"].value;
emit(identifier);
return
}
`,
},
},
});

View file

@ -26,7 +26,7 @@ const getFakeFindingsByResource = (): FindingsByResourcePage => {
);
return {
cluster_id: chance.guid(),
belongs_to: chance.guid(),
resource_id: chance.guid(),
'resource.name': resourceName,
'resource.sub_type': resourceSubtype,

View file

@ -17,6 +17,8 @@ import {
import { FormattedMessage } from '@kbn/i18n-react';
import numeral from '@elastic/numeral';
import { Link, generatePath } from 'react-router-dom';
import { i18n } from '@kbn/i18n';
import { ColumnNameWithTooltip } from '../../../components/column_name_with_tooltip';
import { ComplianceScoreBar } from '../../../components/compliance_score_bar';
import * as TEST_SUBJECTS from '../test_subjects';
import type { FindingsByResourcePage } from './use_findings_by_resource';
@ -76,7 +78,7 @@ const FindingsByResourceTableComponent = ({
getNonSortableColumn(findingsByResourceColumns['rule.benchmark.name']),
{ onAddFilter }
),
createColumnWithFilters(getNonSortableColumn(findingsByResourceColumns.cluster_id), {
createColumnWithFilters(getNonSortableColumn(findingsByResourceColumns.belongs_to), {
onAddFilter,
}),
findingsByResourceColumns.compliance_score,
@ -149,7 +151,22 @@ const baseColumns: Array<EuiTableFieldDataColumnType<FindingsByResourcePage>> =
);
},
},
baseFindingsColumns.cluster_id,
{
field: 'belongs_to',
name: (
<ColumnNameWithTooltip
columnName={i18n.translate(
'xpack.csp.findings.findingsTable.findingsTableColumn.clusterIdColumnLabel',
{ defaultMessage: 'Belongs To' }
)}
tooltipContent={i18n.translate(
'xpack.csp.findings.findingsTable.findingsTableColumn.clusterIdColumnTooltipLabel',
{ defaultMessage: 'Kubernetes Cluster ID or Cloud Account Name' }
)}
/>
),
truncateText: true,
},
{
field: 'compliance_score',
width: '150px',

View file

@ -9,6 +9,7 @@ import { lastValueFrom } from 'rxjs';
import { IKibanaSearchRequest, IKibanaSearchResponse } from '@kbn/data-plugin/common';
import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import type { Pagination } from '@elastic/eui';
import { getBelongsToRuntimeMapping } from '../../../../common/runtime_mappings/get_belongs_to_runtime_mapping';
import { MAX_FINDINGS_TO_LOAD } from '../../../common/constants';
import { useKibana } from '../../../common/hooks/use_kibana';
import { showErrorToast } from '../latest_findings/use_latest_findings';
@ -43,7 +44,7 @@ export interface FindingsByResourcePage {
};
compliance_score: number;
resource_id: string;
cluster_id: string;
belongs_to: string;
'resource.name': string;
'resource.sub_type': string;
'rule.benchmark.name': string;
@ -62,7 +63,7 @@ interface FindingsAggBucket extends estypes.AggregationsStringRareTermsBucketKey
passed_findings: estypes.AggregationsMultiBucketBase;
name: estypes.AggregationsMultiBucketAggregateBase<estypes.AggregationsStringTermsBucketKeys>;
subtype: estypes.AggregationsMultiBucketAggregateBase<estypes.AggregationsStringTermsBucketKeys>;
cluster_id: estypes.AggregationsMultiBucketAggregateBase<estypes.AggregationsStringTermsBucketKeys>;
belongs_to: estypes.AggregationsMultiBucketAggregateBase<estypes.AggregationsStringTermsBucketKeys>;
benchmarkName: estypes.AggregationsMultiBucketAggregateBase<estypes.AggregationsStringRareTermsBucketKeys>;
cis_sections: estypes.AggregationsMultiBucketAggregateBase<estypes.AggregationsStringRareTermsBucketKeys>;
}
@ -75,6 +76,7 @@ export const getFindingsByResourceAggQuery = ({
body: {
query,
size: 0,
runtime_mappings: getBelongsToRuntimeMapping(),
aggs: {
...getFindingsCountAggQuery(),
resource_total: { cardinality: { field: 'resource.id' } },
@ -99,8 +101,9 @@ export const getFindingsByResourceAggQuery = ({
passed_findings: {
filter: { term: { 'result.evaluation': 'passed' } },
},
cluster_id: {
terms: { field: 'cluster_id', size: 1 },
// this field is runtime generated
belongs_to: {
terms: { field: 'belongs_to', size: 1 },
},
compliance_score: {
bucket_script: {
@ -177,12 +180,12 @@ const createFindingsByResource = (resource: FindingsAggBucket): FindingsByResour
!Array.isArray(resource.cis_sections.buckets) ||
!Array.isArray(resource.name.buckets) ||
!Array.isArray(resource.subtype.buckets) ||
!Array.isArray(resource.cluster_id.buckets) ||
!Array.isArray(resource.belongs_to.buckets) ||
!resource.benchmarkName.buckets.length ||
!resource.cis_sections.buckets.length ||
!resource.name.buckets.length ||
!resource.subtype.buckets.length ||
!resource.cluster_id.buckets.length
!resource.belongs_to.buckets.length
)
throw new Error('expected buckets to be an array');
@ -190,9 +193,9 @@ const createFindingsByResource = (resource: FindingsAggBucket): FindingsByResour
resource_id: resource.key,
['resource.name']: resource.name.buckets[0]?.key,
['resource.sub_type']: resource.subtype.buckets[0]?.key,
cluster_id: resource.cluster_id.buckets[0]?.key,
['rule.section']: resource.cis_sections.buckets.map((v) => v.key),
['rule.benchmark.name']: resource.benchmarkName.buckets[0]?.key,
belongs_to: resource.belongs_to.buckets[0]?.key,
compliance_score: resource.compliance_score.value,
findings: {
failed_findings: resource.failed_findings.doc_count,

View file

@ -175,28 +175,6 @@ const baseColumns = [
</EuiToolTip>
),
},
{
field: 'cluster_id',
name: (
<ColumnNameWithTooltip
columnName={i18n.translate(
'xpack.csp.findings.findingsTable.findingsTableColumn.clusterIdColumnLabel',
{ defaultMessage: 'Belongs To' }
)}
tooltipContent={i18n.translate(
'xpack.csp.findings.findingsTable.findingsTableColumn.clusterIdColumnTooltipLabel',
{ defaultMessage: 'Kubernetes Cluster ID or Cloud Account Name' }
)}
/>
),
sortable: true,
truncateText: true,
render: (section: string) => (
<EuiToolTip content={section} anchorClassName="eui-textTruncate">
<>{section}</>
</EuiToolTip>
),
},
{
field: '@timestamp',
align: 'right',

View file

@ -10,7 +10,7 @@ import type {
AggregationsMultiBucketBase,
SearchRequest,
} from '@elastic/elasticsearch/lib/api/types';
import { getIdentifierRuntimeMapping } from '../../get_identifier_runtime_mapping';
import { getIdentifierRuntimeMapping } from '../../../../common/runtime_mappings/get_identifier_runtime_mapping';
import { calculatePostureScore } from '../../../../common/utils/helpers';
import type { CspmAccountsStats } from './types';
import { LATEST_FINDINGS_INDEX_DEFAULT_NS } from '../../../../common/constants';

View file

@ -7,7 +7,7 @@
import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server';
import type { Logger } from '@kbn/core/server';
import type { SearchRequest } from '@elastic/elasticsearch/lib/api/types';
import { getIdentifierRuntimeMapping } from '../../get_identifier_runtime_mapping';
import { getIdentifierRuntimeMapping } from '../../../../common/runtime_mappings/get_identifier_runtime_mapping';
import type { CspmResourcesStats } from './types';
import { LATEST_FINDINGS_INDEX_DEFAULT_NS } from '../../../../common/constants';

View file

@ -22,7 +22,7 @@ import {
import type { FailedFindingsQueryResult } from './get_grouped_findings_evaluation';
import { findingsEvaluationAggsQuery, getStatsFromFindingsEvaluationsAggs } from './get_stats';
import { KeyDocCount } from './compliance_dashboard';
import { getIdentifierRuntimeMapping } from '../../lib/get_identifier_runtime_mapping';
import { getIdentifierRuntimeMapping } from '../../../common/runtime_mappings/get_identifier_runtime_mapping';
export interface ClusterBucket extends FailedFindingsQueryResult, KeyDocCount {
failed_findings: {

View file

@ -14,7 +14,7 @@ import {
import { SearchRequest } from '@kbn/data-plugin/common';
import { ElasticsearchClient } from '@kbn/core/server';
import type { Logger } from '@kbn/core/server';
import { getIdentifierRuntimeMapping } from '../lib/get_identifier_runtime_mapping';
import { getIdentifierRuntimeMapping } from '../../common/runtime_mappings/get_identifier_runtime_mapping';
import { FindingsStatsTaskResult, TaskHealthStatus, ScoreByPolicyTemplateBucket } from './types';
import {
BENCHMARK_SCORE_INDEX_DEFAULT_NS,