diff --git a/src/portal/src/app/project/repository/artifact/artifact-additions/artifact-vulnerabilities/artifact-vulnerabilities.component.html b/src/portal/src/app/project/repository/artifact/artifact-additions/artifact-vulnerabilities/artifact-vulnerabilities.component.html
index d9102ef01..2dd2e71c1 100644
--- a/src/portal/src/app/project/repository/artifact/artifact-additions/artifact-vulnerabilities/artifact-vulnerabilities.component.html
+++ b/src/portal/src/app/project/repository/artifact/artifact-additions/artifact-vulnerabilities/artifact-vulnerabilities.component.html
@@ -28,7 +28,7 @@
{{'VULNERABILITY.GRID.COLUMN_PACKAGE' | translate}}
{{'VULNERABILITY.GRID.COLUMN_VERSION' | translate}}
{{'VULNERABILITY.GRID.COLUMN_FIXED' | translate}}
-
+ {{'VULNERABILITY.GRID.IN_ALLOW_LIST' | translate}}
{{'VULNERABILITY.STATE.OTHER_STATUS' | translate}}
@@ -67,6 +67,9 @@
{{res.fix_version}}
+
+ {{(isInAllowList(res.id)?"TAG_RETENTION.YES":"TAG_RETENTION.NO") | translate}}
+
{{'VULNERABILITY.GRID.COLUMN_DESCRIPTION' | translate}}: {{res.description}}
diff --git a/src/portal/src/app/project/repository/artifact/artifact-additions/artifact-vulnerabilities/artifact-vulnerabilities.component.spec.ts b/src/portal/src/app/project/repository/artifact/artifact-additions/artifact-vulnerabilities/artifact-vulnerabilities.component.spec.ts
index c25009e81..eac55394b 100644
--- a/src/portal/src/app/project/repository/artifact/artifact-additions/artifact-vulnerabilities/artifact-vulnerabilities.component.spec.ts
+++ b/src/portal/src/app/project/repository/artifact/artifact-additions/artifact-vulnerabilities/artifact-vulnerabilities.component.spec.ts
@@ -6,11 +6,20 @@ import { AdditionsService } from "../additions.service";
import { of } from "rxjs";
import { TranslateFakeLoader, TranslateLoader, TranslateModule } from "@ngx-translate/core";
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
-import { ScanningResultService, UserPermissionService, VulnerabilityItem } from "../../../../../../lib/services";
+import {
+ ProjectService,
+ ScanningResultService,
+ SystemInfoService,
+ UserPermissionService,
+ VulnerabilityItem
+} from "../../../../../../lib/services";
import { AdditionLink } from "../../../../../../../ng-swagger-gen/models/addition-link";
import { ErrorHandler } from "../../../../../../lib/utils/error-handler";
import { ChannelService } from "../../../../../../lib/services/channel.service";
import { DEFAULT_SUPPORTED_MIME_TYPE } from "../../../../../../lib/utils/utils";
+import {SessionService} from "../../../../../shared/session.service";
+import {SessionUser} from "../../../../../shared/session-user";
+import {delay} from "rxjs/operators";
describe('ArtifactVulnerabilitiesComponent', () => {
@@ -65,6 +74,34 @@ describe('ArtifactVulnerabilitiesComponent', () => {
}
}
};
+ const mockedUser: SessionUser = {
+ user_id: 1,
+ username: 'admin',
+ email: 'harbor@vmware.com',
+ realname: 'admin',
+ has_admin_role: true,
+ comment: 'no comment'
+ };
+ const fakedSessionService = {
+ getCurrentUser() {
+ return mockedUser;
+ }
+ };
+ const fakedProjectService = {
+ getProject() {
+ return of({
+ name: 'test',
+ metadata: {
+ reuse_sys_cve_allowlist: "false"
+ },
+ cve_allowlist: {
+ items: [
+ {cve_id: "123"}
+ ]
+ }
+ }).pipe(delay(0));
+ }
+ };
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [
@@ -80,10 +117,13 @@ describe('ArtifactVulnerabilitiesComponent', () => {
declarations: [ArtifactVulnerabilitiesComponent],
providers: [
ErrorHandler,
+ SystemInfoService,
{provide: AdditionsService, useValue: fakedAdditionsService},
{provide: UserPermissionService, useValue: fakedUserPermissionService},
{provide: ScanningResultService, useValue: fakedScanningResultService},
{provide: ChannelService, useValue: fakedChannelService},
+ {provide: SessionService, useValue: fakedSessionService},
+ {provide: ProjectService, useValue: fakedProjectService},
],
schemas: [
NO_ERRORS_SCHEMA
@@ -111,4 +151,14 @@ describe('ArtifactVulnerabilitiesComponent', () => {
const rows = fixture.nativeElement.getElementsByTagName('clr-dg-row');
expect(rows.length).toEqual(2);
});
+ it("should show column 'Listed In CVE Allowlist'", async () => {
+ fixture.autoDetectChanges(true);
+ await fixture.whenStable();
+ const cols = fixture.nativeElement.querySelectorAll("clr-dg-column");
+ expect(cols).toBeTruthy();
+ expect(cols.length).toEqual(6);
+ const firstRow = fixture.nativeElement.querySelector("clr-dg-row");
+ const cells = firstRow.querySelectorAll("clr-dg-cell");
+ expect(cells[cells.length - 1].innerText).toEqual("TAG_RETENTION.YES");
+ });
});
diff --git a/src/portal/src/app/project/repository/artifact/artifact-additions/artifact-vulnerabilities/artifact-vulnerabilities.component.ts b/src/portal/src/app/project/repository/artifact/artifact-additions/artifact-vulnerabilities/artifact-vulnerabilities.component.ts
index 5edbb3561..7e5ba4df2 100644
--- a/src/portal/src/app/project/repository/artifact/artifact-additions/artifact-vulnerabilities/artifact-vulnerabilities.component.ts
+++ b/src/portal/src/app/project/repository/artifact/artifact-additions/artifact-vulnerabilities/artifact-vulnerabilities.component.ts
@@ -4,8 +4,9 @@ import { ClrDatagridComparatorInterface, ClrLoadingState } from "@clr/angular";
import { finalize } from "rxjs/operators";
import { AdditionLink } from "../../../../../../../ng-swagger-gen/models/addition-link";
import {
+ ProjectService,
ScannerVo,
- ScanningResultService,
+ ScanningResultService, SystemInfoService,
UserPermissionService,
USERSTATICPERMISSION,
VulnerabilityItem
@@ -20,6 +21,7 @@ import { ChannelService } from "../../../../../../lib/services/channel.service";
import { ResultBarChartComponent } from "../../../vulnerability-scanning/result-bar-chart.component";
import { Subscription } from "rxjs";
import { Artifact } from "../../../../../../../ng-swagger-gen/models/artifact";
+import {SessionService} from "../../../../../shared/session.service";
@Component({
selector: 'hbr-artifact-vulnerabilities',
@@ -53,12 +55,16 @@ export class ArtifactVulnerabilitiesComponent implements OnInit, OnDestroy {
resultBarChartComponent: ResultBarChartComponent;
sub: Subscription;
hasViewInitWithDelay: boolean = false;
+ currentCVEList: Array<{ "cve_id": string; }> = [];
constructor(
private errorHandler: ErrorHandler,
private additionsService: AdditionsService,
private userPermissionService: UserPermissionService,
private scanningService: ScanningResultService,
private channel: ChannelService,
+ private session: SessionService,
+ private projectService: ProjectService,
+ private systemInfoService: SystemInfoService,
) {
const that = this;
this.severitySort = {
@@ -80,6 +86,10 @@ export class ArtifactVulnerabilitiesComponent implements OnInit, OnDestroy {
setTimeout(() => {
this.hasViewInitWithDelay = true;
}, 0);
+ if (this.isSystemAdmin()) {
+ // get system and project CVE allow list
+ this.getCurrentCVEAllowList();
+ }
}
ngOnDestroy() {
if (this.sub) {
@@ -194,4 +204,37 @@ export class ArtifactVulnerabilitiesComponent implements OnInit, OnDestroy {
}
return null;
}
+ isSystemAdmin(): boolean {
+ const account = this.session.getCurrentUser();
+ return account && account.has_admin_role;
+ }
+ getCurrentCVEAllowList() {
+ this.projectService.getProject(this.projectId).subscribe(
+ projectRes => {
+ if (projectRes && projectRes.cve_allowlist
+ && projectRes.metadata && projectRes.metadata.reuse_sys_cve_allowlist !== "true"
+ ) { // use project CVE allow list
+ this.currentCVEList = projectRes.cve_allowlist['items'];
+ } else { // use system CVE allow list
+ this.systemInfoService.getSystemAllowlist().subscribe(
+ systemRes => {
+ if (systemRes && systemRes.items && systemRes.items.length) {
+ this.currentCVEList = systemRes.items;
+ }
+ }
+ );
+ }
+ }
+ );
+ }
+ isInAllowList(CVEId: string): boolean {
+ if (this.currentCVEList && this.currentCVEList.length) {
+ for (let i = 0; i < this.currentCVEList.length; i++) {
+ if (CVEId === this.currentCVEList[i].cve_id) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
}
diff --git a/src/portal/src/i18n/lang/en-us-lang.json b/src/portal/src/i18n/lang/en-us-lang.json
index aba6a278c..6ac9b6d6f 100644
--- a/src/portal/src/i18n/lang/en-us-lang.json
+++ b/src/portal/src/i18n/lang/en-us-lang.json
@@ -1016,7 +1016,8 @@
"COLUMN_FIXED": "Fixed in version",
"COLUMN_DESCRIPTION": "Description",
"FOOT_ITEMS": "Items",
- "FOOT_OF": "of"
+ "FOOT_OF": "of",
+ "IN_ALLOW_LIST": "Listed In CVE Allowlist"
},
"CHART": {
"SCANNING_TIME": "Scan completed time:",
diff --git a/src/portal/src/i18n/lang/es-es-lang.json b/src/portal/src/i18n/lang/es-es-lang.json
index 68740fdd9..cc7607829 100644
--- a/src/portal/src/i18n/lang/es-es-lang.json
+++ b/src/portal/src/i18n/lang/es-es-lang.json
@@ -1016,7 +1016,8 @@
"COLUMN_FIXED": "Fixed in version",
"COLUMN_DESCRIPTION": "Description",
"FOOT_ITEMS": "Items",
- "FOOT_OF": "of"
+ "FOOT_OF": "of",
+ "IN_ALLOW_LIST": "Listed In CVE Allowlist"
},
"CHART": {
"SCANNING_TIME": "Scan completed time:",
diff --git a/src/portal/src/i18n/lang/fr-fr-lang.json b/src/portal/src/i18n/lang/fr-fr-lang.json
index 0b46878c6..790522503 100644
--- a/src/portal/src/i18n/lang/fr-fr-lang.json
+++ b/src/portal/src/i18n/lang/fr-fr-lang.json
@@ -989,7 +989,8 @@
"COLUMN_FIXED": "Fixé dans le version",
"COLUMN_DESCRIPTION": "Description",
"FOOT_ITEMS": "Items",
- "FOOT_OF": "de"
+ "FOOT_OF": "de",
+ "IN_ALLOW_LIST": "Listed In CVE Allowlist"
},
"CHART": {
"SCANNING_TIME": "Temps d'analyse complète :",
diff --git a/src/portal/src/i18n/lang/pt-br-lang.json b/src/portal/src/i18n/lang/pt-br-lang.json
index cc174b33a..0d9f5c44c 100644
--- a/src/portal/src/i18n/lang/pt-br-lang.json
+++ b/src/portal/src/i18n/lang/pt-br-lang.json
@@ -1012,7 +1012,8 @@
"COLUMN_FIXED": "Corrigido na versão",
"COLUMN_DESCRIPTION": "Descrição",
"FOOT_ITEMS": "Itens",
- "FOOT_OF": "de"
+ "FOOT_OF": "de",
+ "IN_ALLOW_LIST": "Listed In CVE Allowlist"
},
"CHART": {
"SCANNING_TIME": "Tempo de conclusão da análise:",
diff --git a/src/portal/src/i18n/lang/tr-tr-lang.json b/src/portal/src/i18n/lang/tr-tr-lang.json
index adb2f6211..96dccacb3 100644
--- a/src/portal/src/i18n/lang/tr-tr-lang.json
+++ b/src/portal/src/i18n/lang/tr-tr-lang.json
@@ -1016,7 +1016,8 @@
"COLUMN_FIXED": "Sürümde düzeltildi",
"COLUMN_DESCRIPTION": "Açıklama",
"FOOT_ITEMS": "Öğeler",
- "FOOT_OF": "of"
+ "FOOT_OF": "of",
+ "IN_ALLOW_LIST": "Listed In CVE Allowlist"
},
"CHART": {
"SCANNING_TIME": "Tarama tamamlanma zamanı:",
diff --git a/src/portal/src/i18n/lang/zh-cn-lang.json b/src/portal/src/i18n/lang/zh-cn-lang.json
index c8e70483b..60076cc86 100644
--- a/src/portal/src/i18n/lang/zh-cn-lang.json
+++ b/src/portal/src/i18n/lang/zh-cn-lang.json
@@ -1016,7 +1016,8 @@
"COLUMN_FIXED": "修复版本",
"COLUMN_DESCRIPTION": "简介",
"FOOT_ITEMS": "项目",
- "FOOT_OF": "总共"
+ "FOOT_OF": "总共",
+ "IN_ALLOW_LIST": "已入特赦名单"
},
"CHART": {
"SCANNING_TIME": "扫描完成时间:",
diff --git a/src/portal/src/i18n/lang/zh-tw-lang.json b/src/portal/src/i18n/lang/zh-tw-lang.json
index 03e1dd475..efd9e959d 100644
--- a/src/portal/src/i18n/lang/zh-tw-lang.json
+++ b/src/portal/src/i18n/lang/zh-tw-lang.json
@@ -1011,7 +1011,8 @@
"COLUMN_FIXED": "修復版本",
"COLUMN_DESCRIPTION": "簡介",
"FOOT_ITEMS": "項目",
- "FOOT_OF": "總共"
+ "FOOT_OF": "總共",
+ "IN_ALLOW_LIST": "Listed In CVE Allowlist"
},
"CHART":{
"SCANNING_TIME": "掃描完成時間:",