Merge pull request #9884 from AllForNothing/database

Add vulnerability database update time and scanner name
This commit is contained in:
Will Sun 2019-11-15 13:39:32 +08:00 committed by GitHub
commit d4c5d93264
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 108 additions and 25 deletions

View File

@ -60,4 +60,12 @@ export class ScanAllRepoService {
.pipe(catchError(error => observableThrowError(error)))
.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)));
}
}

View File

@ -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">
<cron-selection [labelCurrent]="getLabelCurrent" [labelEdit]='getLabelCurrent'
[originCron]='originCron' (inputvalue)="saveSchedule($event)"></cron-selection>
</div>
</section>
<div class="clr-row">
<div class="clr-row">
<div class="clr-col-2 flex-200">
<div class="btn-scan-right btn-scan margin-top-16px">
<button id="scan-now" class="btn btn-outline btn-sm btn-scan" (click)="scanNow()"
@ -35,3 +41,6 @@
</div>
</div>
</div>
</ng-container>

View File

@ -97,4 +97,7 @@
}
.float-left {
float: left;
}
.display-flex {
display: flex;
}

View File

@ -42,6 +42,9 @@ let fakedScanAllRepoService = {
},
manualScan() {
return of(true);
},
getScanners() {
return of([]);
}
};
let fakedErrorHandler = {

View File

@ -6,8 +6,9 @@ import { TranslateService } from '@ngx-translate/core';
import { ScanAllRepoService } from './scanAll.service';
import { OriginCron } from '../../service/interface';
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 { DatePipe } from "@angular/common";
const SCHEDULE_TYPE_NONE = "None";
@Component({
@ -38,6 +39,8 @@ export class VulnerabilityConfigComponent implements OnInit, OnDestroy {
};
private _loopScheduleInterval;
private _loopManualInterval;
updatedTimeStr: string;
onGettingUpdatedTimeStr: boolean;
constructor(
private scanningService: ScanAllRepoService,
private errorHandler: ErrorHandler,
@ -103,6 +106,39 @@ export class VulnerabilityConfigComponent implements OnInit, OnDestroy {
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) {
if (schedule && schedule.schedule !== null) {
@ -119,6 +155,7 @@ export class VulnerabilityConfigComponent implements OnInit, OnDestroy {
this.getScanText();
this.getSchedule();
this.initMetrics();
this.getScanners();
}
ngOnDestroy() {

View File

@ -312,6 +312,12 @@ export interface VulnerabilitySummary {
summary?: SeveritySummary;
start_time?: Date;
end_time?: Date;
scanner?: ScannerVo;
}
export interface ScannerVo {
name?: string;
vendor?: string;
version?: string;
}
export interface SeveritySummary {
total: number;

View File

@ -109,7 +109,7 @@
</clr-dg-cell>
<clr-dg-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>
</clr-dg-cell>
<clr-dg-cell *ngIf="withNotary" [ngSwitch]="t.signature !== null">

View File

@ -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";
/**
* 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
*/

View File

@ -13,7 +13,7 @@
<div class="progress loop loop-height"><progress></progress></div>
</div>
<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 *ngIf="otherStatus" class="bar-state">
<span class="label">{{'VULNERABILITY.STATE.OTHER_STATUS' | translate}}</span>

View File

@ -12,7 +12,7 @@ import {
VulnerabilitySummary,
TagService,
ScanningResultService,
Tag
Tag, ScannerVo
} from '../service/index';
import { ErrorHandler } from '../error-handler/index';
import { ChannelService } from '../channel/index';
@ -28,6 +28,7 @@ const RETRY_TIMES: number = 3;
styleUrls: ['./scanning.scss']
})
export class ResultBarChartComponent implements OnInit, OnDestroy {
@Input() scanner: ScannerVo;
@Input() repoName: string = "";
@Input() tagId: string = "";
@Input() summary: VulnerabilitySummary;

View File

@ -63,6 +63,10 @@
<div class="bar-summary bar-tooltip-fon" *ngIf="!isNone">
<histogram-chart [isWhiteBackground]="false" [metadata]="passMetadataToChart()"></histogram-chart>
</div>
<div *ngIf="scanner">
<span class="bar-scanning-time">{{'SCANNER.SCANNED_BY' | translate }}</span>
<span class="margin-left-5">{{scanner?.name}}</span>
</div>
<div>
<span class="bar-scanning-time">{{'SCANNER.DURATION' | translate }}</span>
<span class="margin-left-5">{{duration()}}</span>

View File

@ -1,5 +1,5 @@
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 { TranslateService } from "@ngx-translate/core";
@ -21,6 +21,7 @@ const CLASS_MAP = {
styleUrls: ['./result-tip-histogram.component.scss']
})
export class ResultTipHistogramComponent implements OnInit {
@Input() scanner: ScannerVo;
_tipTitle: string = "";
@Input() vulnerabilitySummary: VulnerabilitySummary = {
scan_status: VULNERABILITY_SCAN_STATUS.NOT_SCANNED,

View File

@ -1,12 +1,13 @@
import {
Component, Inject, Input, LOCALE_ID,
Component, Input,
OnInit
} from "@angular/core";
import { ConfigScannerService } from "../config-scanner.service";
import { finalize } from "rxjs/operators";
import { ErrorHandler } from "@harbor/ui";
import { ErrorHandler, DATABASE_UPDATED_PROPERTY } from "@harbor/ui";
import { ScannerMetadata } from "../scanner-metadata";
import { DatePipe } from "@angular/common";
import { TranslateService } from "@ngx-translate/core";
@Component({
selector: 'scanner-metadata',
@ -19,7 +20,7 @@ export class ScannerMetadataComponent implements OnInit {
scannerMetadata: ScannerMetadata;
constructor(private configScannerService: ConfigScannerService,
private errorHandler: ErrorHandler,
@Inject(LOCALE_ID) private _locale: string) {
private translate: TranslateService) {
}
ngOnInit(): void {
this.loading = true;
@ -31,15 +32,14 @@ export class ScannerMetadataComponent implements OnInit {
this.errorHandler.error(error);
});
}
parseDate(str: string): string {
try {
if (str === new Date(str).toISOString()) {
return new DatePipe(this._locale).transform(str, 'short');
}
} catch (e) {
return str;
parseDate(item: any): string {
if (item && item.value && item.key === DATABASE_UPDATED_PROPERTY) {
return new DatePipe(this.translate.currentLang).transform(item.value, 'short');
}
return str;
if (item && item.value) {
return item.value;
}
return '';
}
toString(arr: string[]) {
if (arr && arr.length > 0) {

View File

@ -24,7 +24,7 @@
<div class="clr-control-label">{{'SCANNER.PROPERTIES' | translate}}</div>
<div class="ml-1" *ngFor="let item of scannerMetadata?.properties | keyvalue">
<span>{{item?.key}}:</span>
<span class="ml-1">{{parseDate(item?.value)}}</span>
<span class="ml-1">{{parseDate(item)}}</span>
</div>
</div>

View File

@ -1343,6 +1343,7 @@
"VULNERABILITY_SEVERITY": "Vulnerability severity:",
"CONFIRM_DELETION": "Confirm Scanner deletion",
"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:"
}
}

View File

@ -1340,6 +1340,7 @@
"VULNERABILITY_SEVERITY": "Vulnerability severity:",
"CONFIRM_DELETION": "Confirm Scanner deletion",
"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:"
}
}

View File

@ -1312,6 +1312,7 @@
"VULNERABILITY_SEVERITY": "Vulnerability severity:",
"CONFIRM_DELETION": "Confirm Scanner deletion",
"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:"
}
}

View File

@ -1337,7 +1337,8 @@
"VULNERABILITY_SEVERITY": "Vulnerability severity:",
"CONFIRM_DELETION": "Confirm Scanner deletion",
"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:"
}
}

View File

@ -1342,6 +1342,7 @@
"VULNERABILITY_SEVERITY": "Vulnerability severity:",
"CONFIRM_DELETION": "Confirm Scanner deletion",
"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:"
}
}

View File

@ -1339,6 +1339,7 @@
"VULNERABILITY_SEVERITY": "漏洞严重度:",
"CONFIRM_DELETION": "删除扫描器确认",
"NO_PROJECT_SCANNER": "无扫描器",
"SET_UNHEALTHY_SCANNER": "选择的扫描器:{{name}}是不健康的"
"SET_UNHEALTHY_SCANNER": "选择的扫描器:{{name}}是不健康的",
"SCANNED_BY": "扫描器:"
}
}