Skip to content

Commit

Permalink
[Cloud Security] do not filter out vulnerabilities without the score …
Browse files Browse the repository at this point in the history
…field (#163949)

## Summary

as a part of an effort to remove the vulnerability documents filter in
elastic/security-team#7146 this PR removes the
filter for missing `vulnerabiltiy.score.*` fields.

Here is how the CNVM features look like when documents without these
fields are present

<img width="1728" alt="Screenshot 2023-08-15 at 17 54 28"
src="https://github.com/elastic/kibana/assets/478762/0cec1eae-7429-4752-a573-34fcd73fcfed">
<img width="1728" alt="Screenshot 2023-08-15 at 17 53 54"
src="https://github.com/elastic/kibana/assets/478762/775569c5-118d-42dd-8ab1-9974996b3613">
<img width="1439" alt="Screenshot 2023-08-15 at 17 54 56"
src="https://github.com/elastic/kibana/assets/478762/0e98d51f-1732-408f-bffa-758295e953e6">
<img width="719" alt="Screenshot 2023-08-15 at 17 54 49"
src="https://github.com/elastic/kibana/assets/478762/ebd3b24b-45a5-47e4-a11b-181a415df9aa">


### Checklist

Delete any items that are not applicable to this PR.

- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios

---------

Co-authored-by: kibanamachine <[email protected]>
  • Loading branch information
maxcold and kibanamachine authored Aug 23, 2023
1 parent d65b02c commit 443283c
Show file tree
Hide file tree
Showing 5 changed files with 256 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,9 @@ export interface CspVulnerabilityFinding {

export interface Vulnerability {
published_date: string;
score: {
version: string;
base: number;
score?: {
version?: string;
base?: number;
};
cwe: string[];
id: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,6 @@ export const getSafeVulnerabilitiesQueryFilter = (query?: QueryDslQueryContainer
...query,
bool: {
...query?.bool,
filter: [
...((query?.bool?.filter as []) || []),
{ exists: { field: 'vulnerability.score.base' } },
{ exists: { field: 'vulnerability.score.version' } },
{ exists: { field: 'resource.id' } },
],
filter: [...((query?.bool?.filter as []) || []), { exists: { field: 'resource.id' } }],
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
/*
* 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 { getRowValueByColumnId } from './get_vulnerabilities_grid_cell_actions';
import { vulnerabilitiesColumns } from '../vulnerabilities_table_columns';
import { vulnerabilitiesByResourceColumns } from '../vulnerabilities_by_resource/vulnerabilities_by_resource_table_columns';
import { CspVulnerabilityFinding } from '../../../../common/schemas';

describe('getRowValueByColumnId', () => {
it('should return vulnerability id', () => {
const vulnerabilityRow = {
vulnerability: {
id: 'CVE-2017-1000117',
},
};
const columns = vulnerabilitiesColumns;
const columnId = columns.vulnerability;

expect(
getRowValueByColumnId(vulnerabilityRow as Partial<CspVulnerabilityFinding>, columns, columnId)
).toEqual('CVE-2017-1000117');
});

it('should return base as a vulnerability score', () => {
const vulnerabilityRow = {
vulnerability: {
score: {
base: 5,
version: 'v1',
},
},
};
const columns = vulnerabilitiesColumns;
const columnId = columns.cvss;

expect(
getRowValueByColumnId(vulnerabilityRow as Partial<CspVulnerabilityFinding>, columns, columnId)
).toEqual(5);
});

it('should return undefined when no base score is available', () => {
const vulnerabilityRow = {
vulnerability: {},
};
const columns = vulnerabilitiesColumns;
const columnId = columns.cvss;

expect(
getRowValueByColumnId(vulnerabilityRow as Partial<CspVulnerabilityFinding>, columns, columnId)
).toEqual(undefined);

const vulnerabilityRow2 = {
vulnerability: {
score: {
version: 'v1',
},
},
};

expect(
getRowValueByColumnId(
vulnerabilityRow2 as Partial<CspVulnerabilityFinding>,
columns,
columnId
)
).toEqual(undefined);
});

it('should return resource id', () => {
const vulnerabilityRow = {
resource: {
id: 'i-1234567890abcdef0',
},
};
const columns = vulnerabilitiesByResourceColumns;
const columnId = columns.resourceId;

expect(
getRowValueByColumnId(vulnerabilityRow as Partial<CspVulnerabilityFinding>, columns, columnId)
).toEqual('i-1234567890abcdef0');
});

it('should return resource name', () => {
const vulnerabilityRow = {
resource: {
name: 'test',
},
};
const columns1 = vulnerabilitiesByResourceColumns;
const columns2 = vulnerabilitiesColumns;
const columnId1 = columns1.resourceName;
const columnId2 = columns2.resourceName;

expect(
getRowValueByColumnId(
vulnerabilityRow as Partial<CspVulnerabilityFinding>,
columns1,
columnId1
)
).toEqual('test');
expect(
getRowValueByColumnId(
vulnerabilityRow as Partial<CspVulnerabilityFinding>,
columns2,
columnId2
)
).toEqual('test');
});

it('should return vulnerability severity', () => {
const vulnerabilityRow = {
vulnerability: {
severity: 'high',
},
};
const columns = vulnerabilitiesColumns;
const columnId = columns.severity;

expect(
getRowValueByColumnId(vulnerabilityRow as Partial<CspVulnerabilityFinding>, columns, columnId)
).toEqual('high');
});

it('should return package fields', () => {
const vulnerabilityRow = {
vulnerability: {
package: {
name: 'test',
version: '1.0.0',
fixed_version: '1.0.1',
},
},
};
const columns1 = vulnerabilitiesColumns;
const columnId1 = columns1.package;
const columnId2 = columns1.version;
const columnId3 = columns1.fixedVersion;

expect(
getRowValueByColumnId(
vulnerabilityRow as Partial<CspVulnerabilityFinding>,
columns1,
columnId1
)
).toEqual('test');
expect(
getRowValueByColumnId(
vulnerabilityRow as Partial<CspVulnerabilityFinding>,
columns1,
columnId2
)
).toEqual('1.0.0');
expect(
getRowValueByColumnId(
vulnerabilityRow as Partial<CspVulnerabilityFinding>,
columns1,
columnId3
)
).toEqual('1.0.1');
});

it('should return undefined is package is missing', () => {
const vulnerabilityRow = {
vulnerability: {},
};
const columns = vulnerabilitiesColumns;
const columnId = columns.package;

expect(
getRowValueByColumnId(vulnerabilityRow as Partial<CspVulnerabilityFinding>, columns, columnId)
).toEqual(undefined);
});

it('should return cloud region', () => {
const vulnerabilityRow = {
cloud: {
region: 'us-east-1',
},
};
const columns = vulnerabilitiesByResourceColumns;
const columnId = columns.region;

expect(
getRowValueByColumnId(vulnerabilityRow as Partial<CspVulnerabilityFinding>, columns, columnId)
).toEqual('us-east-1');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,40 @@ import { CspVulnerabilityFinding } from '../../../../common/schemas';
import { getFilters } from './get_filters';
import { FILTER_IN, FILTER_OUT } from '../translations';

export const getRowValueByColumnId = (
vulnerabilityRow: Partial<CspVulnerabilityFinding>,
columns: Record<string, string>,
columnId: string
) => {
if (columnId === columns.vulnerability) {
return vulnerabilityRow.vulnerability?.id;
}
if (columnId === columns.cvss) {
return vulnerabilityRow.vulnerability?.score?.base;
}
if (columnId === columns.resourceId) {
return vulnerabilityRow.resource?.id;
}
if (columnId === columns.resourceName) {
return vulnerabilityRow.resource?.name;
}
if (columnId === columns.severity) {
return vulnerabilityRow.vulnerability?.severity;
}
if (columnId === columns.package) {
return vulnerabilityRow.vulnerability?.package?.name;
}
if (columnId === columns.version) {
return vulnerabilityRow.vulnerability?.package?.version;
}
if (columnId === columns.fixedVersion) {
return vulnerabilityRow.vulnerability?.package?.fixed_version;
}
if (columnId === columns.region) {
return vulnerabilityRow.cloud?.region;
}
};

export const getVulnerabilitiesGridCellActions = <
T extends Array<Partial<CspVulnerabilityFinding>>
>({
Expand All @@ -34,33 +68,7 @@ export const getVulnerabilitiesGridCellActions = <
const vulnerabilityRow = data[rowIndex];
if (!vulnerabilityRow) return null;

if (columnId === columns.vulnerability) {
return vulnerabilityRow.vulnerability?.id;
}
if (columnId === columns.cvss) {
return vulnerabilityRow.vulnerability?.score.base;
}
if (columnId === columns.resourceId) {
return vulnerabilityRow.resource?.id;
}
if (columnId === columns.resourceName) {
return vulnerabilityRow.resource?.name;
}
if (columnId === columns.severity) {
return vulnerabilityRow.vulnerability?.severity;
}
if (columnId === columns.package) {
return vulnerabilityRow.vulnerability?.package?.name;
}
if (columnId === columns.version) {
return vulnerabilityRow.vulnerability?.package?.version;
}
if (columnId === columns.fixedVersion) {
return vulnerabilityRow.vulnerability?.package?.fixed_version;
}
if (columnId === columns.region) {
return vulnerabilityRow.cloud?.region;
}
return getRowValueByColumnId(vulnerabilityRow, columns, columnId);
};

const cellActions: EuiDataGridColumnCellAction[] = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,11 +159,19 @@ export const VulnerabilityTablePanelSection = () => {
defaultMessage: 'CVSS',
}
),
render: (cvss: { score: number; version: string }) => (
<EuiLink onClick={() => onCellClick({ 'vulnerability.score.base': cvss.score })}>
<CVSScoreBadge version={cvss.version} score={cvss.score} />
</EuiLink>
),
render: (cvss: PatchableVulnerabilityStat['cvss']) => {
if (!cvss.score || !cvss.version) {
return null;
}

const esQuery = { 'vulnerability.score.base': cvss.score };

return (
<EuiLink onClick={() => onCellClick(esQuery)}>
<CVSScoreBadge version={cvss.version} score={cvss.score} />
</EuiLink>
);
},
},
{
field: 'packageFixVersion',
Expand Down Expand Up @@ -229,11 +237,19 @@ export const VulnerabilityTablePanelSection = () => {
defaultMessage: 'CVSS',
}
),
render: (cvss: { score: number; version: string }) => (
<EuiLink onClick={() => onCellClick({ 'vulnerability.score.base': cvss.score })}>
<CVSScoreBadge version={cvss.version} score={cvss.score} />
</EuiLink>
),
render: (cvss: VulnerabilityStat['cvss']) => {
if (!cvss.score || !cvss.version) {
return null;
}

const esQuery = { 'vulnerability.score.base': cvss.score };

return (
<EuiLink onClick={() => onCellClick(esQuery)}>
<CVSScoreBadge version={cvss.version} score={cvss.score} />
</EuiLink>
);
},
},
{
field: 'severity',
Expand Down

0 comments on commit 443283c

Please sign in to comment.