{
+ if (!!onLineClick) {
+ onLineClick(row.original);
+ }
+ }}
+ >
{
row.cells.map(cell => {
const {className, alignToTop} = cell.column;
@@ -267,15 +275,7 @@ const Table = props => {
const isTextValue = !!cell.column.accessor;
return (
-
{
- if (!!onLineClick) {
- onLineClick(row.original);
- }
- }}
- >{isTextValue ? cell.value : cell.render('Cell')}
+
{isTextValue ? cell.value : cell.render('Cell')}
)
})
}
diff --git a/ui/src/layout/AssetScans/AssetScansTable.js b/ui/src/layout/AssetScans/AssetScansTable.js
index 4f4298f05..9cdde9c5d 100644
--- a/ui/src/layout/AssetScans/AssetScansTable.js
+++ b/ui/src/layout/AssetScans/AssetScansTable.js
@@ -6,6 +6,14 @@ import { FILTER_TYPES } from 'context/FiltersProvider';
const TABLE_TITLE = "asset scans";
+const STATUS_MAPPING = {
+ NOT_SCANNED: "Not Scanned",
+ INIT: "Initialized",
+ ATTACHED: "Volume Snapshot Attached",
+ IN_PROGRESS: "In Progress",
+ DONE: "Done"
+}
+
const AssetScansTable = () => {
const columns = useMemo(() => [
{
@@ -36,6 +44,16 @@ const AssetScansTable = () => {
},
disableSort: true
},
+ {
+ Header: "Scan status",
+ id: "status",
+ accessor: original => {
+ const {state} = original?.status?.general || {};
+
+ return STATUS_MAPPING[state];
+ },
+ disableSort: true
+ },
getVulnerabilitiesColumnConfigItem(TABLE_TITLE),
...getFindingsColumnsConfigList(TABLE_TITLE)
], []);
@@ -45,7 +63,7 @@ const AssetScansTable = () => {
columns={columns}
url={APIS.ASSET_SCANS}
expand="scan,target"
- select="id,target,summary,scan"
+ select="id,target,summary,scan,status"
tableTitle={TABLE_TITLE}
filterType={FILTER_TYPES.ASSET_SCANS}
withMargin
diff --git a/ui/src/layout/Dashboard/FindingsImpactWidget/index.js b/ui/src/layout/Dashboard/FindingsImpactWidget/index.js
new file mode 100644
index 000000000..cf1ba190a
--- /dev/null
+++ b/ui/src/layout/Dashboard/FindingsImpactWidget/index.js
@@ -0,0 +1,90 @@
+import React from 'react';
+import SeverityWithCvssDisplay from 'components/SeverityWithCvssDisplay';
+import { getHigestVersionCvssData } from 'utils/utils';
+import { FINDINGS_MAPPING, VULNERABIITY_FINDINGS_ITEM, APIS } from 'utils/systemConsts';
+import FindingsTabsWidget from '../FindingsTabsWidget';
+
+const FINDINGS_ITEMS = [VULNERABIITY_FINDINGS_ITEM, ...Object.values(FINDINGS_MAPPING)];
+
+const TABS_COLUMNS_MAPPING = {
+ [VULNERABIITY_FINDINGS_ITEM.dataKey]: {
+ headerItems: ["Name", "Severity"],
+ bodyItems: [
+ {dataKey: "vulnerability.vulnerabilityName"},
+ {customDisplay: ({vulnerability}) => {
+ const {severity, cvss, vulnerabilityName} = vulnerability || {};
+ const {score, severity: cvssSeverity} = getHigestVersionCvssData(cvss);
+
+ return (
+
+ )
+ }}
+ ]
+ },
+ [FINDINGS_MAPPING.EXPLOITS.dataKey]: {
+ headerItems: ["Vulnerability name"],
+ bodyItems: [
+ {dataKey: "exploit.cveID"}
+ ]
+ },
+ [FINDINGS_MAPPING.MISCONFIGURATIONS.dataKey]: {
+ headerItems: ["Test description"],
+ bodyItems: [
+ {dataKey: "misconfiguration.testDescription"}
+ ]
+ },
+ [FINDINGS_MAPPING.SECRETS.dataKey]: {
+ headerItems: ["Fingerprint"],
+ bodyItems: [
+ {dataKey: "secret.fingerprint"}
+ ]
+ },
+ [FINDINGS_MAPPING.MALWARE.dataKey]: {
+ headerItems: ["Malware name"],
+ bodyItems: [
+ {dataKey: "malware.malwareName"}
+ ]
+ },
+ [FINDINGS_MAPPING.ROOTKITS.dataKey]: {
+ headerItems: ["Rootkit name"],
+ bodyItems: [
+ {dataKey: "rootkit.rootkitName"}
+ ]
+ },
+ [FINDINGS_MAPPING.PACKAGES.dataKey]: {
+ headerItems: ["Package name", "Version"],
+ bodyItems: [
+ {dataKey: "package.name"},
+ {dataKey: "package.version"}
+ ]
+ }
+}
+
+const FindingsImpactWidget = ({className}) => (
+
{
+ const {headerItems=[]} = TABS_COLUMNS_MAPPING[selectedId] || {};
+
+ return (
+ ([...headerItems, "Affected assets"])
+ )
+ }}
+ getBodyItems={(selectedId) => {
+ const {bodyItems=[]} = TABS_COLUMNS_MAPPING[selectedId] || {};
+
+ return ([...bodyItems, {dataKey: "affectedAssetsCount"}])
+ }}
+ />
+)
+
+export default FindingsImpactWidget;
\ No newline at end of file
diff --git a/ui/src/layout/Dashboard/FindingsTabsWidget/findings-tabs-widget.scss b/ui/src/layout/Dashboard/FindingsTabsWidget/findings-tabs-widget.scss
new file mode 100644
index 000000000..15d05b1e0
--- /dev/null
+++ b/ui/src/layout/Dashboard/FindingsTabsWidget/findings-tabs-widget.scss
@@ -0,0 +1,32 @@
+@import 'utils/scss_variables.module.scss';
+
+.findings-tabs-widget {
+ .tabbed-widget-table-wrapper {
+ height: calc(100% - 90px);
+ overflow-y: auto;
+
+ .tabbed-widget-table {
+ font-size: 14px;
+ border-collapse: collapse;
+ width: 100%;
+
+ thead {
+ font-size: 12px;
+ text-align: left;
+ text-transform: uppercase;
+
+ }
+ tbody tr {
+ border-bottom: 1px solid $color-grey-light;
+ }
+ th {
+ padding-top: 10px;
+ white-space: nowrap;
+ }
+ td {
+ padding: 12px 0 5px 0;
+ overflow-wrap: anywhere;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/ui/src/layout/Dashboard/FindingsTabsWidget/index.js b/ui/src/layout/Dashboard/FindingsTabsWidget/index.js
index 7abfe6842..16f21ead4 100644
--- a/ui/src/layout/Dashboard/FindingsTabsWidget/index.js
+++ b/ui/src/layout/Dashboard/FindingsTabsWidget/index.js
@@ -1,13 +1,46 @@
import React, { useState } from 'react';
import classnames from 'classnames';
+import { get } from 'lodash';
+import { useFetch } from 'hooks';
+import Loader from 'components/Loader';
import Tabs from 'components/Tabs';
import IconWithTooltip from 'components/IconWithTooltip';
-import { FINDINGS_MAPPING, VULNERABIITY_FINDINGS_ITEM } from 'utils/systemConsts';
import WidgetWrapper from '../WidgetWrapper';
import COLORS from 'utils/scss_variables.module.scss';
-const FINDINGS_ITEMS = [VULNERABIITY_FINDINGS_ITEM, ...Object.values(FINDINGS_MAPPING).filter(({value}) => value !== FINDINGS_MAPPING.PACKAGES.value)];
+import './findings-tabs-widget.scss';
+
+const WidgetContent = ({data=[], getHeaderItems, getBodyItems, selectedId}) => {
+ const displayData = (data || []).slice(0, 5);
+
+ return (
+
+
+
+ {getHeaderItems(selectedId).map((item, index, items) => (
+ {item} |
+ ))}
+
+
+
+ {
+ displayData.map((item, index) => {
+ return (
+
+ {getBodyItems(selectedId).map(({dataKey, customDisplay: CustomDisplay}, index, items) => (
+
+ {!!CustomDisplay ? : get(item, dataKey)}
+ |
+ ))}
+
+ )
+ })
+ }
+
+
+ )
+}
const Tab = ({widgetName, title, icon, isActive}) => (
(
/>
)
-const FindingsTabsWidget = ({widgetName, className, title, tabContent: TabContent}) => {
- const WIDGET_TAB_ITEMS = FINDINGS_ITEMS.map(({dataKey, icon, title}) => (
+const FindingsTabsWidget = ({widgetName, findingsItems, className, title, url, getHeaderItems, getBodyItems}) => {
+ const [{data, error, loading}] = useFetch(url, {urlPrefix: "ui"});
+
+ const WIDGET_TAB_ITEMS = findingsItems.map(({dataKey, icon, title}) => (
{id: dataKey, customTitle: ({isActive}) => }
))
@@ -34,7 +69,18 @@ const FindingsTabsWidget = ({widgetName, className, title, tabContent: TabConten
onClick={({id}) => setSelectedTabId(id)}
tabItemPadding={15}
/>
-
+
+ {
+ loading ? : (error ? null :
+
+ )
+ }
+
)
}
diff --git a/ui/src/layout/Dashboard/FindingsTrendsWidget/index.js b/ui/src/layout/Dashboard/FindingsTrendsWidget/index.js
index 0ad49f92e..16b5a238e 100644
--- a/ui/src/layout/Dashboard/FindingsTrendsWidget/index.js
+++ b/ui/src/layout/Dashboard/FindingsTrendsWidget/index.js
@@ -105,7 +105,7 @@ const WidgetChart = ({data, selectedFilters}) => {
}
const FindingsTrendsWidget = ({className}) => {
- const {value, label} = TIME_RANGES.HOUR;
+ const {value, label} = TIME_RANGES.WEEK;
const [selectedRange, setSelectedRange] = useState({value, label});
const [{data, error, loading}, fetchData] = useFetch(APIS.DASHBOARD_FINDINGS_TRENDS, {loadOnMount: false});
@@ -121,7 +121,7 @@ const FindingsTrendsWidget = ({className}) => {
]);
return (
-
+
{
diff --git a/ui/src/layout/Dashboard/RiskiestAssetsWidget/index.js b/ui/src/layout/Dashboard/RiskiestAssetsWidget/index.js
index 17bc4668b..0e32b6d77 100644
--- a/ui/src/layout/Dashboard/RiskiestAssetsWidget/index.js
+++ b/ui/src/layout/Dashboard/RiskiestAssetsWidget/index.js
@@ -1,80 +1,42 @@
import React from 'react';
-import { useFetch } from 'hooks';
-import Loader from 'components/Loader';
import VulnerabilitiesDisplay, { VULNERABILITY_SEVERITY_ITEMS } from 'components/VulnerabilitiesDisplay';
-import { APIS, VULNERABIITY_FINDINGS_ITEM } from 'utils/systemConsts';
+import { APIS, VULNERABIITY_FINDINGS_ITEM, FINDINGS_MAPPING } from 'utils/systemConsts';
import FindingsTabsWidget from '../FindingsTabsWidget';
-import './riskiest-assets-widget.scss';
-
-const WidgetContent = ({data=[], maxItems, getCountDisplay}) => {
- const displayData = data.slice(0, maxItems);
-
- return (
-
-
-
- Name |
- Type |
- Findings |
-
-
-
- {
- displayData.map((item, index) => {
- const {name, type} = item?.assetInfo || {};
-
- return (
-
- {name} |
- {type} |
- {getCountDisplay(item || {})} |
-
- )
- })
+const FINDINGS_ITEMS = [VULNERABIITY_FINDINGS_ITEM, ...Object.values(FINDINGS_MAPPING).filter(({value}) => value !== FINDINGS_MAPPING.PACKAGES.value)];
+
+const RiskiestAssetsWidget = ({className}) => (
+ (["Name", "Type", "Findings"])}
+ getBodyItems={(selectedId) => ([
+ {dataKey: "assetInfo.name"},
+ {dataKey: "assetInfo.type"},
+ {customDisplay: ({count, assetInfo, ...props}) => {
+ if (selectedId === VULNERABIITY_FINDINGS_ITEM.dataKey) {
+ const counters = Object.values(VULNERABILITY_SEVERITY_ITEMS).reduce((acc, curr) => {
+ const {totalKey, countKey} = curr;
+
+ return {...acc, [totalKey]: props[countKey]};
+ }, {});
+
+ return (
+
+ )
}
-
-
- )
-}
-
-const RiskiestAssetsWidget = ({className, maxItems=5}) => {
- const [{data, error, loading}] = useFetch(APIS.DASHBOARD_RISKIEST_ASSETS, {urlPrefix: "ui"});
-
- return (
-
(
- loading ? : (error ? null :
- {
- if (selectedTabId === VULNERABIITY_FINDINGS_ITEM.dataKey) {
- const counters = Object.values(VULNERABILITY_SEVERITY_ITEMS).reduce((acc, curr) => {
- const {totalKey, countKey} = curr;
-
- return {...acc, [totalKey]: props[countKey]};
- }, {});
-
- return (
-
- )
- }
-
- return count;
- }}
- />
- )
- )}
- />
- )
-}
+
+ return count;
+ }}
+ ])}
+ />
+)
export default RiskiestAssetsWidget;
\ No newline at end of file
diff --git a/ui/src/layout/Dashboard/RiskiestAssetsWidget/riskiest-assets-widget.scss b/ui/src/layout/Dashboard/RiskiestAssetsWidget/riskiest-assets-widget.scss
deleted file mode 100644
index 4e6f41896..000000000
--- a/ui/src/layout/Dashboard/RiskiestAssetsWidget/riskiest-assets-widget.scss
+++ /dev/null
@@ -1,22 +0,0 @@
-@import 'utils/scss_variables.module.scss';
-
-.tabbed-widget-table {
- font-size: 14px;
- border-collapse: collapse;
- width: 100%;
-
- thead {
- font-size: 12px;
- text-align: left;
- text-transform: uppercase;
- }
- tbody tr {
- border-bottom: 1px solid $color-grey-light;
- }
- th {
- padding-top: 10px;
- }
- td {
- padding: 12px 0 5px 0;
- }
-}
\ No newline at end of file
diff --git a/ui/src/layout/Dashboard/index.js b/ui/src/layout/Dashboard/index.js
index 8e4aa32d7..ca3346009 100644
--- a/ui/src/layout/Dashboard/index.js
+++ b/ui/src/layout/Dashboard/index.js
@@ -4,7 +4,7 @@ import CounterDisplay from './CounterDisplay';
import FindingsTrendsWidget from './FindingsTrendsWidget';
import RiskiestRegionsWidget from './RiskiestRegionsWidget';
import RiskiestAssetsWidget from './RiskiestAssetsWidget';
-import FindingsTabsWidget from './FindingsTabsWidget';
+import FindingsImpactWidget from './FindingsImpactWidget';
import COLORS from 'utils/scss_variables.module.scss';
@@ -27,7 +27,7 @@ const Dashboard = () => {
-
+
)
}
diff --git a/ui/src/layout/Findings/Exploits/ExploitsTable.js b/ui/src/layout/Findings/Exploits/ExploitsTable.js
index b0e37879f..319a3cb6f 100644
--- a/ui/src/layout/Findings/Exploits/ExploitsTable.js
+++ b/ui/src/layout/Findings/Exploits/ExploitsTable.js
@@ -4,23 +4,12 @@ import FindingsTablePage from '../FindingsTablePage';
const ExploitsTable = () => {
const columns = useMemo(() => [
- {
- Header: "Exploit name",
- id: "name",
- accessor: "findingInfo.name",
- disableSort: true
- },
- {
- Header: "Title",
- id: "title",
- accessor: "findingInfo.title",
- disableSort: true
- },
{
Header: "Description",
id: "description",
accessor: "findingInfo.description",
- disableSort: true
+ disableSort: true,
+ width: 300
},
{
Header: "Source DB",
diff --git a/ui/src/layout/Findings/Exploits/TabExploitDetails.js b/ui/src/layout/Findings/Exploits/TabExploitDetails.js
index 1874dda99..bdf28d7cb 100644
--- a/ui/src/layout/Findings/Exploits/TabExploitDetails.js
+++ b/ui/src/layout/Findings/Exploits/TabExploitDetails.js
@@ -4,16 +4,12 @@ import DoublePaneDisplay from 'components/DoublePaneDisplay';
import LinksDisplay from 'layout/Findings/LinkesDisplay';
const TabExploitDetails = ({data}) => {
- const {cveID, name, description, title, sourceDB, urls} = data.findingInfo;
+ const {cveID, description, sourceDB, urls} = data.findingInfo;
return (
(
<>
-
- {name}
- {title}
-
{sourceDB}
{cveID}
diff --git a/ui/src/layout/Findings/Malware/MalwareTable.js b/ui/src/layout/Findings/Malware/MalwareTable.js
index 0147f1ec4..9657e58ac 100644
--- a/ui/src/layout/Findings/Malware/MalwareTable.js
+++ b/ui/src/layout/Findings/Malware/MalwareTable.js
@@ -14,7 +14,8 @@ const MalwareTable = () => {
Header: "File path",
id: "filePath",
accessor: "findingInfo.path",
- disableSort: true
+ disableSort: true,
+ width: 300
},
...getAssetAndScanColumnsConfigList()
], []);
diff --git a/ui/src/layout/Findings/Misconfigurations/MisconfigurationTable.js b/ui/src/layout/Findings/Misconfigurations/MisconfigurationTable.js
index bb8f020da..fdf2368fa 100644
--- a/ui/src/layout/Findings/Misconfigurations/MisconfigurationTable.js
+++ b/ui/src/layout/Findings/Misconfigurations/MisconfigurationTable.js
@@ -1,20 +1,28 @@
import React, { useMemo } from 'react';
import { getAssetAndScanColumnsConfigList } from 'layout/Findings/utils';
import FindingsTablePage from '../FindingsTablePage';
+import { MISCONFIGURATION_SEVERITY_MAP } from './utils';
const MisconfigurationsTable = () => {
const columns = useMemo(() => [
{
- Header: "File path",
- id: "path",
- accessor: "findingInfo.path",
+ Header: "Test ID",
+ id: "testId",
+ accessor: "findingInfo.testID",
+ disableSort: true
+ },
+ {
+ Header: "Severity",
+ id: "severity",
+ accessor: original => MISCONFIGURATION_SEVERITY_MAP[original.findingInfo?.severity],
disableSort: true
},
{
Header: "Description",
id: "description",
- accessor: "findingInfo.description",
- disableSort: true
+ accessor: "findingInfo.testDescription",
+ disableSort: true,
+ width: 200
},
...getAssetAndScanColumnsConfigList()
], []);
diff --git a/ui/src/layout/Findings/Misconfigurations/TabMisconfigurationDetails.js b/ui/src/layout/Findings/Misconfigurations/TabMisconfigurationDetails.js
index f00725e0a..65cb0fee9 100644
--- a/ui/src/layout/Findings/Misconfigurations/TabMisconfigurationDetails.js
+++ b/ui/src/layout/Findings/Misconfigurations/TabMisconfigurationDetails.js
@@ -1,19 +1,32 @@
import React from 'react';
import TitleValueDisplay, { TitleValueDisplayRow } from 'components/TitleValueDisplay';
import DoublePaneDisplay from 'components/DoublePaneDisplay';
+import { MISCONFIGURATION_SEVERITY_MAP } from './utils';
const TabMisconfigurationDetails = ({data}) => {
- const {path, description} = data.findingInfo;
+ const {testID, severity, testDescription, scannerName, scannedPath, remediation, testCategory, message} = data.findingInfo;
return (
(
<>
- {path}
+ {testID}
+ {MISCONFIGURATION_SEVERITY_MAP[severity]}
- {description}
+ {scannerName}
+ {scannedPath}
+
+
+ {testCategory}
+ {remediation}
+
+
+ {message}
+
+
+ {testDescription}
>
)}
diff --git a/ui/src/layout/Findings/Misconfigurations/utils.js b/ui/src/layout/Findings/Misconfigurations/utils.js
new file mode 100644
index 000000000..97979c492
--- /dev/null
+++ b/ui/src/layout/Findings/Misconfigurations/utils.js
@@ -0,0 +1,5 @@
+export const MISCONFIGURATION_SEVERITY_MAP = {
+ MisconfigurationHighSeverity: "High",
+ MisconfigurationMediumSeverity: "Medium",
+ MisconfigurationLowSeverity: "Low"
+};
\ No newline at end of file
diff --git a/ui/src/layout/Findings/Secrets/SecretsTable.js b/ui/src/layout/Findings/Secrets/SecretsTable.js
index 4f0d25925..4bec48e65 100644
--- a/ui/src/layout/Findings/Secrets/SecretsTable.js
+++ b/ui/src/layout/Findings/Secrets/SecretsTable.js
@@ -8,7 +8,8 @@ const SecretsTable = () => {
Header: "Fingerprint",
id: "fingerprint",
accessor: "findingInfo.fingerprint",
- disableSort: true
+ disableSort: true,
+ width: 200
},
{
Header: "Description",
@@ -20,7 +21,8 @@ const SecretsTable = () => {
Header: "File path",
id: "findingInfo",
accessor: "findingInfo.filePath",
- disableSort: true
+ disableSort: true,
+ width: 200
},
...getAssetAndScanColumnsConfigList()
], []);
diff --git a/ui/src/layout/Findings/Vulnerabilities/TabVulnerabilityDetails.js b/ui/src/layout/Findings/Vulnerabilities/TabVulnerabilityDetails.js
index 5b42d23eb..0c5df0cba 100644
--- a/ui/src/layout/Findings/Vulnerabilities/TabVulnerabilityDetails.js
+++ b/ui/src/layout/Findings/Vulnerabilities/TabVulnerabilityDetails.js
@@ -4,11 +4,10 @@ import DoublePaneDisplay from 'components/DoublePaneDisplay';
import Title from 'components/Title';
import ProgressBar, { STATUS_MAPPPING } from 'components/ProgressBar';
import SeverityDisplay from 'components/SeverityDisplay';
-import { formatDate } from 'utils/utils';
+import SeverityWithCvssDisplay from 'components/SeverityWithCvssDisplay';
+import { formatDate, getHigestVersionCvssData } from 'utils/utils';
import LinksDisplay from 'layout/Findings/LinkesDisplay';
import ScoreTag from './ScoreTag';
-import SeverityWithCvssDisplay from './SeverityWithCvssDisplay';
-import { getHigestVersionCvssData } from './utils';
import COLORS from 'utils/scss_variables.module.scss';
@@ -31,7 +30,7 @@ const ScoreBar = ({score}) => {
}
const TabVulnerabilityDetails = ({data}) => {
- const {findingInfo, scan} = data;
+ const {id, findingInfo, scan} = data;
const {vulnerabilityName, package: packageInfo, severity, fix, cvss, description, links} = findingInfo;
const {name: packageName, version} = packageInfo;
@@ -49,7 +48,14 @@ const TabVulnerabilityDetails = ({data}) => {
{version}
-
+
+
+
{formatDate(scan.startTime)}
diff --git a/ui/src/layout/Findings/Vulnerabilities/VulnerabilitiesTable.js b/ui/src/layout/Findings/Vulnerabilities/VulnerabilitiesTable.js
index e0decafe9..d97612a5a 100644
--- a/ui/src/layout/Findings/Vulnerabilities/VulnerabilitiesTable.js
+++ b/ui/src/layout/Findings/Vulnerabilities/VulnerabilitiesTable.js
@@ -1,9 +1,9 @@
import React, { useMemo } from 'react';
import ExpandableList from 'components/ExpandableList';
+import SeverityWithCvssDisplay from 'components/SeverityWithCvssDisplay';
+import { getHigestVersionCvssData } from 'utils/utils';
import { getAssetAndScanColumnsConfigList } from 'layout/Findings/utils';
import FindingsTablePage from '../FindingsTablePage';
-import SeverityWithCvssDisplay from './SeverityWithCvssDisplay';
-import { getHigestVersionCvssData } from './utils';
const VulnerabilitiesTable = () => {
const columns = useMemo(() => [
@@ -25,7 +25,7 @@ const VulnerabilitiesTable = () => {
)
diff --git a/ui/src/layout/Findings/Vulnerabilities/utils.js b/ui/src/layout/Findings/Vulnerabilities/utils.js
deleted file mode 100644
index 3e1992e44..000000000
--- a/ui/src/layout/Findings/Vulnerabilities/utils.js
+++ /dev/null
@@ -1,33 +0,0 @@
-import { orderBy, isEmpty } from 'lodash';
-import CVSS from '@turingpointde/cvss.js';
-
-export const getHigestVersionCvssData = (cvssData) => {
- if (isEmpty(cvssData)) {
- return {};
- }
-
- const sortedCvss = orderBy(cvssData || [], ["version"], ["desc"]);
-
- const {vector, metrics, version} = sortedCvss[0];
-
- const serverData = {
- vector,
- score: metrics.baseScore,
- exploitabilityScore: metrics.exploitabilityScore,
- impactScore: metrics.impactScore
- }
-
- if (version === "2.0") {
- return serverData
- }
-
- const cvssVector = CVSS(vector);
-
- return {
- ...serverData,
- temporalScore: cvssVector.getTemporalScore(),
- environmentalScore: cvssVector.getEnvironmentalScore(),
- severity: cvssVector.getRating(),
- metrics: cvssVector.getDetailedVectorObject().metrics,
- }
-}
\ No newline at end of file
diff --git a/ui/src/layout/Findings/index.js b/ui/src/layout/Findings/index.js
index a4dddb183..30157a444 100644
--- a/ui/src/layout/Findings/index.js
+++ b/ui/src/layout/Findings/index.js
@@ -1,6 +1,7 @@
import React from 'react';
import { useLocation } from 'react-router-dom';
import TabbedPage from 'components/TabbedPage';
+import { FINDINGS_MAPPING, VULNERABIITY_FINDINGS_ITEM, ROUTES } from 'utils/systemConsts';
import Vulnerabilities from './Vulnerabilities';
import Exploits from './Exploits';
import Misconfigurations from './Misconfigurations';
@@ -10,17 +11,65 @@ import Rootkits from './Rootkits';
import Packages from './Packages';
const FINDINGS_TAB_ITEMS = {
- VULNERABILITIES: {id: "vulnerabilities", path: "vulnerabilities", title: "Vulnerabilities", component: Vulnerabilities},
- EXPLOITS: {id: "exploits", path: "exploits", title: "Exploits", component: Exploits},
- MISCONFIGURATIONS: {id: "misconfigurations", path: "misconfigurations", title: "Misconfigurations", component: Misconfigurations},
- SECRETS: {id: "secrets", path: "secrets", title: "Secrets", component: Secrets},
- MALWARE: {id: "malware", path: "malware", title: "Malware", component: Malware},
- ROOTKITS: {id: "rootkits", path: "rootkits", title: "Rootkits", component: Rootkits},
- PACKAGES: {id: "packages", path: "packages", title: "Packages", component: Packages},
+ VULNERABILITIES: {
+ id: "vulnerabilities",
+ path: "vulnerabilities",
+ title: "Vulnerabilities",
+ component: Vulnerabilities,
+ findingsType: VULNERABIITY_FINDINGS_ITEM.value
+ },
+ EXPLOITS: {
+ id: "exploits",
+ path: "exploits",
+ title: "Exploits",
+ component: Exploits,
+ findingsType: FINDINGS_MAPPING.EXPLOITS.value
+ },
+ MISCONFIGURATIONS: {
+ id: "misconfigurations",
+ path: "misconfigurations",
+ title: "Misconfigurations",
+ component: Misconfigurations,
+ findingsType: FINDINGS_MAPPING.MISCONFIGURATIONS.value
+ },
+ SECRETS: {
+ id: "secrets",
+ path: "secrets",
+ title: "Secrets",
+ component: Secrets,
+ findingsType: FINDINGS_MAPPING.SECRETS.value
+ },
+ MALWARE: {
+ id: "malware",
+ path: "malware",
+ title: "Malware",
+ component: Malware,
+ findingsType: FINDINGS_MAPPING.MALWARE.value
+ },
+ ROOTKITS: {
+ id: "rootkits",
+ path: "rootkits",
+ title: "Rootkits",
+ component: Rootkits,
+ findingsType: FINDINGS_MAPPING.ROOTKITS.value
+ },
+ PACKAGES: {
+ id: "packages",
+ path: "packages",
+ title: "Packages",
+ component: Packages,
+ findingsType: FINDINGS_MAPPING.PACKAGES.value
+ }
}
export const FINDINGS_PATHS = Object.keys(FINDINGS_TAB_ITEMS).reduce((acc, curr) => ({...acc, [curr]: FINDINGS_TAB_ITEMS[curr].path}), {});
+export const getFindingsAbsolutePathByFindingType = type => {
+ const relativePath = Object.values(FINDINGS_TAB_ITEMS).find(({findingsType}) => type === findingsType)?.path;
+
+ return `${ROUTES.FINDINGS}/${relativePath}`
+};
+
const Findings = () => {
const {pathname} = useLocation();
diff --git a/ui/src/layout/Scans/ScanConfigWizardModal/index.js b/ui/src/layout/Scans/ScanConfigWizardModal/index.js
index ae7fbc7ae..fb93cd42d 100644
--- a/ui/src/layout/Scans/ScanConfigWizardModal/index.js
+++ b/ui/src/layout/Scans/ScanConfigWizardModal/index.js
@@ -54,7 +54,7 @@ const ScanConfigWizardModal = ({initialData, onClose, onSubmitSuccess}) => {
if (!isEmpty(regions)) {
initialValues.scope.regions = regions.map(({name, vpcs}) => {
- return {name, vpcs: !vpcs ? VPCS_EMPTY_VALUE : vpcs.map(({id, securityGroups}) => {
+ return {name, vpcs: isEmpty(vpcs) ? VPCS_EMPTY_VALUE : vpcs.map(({id, securityGroups}) => {
return {id: id || "", securityGroups: (securityGroups || []).map(({id}) => id)}
})}
})
@@ -112,7 +112,7 @@ const ScanConfigWizardModal = ({initialData, onClose, onSubmitSuccess}) => {
objectType: "AwsScanScope",
allRegions: isAllScope,
regions: isAllScope ? [] : regions.map(({name, vpcs}) => {
- return {name, vpcs: vpcs.map(({id, securityGroups}) => {
+ return {name, vpcs: vpcs.filter(({id}) => !!id).map(({id, securityGroups}) => {
return {id, securityGroups: securityGroups.map(id => ({id}))}
})}
}),
diff --git a/ui/src/layout/Scans/Scans/ScansTable.js b/ui/src/layout/Scans/Scans/ScansTable.js
index f76b39a33..9ca4a5868 100644
--- a/ui/src/layout/Scans/Scans/ScansTable.js
+++ b/ui/src/layout/Scans/Scans/ScansTable.js
@@ -61,7 +61,7 @@ const ScansTable = () => {
id: "status",
Cell: ({row}) => {
const {id, state, stateReason, stateMessage, summary} = row.original;
- const {jobsCompleted, jobsLeftToRun} = summary;
+ const {jobsCompleted, jobsLeftToRun} = summary || {};
return (
{
Header: "Scanned assets",
id: "assets",
accessor: original => {
- const {jobsCompleted, jobsLeftToRun} = original.summary;
+ const {jobsCompleted, jobsLeftToRun} = original.summary || {};
return `${jobsCompleted}/${jobsCompleted + jobsLeftToRun}`;
},
diff --git a/ui/src/layout/detail-displays/Findings/FindingsSystemFilterLinks/index.js b/ui/src/layout/detail-displays/Findings/FindingsSystemFilterLinks/index.js
index 1fc2aa8a3..9c9ee3197 100644
--- a/ui/src/layout/detail-displays/Findings/FindingsSystemFilterLinks/index.js
+++ b/ui/src/layout/detail-displays/Findings/FindingsSystemFilterLinks/index.js
@@ -3,6 +3,7 @@ import { useNavigate } from 'react-router-dom';
import Button from 'components/Button';
import Icon from 'components/Icon';
import { FINDINGS_MAPPING, VULNERABIITY_FINDINGS_ITEM } from 'utils/systemConsts';
+import { getFindingsAbsolutePathByFindingType } from 'layout/Findings';
import './findings-system-filter-links.scss';
@@ -21,12 +22,12 @@ const FindingsSystemFilterLinks = ({totalVulnerabilitiesCount, findingsSummary})
See other findings:
{
- [VULNERABIITY_FINDINGS_ITEM, ...Object.values(FINDINGS_MAPPING)].map(({value, totalKey, title, icon, appRoute}) => {
+ [VULNERABIITY_FINDINGS_ITEM, ...Object.values(FINDINGS_MAPPING)].map(({value, totalKey, title, icon}) => {
const LinkTitle = VULNERABIITY_FINDINGS_ITEM.value === value ? `${totalVulnerabilitiesCount} ${title}` :
- `${findingsSummary[totalKey] || 0} ${title}`;
+ `${!!findingsSummary ? (findingsSummary[totalKey] || 0) : 0} ${title}`;
return (
-
+
)
})
}
diff --git a/ui/src/layout/detail-displays/Findings/index.js b/ui/src/layout/detail-displays/Findings/index.js
index 0b1039855..eeeb3c413 100644
--- a/ui/src/layout/detail-displays/Findings/index.js
+++ b/ui/src/layout/detail-displays/Findings/index.js
@@ -6,11 +6,12 @@ import LinksList from 'components/LinksList';
import VulnerabilitiesDisplay, { getTotlalVulnerabilitiesFromCounters } from 'components/VulnerabilitiesDisplay';
import { FINDINGS_MAPPING, VULNERABIITY_FINDINGS_ITEM } from 'utils/systemConsts';
import { useFilterDispatch, setFilters, FILTER_TYPES } from 'context/FiltersProvider';
+import { getFindingsAbsolutePathByFindingType } from 'layout/Findings';
import FindingsCounterDisplay from './FindingsCounterDisplay';
import FindingsSystemFilterLinks from './FindingsSystemFilterLinks';
-const Findings = ({findingsSummary={}, findingsFilter, findingsFilterTitle, findingsFilterSuffix=""}) => {
- const {totalVulnerabilities} = findingsSummary;
+const Findings = ({findingsSummary, findingsFilter, findingsFilterTitle, findingsFilterSuffix=""}) => {
+ const {totalVulnerabilities} = findingsSummary || {};
const {pathname} = useLocation();
const filtersDispatch = useFilterDispatch();
@@ -25,7 +26,7 @@ const Findings = ({findingsSummary={}, findingsFilter, findingsFilterTitle, find
backPath: pathname,
customDisplay: () => (
)
@@ -42,15 +43,15 @@ const Findings = ({findingsSummary={}, findingsFilter, findingsFilterTitle, find
,
callback: onFindingsClick
},
...Object.keys(FINDINGS_MAPPING).map(findingType => {
- const {totalKey, title, icon, color, appRoute} = FINDINGS_MAPPING[findingType];
+ const {totalKey, title, icon, color, value} = FINDINGS_MAPPING[findingType];
return {
- path: appRoute,
+ path: getFindingsAbsolutePathByFindingType(value),
component: () => (
),
diff --git a/ui/src/layout/detail-displays/ScanDetails/index.js b/ui/src/layout/detail-displays/ScanDetails/index.js
index a3f1fde20..270ad7ec9 100644
--- a/ui/src/layout/detail-displays/ScanDetails/index.js
+++ b/ui/src/layout/detail-displays/ScanDetails/index.js
@@ -28,7 +28,7 @@ const ScanDetails = ({scanData, withAssetScansLink=false}) => {
const filtersDispatch = useFilterDispatch();
const {id, scanConfig, scanConfigSnapshot, startTime, endTime, summary, state, stateMessage, stateReason} = scanData || {};
- const {jobsCompleted, jobsLeftToRun} = summary;
+ const {jobsCompleted, jobsLeftToRun} = summary || {};
const formattedStartTime = formatDate(startTime);
diff --git a/ui/src/utils/systemConsts.js b/ui/src/utils/systemConsts.js
index 8121a4992..9cef90df6 100644
--- a/ui/src/utils/systemConsts.js
+++ b/ui/src/utils/systemConsts.js
@@ -1,5 +1,4 @@
import { ICON_NAMES } from 'components/Icon';
-import { FINDINGS_PATHS } from 'layout/Findings'
import COLORS from 'utils/scss_variables.module.scss';
@@ -20,7 +19,8 @@ export const APIS = {
FINDINGS: "findings",
DASHBOARD_RISKIEST_REGIONS: "dashboard/riskiestRegions",
DASHBOARD_RISKIEST_ASSETS: "dashboard/riskiestAssets",
- DASHBOARD_FINDINGS_TRENDS: "dashboard/findingsTrends"
+ DASHBOARD_FINDINGS_TRENDS: "dashboard/findingsTrends",
+ DASHBOARD_FINDINGS_IMPACT: "dashboard/findingsImpact"
}
export const FINDINGS_MAPPING = {
@@ -32,8 +32,7 @@ export const FINDINGS_MAPPING = {
title: "Exploits",
icon: ICON_NAMES.BOMB,
color: COLORS["color-main"],
- darkColor: COLORS["color-main-variation-dark"],
- appRoute: `${ROUTES.FINDINGS}/${FINDINGS_PATHS.EXPLOITS}`
+ darkColor: COLORS["color-main-variation-dark"]
},
MISCONFIGURATIONS: {
value: "MISCONFIGURATIONS",
@@ -43,8 +42,7 @@ export const FINDINGS_MAPPING = {
title: "Misconfigurations",
icon: ICON_NAMES.COG,
color: COLORS["color-findings-1"],
- darkColor: COLORS["color-findings-1-variation-dark"],
- appRoute: `${ROUTES.FINDINGS}/${FINDINGS_PATHS.MISCONFIGURATIONS}`
+ darkColor: COLORS["color-findings-1-variation-dark"]
},
SECRETS: {
value: "SECRETS",
@@ -53,8 +51,7 @@ export const FINDINGS_MAPPING = {
typeKey: "SECRET",
title: "Secrets",
icon: ICON_NAMES.KEY,
- color: COLORS["color-findings-2"],
- appRoute: `${ROUTES.FINDINGS}/${FINDINGS_PATHS.SECRETS}`
+ color: COLORS["color-findings-2"]
},
MALWARE: {
value: "MALWARE",
@@ -63,8 +60,7 @@ export const FINDINGS_MAPPING = {
typeKey: "MALWARE",
title: "Malware",
icon: ICON_NAMES.BUG,
- color: COLORS["color-findings-3"],
- appRoute: `${ROUTES.FINDINGS}/${FINDINGS_PATHS.MALWARE}`
+ color: COLORS["color-findings-3"]
},
ROOTKITS: {
value: "ROOTKITS",
@@ -73,8 +69,7 @@ export const FINDINGS_MAPPING = {
typeKey: "ROOTKIT",
title: "Rootkits",
icon: ICON_NAMES.GHOST,
- color: COLORS["color-findings-4"],
- appRoute: `${ROUTES.FINDINGS}/${FINDINGS_PATHS.ROOTKITS}`
+ color: COLORS["color-findings-4"]
},
PACKAGES: {
value: "PACKAGES",
@@ -83,8 +78,7 @@ export const FINDINGS_MAPPING = {
typeKey: "PACKAGE",
title: "Packages",
icon: ICON_NAMES.PACKAGE,
- color: COLORS["color-findings-5"],
- appRoute: `${ROUTES.FINDINGS}/${FINDINGS_PATHS.PACKAGES}`
+ color: COLORS["color-findings-5"]
}
}
@@ -96,5 +90,4 @@ export const VULNERABIITY_FINDINGS_ITEM = {
icon: ICON_NAMES.SHIELD,
color: COLORS["color-main-dark"],
darkColor: COLORS["color-main-dark-variation-dark"],
- appRoute: `${ROUTES.FINDINGS}/${FINDINGS_PATHS.VULNERABILITIES}`
}
\ No newline at end of file
diff --git a/ui/src/utils/utils.js b/ui/src/utils/utils.js
index 094dda56b..52237d1ed 100644
--- a/ui/src/utils/utils.js
+++ b/ui/src/utils/utils.js
@@ -1,6 +1,7 @@
import moment from 'moment';
import cronstrue from 'cronstrue';
-import { isNull } from 'lodash';
+import CVSS from '@turingpointde/cvss.js';
+import { isEmpty, orderBy } from 'lodash';
import { FINDINGS_MAPPING, VULNERABIITY_FINDINGS_ITEM } from 'utils/systemConsts';
import IconWithTooltip from 'components/IconWithTooltip';
import VulnerabilitiesDisplay from 'components/VulnerabilitiesDisplay';
@@ -16,6 +17,37 @@ export const cronExpressionToHuman = value => cronstrue.toString(value, {use24Ho
export const getScanName = ({name, startTime}) => `${name} ${formatDate(startTime)}`;
+export const getHigestVersionCvssData = (cvssData) => {
+ if (isEmpty(cvssData)) {
+ return {};
+ }
+
+ const sortedCvss = orderBy(cvssData || [], ["version"], ["desc"]);
+
+ const {vector, metrics, version} = sortedCvss[0];
+
+ const serverData = {
+ vector,
+ score: metrics.baseScore,
+ exploitabilityScore: metrics.exploitabilityScore,
+ impactScore: metrics.impactScore
+ }
+
+ if (version === "2.0") {
+ return serverData
+ }
+
+ const cvssVector = CVSS(vector);
+
+ return {
+ ...serverData,
+ temporalScore: cvssVector.getTemporalScore(),
+ environmentalScore: cvssVector.getEnvironmentalScore(),
+ severity: cvssVector.getRating(),
+ metrics: cvssVector.getDetailedVectorObject().metrics,
+ }
+}
+
export const getFindingsColumnsConfigList = (tableTitle) => Object.keys(FINDINGS_MAPPING).map(findingKey => {
const {totalKey, title, icon} = FINDINGS_MAPPING[findingKey];
@@ -25,7 +57,7 @@ export const getFindingsColumnsConfigList = (tableTitle) => Object.keys(FINDINGS
accessor: original => {
const {summary} = original;
- return isNull(summary) ? 0 : (summary[totalKey] || 0);
+ return isEmpty(summary) ? 0 : (summary[totalKey] || 0);
},
width: 50,
disableSort: true
diff --git a/ui_backend/pkg/rest/dashboard_findings_impact.go b/ui_backend/pkg/rest/dashboard_findings_impact.go
index b9267b953..507e415b1 100644
--- a/ui_backend/pkg/rest/dashboard_findings_impact.go
+++ b/ui_backend/pkg/rest/dashboard_findings_impact.go
@@ -346,6 +346,9 @@ func toModelsVulnerabilitySeverity(severity *backendmodels.VulnerabilitySeverity
}
func toModelsVulnerabilityCVSSArray(cvss *[]backendmodels.VulnerabilityCvss) *[]models.VulnerabilityCvss {
+ if cvss == nil {
+ return nil
+ }
ret := make([]models.VulnerabilityCvss, len(*cvss))
for i, vulnerabilityCvss := range *cvss {
ret[i] = toModelsVulnerabilityCVSS(vulnerabilityCvss)
@@ -362,6 +365,9 @@ func toModelsVulnerabilityCVSS(cvss backendmodels.VulnerabilityCvss) models.Vuln
}
func toModelsVulnerabilityCVSSMetrics(metrics *backendmodels.VulnerabilityCvssMetrics) *models.VulnerabilityCvssMetrics {
+ if metrics == nil {
+ return nil
+ }
return &models.VulnerabilityCvssMetrics{
BaseScore: metrics.BaseScore,
ExploitabilityScore: metrics.ExploitabilityScore,