mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
# Backport This will backport the following commits from `main` to `8.x`: - [[Cloud Security] Fix vulnerability detection rule creation logic (#195291)](https://github.com/elastic/kibana/pull/195291) <!--- Backport version: 9.4.3 --> ### 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":"2024-10-09T13:18:33Z","message":"[Cloud Security] Fix vulnerability detection rule creation logic (#195291)","sha":"fbf3f8b8b24575bd9fdc10e05ed0e5032a1a4340","branchLabelMapping":{"^v9.0.0$":"main","^v8.16.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","v9.0.0","Team:Cloud Security","backport:prev-minor"],"title":"[Cloud Security] Fix vulnerability detection rule creation logic","number":195291,"url":"https://github.com/elastic/kibana/pull/195291","mergeCommit":{"message":"[Cloud Security] Fix vulnerability detection rule creation logic (#195291)","sha":"fbf3f8b8b24575bd9fdc10e05ed0e5032a1a4340"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","branchLabelMappingKey":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/195291","number":195291,"mergeCommit":{"message":"[Cloud Security] Fix vulnerability detection rule creation logic (#195291)","sha":"fbf3f8b8b24575bd9fdc10e05ed0e5032a1a4340"}}]}] BACKPORT--> Co-authored-by: Jordan <51442161+JordanSh@users.noreply.github.com>
This commit is contained in:
parent
4de542f2c4
commit
0556cfc88f
6 changed files with 142 additions and 44 deletions
|
@ -18,7 +18,10 @@ export type {
|
|||
CspSetupStatus,
|
||||
} from './types/status';
|
||||
export type { CspFinding, CspFindingResult } from './types/findings';
|
||||
export type { CspVulnerabilityFinding } from './schema/vulnerabilities/csp_vulnerability_finding';
|
||||
export type {
|
||||
CspVulnerabilityFinding,
|
||||
Vulnerability,
|
||||
} from './schema/vulnerabilities/csp_vulnerability_finding';
|
||||
export type { BenchmarksCisId } from './types/benchmark';
|
||||
export type { VulnSeverity } from './types/vulnerabilities';
|
||||
export * from './constants';
|
||||
|
|
|
@ -108,11 +108,11 @@ export const LatestVulnerabilitiesTable = ({
|
|||
});
|
||||
|
||||
const createVulnerabilityRuleFn = (rowIndex: number) => {
|
||||
const finding = getCspVulnerabilityFinding(rows[rowIndex].raw._source);
|
||||
if (!finding) return;
|
||||
const vulnerabilityFinding = getCspVulnerabilityFinding(rows[rowIndex].raw._source);
|
||||
if (!vulnerabilityFinding) return;
|
||||
|
||||
return async (http: HttpSetup) =>
|
||||
createDetectionRuleFromVulnerabilityFinding(http, finding.vulnerability);
|
||||
createDetectionRuleFromVulnerabilityFinding(http, vulnerabilityFinding);
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* 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 {
|
||||
getVulnerabilityTags,
|
||||
getVulnerabilityRuleName,
|
||||
generateVulnerabilitiesRuleQuery,
|
||||
} from './create_detection_rule_from_vulnerability';
|
||||
import { CspVulnerabilityFinding, Vulnerability } from '@kbn/cloud-security-posture-common';
|
||||
import { isNativeCspFinding } from '../../../common/utils/is_native_csp_finding';
|
||||
|
||||
// Mocking the isNativeCspFinding function
|
||||
jest.mock('../../../common/utils/is_native_csp_finding', () => ({
|
||||
isNativeCspFinding: jest.fn(),
|
||||
}));
|
||||
|
||||
describe('CreateDetectionRuleFromVulnerability', () => {
|
||||
describe('getVulnerabilityTags', () => {
|
||||
it('should return tags with CSP_RULE_TAG and vulnerability id', () => {
|
||||
const mockVulnerability = {
|
||||
vulnerability: { id: 'CVE-2024-00001' },
|
||||
observer: undefined,
|
||||
data_stream: undefined,
|
||||
} as unknown as CspVulnerabilityFinding;
|
||||
|
||||
(isNativeCspFinding as jest.Mock).mockReturnValue(false);
|
||||
|
||||
const tags = getVulnerabilityTags(mockVulnerability);
|
||||
expect(tags).toEqual(['Cloud Security', 'CVE-2024-00001']);
|
||||
});
|
||||
|
||||
it('should include vendor tag if available', () => {
|
||||
const mockVulnerability = {
|
||||
vulnerability: { id: 'CVE-2024-00002' },
|
||||
observer: { vendor: 'Wiz' },
|
||||
data_stream: undefined,
|
||||
} as unknown as CspVulnerabilityFinding;
|
||||
|
||||
(isNativeCspFinding as jest.Mock).mockReturnValue(false);
|
||||
|
||||
const tags = getVulnerabilityTags(mockVulnerability);
|
||||
expect(tags).toEqual(['Cloud Security', 'CVE-2024-00002', 'Wiz']);
|
||||
});
|
||||
|
||||
it('should include CNVM tags for native findings', () => {
|
||||
const mockVulnerability = {
|
||||
vulnerability: { id: 'CVE-2024-00003' },
|
||||
observer: undefined,
|
||||
data_stream: undefined,
|
||||
} as unknown as CspVulnerabilityFinding;
|
||||
|
||||
(isNativeCspFinding as jest.Mock).mockReturnValue(true);
|
||||
|
||||
const tags = getVulnerabilityTags(mockVulnerability);
|
||||
expect(tags).toEqual([
|
||||
'Cloud Security',
|
||||
'CNVM',
|
||||
'Data Source: Cloud Native Vulnerability Management',
|
||||
'Use Case: Vulnerability',
|
||||
'OS: Linux',
|
||||
'CVE-2024-00003',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getVulnerabilityRuleName', () => {
|
||||
it('should return correct rule name for a vulnerability', () => {
|
||||
const mockVulnerability = {
|
||||
id: 'CVE-2024-00004',
|
||||
description: '',
|
||||
reference: '',
|
||||
} as Vulnerability;
|
||||
|
||||
const ruleName = getVulnerabilityRuleName(mockVulnerability);
|
||||
expect(ruleName).toEqual('Vulnerability: CVE-2024-00004');
|
||||
});
|
||||
});
|
||||
|
||||
describe('generateVulnerabilitiesRuleQuery', () => {
|
||||
it('should generate correct query for a vulnerability', () => {
|
||||
const mockVulnerability = {
|
||||
id: 'CVE-2024-00005',
|
||||
description: '',
|
||||
reference: '',
|
||||
} as Vulnerability;
|
||||
const currentTimestamp = new Date().toISOString();
|
||||
|
||||
const query = generateVulnerabilitiesRuleQuery(mockVulnerability);
|
||||
expect(query).toEqual(
|
||||
`vulnerability.id: "CVE-2024-00005" AND event.ingested >= "${currentTimestamp}"`
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -8,10 +8,12 @@
|
|||
import { HttpSetup } from '@kbn/core/public';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import {
|
||||
CspVulnerabilityFinding,
|
||||
LATEST_VULNERABILITIES_RETENTION_POLICY,
|
||||
VULNERABILITIES_SEVERITY,
|
||||
} from '@kbn/cloud-security-posture-common';
|
||||
import type { Vulnerability } from '@kbn/cloud-security-posture-common/schema/vulnerabilities/latest';
|
||||
import { isNativeCspFinding } from '../../../common/utils/is_native_csp_finding';
|
||||
import { VULNERABILITIES_INDEX_PATTERN } from '../../../../common/constants';
|
||||
import { createDetectionRule } from '../../../common/api/create_detection_rule';
|
||||
|
||||
|
@ -42,15 +44,7 @@ enum AlertSuppressionMissingFieldsStrategy {
|
|||
Suppress = 'suppress',
|
||||
}
|
||||
|
||||
const CSP_RULE_TAG = 'Cloud Security';
|
||||
|
||||
const STATIC_RULE_TAGS = [CSP_RULE_TAG];
|
||||
|
||||
const generateVulnerabilitiesTags = (tags?: string[]) => {
|
||||
return [...STATIC_RULE_TAGS, ...(!!tags?.length ? tags : [])];
|
||||
};
|
||||
|
||||
const getVulnerabilityRuleName = (vulnerability: Vulnerability) => {
|
||||
export const getVulnerabilityRuleName = (vulnerability: Vulnerability) => {
|
||||
return i18n.translate('xpack.csp.vulnerabilities.detectionRuleNamePrefix', {
|
||||
defaultMessage: 'Vulnerability: {vulnerabilityId}',
|
||||
values: {
|
||||
|
@ -59,20 +53,42 @@ const getVulnerabilityRuleName = (vulnerability: Vulnerability) => {
|
|||
});
|
||||
};
|
||||
|
||||
const generateVulnerabilitiesRuleQuery = (vulnerability: Vulnerability) => {
|
||||
export const generateVulnerabilitiesRuleQuery = (vulnerability: Vulnerability) => {
|
||||
const currentTimestamp = new Date().toISOString();
|
||||
|
||||
return `vulnerability.id: "${vulnerability.id}" AND event.ingested >= "${currentTimestamp}"`;
|
||||
};
|
||||
|
||||
const CSP_RULE_TAG = 'Cloud Security';
|
||||
const CNVM_TAG = 'CNVM';
|
||||
const CNVM_RULE_TAG_DATA_SOURCE = 'Data Source: Cloud Native Vulnerability Management';
|
||||
const CNVM_RULE_TAG_USE_CASE = 'Use Case: Vulnerability';
|
||||
const CNVM_RULE_TAG_OS = 'OS: Linux';
|
||||
|
||||
export const getVulnerabilityTags = (vulnerabilityFinding: CspVulnerabilityFinding) => {
|
||||
let tags = [vulnerabilityFinding.vulnerability.id];
|
||||
const vendor =
|
||||
vulnerabilityFinding.observer?.vendor || vulnerabilityFinding?.data_stream?.dataset;
|
||||
|
||||
if (isNativeCspFinding(vulnerabilityFinding)) {
|
||||
tags = [CNVM_TAG, CNVM_RULE_TAG_DATA_SOURCE, CNVM_RULE_TAG_USE_CASE, CNVM_RULE_TAG_OS, ...tags];
|
||||
} else if (!!vendor) {
|
||||
tags.push(vendor);
|
||||
}
|
||||
|
||||
return [CSP_RULE_TAG, ...tags];
|
||||
};
|
||||
|
||||
/*
|
||||
* Creates a detection rule from a Vulnerability
|
||||
*/
|
||||
export const createDetectionRuleFromVulnerabilityFinding = async (
|
||||
http: HttpSetup,
|
||||
vulnerability: Vulnerability,
|
||||
tags?: string[]
|
||||
vulnerabilityFinding: CspVulnerabilityFinding
|
||||
) => {
|
||||
const tags = getVulnerabilityTags(vulnerabilityFinding);
|
||||
const vulnerability = vulnerabilityFinding.vulnerability;
|
||||
|
||||
return await createDetectionRule({
|
||||
http,
|
||||
rule: {
|
||||
|
@ -135,7 +151,7 @@ export const createDetectionRuleFromVulnerabilityFinding = async (
|
|||
references: vulnerability.reference ? [vulnerability.reference] : [],
|
||||
name: getVulnerabilityRuleName(vulnerability),
|
||||
description: vulnerability.description,
|
||||
tags: generateVulnerabilitiesTags(tags),
|
||||
tags,
|
||||
investigation_fields: DEFAULT_INVESTIGATION_FIELDS,
|
||||
},
|
||||
});
|
||||
|
|
|
@ -8,40 +8,21 @@
|
|||
import React from 'react';
|
||||
import type { HttpSetup } from '@kbn/core/public';
|
||||
import type { CspVulnerabilityFinding } from '@kbn/cloud-security-posture-common/schema/vulnerabilities/latest';
|
||||
import { isNativeCspFinding } from '../../../common/utils/is_native_csp_finding';
|
||||
import { DetectionRuleCounter } from '../../../components/detection_rule_counter';
|
||||
import { createDetectionRuleFromVulnerabilityFinding } from '../utils/create_detection_rule_from_vulnerability';
|
||||
|
||||
const CNVM_TAG = 'CNVM';
|
||||
const CNVM_RULE_TAG_DATA_SOURCE = 'Data Source: Cloud Native Vulnerability Management';
|
||||
const CNVM_RULE_TAG_USE_CASE = 'Use Case: Vulnerability';
|
||||
const CNVM_RULE_TAG_OS = 'OS: Linux';
|
||||
|
||||
const getTags = (vulnerabilityRecord: CspVulnerabilityFinding) => {
|
||||
let tags = [vulnerabilityRecord.vulnerability.id];
|
||||
const vendor = vulnerabilityRecord.observer?.vendor || vulnerabilityRecord?.data_stream?.dataset;
|
||||
|
||||
if (isNativeCspFinding(vulnerabilityRecord)) {
|
||||
tags = [CNVM_TAG, CNVM_RULE_TAG_DATA_SOURCE, CNVM_RULE_TAG_USE_CASE, CNVM_RULE_TAG_OS, ...tags];
|
||||
} else if (!!vendor) {
|
||||
tags.push(vendor);
|
||||
}
|
||||
|
||||
return tags;
|
||||
};
|
||||
import {
|
||||
createDetectionRuleFromVulnerabilityFinding,
|
||||
getVulnerabilityTags,
|
||||
} from '../utils/create_detection_rule_from_vulnerability';
|
||||
|
||||
export const VulnerabilityDetectionRuleCounter = ({
|
||||
vulnerabilityRecord,
|
||||
}: {
|
||||
vulnerabilityRecord: CspVulnerabilityFinding;
|
||||
}) => {
|
||||
const tags = getTags(vulnerabilityRecord);
|
||||
const tags = getVulnerabilityTags(vulnerabilityRecord);
|
||||
|
||||
const createVulnerabilityRuleFn = async (http: HttpSetup) =>
|
||||
await createDetectionRuleFromVulnerabilityFinding(
|
||||
http,
|
||||
vulnerabilityRecord.vulnerability,
|
||||
tags
|
||||
);
|
||||
await createDetectionRuleFromVulnerabilityFinding(http, vulnerabilityRecord);
|
||||
|
||||
return <DetectionRuleCounter tags={tags} createRuleFn={createVulnerabilityRuleFn} />;
|
||||
};
|
||||
|
|
|
@ -162,7 +162,7 @@ export const VulnerabilityFindingFlyout = ({
|
|||
const vulnerabilityReference = vulnerability?.reference;
|
||||
|
||||
const createVulnerabilityRuleFn = async (http: HttpSetup) =>
|
||||
await createDetectionRuleFromVulnerabilityFinding(http, vulnerabilityRecord.vulnerability);
|
||||
await createDetectionRuleFromVulnerabilityFinding(http, vulnerabilityRecord);
|
||||
|
||||
return (
|
||||
<EuiFlyout onClose={closeFlyout}>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue