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

10751 app findings group by #207155

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -144,4 +144,21 @@ run serverless Cloud Security Posture e2e tests:
yarn cypress:cloud_security_posture:run:serverless
```

Unlike FTR where we have to set server and runner separately, Cypress handles everything in 1 go, so just running the above the script is enough to get it running
Unlike FTR where we have to set server and runner separately, Cypress handles everything in 1 go, so just running the above the script is enough to get it running

### Troubleshooting

If you encounter an error related to running machine learning code, you should add the following string `'xpack.ml.enabled=false'` under the `esTestCluster` property in the `x-pack/test/functional/config.base.js` file.

Example:
```javascript
module.exports = {
esTestCluster: {
// ...existing configuration...
serverArgs: [
// ...existing arguments...
'xpack.ml.enabled=false', // Add this line to disable ML
],
},
// ...other configurations...
};
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,9 @@ export const FINDINGS_GROUPING_OPTIONS = {
RULE_NAME: 'rule.name',
RULE_SECTION: 'rule.section',
CLOUD_ACCOUNT_NAME: 'cloud.account.name',
CLOUD_ACCOUNT_ID: 'cloud.account.id',
ORCHESTRATOR_CLUSTER_NAME: 'orchestrator.cluster.name',
ORCHESTRATOR_CLUSTER_ID: 'orchestrator.cluster.id',
};

export const VULNERABILITY_FIELDS = {
Expand Down Expand Up @@ -224,6 +226,6 @@ the fields from the runtime mappings if they are removed from the Data Table.
*/
export const CDR_VULNERABILITY_GROUPING_RUNTIME_MAPPING_FIELDS: Record<string, string[]> = {};
export const CDR_MISCONFIGURATION_GROUPING_RUNTIME_MAPPING_FIELDS: Record<string, string[]> = {
[FINDINGS_GROUPING_OPTIONS.ORCHESTRATOR_CLUSTER_NAME]: ['orchestrator.cluster.name'],
[FINDINGS_GROUPING_OPTIONS.CLOUD_ACCOUNT_NAME]: ['cloud.account.name'],
[FINDINGS_GROUPING_OPTIONS.ORCHESTRATOR_CLUSTER_ID]: ['orchestrator.cluster.id'],
[FINDINGS_GROUPING_OPTIONS.CLOUD_ACCOUNT_ID]: ['cloud.account.id'],
};
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,13 @@ export const AccountsEvaluatedWidget = ({
const navToFindingsByCloudProvider = (provider: string) => {
navToFindings(
{ 'cloud.provider': provider, 'rule.benchmark.posture_type': CSPM_POLICY_TEMPLATE },
[FINDINGS_GROUPING_OPTIONS.CLOUD_ACCOUNT_NAME]
[FINDINGS_GROUPING_OPTIONS.CLOUD_ACCOUNT_ID]
);
};

const navToFindingsByCisBenchmark = (cisBenchmark: string) => {
navToFindings({ 'rule.benchmark.id': cisBenchmark }, [
FINDINGS_GROUPING_OPTIONS.ORCHESTRATOR_CLUSTER_NAME,
FINDINGS_GROUPING_OPTIONS.ORCHESTRATOR_CLUSTER_ID,
]);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,14 +145,12 @@ const getBenchmarkTableColumns = (
'data-test-subj': TEST_SUBJ.BENCHMARKS_TABLE_COLUMNS.APPLICABLE_TO,
render: (benchmarkId: BenchmarksCisId) => {
return (
<>
<EuiFlexGroup gutterSize="s" alignItems="center">
<EuiFlexItem grow={false}>
<CISBenchmarkIcon type={benchmarkId} size={'l'} />
</EuiFlexItem>
<EuiFlexItem grow={false}>{getBenchmarkApplicableTo(benchmarkId)}</EuiFlexItem>
</EuiFlexGroup>
</>
<EuiFlexGroup gutterSize="s" alignItems="center">
<EuiFlexItem grow={false}>
<CISBenchmarkIcon type={benchmarkId} size={'l'} />
</EuiFlexItem>
<EuiFlexItem grow={false}>{getBenchmarkApplicableTo(benchmarkId)}</EuiFlexItem>
</EuiFlexGroup>
);
},
},
Expand Down Expand Up @@ -189,8 +187,8 @@ const getBenchmarkTableColumns = (

const isKspmBenchmark = ['cis_k8s', 'cis_eks'].includes(benchmark.id);
const groupByField = isKspmBenchmark
? FINDINGS_GROUPING_OPTIONS.ORCHESTRATOR_CLUSTER_NAME
: FINDINGS_GROUPING_OPTIONS.CLOUD_ACCOUNT_NAME;
? FINDINGS_GROUPING_OPTIONS.ORCHESTRATOR_CLUSTER_ID
: FINDINGS_GROUPING_OPTIONS.CLOUD_ACCOUNT_ID;

return (
<EuiButtonEmpty
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ export const BenchmarkDetailsBox = ({ benchmark }: { benchmark: BenchmarkData })
const navToFindings = useNavigateFindings();

const handleClickCloudProvider = () =>
navToFindings(getBenchmarkIdQuery(benchmark), [FINDINGS_GROUPING_OPTIONS.CLOUD_ACCOUNT_NAME]);
navToFindings(getBenchmarkIdQuery(benchmark), [FINDINGS_GROUPING_OPTIONS.CLOUD_ACCOUNT_ID]);

const handleClickCluster = () =>
navToFindings(getBenchmarkIdQuery(benchmark), [
FINDINGS_GROUPING_OPTIONS.ORCHESTRATOR_CLUSTER_NAME,
FINDINGS_GROUPING_OPTIONS.ORCHESTRATOR_CLUSTER_ID,
]);

const getBenchmarkInfo = (benchmarkId: string, cloudAssetCount: number): BenchmarkInfo => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ export const MISCONFIGURATIONS_GROUPS_UNIT = (
values: { groupCount },
defaultMessage: `{groupCount} {groupCount, plural, =1 {rule} other {rules}}`,
});
case FINDINGS_GROUPING_OPTIONS.CLOUD_ACCOUNT_NAME:
case FINDINGS_GROUPING_OPTIONS.CLOUD_ACCOUNT_ID:
return i18n.translate('xpack.csp.findings.groupUnit.cloudAccount', {
values: { groupCount },
defaultMessage: `{groupCount} {groupCount, plural, =1 {cloud account} other {cloud accounts}}`,
});
case FINDINGS_GROUPING_OPTIONS.ORCHESTRATOR_CLUSTER_NAME:
case FINDINGS_GROUPING_OPTIONS.ORCHESTRATOR_CLUSTER_ID:
return i18n.translate('xpack.csp.findings.groupUnit.kubernetes', {
values: { groupCount },
defaultMessage: `{groupCount} {groupCount, plural, =1 {kubernetes cluster} other {kubernetes clusters}}`,
Expand All @@ -67,10 +67,9 @@ export const NULL_GROUPING_MESSAGES = {
CLOUD_ACCOUNT_NAME: i18n.translate('xpack.csp.findings.grouping.cloudAccount.nullGroupTitle', {
defaultMessage: 'No cloud account',
}),
ORCHESTRATOR_CLUSTER_NAME: i18n.translate(
'xpack.csp.findings.grouping.kubernetes.nullGroupTitle',
{ defaultMessage: 'No Kubernetes cluster' }
),
ORCHESTRATOR_CLUSTER_ID: i18n.translate('xpack.csp.findings.grouping.kubernetes.nullGroupTitle', {
defaultMessage: 'No Kubernetes cluster',
}),
DEFAULT: i18n.translate('xpack.csp.findings.grouping.default.nullGroupTitle', {
defaultMessage: 'No grouping',
}),
Expand All @@ -91,15 +90,15 @@ export const defaultGroupingOptions: GroupOption[] = [
},
{
label: i18n.translate('xpack.csp.findings.latestFindings.groupByCloudAccount', {
defaultMessage: 'Cloud account',
defaultMessage: 'Cloud account ID',
}),
key: FINDINGS_GROUPING_OPTIONS.CLOUD_ACCOUNT_NAME,
key: FINDINGS_GROUPING_OPTIONS.CLOUD_ACCOUNT_ID,
},
{
label: i18n.translate('xpack.csp.findings.latestFindings.groupByKubernetesCluster', {
defaultMessage: 'Kubernetes cluster',
defaultMessage: 'Kubernetes cluster ID',
}),
key: FINDINGS_GROUPING_OPTIONS.ORCHESTRATOR_CLUSTER_NAME,
key: FINDINGS_GROUPING_OPTIONS.ORCHESTRATOR_CLUSTER_ID,
},
];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
useEuiTheme,
} from '@elastic/eui';
import { css } from '@emotion/react';
import { GroupPanelRenderer, GroupStatsItem, RawBucket } from '@kbn/grouping/src';
import { GenericBuckets, GroupPanelRenderer, GroupStatsItem, RawBucket } from '@kbn/grouping/src';
import React from 'react';
import { i18n } from '@kbn/i18n';
import { getAbbreviatedNumber } from '@kbn/cloud-security-posture-common';
Expand Down Expand Up @@ -45,13 +45,15 @@ export const groupPanelRenderer: GroupPanelRenderer<FindingsGroupingAggregation>
<NullGroup title={title} field={selectedGroup} unit={NULL_GROUPING_UNIT} />
);

const getGroupPanelTitle = () => {
const resourceId = bucket.resourceName?.buckets?.[0]?.key;
const getGroupPanelTitle = (aggregationField?: keyof FindingsGroupingAggregation) => {
const aggregationFieldValue = aggregationField
? (bucket[aggregationField] as { buckets?: GenericBuckets[] })?.buckets?.[0]?.key
: null;

if (resourceId) {
if (aggregationFieldValue) {
return (
<>
<strong>{resourceId}</strong> - {bucket.key_as_string}
<strong>{aggregationFieldValue}</strong> - {bucket.key_as_string}
</>
);
}
Expand Down Expand Up @@ -80,7 +82,7 @@ export const groupPanelRenderer: GroupPanelRenderer<FindingsGroupingAggregation>
`}
title={bucket.resourceName?.buckets?.[0]?.key as string}
>
{getGroupPanelTitle()}
{getGroupPanelTitle('resourceName')}
</EuiTextBlockTruncate>
</EuiText>
</EuiFlexItem>
Expand All @@ -101,9 +103,7 @@ export const groupPanelRenderer: GroupPanelRenderer<FindingsGroupingAggregation>
<EuiFlexItem>
<EuiFlexGroup direction="column" gutterSize="none">
<EuiFlexItem>
<EuiText size="s">
<strong>{bucket.key_as_string}</strong>
</EuiText>
<EuiText size="s"> {getGroupPanelTitle()}</EuiText>
</EuiFlexItem>
<EuiFlexItem>
<EuiText size="xs" color="subdued">
Expand All @@ -115,7 +115,7 @@ export const groupPanelRenderer: GroupPanelRenderer<FindingsGroupingAggregation>
</EuiFlexItem>
</EuiFlexGroup>
);
case FINDINGS_GROUPING_OPTIONS.CLOUD_ACCOUNT_NAME:
case FINDINGS_GROUPING_OPTIONS.CLOUD_ACCOUNT_ID:
return nullGroupMessage ? (
renderNullGroup(NULL_GROUPING_MESSAGES.CLOUD_ACCOUNT_NAME)
) : (
Expand All @@ -131,9 +131,7 @@ export const groupPanelRenderer: GroupPanelRenderer<FindingsGroupingAggregation>
<EuiFlexItem>
<EuiFlexGroup direction="column" gutterSize="none">
<EuiFlexItem>
<EuiText size="s">
<strong>{bucket.key_as_string}</strong>
</EuiText>
<EuiText size="s">{getGroupPanelTitle('accountName')}</EuiText>
</EuiFlexItem>
<EuiFlexItem>
<EuiText size="xs" color="subdued">
Expand All @@ -144,9 +142,9 @@ export const groupPanelRenderer: GroupPanelRenderer<FindingsGroupingAggregation>
</EuiFlexItem>
</EuiFlexGroup>
);
case FINDINGS_GROUPING_OPTIONS.ORCHESTRATOR_CLUSTER_NAME:
case FINDINGS_GROUPING_OPTIONS.ORCHESTRATOR_CLUSTER_ID:
return nullGroupMessage ? (
renderNullGroup(NULL_GROUPING_MESSAGES.ORCHESTRATOR_CLUSTER_NAME)
renderNullGroup(NULL_GROUPING_MESSAGES.ORCHESTRATOR_CLUSTER_ID)
) : (
<EuiFlexGroup alignItems="center" gutterSize="m">
{benchmarkId && (
Expand All @@ -160,9 +158,7 @@ export const groupPanelRenderer: GroupPanelRenderer<FindingsGroupingAggregation>
<EuiFlexItem>
<EuiFlexGroup direction="column" gutterSize="none">
<EuiFlexItem>
<EuiText size="s">
<strong>{bucket.key_as_string}</strong>
</EuiText>
<EuiText size="s">{getGroupPanelTitle('clusterName')}</EuiText>
</EuiFlexItem>
<EuiFlexItem>
<EuiText size="xs" color="subdued">
Expand All @@ -181,9 +177,7 @@ export const groupPanelRenderer: GroupPanelRenderer<FindingsGroupingAggregation>
<EuiFlexItem>
<EuiFlexGroup direction="column" gutterSize="none">
<EuiFlexItem>
<EuiText size="s">
<strong>{bucket.key_as_string}</strong>
</EuiText>
<EuiText size="s">{getGroupPanelTitle()}</EuiText>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ export interface FindingsGroupingAggregation {
benchmarkId?: {
buckets?: GenericBuckets[];
};
accountName?: {
buckets?: GenericBuckets[];
};
clusterName?: {
buckets?: GenericBuckets[];
};
isLoading?: boolean;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,17 +98,19 @@ const getAggregationsByGroupField = (field: string): NamedAggregation[] => {
getTermAggregation('benchmarkName', 'rule.benchmark.name'),
getTermAggregation('benchmarkVersion', 'rule.benchmark.version'),
];
case FINDINGS_GROUPING_OPTIONS.CLOUD_ACCOUNT_NAME:
case FINDINGS_GROUPING_OPTIONS.CLOUD_ACCOUNT_ID:
return [
...aggMetrics,
getTermAggregation('benchmarkName', 'rule.benchmark.name'),
getTermAggregation('benchmarkId', 'rule.benchmark.id'),
getTermAggregation('accountName', 'cloud.account.name'),
];
case FINDINGS_GROUPING_OPTIONS.ORCHESTRATOR_CLUSTER_NAME:
case FINDINGS_GROUPING_OPTIONS.ORCHESTRATOR_CLUSTER_ID:
return [
...aggMetrics,
getTermAggregation('benchmarkName', 'rule.benchmark.name'),
getTermAggregation('benchmarkId', 'rule.benchmark.id'),
getTermAggregation('clusterName', 'orchestrator.cluster.name'),
];
}
return aggMetrics;
Expand Down
Loading