Skip to content

Commit 1b9f47e

Browse files
NVSHAS-9915: Show scan result from harbor scanner module in Neuvector UI.
1 parent 8989953 commit 1b9f47e

File tree

16 files changed

+349
-170
lines changed

16 files changed

+349
-170
lines changed

admin/src/main/scala/com/neu/api/policy/PolicyApi.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,15 @@ class PolicyApi(resourceService: PolicyService) extends BaseApi {
328328
}
329329
}
330330
} ~
331+
path("fed-repo") {
332+
get {
333+
parameter(Symbol("fed_repo")) { fedRepo =>
334+
Utils.respondWithWebServerHeaders() {
335+
resourceService.getFederatedRepoScanRegistrySummary(tokenId, fedRepo)
336+
}
337+
}
338+
}
339+
} ~
331340
path("image") {
332341
get {
333342
parameter(Symbol("name"), Symbol("imageId"), Symbol("show").?) {

admin/src/main/scala/com/neu/service/policy/PolicyService.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,16 @@ class PolicyService() extends BaseService with DefaultJsonFormats with LazyLoggi
669669
)
670670
}
671671

672+
def getFederatedRepoScanRegistrySummary(tokenId: String, fedRepo: String): Route = complete {
673+
logger.info("Getting federated scan registry summary")
674+
RestClient.httpRequestWithHeader(
675+
s"${baseClusterUri(tokenId)}/$scanRegistryPath/$fedRepo/images",
676+
GET,
677+
"",
678+
tokenId
679+
)
680+
}
681+
672682
def getImageScanReport(
673683
tokenId: String,
674684
name: String,

admin/webapp/websrc/app/app.component.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ import { AuthService } from '@common/services/auth.service';
1818
import { SummaryService } from '@services/summary.service';
1919
import { CommonHttpService } from '@common/api/common-http.service';
2020
import { SettingsService } from '@services/settings.service';
21+
import { MultiClusterService } from '@services/multi-cluster.service';
22+
import { Cluster, ClusterData } from '@common/types';
23+
import { MapConstant } from '@common/constants/map.constant';
2124

2225
@Component({
2326
selector: 'app-root',
@@ -37,7 +40,8 @@ export class AppComponent implements OnInit {
3740
private translatorService: TranslatorService,
3841
private summaryService: SummaryService,
3942
private authService: AuthService,
40-
private commonHttpService: CommonHttpService
43+
private commonHttpService: CommonHttpService,
44+
private multiClusterService: MultiClusterService
4145
) {
4246
this.win = GlobalVariable.window;
4347
this.initTimer = new Date().getTime();
@@ -85,6 +89,27 @@ export class AppComponent implements OnInit {
8589
}
8690

8791
ngOnInit() {
92+
this.multiClusterService.getClusters().subscribe({
93+
next: (data: ClusterData) => {
94+
GlobalVariable.isMaster =
95+
data.fed_role === MapConstant.FED_ROLES.MASTER;
96+
GlobalVariable.isMember =
97+
data.fed_role === MapConstant.FED_ROLES.MEMBER;
98+
GlobalVariable.isStandAlone = data.fed_role === '';
99+
//get the status of the chosen cluster
100+
const sessionCluster = this.localStorage.get(
101+
GlobalConstant.LOCAL_STORAGE_CLUSTER
102+
);
103+
const clusterInSession = sessionCluster
104+
? JSON.parse(sessionCluster)
105+
: null;
106+
if (clusterInSession) {
107+
GlobalVariable.isRemote = clusterInSession.isRemote;
108+
} else {
109+
GlobalVariable.isRemote = false;
110+
}
111+
},
112+
});
88113
document.addEventListener('click', e => {
89114
const target = e.target as HTMLElement;
90115
if (

admin/webapp/websrc/app/common/constants/path.constant.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,4 +149,5 @@ export class PathConstant {
149149
public static NOTIFICATION_PERSIST_URL = 'notification/accept';
150150
public static REMOTE_REPO_URL = 'remote_repository';
151151
public static SCANNED_ASSETS_URL = 'scanned-assets';
152+
public static SCANNED_FED_REPO = 'scan/registry/fed-repo';
152153
}

admin/webapp/websrc/app/common/services/multi-cluster.service.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { PathConstant } from '@common/constants/path.constant';
66
import { Router } from '@angular/router';
77
import { SESSION_STORAGE, StorageService } from 'ngx-webstorage-service';
88
import { BehaviorSubject, Observable, Subject } from 'rxjs';
9+
import { tap } from 'rxjs/operators';
910
import { Cluster, ClusterData, ClusterSummary } from '@common/types';
1011
import { GlobalVariable } from '@common/variables/global.variable';
1112
import { TranslateService } from '@ngx-translate/core';
@@ -32,11 +33,13 @@ export interface Cluster2Join {
3233
master_port: string;
3334
}
3435

35-
@Injectable()
36+
@Injectable({ providedIn: 'root' })
3637
export class MultiClusterService {
3738
public clusterName: string = '';
3839
public clusters: Cluster[] = [];
3940
public primaryClusterRestVersion: string = '';
41+
private memberSubject = new BehaviorSubject<any>(null);
42+
public member$: Observable<any> = this.memberSubject.asObservable();
4043
private _clusterSwitchedEvent = new Subject();
4144
private _clusterRefreshEvent = new Subject();
4245
private _manageClusterEvent = new Subject();
@@ -98,7 +101,9 @@ export class MultiClusterService {
98101
}
99102

100103
getClusters(): Observable<any> {
101-
return GlobalVariable.http.get(PathConstant.FED_MEMBER_URL);
104+
return GlobalVariable.http
105+
.get(PathConstant.FED_MEMBER_URL)
106+
.pipe(tap(member => this.memberSubject.next(member)));
102107
}
103108

104109
getRemoteSummary(id): Observable<any> {

admin/webapp/websrc/app/common/services/registries.service.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,4 +259,12 @@ export class RegistriesService {
259259
})
260260
.pipe();
261261
}
262+
263+
getFederatedRepoScanRegistrySummary(fedRepo: string) {
264+
return GlobalVariable.http
265+
.get<AllScannedImages>(PathConstant.SCANNED_FED_REPO, {
266+
params: { fed_repo: fedRepo },
267+
})
268+
.pipe();
269+
}
262270
}

admin/webapp/websrc/app/common/types/registries/registries.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ export interface Summary {
120120
ignore_proxy: boolean;
121121
use_proxy: boolean;
122122
isAllView?: boolean;
123+
isFedRepo?: boolean;
123124
}
124125

125126
interface RegistryType {

admin/webapp/websrc/app/frame/header/header.component.ts

Lines changed: 86 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import { AuthUtilsService } from '@common/utils/auth.utils';
2828
import { CommonHttpService } from '@common/api/common-http.service';
2929
import { AuthService } from '@services/auth.service';
3030
import { SettingsService } from '@services/settings.service';
31-
import { switchMap } from 'rxjs/operators';
31+
import { switchMap, take } from 'rxjs/operators';
3232
import { FrameService } from '../frame.service';
3333

3434
@Component({
@@ -70,6 +70,7 @@ export class HeaderComponent implements OnInit, OnDestroy {
7070
private _getRebrandCustomValuesSubscription;
7171
private _clusterNameSubScription;
7272
public isAuthReadConfig: boolean = false;
73+
member$ = this.multiClusterService.member$;
7374

7475
@ViewChild('fsbutton', { static: true }) fsbutton;
7576

@@ -284,102 +285,98 @@ export class HeaderComponent implements OnInit, OnDestroy {
284285
});
285286
}
286287
getClusters() {
287-
this.multiClusterService
288-
.getClusters()
289-
.pipe()
290-
.subscribe({
291-
next: (data: ClusterData) => {
292-
this.clusters = data.clusters || [];
293-
//get primary cluster's rest_version
294-
const primaryCluster = this.clusters.find(
295-
cluster =>
296-
cluster.clusterType === GlobalConstant.CLUSTER_TYPES.MASTER
297-
);
298-
this.primaryClusterRestVersion = primaryCluster
299-
? primaryCluster.rest_version
300-
: '';
301-
this.multiClusterService.primaryClusterRestVersion =
302-
this.primaryClusterRestVersion;
303-
//init the cluster role
304-
this.isMemberRole = data.fed_role === MapConstant.FED_ROLES.MEMBER;
305-
this.isMasterRole = data.fed_role === MapConstant.FED_ROLES.MASTER;
306-
this.isStandaloneRole = data.fed_role === '';
307-
GlobalVariable.isMaster = this.isMasterRole;
308-
GlobalVariable.isMember = this.isMemberRole;
309-
GlobalVariable.isStandAlone = this.isStandaloneRole;
310-
311-
const resource = {
312-
multiClusterOp: {
313-
global: 2,
314-
},
315-
manageAuth: {
316-
global: 3,
317-
},
318-
multiClusterView: {
319-
global: 1,
320-
},
321-
};
322-
323-
this.isAllowedToRedirectMultiCluster =
288+
this.member$.pipe(take(1)).subscribe({
289+
next: (data: ClusterData) => {
290+
this.clusters = data.clusters || [];
291+
//get primary cluster's rest_version
292+
const primaryCluster = this.clusters.find(
293+
cluster => cluster.clusterType === GlobalConstant.CLUSTER_TYPES.MASTER
294+
);
295+
this.primaryClusterRestVersion = primaryCluster
296+
? primaryCluster.rest_version
297+
: '';
298+
this.multiClusterService.primaryClusterRestVersion =
299+
this.primaryClusterRestVersion;
300+
//init the cluster role
301+
this.isMemberRole = data.fed_role === MapConstant.FED_ROLES.MEMBER;
302+
this.isMasterRole = data.fed_role === MapConstant.FED_ROLES.MASTER;
303+
this.isStandaloneRole = data.fed_role === '';
304+
GlobalVariable.isMaster = this.isMasterRole;
305+
GlobalVariable.isMember = this.isMemberRole;
306+
GlobalVariable.isStandAlone = this.isStandaloneRole;
307+
308+
const resource = {
309+
multiClusterOp: {
310+
global: 2,
311+
},
312+
manageAuth: {
313+
global: 3,
314+
},
315+
multiClusterView: {
316+
global: 1,
317+
},
318+
};
319+
320+
this.isAllowedToRedirectMultiCluster =
321+
this.authUtilsService.getGlobalPermissionDisplayFlag(
322+
'multi_cluster'
323+
) ||
324+
(isAuthorized(GlobalVariable.user.roles, resource.multiClusterOp) &&
325+
data.fed_role !== MapConstant.FED_ROLES.MASTER);
326+
327+
//get the status of the chosen cluster
328+
const sessionCluster = this.localStorage.get(
329+
GlobalConstant.LOCAL_STORAGE_CLUSTER
330+
);
331+
const clusterInSession = sessionCluster
332+
? JSON.parse(sessionCluster)
333+
: null;
334+
if (clusterInSession) {
335+
this.isOnRemoteCluster = clusterInSession.isRemote;
336+
GlobalVariable.isRemote = clusterInSession.isRemote;
337+
} else {
338+
GlobalVariable.isRemote = false;
339+
}
340+
341+
if (GlobalVariable.isMaster) {
342+
this.isAllowedToOperateMultiCluster =
343+
isAuthorized(GlobalVariable.user.roles, resource.manageAuth) ||
324344
this.authUtilsService.getGlobalPermissionDisplayFlag(
325345
'multi_cluster'
326-
) ||
327-
(isAuthorized(GlobalVariable.user.roles, resource.multiClusterOp) &&
328-
data.fed_role !== MapConstant.FED_ROLES.MASTER);
329-
330-
//get the status of the chosen cluster
331-
const sessionCluster = this.localStorage.get(
332-
GlobalConstant.LOCAL_STORAGE_CLUSTER
333-
);
334-
const clusterInSession = sessionCluster
335-
? JSON.parse(sessionCluster)
336-
: null;
337-
if (clusterInSession) {
338-
this.isOnRemoteCluster = clusterInSession.isRemote;
339-
GlobalVariable.isRemote = clusterInSession.isRemote;
346+
);
347+
if (clusterInSession !== null) {
348+
this.selectedCluster = clusterInSession;
340349
} else {
341-
GlobalVariable.isRemote = false;
350+
this.selectedCluster = this.clusters.find(cluster => {
351+
return cluster.clusterType === MapConstant.FED_ROLES.MASTER;
352+
});
342353
}
354+
}
343355

344-
if (GlobalVariable.isMaster) {
345-
this.isAllowedToOperateMultiCluster =
346-
isAuthorized(GlobalVariable.user.roles, resource.manageAuth) ||
347-
this.authUtilsService.getGlobalPermissionDisplayFlag(
348-
'multi_cluster'
349-
);
350-
if (clusterInSession !== null) {
351-
this.selectedCluster = clusterInSession;
356+
if (GlobalVariable.isMember) {
357+
this.isAllowedToOperateMultiCluster =
358+
isAuthorized(
359+
GlobalVariable.user.roles,
360+
resource.multiClusterView
361+
) ||
362+
this.authUtilsService.getGlobalPermissionDisplayFlag(
363+
'multi_cluster'
364+
);
365+
this.clusters.forEach(cluster => {
366+
if (cluster.clusterType === MapConstant.FED_ROLES.MASTER) {
367+
this.primaryMasterName = cluster.name;
352368
} else {
353-
this.selectedCluster = this.clusters.find(cluster => {
354-
return cluster.clusterType === MapConstant.FED_ROLES.MASTER;
355-
});
369+
this.managedClusterName = cluster.name;
356370
}
357-
}
358-
359-
if (GlobalVariable.isMember) {
360-
this.isAllowedToOperateMultiCluster =
361-
isAuthorized(
362-
GlobalVariable.user.roles,
363-
resource.multiClusterView
364-
) ||
365-
this.authUtilsService.getGlobalPermissionDisplayFlag(
366-
'multi_cluster'
367-
);
368-
this.clusters.forEach(cluster => {
369-
if (cluster.clusterType === MapConstant.FED_ROLES.MASTER) {
370-
this.primaryMasterName = cluster.name;
371-
} else {
372-
this.managedClusterName = cluster.name;
373-
}
374-
});
375-
}
371+
});
372+
}
376373

377-
this.multiClusterService.dispatchGetClustersFinishEvent();
378-
},
379-
error: error => {
380-
this.clustersError = true;
381-
},
382-
});
374+
this.multiClusterService.dispatchGetClustersFinishEvent();
375+
},
376+
error: error => {
377+
this.clustersError = true;
378+
},
379+
});
383380
}
384381

385382
redirectCluster(cluster: Cluster) {

0 commit comments

Comments
 (0)