diff --git a/src/portal/src/app/base/project/project-config/project-policy-config/project-policy-config.component.html b/src/portal/src/app/base/project/project-config/project-policy-config/project-policy-config.component.html
index c0092c78b..882778aa1 100644
--- a/src/portal/src/app/base/project/project-config/project-policy-config/project-policy-config.component.html
+++ b/src/portal/src/app/base/project/project-config/project-policy-config/project-policy-config.component.html
@@ -16,6 +16,84 @@
{{ 'PROJECT_CONFIG.PUBLIC_POLICY' | translate }}
+
+
+
+
+
+
+ {{ 'PROJECT.PROXY_CACHE_TOOLTIP' | translate }}
+
+
+
+
{
let fixture: ComponentFixture,
component: TestHostComponent;
@@ -114,6 +123,7 @@ describe('ProjectPolicyConfigComponent', () => {
{ provide: ErrorHandler, useClass: MessageHandlerService },
{ provide: ProjectService, useValue: projectService },
{ provide: SystemInfoService, useValue: systemInfoService },
+ { provide: SessionService, useValue: sessionService },
{
provide: UserPermissionService,
useValue: userPermissionService,
diff --git a/src/portal/src/app/base/project/project-config/project-policy-config/project-policy-config.component.ts b/src/portal/src/app/base/project/project-config/project-policy-config/project-policy-config.component.ts
index 2be4f3407..66897a1c3 100644
--- a/src/portal/src/app/base/project/project-config/project-policy-config/project-policy-config.component.ts
+++ b/src/portal/src/app/base/project/project-config/project-policy-config/project-policy-config.component.ts
@@ -4,6 +4,7 @@ import { ProjectService } from '../../../../shared/services';
import { ErrorHandler } from '../../../../shared/units/error-handler';
import { State, SystemCVEAllowlist } from '../../../../shared/services';
import {
+ BandwidthUnit,
ConfirmationState,
ConfirmationTargets,
} from '../../../../shared/entities/shared.const';
@@ -15,10 +16,15 @@ import { Project } from './project';
import { SystemInfo, SystemInfoService } from '../../../../shared/services';
import { UserPermissionService } from '../../../../shared/services';
import { USERSTATICPERMISSION } from '../../../../shared/services';
+import { SessionService } from '../../../../shared/services/session.service';
+import { Registry } from '../../../../../../ng-swagger-gen/models/registry';
import {
EventService,
HarborEvent,
} from '../../../../services/event-service/event.service';
+import { forkJoin, Observable } from 'rxjs';
+import { MessageHandlerService } from 'src/app/shared/services/message-handler.service';
+import { RegistryService } from 'ng-swagger-gen/services';
const ONE_THOUSAND: number = 1000;
const LOW: string = 'low';
@@ -33,6 +39,9 @@ export class ProjectPolicy {
PreventVulImgSeverity: string;
ScanImgOnPush: boolean;
GenerateSbomOnPush: boolean;
+ ProxyCacheEnabled: boolean;
+ RegistryId?: number | null;
+ ProxySpeedKb?: number | null;
constructor() {
this.Public = false;
@@ -42,6 +51,9 @@ export class ProjectPolicy {
this.PreventVulImgSeverity = LOW;
this.ScanImgOnPush = false;
this.GenerateSbomOnPush = false;
+ this.ProxyCacheEnabled = false;
+ this.RegistryId = null;
+ this.ProxySpeedKb = -1;
}
initByProject(pro: Project) {
@@ -55,8 +67,14 @@ export class ProjectPolicy {
}
this.ScanImgOnPush = pro.metadata.auto_scan === 'true';
this.GenerateSbomOnPush = pro.metadata.auto_sbom_generation === 'true';
+ this.ProxyCacheEnabled = pro.registry_id ? true : false;
+ this.RegistryId = pro.registry_id;
+ this.ProxySpeedKb = pro.metadata.proxy_speed_kb
+ ? pro.metadata.proxy_speed_kb
+ : -1;
}
}
+const PAGE_SIZE: number = 100;
@Component({
selector: 'hbr-project-policy-config',
@@ -65,6 +83,7 @@ export class ProjectPolicy {
})
export class ProjectPolicyConfigComponent implements OnInit {
onGoing = false;
+ allowUpdateProxyCacheConfiguration = false;
@Input() projectId: number;
@Input() projectName = 'unknown';
@Input() isProxyCacheProject: boolean = false;
@@ -81,6 +100,7 @@ export class ProjectPolicyConfigComponent implements OnInit {
orgProjectPolicy = new ProjectPolicy();
projectPolicy = new ProjectPolicy();
hasChangeConfigRole: boolean;
+
severityOptions = [
{
severity: 'critical',
@@ -102,6 +122,20 @@ export class ProjectPolicyConfigComponent implements OnInit {
systemAllowlistOrProjectAllowlistOrigin: string;
projectAllowlist;
projectAllowlistOrigin;
+ speedUnit = BandwidthUnit.KB;
+ speedUnits = [
+ {
+ UNIT: BandwidthUnit.KB,
+ },
+ {
+ UNIT: BandwidthUnit.MB,
+ },
+ ];
+ // **Added property for bandwidth error message**
+ bandwidthError: string | null = null;
+ registries: Registry[] = [];
+ supportedRegistryTypeQueryString: string =
+ 'type={docker-hub harbor azure-acr aws-ecr google-gcr quay docker-registry github-ghcr jfrog-artifactory}';
constructor(
private errorHandler: ErrorHandler,
@@ -109,6 +143,9 @@ export class ProjectPolicyConfigComponent implements OnInit {
private projectService: ProjectService,
private systemInfoService: SystemInfoService,
private userPermission: UserPermissionService,
+ private session: SessionService,
+ private messageHandlerService: MessageHandlerService,
+ private endpointService: RegistryService,
private event: EventService
) {}
@@ -135,6 +172,74 @@ export class ProjectPolicyConfigComponent implements OnInit {
this.retrieve();
this.getPermission();
this.getSystemAllowlist();
+ if (this.isSystemAdmin) {
+ this.getRegistries();
+ }
+ }
+
+ validateBandwidth(): void {
+ const value = Number(this.projectPolicy.ProxySpeedKb);
+ if (
+ isNaN(value) ||
+ (!Number.isInteger(value) && value !== -1) ||
+ (value <= 0 && value !== -1)
+ ) {
+ this.bandwidthError =
+ 'Please enter -1 or an integer greater than 0.';
+ } else {
+ this.bandwidthError = null;
+ }
+ }
+
+ getRegistries() {
+ this.endpointService
+ .listRegistriesResponse({
+ page: 1,
+ pageSize: PAGE_SIZE,
+ q: this.supportedRegistryTypeQueryString,
+ })
+ .subscribe(
+ result => {
+ // Get total count
+ if (result.headers) {
+ const xHeader: string =
+ result.headers.get('X-Total-Count');
+ const totalCount = parseInt(xHeader, 0);
+ let arr = result.body || [];
+ if (totalCount <= PAGE_SIZE) {
+ // already gotten all Registries
+ this.registries = result.body || [];
+ } else {
+ // get all the registries in specified times
+ const times: number = Math.ceil(
+ totalCount / PAGE_SIZE
+ );
+ const observableList: Observable[] = [];
+ for (let i = 2; i <= times; i++) {
+ observableList.push(
+ this.endpointService.listRegistries({
+ page: i,
+ pageSize: PAGE_SIZE,
+ q: this
+ .supportedRegistryTypeQueryString,
+ })
+ );
+ }
+ forkJoin(observableList).subscribe(res => {
+ if (res && res.length) {
+ res.forEach(item => {
+ arr = arr.concat(item);
+ });
+ this.registries = arr;
+ }
+ });
+ }
+ }
+ },
+ error => {
+ this.messageHandlerService.error(error);
+ }
+ );
}
getSystemAllowlist() {
@@ -171,6 +276,11 @@ export class ProjectPolicyConfigComponent implements OnInit {
});
}
+ public get isSystemAdmin(): boolean {
+ let account = this.session.getCurrentUser();
+ return account != null && account.has_admin_role;
+ }
+
retrieve(state?: State): any {
this.projectService.getProject(this.projectId).subscribe(
response => {
diff --git a/src/portal/src/app/base/project/project-config/project-policy-config/project.ts b/src/portal/src/app/base/project/project-config/project-policy-config/project.ts
index 8772eab01..b1f1d158d 100644
--- a/src/portal/src/app/base/project/project-config/project-policy-config/project.ts
+++ b/src/portal/src/app/base/project/project-config/project-policy-config/project.ts
@@ -1,6 +1,7 @@
export class Project {
project_id: number;
owner_id?: number;
+ registry_id?: number | null;
name: string;
creation_time?: Date | string;
deleted?: number;
@@ -21,6 +22,7 @@ export class Project {
auto_scan: string | boolean;
auto_sbom_generation: string | boolean;
reuse_sys_cve_allowlist?: string;
+ proxy_speed_kb?: number | null;
};
cve_allowlist?: object;
constructor() {
@@ -30,5 +32,6 @@ export class Project {
this.metadata.severity = 'low';
this.metadata.auto_scan = false;
this.metadata.auto_sbom_generation = false;
+ this.metadata.proxy_speed_kb = -1;
}
}
diff --git a/src/portal/src/app/shared/services/project.service.ts b/src/portal/src/app/shared/services/project.service.ts
index 6b8fa2e74..107937785 100644
--- a/src/portal/src/app/shared/services/project.service.ts
+++ b/src/portal/src/app/shared/services/project.service.ts
@@ -144,6 +144,7 @@ export class ProjectDefaultService extends ProjectService {
.put(
`${baseUrl}/${projectId}`,
{
+ registry_id: projectPolicy.RegistryId,
metadata: {
public: projectPolicy.Public ? 'true' : 'false',
enable_content_trust: projectPolicy.ContentTrust
@@ -162,6 +163,7 @@ export class ProjectDefaultService extends ProjectService {
? 'true'
: 'false',
reuse_sys_cve_allowlist: reuseSysCVEVAllowlist,
+ proxy_speed_kb: projectPolicy.ProxySpeedKb.toString(),
},
cve_allowlist: projectAllowlist,
},