Skip to content

Commit 7017fde

Browse files
Merge branch '8.x' into backport/8.x/pr-192345
2 parents 10d2892 + 676d73f commit 7017fde

45 files changed

Lines changed: 1736 additions & 1100 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

test/functional/apps/dashboard/group1/url_field_formatter.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
3737
expect(currentUrl).to.equal(fieldUrl);
3838
};
3939

40-
describe('Changing field formatter to Url', () => {
40+
// Fails in chrome 129+: https://github.com/elastic/kibana-operations/issues/199
41+
describe.skip('Changing field formatter to Url', () => {
4142
before(async function () {
4243
await security.testUser.setRoles(['kibana_admin', 'test_logstash_reader', 'animals']);
4344
await kibanaServer.savedObjects.cleanStandardList();

test/functional/apps/dashboard/group5/embed_mode.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export default function ({
5757
await browser.setWindowSize(1300, 900);
5858
});
5959

60-
// Fails in with chrome 128+ https://github.com/elastic/kibana/issues/163207
60+
// Fails in chrome 128+ https://github.com/elastic/kibana-operations/issues/199
6161
describe.skip('default URL params', () => {
6262
it('hides the chrome', async () => {
6363
const globalNavShown = await globalNav.exists();
@@ -92,7 +92,7 @@ export default function ({
9292
});
9393
});
9494

95-
// Fails in with chrome 128+ https://github.com/elastic/kibana/issues/163207
95+
// Fails in chrome 128+ https://github.com/elastic/kibana-operations/issues/199
9696
describe.skip('non-default URL params', () => {
9797
it('shows or hides elements based on URL params', async () => {
9898
const currentUrl = await browser.getCurrentUrl();

test/functional/apps/discover/group6/_time_field_column.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
308308
});
309309
});
310310

311-
it('should render selected columns correctly', async () => {
311+
// Fails in chrome 129+: https://github.com/elastic/kibana-operations/issues/199
312+
it.skip('should render selected columns correctly', async () => {
312313
await discover.selectTextBaseLang();
313314

314315
await checkSelectedColumns({

x-pack/packages/kbn-cloud-security-posture-common/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export type {
1717
BaseCspSetupStatus,
1818
CspSetupStatus,
1919
} from './types/status';
20-
export type { CspFinding } from './types/findings';
20+
export type { CspFinding, CspFindingResult } from './types/findings';
2121
export type { BenchmarksCisId } from './types/benchmark';
2222
export * from './constants';
2323
export {

x-pack/packages/kbn-cloud-security-posture-common/types/findings.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ interface CspFindingCloud {
4141
region?: string;
4242
}
4343

44-
interface CspFindingResult {
44+
export interface CspFindingResult {
4545
evaluation: 'passed' | 'failed';
4646
expected?: Record<string, unknown>;
4747
evidence: Record<string, unknown>;
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
import { useQuery } from '@tanstack/react-query';
8+
import { lastValueFrom } from 'rxjs';
9+
import { CspFinding } from '@kbn/cloud-security-posture-common';
10+
import { useKibana } from '@kbn/kibana-react-plugin/public';
11+
import type { CoreStart } from '@kbn/core/public';
12+
import { showErrorToast } from '../..';
13+
import type {
14+
CspClientPluginStartDeps,
15+
LatestFindingsRequest,
16+
LatestFindingsResponse,
17+
UseMisconfigurationOptions,
18+
} from '../../type';
19+
20+
import { useGetCspBenchmarkRulesStatesApi } from './use_get_benchmark_rules_state_api';
21+
import {
22+
buildMisconfigurationsFindingsQuery,
23+
getMisconfigurationAggregationCount,
24+
} from '../utils/hooks_utils';
25+
26+
export const useMisconfigurationFindings = (options: UseMisconfigurationOptions) => {
27+
const {
28+
data,
29+
notifications: { toasts },
30+
} = useKibana<CoreStart & CspClientPluginStartDeps>().services;
31+
const { data: rulesStates } = useGetCspBenchmarkRulesStatesApi();
32+
33+
return useQuery(
34+
['csp_misconfiguration_findings', { params: options }, rulesStates],
35+
async () => {
36+
const {
37+
rawResponse: { hits, aggregations },
38+
} = await lastValueFrom(
39+
data.search.search<LatestFindingsRequest, LatestFindingsResponse>({
40+
params: buildMisconfigurationsFindingsQuery(options, rulesStates!),
41+
})
42+
);
43+
if (!aggregations) throw new Error('expected aggregations to be defined');
44+
45+
return {
46+
count: getMisconfigurationAggregationCount(aggregations.count.buckets),
47+
rows: hits.hits.map((finding) => ({
48+
result: finding._source?.result,
49+
rule: finding?._source?.rule,
50+
resource: finding?._source?.resource,
51+
})) as Array<Pick<CspFinding, 'result' | 'rule' | 'resource'>>,
52+
};
53+
},
54+
{
55+
enabled: options.enabled && !!rulesStates,
56+
keepPreviousData: true,
57+
onError: (err: Error) => showErrorToast(toasts, err),
58+
}
59+
);
60+
};

x-pack/packages/kbn-cloud-security-posture/src/hooks/use_misconfiguration_preview.ts

Lines changed: 14 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -6,118 +6,22 @@
66
*/
77
import { useQuery } from '@tanstack/react-query';
88
import { lastValueFrom } from 'rxjs';
9-
import type { IKibanaSearchResponse, IKibanaSearchRequest } from '@kbn/search-types';
10-
import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
11-
import {
12-
CDR_MISCONFIGURATIONS_INDEX_PATTERN,
13-
LATEST_FINDINGS_RETENTION_POLICY,
14-
CspFinding,
15-
} from '@kbn/cloud-security-posture-common';
16-
import type { CspBenchmarkRulesStates } from '@kbn/cloud-security-posture-common/schema/rules/latest';
17-
import { buildMutedRulesFilter } from '@kbn/cloud-security-posture-common';
189
import { useKibana } from '@kbn/kibana-react-plugin/public';
1910
import type { CoreStart } from '@kbn/core/public';
2011
import { showErrorToast } from '../..';
21-
import type { CspClientPluginStartDeps } from '../../type';
12+
import type {
13+
CspClientPluginStartDeps,
14+
LatestFindingsRequest,
15+
LatestFindingsResponse,
16+
UseMisconfigurationOptions,
17+
} from '../../type';
2218
import { useGetCspBenchmarkRulesStatesApi } from './use_get_benchmark_rules_state_api';
19+
import {
20+
buildMisconfigurationsFindingsQuery,
21+
getMisconfigurationAggregationCount,
22+
} from '../utils/hooks_utils';
2323

24-
interface MisconfigurationPreviewBaseEsQuery {
25-
query?: {
26-
bool: {
27-
filter: estypes.QueryDslQueryContainer[];
28-
};
29-
};
30-
}
31-
32-
interface UseMisconfigurationPreviewOptions extends MisconfigurationPreviewBaseEsQuery {
33-
sort: string[][];
34-
enabled: boolean;
35-
pageSize: number;
36-
}
37-
38-
type LatestFindingsRequest = IKibanaSearchRequest<estypes.SearchRequest>;
39-
type LatestFindingsResponse = IKibanaSearchResponse<
40-
estypes.SearchResponse<CspFinding, FindingsAggs>
41-
>;
42-
43-
interface FindingsAggs {
44-
count: estypes.AggregationsMultiBucketAggregateBase<estypes.AggregationsStringRareTermsBucketKeys>;
45-
}
46-
47-
const RESULT_EVALUATION = {
48-
PASSED: 'passed',
49-
FAILED: 'failed',
50-
UNKNOWN: 'unknown',
51-
};
52-
53-
export const getFindingsCountAggQueryMisconfigurationPreview = () => ({
54-
count: {
55-
filters: {
56-
other_bucket_key: RESULT_EVALUATION.UNKNOWN,
57-
filters: {
58-
[RESULT_EVALUATION.PASSED]: { match: { 'result.evaluation': RESULT_EVALUATION.PASSED } },
59-
[RESULT_EVALUATION.FAILED]: { match: { 'result.evaluation': RESULT_EVALUATION.FAILED } },
60-
},
61-
},
62-
},
63-
});
64-
65-
export const getMisconfigurationAggregationCount = (
66-
buckets: estypes.AggregationsBuckets<estypes.AggregationsStringRareTermsBucketKeys>
67-
) => {
68-
return Object.entries(buckets).reduce(
69-
(evaluation, [key, value]) => {
70-
evaluation[key] = (evaluation[key] || 0) + (value.doc_count || 0);
71-
return evaluation;
72-
},
73-
{
74-
[RESULT_EVALUATION.PASSED]: 0,
75-
[RESULT_EVALUATION.FAILED]: 0,
76-
[RESULT_EVALUATION.UNKNOWN]: 0,
77-
}
78-
);
79-
};
80-
81-
export const buildMisconfigurationsFindingsQuery = (
82-
{ query }: UseMisconfigurationPreviewOptions,
83-
rulesStates: CspBenchmarkRulesStates
84-
) => {
85-
const mutedRulesFilterQuery = buildMutedRulesFilter(rulesStates);
86-
87-
return {
88-
index: CDR_MISCONFIGURATIONS_INDEX_PATTERN,
89-
size: 0,
90-
aggs: getFindingsCountAggQueryMisconfigurationPreview(),
91-
ignore_unavailable: false,
92-
query: buildMisconfigurationsFindingsQueryWithFilters(query, mutedRulesFilterQuery),
93-
};
94-
};
95-
96-
const buildMisconfigurationsFindingsQueryWithFilters = (
97-
query: UseMisconfigurationPreviewOptions['query'],
98-
mutedRulesFilterQuery: estypes.QueryDslQueryContainer[]
99-
) => {
100-
return {
101-
...query,
102-
bool: {
103-
...query?.bool,
104-
filter: [
105-
...(query?.bool?.filter ?? []),
106-
{
107-
range: {
108-
'@timestamp': {
109-
gte: `now-${LATEST_FINDINGS_RETENTION_POLICY}`,
110-
lte: 'now',
111-
},
112-
},
113-
},
114-
],
115-
must_not: [...mutedRulesFilterQuery],
116-
},
117-
};
118-
};
119-
120-
export const useMisconfigurationPreview = (options: UseMisconfigurationPreviewOptions) => {
24+
export const useMisconfigurationPreview = (options: UseMisconfigurationOptions) => {
12125
const {
12226
data,
12327
notifications: { toasts },
@@ -134,10 +38,10 @@ export const useMisconfigurationPreview = (options: UseMisconfigurationPreviewOp
13438
params: buildMisconfigurationsFindingsQuery(options, rulesStates!),
13539
})
13640
);
137-
if (!aggregations) throw new Error('expected aggregations to be defined');
138-
41+
if (!aggregations && !options.ignore_unavailable)
42+
throw new Error('expected aggregations to be defined');
13943
return {
140-
count: getMisconfigurationAggregationCount(aggregations.count.buckets),
44+
count: getMisconfigurationAggregationCount(aggregations?.count?.buckets),
14145
};
14246
},
14347
{
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
9+
import {
10+
CDR_MISCONFIGURATIONS_INDEX_PATTERN,
11+
LATEST_FINDINGS_RETENTION_POLICY,
12+
} from '@kbn/cloud-security-posture-common';
13+
import type { CspBenchmarkRulesStates } from '@kbn/cloud-security-posture-common/schema/rules/latest';
14+
import { buildMutedRulesFilter } from '@kbn/cloud-security-posture-common';
15+
import type { UseMisconfigurationOptions } from '../../type';
16+
17+
const MISCONFIGURATIONS_SOURCE_FIELDS = ['result.*', 'rule.*', 'resource.*'];
18+
interface AggregationBucket {
19+
doc_count?: number;
20+
}
21+
22+
type AggregationBuckets = Record<string, AggregationBucket>;
23+
24+
const RESULT_EVALUATION = {
25+
PASSED: 'passed',
26+
FAILED: 'failed',
27+
UNKNOWN: 'unknown',
28+
};
29+
30+
export const getFindingsCountAggQueryMisconfiguration = () => ({
31+
count: {
32+
filters: {
33+
other_bucket_key: RESULT_EVALUATION.UNKNOWN,
34+
filters: {
35+
[RESULT_EVALUATION.PASSED]: { match: { 'result.evaluation': RESULT_EVALUATION.PASSED } },
36+
[RESULT_EVALUATION.FAILED]: { match: { 'result.evaluation': RESULT_EVALUATION.FAILED } },
37+
},
38+
},
39+
},
40+
});
41+
42+
export const getMisconfigurationAggregationCount = (
43+
buckets?: estypes.AggregationsBuckets<estypes.AggregationsStringRareTermsBucketKeys>
44+
) => {
45+
const defaultBuckets: AggregationBuckets = {
46+
[RESULT_EVALUATION.PASSED]: { doc_count: 0 },
47+
[RESULT_EVALUATION.FAILED]: { doc_count: 0 },
48+
[RESULT_EVALUATION.UNKNOWN]: { doc_count: 0 },
49+
};
50+
51+
// if buckets are undefined we will use default buckets
52+
const usedBuckets = buckets || defaultBuckets;
53+
return Object.entries(usedBuckets).reduce(
54+
(evaluation, [key, value]) => {
55+
evaluation[key] = (evaluation[key] || 0) + (value.doc_count || 0);
56+
return evaluation;
57+
},
58+
{
59+
[RESULT_EVALUATION.PASSED]: 0,
60+
[RESULT_EVALUATION.FAILED]: 0,
61+
[RESULT_EVALUATION.UNKNOWN]: 0,
62+
}
63+
);
64+
};
65+
66+
export const buildMisconfigurationsFindingsQuery = (
67+
{ query }: UseMisconfigurationOptions,
68+
rulesStates: CspBenchmarkRulesStates,
69+
isPreview = false
70+
) => {
71+
const mutedRulesFilterQuery = buildMutedRulesFilter(rulesStates);
72+
73+
return {
74+
index: CDR_MISCONFIGURATIONS_INDEX_PATTERN,
75+
size: isPreview ? 0 : 500,
76+
aggs: getFindingsCountAggQueryMisconfiguration(),
77+
ignore_unavailable: true,
78+
query: buildMisconfigurationsFindingsQueryWithFilters(query, mutedRulesFilterQuery),
79+
_source: MISCONFIGURATIONS_SOURCE_FIELDS,
80+
};
81+
};
82+
83+
const buildMisconfigurationsFindingsQueryWithFilters = (
84+
query: UseMisconfigurationOptions['query'],
85+
mutedRulesFilterQuery: estypes.QueryDslQueryContainer[]
86+
) => {
87+
return {
88+
...query,
89+
bool: {
90+
...query?.bool,
91+
filter: [
92+
...(query?.bool?.filter ?? []),
93+
{
94+
range: {
95+
'@timestamp': {
96+
gte: `now-${LATEST_FINDINGS_RETENTION_POLICY}`,
97+
lte: 'now',
98+
},
99+
},
100+
},
101+
],
102+
must_not: [...mutedRulesFilterQuery],
103+
},
104+
};
105+
};

0 commit comments

Comments
 (0)