From 83834e3f7f0abe7d93d1448aa9bf7ecfe79ae2a0 Mon Sep 17 00:00:00 2001 From: RBickert Date: Mon, 30 Jan 2023 08:48:17 +0100 Subject: [PATCH 01/10] Global Audit View: Vulnerabilities Adds a new view in the sidebar, Vulnerability Audit, which either shows every finding by occurrence or every finding grouped by vulnerability (both are filtered by ACL and other optional filters). Makes it possible to easily audit every finding of one's projects in one place. `VIEW_VULNERABILITY` permission is required to access the view. Signed-off-by: RBickert --- src/containers/DefaultContainer.vue | 18 +- src/i18n/locales/en.json | 15 +- src/router/index.js | 13 + src/shared/utils.js | 2 +- src/views/globalAudit/VulnerabilityAudit.vue | 62 +++ .../VulnerabilityAuditByOccurrence.vue | 437 ++++++++++++++++++ ...lnerabilityAuditGroupedByVulnerability.vue | 383 +++++++++++++++ 7 files changed, 927 insertions(+), 3 deletions(-) create mode 100644 src/views/globalAudit/VulnerabilityAudit.vue create mode 100644 src/views/globalAudit/VulnerabilityAuditByOccurrence.vue create mode 100644 src/views/globalAudit/VulnerabilityAuditGroupedByVulnerability.vue diff --git a/src/containers/DefaultContainer.vue b/src/containers/DefaultContainer.vue index d89bacd8a..2c497315b 100644 --- a/src/containers/DefaultContainer.vue +++ b/src/containers/DefaultContainer.vue @@ -114,7 +114,23 @@ url: '/admin', icon: 'fa fa-cogs', permission: permissions.SYSTEM_CONFIGURATION - } + }, + { + title: true, + name: this.$t('message.global_audit'), + class: '', + wrapper: { + element: '', + attributes: {} + }, + permission: permissions.VIEW_VULNERABILITY + }, + { + name: this.$t('message.vulnerability_audit'), + url: '/vulnerabilityAudit', + icon: 'fa fa-tasks', + permission: permissions.VIEW_VULNERABILITY + }, ] } }, diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json index 3a0a08058..b3254ad1b 100644 --- a/src/i18n/locales/en.json +++ b/src/i18n/locales/en.json @@ -76,6 +76,8 @@ "last_bom_import": "Last BOM Import", "overview": "Overview", "audit": "Audit", + "global_audit": "Global Audit", + "vulnerability_audit": "Vulnerability Audit", "audit_vulnerabilities": "Audit Vulnerabilities", "policy_violations": "Policy Violations", "policy_violations_by_classification": "Policy Violations by Classification", @@ -128,6 +130,8 @@ "project_cloning_in_progress": "The project is being created with the cloning options specified", "vulnerability": "Vulnerability", "analysis": "Analysis", + "analysis_status": "Analysis Status", + "analysis_state": "Analysis State", "analysis_tooltip": "The current state of an occurrence of a vulnerability", "justification": "Justification", "justification_tooltip": "The rationale of why the impact analysis state was asserted to be \"Not Affected\"", @@ -210,6 +214,7 @@ "rollback": "Rollback", "workaround_available": "Workaround available", "response": "Vendor Response (project)", + "vendor_response": "Vendor Response", "response_tooltip": "A response to the vulnerability by the manufacturer, supplier, or project responsible for the affected component or service", "analysis_details_tooltip": "Details (explanation, workaround details, and other impact information)", "updated": "Updated", @@ -511,7 +516,15 @@ "show_complete_graph": "Show complete graph", "not_found_in_dependency_graph": "Dependency could not be found in dependency graph", "reindex": "Rebuild index(es)", - "show_update_information": "Highlight outdated components" + "show_update_information": "Highlight outdated components", + "filters": "Filters", + "clear_all": "Clear all", + "text_search": "Text Search", + "from": "From", + "to": "To", + "vulnerabilities_by_occurrence": "Vulnerabilities By Occurrence", + "grouped_vulnerabilities": "Grouped Vulnerabilities", + "occurrences_in_projects": "Occurrences in projects" }, "admin": { "configuration": "Configuration", diff --git a/src/router/index.js b/src/router/index.js index 945d67bec..d016ff937 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -13,6 +13,7 @@ const Dashboard = () => import('@/views/Dashboard'); const ProjectList = () => import('@/views/portfolio/projects/ProjectList'); const ComponentSearch = () => import('@/views/portfolio/components/ComponentSearch'); const VulnerabilityList = () => import('@/views/portfolio/vulnerabilities/VulnerabilityList'); +const VulnerabilityAudit = () => import('@/views/globalAudit/VulnerabilityAudit'); const LicenseList = () => import('@/views/portfolio/licenses/LicenseList'); const PolicyManagement = () => import('@/views/policy/PolicyManagement'); const Project = () => import('@/views/portfolio/projects/Project'); @@ -592,6 +593,18 @@ function configRoutes() { } ] }, + { + path: 'vulnerabilityAudit', + name: 'Vulnerability Audit', + alias: ['vulnerabilityAudit/occurrences', 'vulnerabilityAudit/grouped'], + component: VulnerabilityAudit, + meta: { + title: i18n.t('message.vulnerability_audit'), + i18n: 'message.vulnerability_audit', + sectionPath: '/globalAudit', + permission: 'VIEW_VULNERABILITY' + } + }, // The following route redirects URLs from legacy Dependency-Track UI to new URL format. { // Old: http://host/project/?uuid=3a38aedf-e9e9-4e0a-8913-2d99951aa76d diff --git a/src/shared/utils.js b/src/shared/utils.js index 7b86e33cf..dff674396 100644 --- a/src/shared/utils.js +++ b/src/shared/utils.js @@ -37,7 +37,7 @@ export function getRedirectUrl(router) { // An array of acceptable root context paths defined in the UI. const acceptableRootContextPaths = [ '/dashboard', '/projects', '/components', '/services', '/vulnerabilities', '/licenses', '/policy', '/admin', - '/project', '/component', '/vulnerability', '/license', '/login', '/change-password' + '/project', '/component', '/vulnerability', '/license', '/vulnerabilityAudit', '/login', '/change-password' ]; /** diff --git a/src/views/globalAudit/VulnerabilityAudit.vue b/src/views/globalAudit/VulnerabilityAudit.vue new file mode 100644 index 000000000..e34c2e1d4 --- /dev/null +++ b/src/views/globalAudit/VulnerabilityAudit.vue @@ -0,0 +1,62 @@ + + + diff --git a/src/views/globalAudit/VulnerabilityAuditByOccurrence.vue b/src/views/globalAudit/VulnerabilityAuditByOccurrence.vue new file mode 100644 index 000000000..ced15cac4 --- /dev/null +++ b/src/views/globalAudit/VulnerabilityAuditByOccurrence.vue @@ -0,0 +1,437 @@ + + + diff --git a/src/views/globalAudit/VulnerabilityAuditGroupedByVulnerability.vue b/src/views/globalAudit/VulnerabilityAuditGroupedByVulnerability.vue new file mode 100644 index 000000000..7eb31be49 --- /dev/null +++ b/src/views/globalAudit/VulnerabilityAuditGroupedByVulnerability.vue @@ -0,0 +1,383 @@ + + + From b5b48ce2631b15b0b72728c2626a7d3345d249c2 Mon Sep 17 00:00:00 2001 From: RBickert Date: Wed, 8 Feb 2023 09:15:41 +0100 Subject: [PATCH 02/10] Fix checkboxes blocking checkboxes of other tab Signed-off-by: RBickert --- ...lnerabilityAuditGroupedByVulnerability.vue | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/views/globalAudit/VulnerabilityAuditGroupedByVulnerability.vue b/src/views/globalAudit/VulnerabilityAuditGroupedByVulnerability.vue index 7eb31be49..fc0d7c3e3 100644 --- a/src/views/globalAudit/VulnerabilityAuditGroupedByVulnerability.vue +++ b/src/views/globalAudit/VulnerabilityAuditGroupedByVulnerability.vue @@ -5,45 +5,45 @@

{{ this.$t('message.filters') }}

{{ this.$t('message.clear_all') }}

- + {{ this.$t('message.show_inactive_projects') }} - + - - - + + + - - + + Search in: - + - - + + From ab8ce0ae0ac9238429df6f2d13b422cf88e672d5 Mon Sep 17 00:00:00 2001 From: RBickert Date: Wed, 8 Feb 2023 09:15:59 +0100 Subject: [PATCH 03/10] Position global audit above administration Signed-off-by: RBickert --- src/containers/DefaultContainer.vue | 32 ++++++++++++++--------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/containers/DefaultContainer.vue b/src/containers/DefaultContainer.vue index 2c497315b..dd7feda0b 100644 --- a/src/containers/DefaultContainer.vue +++ b/src/containers/DefaultContainer.vue @@ -93,6 +93,22 @@ icon: 'fa fa-balance-scale', permission: permissions.VIEW_PORTFOLIO }, + { + title: true, + name: this.$t('message.global_audit'), + class: '', + wrapper: { + element: '', + attributes: {} + }, + permission: permissions.VIEW_VULNERABILITY + }, + { + name: this.$t('message.vulnerability_audit'), + url: '/vulnerabilityAudit', + icon: 'fa fa-tasks', + permission: permissions.VIEW_VULNERABILITY + }, { title: true, name: this.$t('message.administration'), @@ -115,22 +131,6 @@ icon: 'fa fa-cogs', permission: permissions.SYSTEM_CONFIGURATION }, - { - title: true, - name: this.$t('message.global_audit'), - class: '', - wrapper: { - element: '', - attributes: {} - }, - permission: permissions.VIEW_VULNERABILITY - }, - { - name: this.$t('message.vulnerability_audit'), - url: '/vulnerabilityAudit', - icon: 'fa fa-tasks', - permission: permissions.VIEW_VULNERABILITY - }, ] } }, From 44ca5cc2f7f7bc36421e42e4ed7480c8d863d92c Mon Sep 17 00:00:00 2001 From: RBickert Date: Wed, 8 Feb 2023 13:03:19 +0100 Subject: [PATCH 04/10] Preserve visibility of columns Signed-off-by: RBickert --- src/views/globalAudit/VulnerabilityAuditByOccurrence.vue | 9 +++++++-- .../VulnerabilityAuditGroupedByVulnerability.vue | 9 +++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/views/globalAudit/VulnerabilityAuditByOccurrence.vue b/src/views/globalAudit/VulnerabilityAuditByOccurrence.vue index ced15cac4..ea1618923 100644 --- a/src/views/globalAudit/VulnerabilityAuditByOccurrence.vue +++ b/src/views/globalAudit/VulnerabilityAuditByOccurrence.vue @@ -79,7 +79,8 @@ ref="table" :columns="columns" :data="data" - :options="options"> + :options="options" + @on-load-success="onLoadSuccess"> @@ -90,6 +91,7 @@ import common from "@/shared/common"; import xssFilters from "xss-filters"; import $ from "jquery"; +import {loadUserPreferencesForBootstrapTable} from "@/shared/utils"; export default { computed: { @@ -205,7 +207,10 @@ import $ from "jquery"; }, cvssToState() { return this.cvssTo ? (!isNaN(this.cvssTo) && (!this.cvssFrom || !isNaN(this.cvssFrom) || this.cvssTo >= this.cvssFrom) && this.cvssTo <= 10 && this.cvssTo >= 0) : null; - } + }, + onLoadSuccess: function () { + loadUserPreferencesForBootstrapTable(this, "VulnerabilityAuditByOccurrence", this.$refs.table.columns); + }, }, data() { return { diff --git a/src/views/globalAudit/VulnerabilityAuditGroupedByVulnerability.vue b/src/views/globalAudit/VulnerabilityAuditGroupedByVulnerability.vue index fc0d7c3e3..5d7d819db 100644 --- a/src/views/globalAudit/VulnerabilityAuditGroupedByVulnerability.vue +++ b/src/views/globalAudit/VulnerabilityAuditGroupedByVulnerability.vue @@ -58,7 +58,8 @@ ref="table" :columns="columns" :data="data" - :options="options"> + :options="options" + @on-load-success="onLoadSuccess"> @@ -68,6 +69,7 @@