mirror of
https://github.com/goharbor/harbor.git
synced 2024-12-24 09:38:09 +01:00
Add vulnerability database update time and scanner name
Signed-off-by: sshijun <sshijun@vmware.com>
This commit is contained in:
parent
29be93725d
commit
8f3beb3e31
@ -60,4 +60,12 @@ export class ScanAllRepoService {
|
|||||||
.pipe(catchError(error => observableThrowError(error)))
|
.pipe(catchError(error => observableThrowError(error)))
|
||||||
.pipe(map(response => response as ScanningMetrics));
|
.pipe(map(response => response as ScanningMetrics));
|
||||||
}
|
}
|
||||||
|
getScanners(): Observable<any> {
|
||||||
|
return this.http.get('/api/scanners')
|
||||||
|
.pipe(catchError(error => observableThrowError(error)));
|
||||||
|
}
|
||||||
|
getScannerMetadata(uid: string): Observable<any> {
|
||||||
|
return this.http.get(`/api/scanners/${uid}/metadata`)
|
||||||
|
.pipe(catchError(error => observableThrowError(error)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,16 @@
|
|||||||
<section class="form-block">
|
<span *ngIf="onGettingUpdatedTimeStr || onGoing" class="mt-1 ml-1 spinner spinner-inline"></span>
|
||||||
|
<ng-container *ngIf="!(onGettingUpdatedTimeStr || onGoing)">
|
||||||
|
<section class="form-block">
|
||||||
|
<div *ngIf="updatedTimeStr" class="mt-1 display-flex">
|
||||||
|
<label class="update-time">{{ 'CONFIG.SCANNING.DB_REFRESH_TIME' | translate }}</label>
|
||||||
|
<span>{{ updatedTimeStr }} </span>
|
||||||
|
</div>
|
||||||
<div class="button-group">
|
<div class="button-group">
|
||||||
<cron-selection [labelCurrent]="getLabelCurrent" [labelEdit]='getLabelCurrent'
|
<cron-selection [labelCurrent]="getLabelCurrent" [labelEdit]='getLabelCurrent'
|
||||||
[originCron]='originCron' (inputvalue)="saveSchedule($event)"></cron-selection>
|
[originCron]='originCron' (inputvalue)="saveSchedule($event)"></cron-selection>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<div class="clr-row">
|
<div class="clr-row">
|
||||||
<div class="clr-col-2 flex-200">
|
<div class="clr-col-2 flex-200">
|
||||||
<div class="btn-scan-right btn-scan margin-top-16px">
|
<div class="btn-scan-right btn-scan margin-top-16px">
|
||||||
<button id="scan-now" class="btn btn-outline btn-sm btn-scan" (click)="scanNow()"
|
<button id="scan-now" class="btn btn-outline btn-sm btn-scan" (click)="scanNow()"
|
||||||
@ -35,3 +41,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
|
||||||
|
@ -98,3 +98,6 @@
|
|||||||
.float-left {
|
.float-left {
|
||||||
float: left;
|
float: left;
|
||||||
}
|
}
|
||||||
|
.display-flex {
|
||||||
|
display: flex;
|
||||||
|
}
|
@ -42,6 +42,9 @@ let fakedScanAllRepoService = {
|
|||||||
},
|
},
|
||||||
manualScan() {
|
manualScan() {
|
||||||
return of(true);
|
return of(true);
|
||||||
|
},
|
||||||
|
getScanners() {
|
||||||
|
return of([]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let fakedErrorHandler = {
|
let fakedErrorHandler = {
|
||||||
|
@ -6,8 +6,9 @@ import { TranslateService } from '@ngx-translate/core';
|
|||||||
import { ScanAllRepoService } from './scanAll.service';
|
import { ScanAllRepoService } from './scanAll.service';
|
||||||
import { OriginCron } from '../../service/interface';
|
import { OriginCron } from '../../service/interface';
|
||||||
import { CronScheduleComponent } from "../../cron-schedule/cron-schedule.component";
|
import { CronScheduleComponent } from "../../cron-schedule/cron-schedule.component";
|
||||||
import { VULNERABILITY_SCAN_STATUS } from "../../utils";
|
import { DATABASE_UPDATED_PROPERTY, VULNERABILITY_SCAN_STATUS } from "../../utils";
|
||||||
import { errorHandler as errorHandFn} from "../../shared/shared.utils";
|
import { errorHandler as errorHandFn} from "../../shared/shared.utils";
|
||||||
|
import { DatePipe } from "@angular/common";
|
||||||
|
|
||||||
const SCHEDULE_TYPE_NONE = "None";
|
const SCHEDULE_TYPE_NONE = "None";
|
||||||
@Component({
|
@Component({
|
||||||
@ -38,6 +39,8 @@ export class VulnerabilityConfigComponent implements OnInit, OnDestroy {
|
|||||||
};
|
};
|
||||||
private _loopScheduleInterval;
|
private _loopScheduleInterval;
|
||||||
private _loopManualInterval;
|
private _loopManualInterval;
|
||||||
|
updatedTimeStr: string;
|
||||||
|
onGettingUpdatedTimeStr: boolean;
|
||||||
constructor(
|
constructor(
|
||||||
private scanningService: ScanAllRepoService,
|
private scanningService: ScanAllRepoService,
|
||||||
private errorHandler: ErrorHandler,
|
private errorHandler: ErrorHandler,
|
||||||
@ -103,6 +106,39 @@ export class VulnerabilityConfigComponent implements OnInit, OnDestroy {
|
|||||||
this.errorHandler.error(error);
|
this.errorHandler.error(error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
getScanners() {
|
||||||
|
this.onGettingUpdatedTimeStr = true;
|
||||||
|
this.scanningService.getScanners()
|
||||||
|
.subscribe(scanners => {
|
||||||
|
let flag = false;
|
||||||
|
if (scanners && scanners.length) {
|
||||||
|
scanners.forEach(scanner => {
|
||||||
|
if (scanner.is_default) {
|
||||||
|
flag = true;
|
||||||
|
this.getScannerMetadata(scanner.uuid);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!flag) {
|
||||||
|
this.onGettingUpdatedTimeStr = false;
|
||||||
|
}
|
||||||
|
}, error => {
|
||||||
|
this.onGettingUpdatedTimeStr = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
getScannerMetadata(uid: string) {
|
||||||
|
this.scanningService.getScannerMetadata(uid)
|
||||||
|
.pipe(finalize(() => this.onGettingUpdatedTimeStr = false))
|
||||||
|
.subscribe(metadata => {
|
||||||
|
if (metadata && metadata.properties) {
|
||||||
|
for (let key in metadata.properties) {
|
||||||
|
if (key === DATABASE_UPDATED_PROPERTY && metadata.properties[key]) {
|
||||||
|
this.updatedTimeStr = new DatePipe(this.translate.currentLang).transform(metadata.properties[key], 'short');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public initSchedule(schedule: any) {
|
public initSchedule(schedule: any) {
|
||||||
if (schedule && schedule.schedule !== null) {
|
if (schedule && schedule.schedule !== null) {
|
||||||
@ -119,6 +155,7 @@ export class VulnerabilityConfigComponent implements OnInit, OnDestroy {
|
|||||||
this.getScanText();
|
this.getScanText();
|
||||||
this.getSchedule();
|
this.getSchedule();
|
||||||
this.initMetrics();
|
this.initMetrics();
|
||||||
|
this.getScanners();
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
|
@ -312,6 +312,12 @@ export interface VulnerabilitySummary {
|
|||||||
summary?: SeveritySummary;
|
summary?: SeveritySummary;
|
||||||
start_time?: Date;
|
start_time?: Date;
|
||||||
end_time?: Date;
|
end_time?: Date;
|
||||||
|
scanner?: ScannerVo;
|
||||||
|
}
|
||||||
|
export interface ScannerVo {
|
||||||
|
name?: string;
|
||||||
|
vendor?: string;
|
||||||
|
version?: string;
|
||||||
}
|
}
|
||||||
export interface SeveritySummary {
|
export interface SeveritySummary {
|
||||||
total: number;
|
total: number;
|
||||||
|
@ -109,7 +109,7 @@
|
|||||||
</clr-dg-cell>
|
</clr-dg-cell>
|
||||||
<clr-dg-cell>
|
<clr-dg-cell>
|
||||||
<div class="cell">
|
<div class="cell">
|
||||||
<hbr-vulnerability-bar (submitFinish)="submitFinish($event)" [repoName]="repoName" [tagId]="t.name" [summary]="handleScanOverview(t.scan_overview)"></hbr-vulnerability-bar>
|
<hbr-vulnerability-bar [scanner]="handleScanOverview(t.scan_overview)?.scanner" (submitFinish)="submitFinish($event)" [repoName]="repoName" [tagId]="t.name" [summary]="handleScanOverview(t.scan_overview)"></hbr-vulnerability-bar>
|
||||||
</div>
|
</div>
|
||||||
</clr-dg-cell>
|
</clr-dg-cell>
|
||||||
<clr-dg-cell *ngIf="withNotary" [ngSwitch]="t.signature !== null">
|
<clr-dg-cell *ngIf="withNotary" [ngSwitch]="t.signature !== null">
|
||||||
|
@ -230,6 +230,11 @@ export const DEFAULT_PAGE_SIZE: number = 15;
|
|||||||
*/
|
*/
|
||||||
export const DEFAULT_SUPPORTED_MIME_TYPE = "application/vnd.scanner.adapter.vuln.report.harbor+json; version=1.0";
|
export const DEFAULT_SUPPORTED_MIME_TYPE = "application/vnd.scanner.adapter.vuln.report.harbor+json; version=1.0";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the property name of vulnerability database updated time
|
||||||
|
*/
|
||||||
|
export const DATABASE_UPDATED_PROPERTY = "harbor.scanner-adapter/vulnerability-database-updated-at";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The state of vulnerability scanning
|
* The state of vulnerability scanning
|
||||||
*/
|
*/
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
<div class="progress loop loop-height"><progress></progress></div>
|
<div class="progress loop loop-height"><progress></progress></div>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="completed" class="bar-state bar-state-chart">
|
<div *ngIf="completed" class="bar-state bar-state-chart">
|
||||||
<hbr-result-tip-histogram [vulnerabilitySummary]="summary"></hbr-result-tip-histogram>
|
<hbr-result-tip-histogram [scanner]="scanner" [vulnerabilitySummary]="summary"></hbr-result-tip-histogram>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="otherStatus" class="bar-state">
|
<div *ngIf="otherStatus" class="bar-state">
|
||||||
<span class="label">{{'VULNERABILITY.STATE.OTHER_STATUS' | translate}}</span>
|
<span class="label">{{'VULNERABILITY.STATE.OTHER_STATUS' | translate}}</span>
|
||||||
|
@ -12,7 +12,7 @@ import {
|
|||||||
VulnerabilitySummary,
|
VulnerabilitySummary,
|
||||||
TagService,
|
TagService,
|
||||||
ScanningResultService,
|
ScanningResultService,
|
||||||
Tag
|
Tag, ScannerVo
|
||||||
} from '../service/index';
|
} from '../service/index';
|
||||||
import { ErrorHandler } from '../error-handler/index';
|
import { ErrorHandler } from '../error-handler/index';
|
||||||
import { ChannelService } from '../channel/index';
|
import { ChannelService } from '../channel/index';
|
||||||
@ -28,6 +28,7 @@ const RETRY_TIMES: number = 3;
|
|||||||
styleUrls: ['./scanning.scss']
|
styleUrls: ['./scanning.scss']
|
||||||
})
|
})
|
||||||
export class ResultBarChartComponent implements OnInit, OnDestroy {
|
export class ResultBarChartComponent implements OnInit, OnDestroy {
|
||||||
|
@Input() scanner: ScannerVo;
|
||||||
@Input() repoName: string = "";
|
@Input() repoName: string = "";
|
||||||
@Input() tagId: string = "";
|
@Input() tagId: string = "";
|
||||||
@Input() summary: VulnerabilitySummary;
|
@Input() summary: VulnerabilitySummary;
|
||||||
|
@ -63,6 +63,10 @@
|
|||||||
<div class="bar-summary bar-tooltip-fon" *ngIf="!isNone">
|
<div class="bar-summary bar-tooltip-fon" *ngIf="!isNone">
|
||||||
<histogram-chart [isWhiteBackground]="false" [metadata]="passMetadataToChart()"></histogram-chart>
|
<histogram-chart [isWhiteBackground]="false" [metadata]="passMetadataToChart()"></histogram-chart>
|
||||||
</div>
|
</div>
|
||||||
|
<div *ngIf="scanner">
|
||||||
|
<span class="bar-scanning-time">{{'SCANNER.SCANNED_BY' | translate }}</span>
|
||||||
|
<span class="margin-left-5">{{scanner?.name}}</span>
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span class="bar-scanning-time">{{'SCANNER.DURATION' | translate }}</span>
|
<span class="bar-scanning-time">{{'SCANNER.DURATION' | translate }}</span>
|
||||||
<span class="margin-left-5">{{duration()}}</span>
|
<span class="margin-left-5">{{duration()}}</span>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Component, Input, OnInit } from '@angular/core';
|
import { Component, Input, OnInit } from '@angular/core';
|
||||||
import { VulnerabilitySummary } from "../../service";
|
import { ScannerVo, VulnerabilitySummary } from "../../service";
|
||||||
import { VULNERABILITY_SCAN_STATUS, VULNERABILITY_SEVERITY } from "../../utils";
|
import { VULNERABILITY_SCAN_STATUS, VULNERABILITY_SEVERITY } from "../../utils";
|
||||||
import { TranslateService } from "@ngx-translate/core";
|
import { TranslateService } from "@ngx-translate/core";
|
||||||
|
|
||||||
@ -21,6 +21,7 @@ const CLASS_MAP = {
|
|||||||
styleUrls: ['./result-tip-histogram.component.scss']
|
styleUrls: ['./result-tip-histogram.component.scss']
|
||||||
})
|
})
|
||||||
export class ResultTipHistogramComponent implements OnInit {
|
export class ResultTipHistogramComponent implements OnInit {
|
||||||
|
@Input() scanner: ScannerVo;
|
||||||
_tipTitle: string = "";
|
_tipTitle: string = "";
|
||||||
@Input() vulnerabilitySummary: VulnerabilitySummary = {
|
@Input() vulnerabilitySummary: VulnerabilitySummary = {
|
||||||
scan_status: VULNERABILITY_SCAN_STATUS.NOT_SCANNED,
|
scan_status: VULNERABILITY_SCAN_STATUS.NOT_SCANNED,
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
import {
|
import {
|
||||||
Component, Inject, Input, LOCALE_ID,
|
Component, Input,
|
||||||
OnInit
|
OnInit
|
||||||
} from "@angular/core";
|
} from "@angular/core";
|
||||||
import { ConfigScannerService } from "../config-scanner.service";
|
import { ConfigScannerService } from "../config-scanner.service";
|
||||||
import { finalize } from "rxjs/operators";
|
import { finalize } from "rxjs/operators";
|
||||||
import { ErrorHandler } from "@harbor/ui";
|
import { ErrorHandler, DATABASE_UPDATED_PROPERTY } from "@harbor/ui";
|
||||||
import { ScannerMetadata } from "../scanner-metadata";
|
import { ScannerMetadata } from "../scanner-metadata";
|
||||||
import { DatePipe } from "@angular/common";
|
import { DatePipe } from "@angular/common";
|
||||||
|
import { TranslateService } from "@ngx-translate/core";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'scanner-metadata',
|
selector: 'scanner-metadata',
|
||||||
@ -19,7 +20,7 @@ export class ScannerMetadataComponent implements OnInit {
|
|||||||
scannerMetadata: ScannerMetadata;
|
scannerMetadata: ScannerMetadata;
|
||||||
constructor(private configScannerService: ConfigScannerService,
|
constructor(private configScannerService: ConfigScannerService,
|
||||||
private errorHandler: ErrorHandler,
|
private errorHandler: ErrorHandler,
|
||||||
@Inject(LOCALE_ID) private _locale: string) {
|
private translate: TranslateService) {
|
||||||
}
|
}
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
@ -31,15 +32,14 @@ export class ScannerMetadataComponent implements OnInit {
|
|||||||
this.errorHandler.error(error);
|
this.errorHandler.error(error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
parseDate(str: string): string {
|
parseDate(item: any): string {
|
||||||
try {
|
if (item && item.value && item.key === DATABASE_UPDATED_PROPERTY) {
|
||||||
if (str === new Date(str).toISOString()) {
|
return new DatePipe(this.translate.currentLang).transform(item.value, 'short');
|
||||||
return new DatePipe(this._locale).transform(str, 'short');
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
return str;
|
|
||||||
}
|
}
|
||||||
return str;
|
if (item && item.value) {
|
||||||
|
return item.value;
|
||||||
|
}
|
||||||
|
return '';
|
||||||
}
|
}
|
||||||
toString(arr: string[]) {
|
toString(arr: string[]) {
|
||||||
if (arr && arr.length > 0) {
|
if (arr && arr.length > 0) {
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
<div class="clr-control-label">{{'SCANNER.PROPERTIES' | translate}}</div>
|
<div class="clr-control-label">{{'SCANNER.PROPERTIES' | translate}}</div>
|
||||||
<div class="ml-1" *ngFor="let item of scannerMetadata?.properties | keyvalue">
|
<div class="ml-1" *ngFor="let item of scannerMetadata?.properties | keyvalue">
|
||||||
<span>{{item?.key}}:</span>
|
<span>{{item?.key}}:</span>
|
||||||
<span class="ml-1">{{parseDate(item?.value)}}</span>
|
<span class="ml-1">{{parseDate(item)}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -1343,6 +1343,7 @@
|
|||||||
"VULNERABILITY_SEVERITY": "Vulnerability severity:",
|
"VULNERABILITY_SEVERITY": "Vulnerability severity:",
|
||||||
"CONFIRM_DELETION": "Confirm Scanner deletion",
|
"CONFIRM_DELETION": "Confirm Scanner deletion",
|
||||||
"NO_PROJECT_SCANNER": "No Scanner",
|
"NO_PROJECT_SCANNER": "No Scanner",
|
||||||
"SET_UNHEALTHY_SCANNER": "Selected scanner:{{name}} is unhealthy"
|
"SET_UNHEALTHY_SCANNER": "Selected scanner:{{name}} is unhealthy",
|
||||||
|
"SCANNED_BY": "Scanned by:"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1340,6 +1340,7 @@
|
|||||||
"VULNERABILITY_SEVERITY": "Vulnerability severity:",
|
"VULNERABILITY_SEVERITY": "Vulnerability severity:",
|
||||||
"CONFIRM_DELETION": "Confirm Scanner deletion",
|
"CONFIRM_DELETION": "Confirm Scanner deletion",
|
||||||
"NO_PROJECT_SCANNER": "No Scanner",
|
"NO_PROJECT_SCANNER": "No Scanner",
|
||||||
"SET_UNHEALTHY_SCANNER": "Selected scanner:{{name}} is unhealthy"
|
"SET_UNHEALTHY_SCANNER": "Selected scanner:{{name}} is unhealthy",
|
||||||
|
"SCANNED_BY": "Scanned by:"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1312,6 +1312,7 @@
|
|||||||
"VULNERABILITY_SEVERITY": "Vulnerability severity:",
|
"VULNERABILITY_SEVERITY": "Vulnerability severity:",
|
||||||
"CONFIRM_DELETION": "Confirm Scanner deletion",
|
"CONFIRM_DELETION": "Confirm Scanner deletion",
|
||||||
"NO_PROJECT_SCANNER": "No Scanner",
|
"NO_PROJECT_SCANNER": "No Scanner",
|
||||||
"SET_UNHEALTHY_SCANNER": "Selected scanner:{{name}} is unhealthy"
|
"SET_UNHEALTHY_SCANNER": "Selected scanner:{{name}} is unhealthy",
|
||||||
|
"SCANNED_BY": "Scanned by:"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1337,7 +1337,8 @@
|
|||||||
"VULNERABILITY_SEVERITY": "Vulnerability severity:",
|
"VULNERABILITY_SEVERITY": "Vulnerability severity:",
|
||||||
"CONFIRM_DELETION": "Confirm Scanner deletion",
|
"CONFIRM_DELETION": "Confirm Scanner deletion",
|
||||||
"NO_PROJECT_SCANNER": "No Scanner",
|
"NO_PROJECT_SCANNER": "No Scanner",
|
||||||
"SET_UNHEALTHY_SCANNER": "Selected scanner:{{name}} is unhealthy"
|
"SET_UNHEALTHY_SCANNER": "Selected scanner:{{name}} is unhealthy",
|
||||||
|
"SCANNED_BY": "Scanned by:"
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1342,6 +1342,7 @@
|
|||||||
"VULNERABILITY_SEVERITY": "Vulnerability severity:",
|
"VULNERABILITY_SEVERITY": "Vulnerability severity:",
|
||||||
"CONFIRM_DELETION": "Confirm Scanner deletion",
|
"CONFIRM_DELETION": "Confirm Scanner deletion",
|
||||||
"NO_PROJECT_SCANNER": "No Scanner",
|
"NO_PROJECT_SCANNER": "No Scanner",
|
||||||
"SET_UNHEALTHY_SCANNER": "Selected scanner:{{name}} is unhealthy"
|
"SET_UNHEALTHY_SCANNER": "Selected scanner:{{name}} is unhealthy",
|
||||||
|
"SCANNED_BY": "Scanned by:"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1339,6 +1339,7 @@
|
|||||||
"VULNERABILITY_SEVERITY": "漏洞严重度:",
|
"VULNERABILITY_SEVERITY": "漏洞严重度:",
|
||||||
"CONFIRM_DELETION": "删除扫描器确认",
|
"CONFIRM_DELETION": "删除扫描器确认",
|
||||||
"NO_PROJECT_SCANNER": "无扫描器",
|
"NO_PROJECT_SCANNER": "无扫描器",
|
||||||
"SET_UNHEALTHY_SCANNER": "选择的扫描器:{{name}}是不健康的"
|
"SET_UNHEALTHY_SCANNER": "选择的扫描器:{{name}}是不健康的",
|
||||||
|
"SCANNED_BY": "扫描器:"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user