diff --git a/pkg/sbombastic-image-vulnerability-scanner/components/common/VexStatusBadge.vue b/pkg/sbombastic-image-vulnerability-scanner/components/common/VexStatusBadge.vue new file mode 100644 index 0000000..7c43be7 --- /dev/null +++ b/pkg/sbombastic-image-vulnerability-scanner/components/common/VexStatusBadge.vue @@ -0,0 +1,64 @@ + + + {{ t(`imageScanner.enum.status.${status.toLowerCase()}`) }} + + + + + + + diff --git a/pkg/sbombastic-image-vulnerability-scanner/config/sbombastic-image-vulnerability-scanner.ts b/pkg/sbombastic-image-vulnerability-scanner/config/sbombastic-image-vulnerability-scanner.ts index cb4f40a..7bd134c 100644 --- a/pkg/sbombastic-image-vulnerability-scanner/config/sbombastic-image-vulnerability-scanner.ts +++ b/pkg/sbombastic-image-vulnerability-scanner/config/sbombastic-image-vulnerability-scanner.ts @@ -39,6 +39,19 @@ export function init($plugin: IPlugin, store: any) { }, }); + virtualType({ + labelKey: 'imageScanner.vexManagement.title', + name: PAGE.VEX_MANAGEMENT, + namespaced: false, + route: { + name: `c-cluster-${PRODUCT_NAME}-${PAGE.VEX_MANAGEMENT}`, + params: { + product: PRODUCT_NAME + }, + meta: { pkg: PRODUCT_NAME, product: PRODUCT_NAME } + } + }); + virtualType({ label: "Components Demo", name: "demo", @@ -55,6 +68,8 @@ export function init($plugin: IPlugin, store: any) { basicType([ PAGE.IMAGE_OVERVIEW, PAGE.VULNERABILITY_OVERVIEW, + PAGE.VEX_MANAGEMENT, + "demo" ]); basicType([RESOURCE.REGISTRY], 'Advanced'); diff --git a/pkg/sbombastic-image-vulnerability-scanner/config/table-headers.ts b/pkg/sbombastic-image-vulnerability-scanner/config/table-headers.ts index ada2835..32ee8a5 100644 --- a/pkg/sbombastic-image-vulnerability-scanner/config/table-headers.ts +++ b/pkg/sbombastic-image-vulnerability-scanner/config/table-headers.ts @@ -103,3 +103,42 @@ export const REGISTRY_SCAN_HISTORY_TABLE = [ sort: "errors", }, ]; + +export const VEX_MANAGEMENT_TABLE = [ + { + name: "_status", + labelKey: "imageScanner.vexManagement.table.headers.status", + value: "_status", + getValue: (row: any) => row._status, + formatter: "VexStatusCellBadge", + sort: "_status", + }, + { + name: "name", + labelKey: "imageScanner.vexManagement.table.headers.name", + value: "name", + formatter: "VexNameLink", + sort: "name", + }, + { + name: "uri", + labelKey: "imageScanner.vexManagement.table.headers.uri", + value: "uri", + formatter: "UriExternalLink", + sort: "uri", + }, + { + name: "createdBy", + labelKey: "imageScanner.vexManagement.table.headers.createdBy", + value: "createdBy", + sort: "createdBy", + }, + { + name: "updated", + labelKey: "imageScanner.vexManagement.table.headers.updated", + value: "updated", + getValue: (row: any) => row.updated, + formatter: "VexDateFormatter", + sort: "updated", + } +]; diff --git a/pkg/sbombastic-image-vulnerability-scanner/formatters/UriExternalLink.vue b/pkg/sbombastic-image-vulnerability-scanner/formatters/UriExternalLink.vue new file mode 100644 index 0000000..690fa25 --- /dev/null +++ b/pkg/sbombastic-image-vulnerability-scanner/formatters/UriExternalLink.vue @@ -0,0 +1,22 @@ + + + + + {{ value }} + + + diff --git a/pkg/sbombastic-image-vulnerability-scanner/formatters/VexDateFormatter.vue b/pkg/sbombastic-image-vulnerability-scanner/formatters/VexDateFormatter.vue new file mode 100644 index 0000000..7a78a5a --- /dev/null +++ b/pkg/sbombastic-image-vulnerability-scanner/formatters/VexDateFormatter.vue @@ -0,0 +1,33 @@ + + {{ formattedDate }} + + + diff --git a/pkg/sbombastic-image-vulnerability-scanner/formatters/VexNameLink.vue b/pkg/sbombastic-image-vulnerability-scanner/formatters/VexNameLink.vue new file mode 100644 index 0000000..28d978f --- /dev/null +++ b/pkg/sbombastic-image-vulnerability-scanner/formatters/VexNameLink.vue @@ -0,0 +1,19 @@ + + + + {{ value }} + diff --git a/pkg/sbombastic-image-vulnerability-scanner/formatters/VexStatusCellBadge.vue b/pkg/sbombastic-image-vulnerability-scanner/formatters/VexStatusCellBadge.vue new file mode 100644 index 0000000..e119ca2 --- /dev/null +++ b/pkg/sbombastic-image-vulnerability-scanner/formatters/VexStatusCellBadge.vue @@ -0,0 +1,18 @@ + + + + + diff --git a/pkg/sbombastic-image-vulnerability-scanner/l10n/en-us.yaml b/pkg/sbombastic-image-vulnerability-scanner/l10n/en-us.yaml index 8aa067b..59eaf9b 100644 --- a/pkg/sbombastic-image-vulnerability-scanner/l10n/en-us.yaml +++ b/pkg/sbombastic-image-vulnerability-scanner/l10n/en-us.yaml @@ -85,6 +85,27 @@ imageScanner: registry: Registry vulnerabilities: title: Vulnerabilities + vexManagement: + title: VEX management + description: Configure the security scanner to use up-to-date VEX reports. This will prioritize remediation efforts, focusing on vulnerabilities that are confirmed to be exploitable and reducing the noise coming from false positives. + button: + create: Create + buttons: + enable: Enable + disable: Disable + delete: Delete + actions: + clone: Clone + editConfig: Edit configuration + editYaml: Edit YAML + table: + headers: + status: Status + name: Name + uri: URI + createdBy: Created by + updated: Updated + actions: Actions enum: cve: critical: Critical @@ -98,6 +119,8 @@ imageScanner: inprogress: In progress complete: Complete failed: Failed + enabled: Enabled + disabled: Disabled prevScan: none: n/a scheduled: Scheduled diff --git a/pkg/sbombastic-image-vulnerability-scanner/pages/c/_cluster/sbombastic-image-vulnerability-scanner/VexManagement.vue b/pkg/sbombastic-image-vulnerability-scanner/pages/c/_cluster/sbombastic-image-vulnerability-scanner/VexManagement.vue new file mode 100644 index 0000000..ef3146c --- /dev/null +++ b/pkg/sbombastic-image-vulnerability-scanner/pages/c/_cluster/sbombastic-image-vulnerability-scanner/VexManagement.vue @@ -0,0 +1,412 @@ + + + + + + {{ t('imageScanner.vexManagement.title') }} + + {{ t('imageScanner.vexManagement.description') }} + + + + + {{ t('imageScanner.vexManagement.button.create') }} + + + + + + + + + + + {{ t('imageScanner.vexManagement.buttons.enable') || 'Enable' }} + + + + {{ t('imageScanner.vexManagement.buttons.disable') || 'Disable' }} + + + + {{ t('imageScanner.vexManagement.buttons.delete') || 'Delete' }} + + + + + + + + + + diff --git a/pkg/sbombastic-image-vulnerability-scanner/routes/sbombastic-image-vulnerability-scanner-routes.ts b/pkg/sbombastic-image-vulnerability-scanner/routes/sbombastic-image-vulnerability-scanner-routes.ts index 500af8c..bb6f2de 100644 --- a/pkg/sbombastic-image-vulnerability-scanner/routes/sbombastic-image-vulnerability-scanner-routes.ts +++ b/pkg/sbombastic-image-vulnerability-scanner/routes/sbombastic-image-vulnerability-scanner-routes.ts @@ -3,6 +3,7 @@ import ComponentDemo from "@sbombastic-image-vulnerability-scanner/pages/c/_clus import ImageOverview from "@sbombastic-image-vulnerability-scanner/pages/c/_cluster/sbombastic-image-vulnerability-scanner/ImageOverview.vue"; import Registries from "@sbombastic-image-vulnerability-scanner/pages/c/_cluster/sbombastic-image-vulnerability-scanner/Registries.vue"; import Vulnerabilities from "@sbombastic-image-vulnerability-scanner/pages/c/_cluster/sbombastic-image-vulnerability-scanner/Vulnerabilities.vue"; +import VexManagement from "@sbombastic-image-vulnerability-scanner/pages/c/_cluster/sbombastic-image-vulnerability-scanner/VexManagement.vue"; import { PRODUCT_NAME, @@ -20,6 +21,11 @@ const routes = [ path: `/c/:cluster/${PRODUCT_NAME}/${PAGE.VULNERABILITY_OVERVIEW}`, component: Vulnerabilities, }, + { + name: `c-cluster-${PRODUCT_NAME}-${PAGE.VEX_MANAGEMENT}`, + path: `/c/:cluster/${PRODUCT_NAME}/${PAGE.VEX_MANAGEMENT}`, + component: VexManagement, + }, { name: `c-cluster-${PRODUCT_NAME}-demo`, path: `/c/:cluster/${PRODUCT_NAME}/demo`, diff --git a/pkg/sbombastic-image-vulnerability-scanner/types.ts b/pkg/sbombastic-image-vulnerability-scanner/types.ts index c4dcda4..0a5813f 100644 --- a/pkg/sbombastic-image-vulnerability-scanner/types.ts +++ b/pkg/sbombastic-image-vulnerability-scanner/types.ts @@ -1,3 +1,4 @@ export * from "./types/sbombastic-image-vulnerability-scanner"; export * from "./types/image"; -export * from "./types/registry"; \ No newline at end of file +export * from "./types/registry"; +export * from "./types/vex"; diff --git a/pkg/sbombastic-image-vulnerability-scanner/types/sbombastic-image-vulnerability-scanner.ts b/pkg/sbombastic-image-vulnerability-scanner/types/sbombastic-image-vulnerability-scanner.ts index 35abba8..518c5b1 100644 --- a/pkg/sbombastic-image-vulnerability-scanner/types/sbombastic-image-vulnerability-scanner.ts +++ b/pkg/sbombastic-image-vulnerability-scanner/types/sbombastic-image-vulnerability-scanner.ts @@ -2,6 +2,7 @@ export const PRODUCT_NAME = "imageScanner"; export const RESOURCE = { REGISTRY: "sbombastic.rancher.io.registry", SCAN_JOB: "sbombastic.rancher.io.scanjob", + VEX_HUB: "sbombastic.rancher.io.vexhub", }; export const PAGE = { DASHBOARD: "dashboard", @@ -10,6 +11,7 @@ export const PAGE = { IMAGE_DETAIL: "image_detail", VULNERABILITY_OVERVIEW: "vulnerability_overview", CVE_DETAIL: "cve_detail", + VEX_MANAGEMENT: "vex_management", }; export interface MetadataProperty { type: "text" | "tags"; diff --git a/pkg/sbombastic-image-vulnerability-scanner/types/vex.ts b/pkg/sbombastic-image-vulnerability-scanner/types/vex.ts new file mode 100644 index 0000000..6f361ac --- /dev/null +++ b/pkg/sbombastic-image-vulnerability-scanner/types/vex.ts @@ -0,0 +1,4 @@ +export const VEX_STATUS = { + ENABLED: "enabled", + DISABLED: "disabled", +}