diff --git a/deepfence_frontend/apps/dashboard/api-spec.json b/deepfence_frontend/apps/dashboard/api-spec.json index a40ede3e80..5ab058c254 100644 --- a/deepfence_frontend/apps/dashboard/api-spec.json +++ b/deepfence_frontend/apps/dashboard/api-spec.json @@ -5347,6 +5347,51 @@ "security": [{ "bearer_token": [] }] } }, + "/deepfence/scan/results/fields": { + "get": { + "tags": ["Common"], + "summary": "Get Scan Report Fields", + "description": "Get all the fields available in all the scan reports", + "operationId": "getScanReportFields", + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/ModelScanReportFieldsResponse" } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/ApiDocsBadRequestResponse" } + } + } + }, + "401": { "description": "Unauthorized" }, + "403": { "description": "Forbidden" }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/ApiDocsFailureResponse" } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/ApiDocsFailureResponse" } + } + } + } + }, + "security": [{ "bearer_token": [] }] + } + }, "/deepfence/scan/results/malware": { "post": { "tags": ["Malware Scan"], @@ -6245,7 +6290,7 @@ "requestBody": { "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ModelComplianceScanTriggerReq" } + "schema": { "$ref": "#/components/schemas/ModelStopScanRequest" } } } }, @@ -6380,9 +6425,7 @@ "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/ModelVulnerabilityScanTriggerReq" - } + "schema": { "$ref": "#/components/schemas/ModelStopScanRequest" } } } }, @@ -10467,12 +10510,16 @@ "bucket_policy_is_public": { "type": "boolean" }, "cidr_ipv4": { "type": "string" }, "cloud_provider": { "type": "string" }, + "cluster_arn": { "type": "string" }, + "cluster_name": { "type": "string" }, + "connectivity": { "type": "string" }, "container_definitions": {}, "containers": {}, "create_date": { "type": "string" }, "db_cluster_identifier": { "type": "string" }, "description": { "type": "string" }, "event_notification_configuration": {}, + "group": { "type": "string" }, "group_id": { "type": "string" }, "groups": {}, "host_name": { "type": "string" }, @@ -10489,6 +10536,7 @@ "instances": {}, "ip_configuration": {}, "is_egress": { "type": "boolean" }, + "last_status": { "type": "string" }, "name": { "type": "string" }, "network_configuration": {}, "network_interfaces": {}, @@ -10518,6 +10566,7 @@ "tags": {}, "target_group_arn": { "type": "string" }, "target_health_descriptions": {}, + "task_arn": { "type": "string" }, "task_definition": {}, "task_definition_arn": { "type": "string" }, "user-groups": {}, @@ -10961,7 +11010,8 @@ "type": "array", "items": { "type": "string" }, "nullable": true - } + }, + "stop_requested": { "type": "boolean" } } }, "ModelCloudComplianceScanResult": { @@ -11443,6 +11493,7 @@ "ModelContainerImage": { "required": [ "node_id", + "image_node_id", "node_name", "docker_image_name", "docker_image_tag", @@ -11480,6 +11531,7 @@ "nullable": true }, "docker_image_virtual_size": { "type": "string" }, + "image_node_id": { "type": "string" }, "malware_latest_scan_id": { "type": "string" }, "malware_scan_status": { "type": "string" }, "malwares_count": { "type": "integer" }, @@ -12342,6 +12394,23 @@ } } }, + "ModelScanReportFieldsResponse": { + "type": "object", + "properties": { + "compliance": { + "type": "array", + "items": { "type": "string" }, + "nullable": true + }, + "malware": { "type": "array", "items": { "type": "string" }, "nullable": true }, + "secret": { "type": "array", "items": { "type": "string" }, "nullable": true }, + "vulnerability": { + "type": "array", + "items": { "type": "string" }, + "nullable": true + } + } + }, "ModelScanResultBasicNode": { "required": ["result_id", "basic_nodes"], "type": "object", diff --git a/deepfence_frontend/apps/dashboard/src/api/api.ts b/deepfence_frontend/apps/dashboard/src/api/api.ts index 43367b4069..07ff4c0f07 100644 --- a/deepfence_frontend/apps/dashboard/src/api/api.ts +++ b/deepfence_frontend/apps/dashboard/src/api/api.ts @@ -331,6 +331,7 @@ export function getCommonApiClient() { const commonApi = new CommonApi(configuration); return { getEula: commonApi.eula.bind(commonApi), + getScanReportFields: commonApi.getScanReportFields.bind(commonApi), }; } diff --git a/deepfence_frontend/apps/dashboard/src/api/generated/.openapi-generator/FILES b/deepfence_frontend/apps/dashboard/src/api/generated/.openapi-generator/FILES index c3c7a3cbcf..e6109f8668 100644 --- a/deepfence_frontend/apps/dashboard/src/api/generated/.openapi-generator/FILES +++ b/deepfence_frontend/apps/dashboard/src/api/generated/.openapi-generator/FILES @@ -156,6 +156,7 @@ models/ModelScanFilter.ts models/ModelScanInfo.ts models/ModelScanListReq.ts models/ModelScanListResp.ts +models/ModelScanReportFieldsResponse.ts models/ModelScanResultBasicNode.ts models/ModelScanResultsActionRequest.ts models/ModelScanResultsCommon.ts diff --git a/deepfence_frontend/apps/dashboard/src/api/generated/apis/CommonApi.ts b/deepfence_frontend/apps/dashboard/src/api/generated/apis/CommonApi.ts index e32c93f68e..4371668aa4 100644 --- a/deepfence_frontend/apps/dashboard/src/api/generated/apis/CommonApi.ts +++ b/deepfence_frontend/apps/dashboard/src/api/generated/apis/CommonApi.ts @@ -18,6 +18,7 @@ import type { ApiDocsBadRequestResponse, ApiDocsFailureResponse, ModelMessageResponse, + ModelScanReportFieldsResponse, } from '../models'; import { ApiDocsBadRequestResponseFromJSON, @@ -26,6 +27,8 @@ import { ApiDocsFailureResponseToJSON, ModelMessageResponseFromJSON, ModelMessageResponseToJSON, + ModelScanReportFieldsResponseFromJSON, + ModelScanReportFieldsResponseToJSON, } from '../models'; /** @@ -50,6 +53,21 @@ export interface CommonApiInterface { */ eula(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise; + /** + * Get all the fields available in all the scan reports + * @summary Get Scan Report Fields + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof CommonApiInterface + */ + getScanReportFieldsRaw(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>; + + /** + * Get all the fields available in all the scan reports + * Get Scan Report Fields + */ + getScanReportFields(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise; + } /** @@ -85,4 +103,40 @@ export class CommonApi extends runtime.BaseAPI implements CommonApiInterface { return await response.value(); } + /** + * Get all the fields available in all the scan reports + * Get Scan Report Fields + */ + async getScanReportFieldsRaw(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("bearer_token", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + const response = await this.request({ + path: `/deepfence/scan/results/fields`, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => ModelScanReportFieldsResponseFromJSON(jsonValue)); + } + + /** + * Get all the fields available in all the scan reports + * Get Scan Report Fields + */ + async getScanReportFields(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.getScanReportFieldsRaw(initOverrides); + return await response.value(); + } + } diff --git a/deepfence_frontend/apps/dashboard/src/api/generated/apis/ComplianceApi.ts b/deepfence_frontend/apps/dashboard/src/api/generated/apis/ComplianceApi.ts index 3356b57b42..8bff4445af 100644 --- a/deepfence_frontend/apps/dashboard/src/api/generated/apis/ComplianceApi.ts +++ b/deepfence_frontend/apps/dashboard/src/api/generated/apis/ComplianceApi.ts @@ -27,6 +27,7 @@ import type { ModelScanStatusReq, ModelScanStatusResp, ModelScanTriggerResp, + ModelStopScanRequest, SearchSearchCountResp, } from '../models'; import { @@ -54,6 +55,8 @@ import { ModelScanStatusRespToJSON, ModelScanTriggerRespFromJSON, ModelScanTriggerRespToJSON, + ModelStopScanRequestFromJSON, + ModelStopScanRequestToJSON, SearchSearchCountRespFromJSON, SearchSearchCountRespToJSON, } from '../models'; @@ -87,7 +90,7 @@ export interface StatusComplianceScanRequest { } export interface StopComplianceScanRequest { - modelComplianceScanTriggerReq?: ModelComplianceScanTriggerReq; + modelStopScanRequest?: ModelStopScanRequest; } /** @@ -212,7 +215,7 @@ export interface ComplianceApiInterface { /** * Stop Compliance Scan on agent or registry * @summary Stop Compliance Scan - * @param {ModelComplianceScanTriggerReq} [modelComplianceScanTriggerReq] + * @param {ModelStopScanRequest} [modelStopScanRequest] * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof ComplianceApiInterface @@ -527,7 +530,7 @@ export class ComplianceApi extends runtime.BaseAPI implements ComplianceApiInter method: 'POST', headers: headerParameters, query: queryParameters, - body: ModelComplianceScanTriggerReqToJSON(requestParameters.modelComplianceScanTriggerReq), + body: ModelStopScanRequestToJSON(requestParameters.modelStopScanRequest), }, initOverrides); return new runtime.VoidApiResponse(response); diff --git a/deepfence_frontend/apps/dashboard/src/api/generated/apis/VulnerabilityApi.ts b/deepfence_frontend/apps/dashboard/src/api/generated/apis/VulnerabilityApi.ts index 9a6143b541..065cfbaa04 100644 --- a/deepfence_frontend/apps/dashboard/src/api/generated/apis/VulnerabilityApi.ts +++ b/deepfence_frontend/apps/dashboard/src/api/generated/apis/VulnerabilityApi.ts @@ -28,6 +28,7 @@ import type { ModelScanStatusReq, ModelScanStatusResp, ModelScanTriggerResp, + ModelStopScanRequest, ModelVulnerabilityScanResult, ModelVulnerabilityScanTriggerReq, SearchSearchCountResp, @@ -60,6 +61,8 @@ import { ModelScanStatusRespToJSON, ModelScanTriggerRespFromJSON, ModelScanTriggerRespToJSON, + ModelStopScanRequestFromJSON, + ModelStopScanRequestToJSON, ModelVulnerabilityScanResultFromJSON, ModelVulnerabilityScanResultToJSON, ModelVulnerabilityScanTriggerReqFromJSON, @@ -111,7 +114,7 @@ export interface StatusVulnerabilityScanRequest { } export interface StopVulnerabilityScanRequest { - modelVulnerabilityScanTriggerReq?: ModelVulnerabilityScanTriggerReq; + modelStopScanRequest?: ModelStopScanRequest; } /** @@ -284,7 +287,7 @@ export interface VulnerabilityApiInterface { /** * Stop Vulnerability Scan on agent or registry * @summary Stop Vulnerability Scan - * @param {ModelVulnerabilityScanTriggerReq} [modelVulnerabilityScanTriggerReq] + * @param {ModelStopScanRequest} [modelStopScanRequest] * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof VulnerabilityApiInterface @@ -715,7 +718,7 @@ export class VulnerabilityApi extends runtime.BaseAPI implements VulnerabilityAp method: 'POST', headers: headerParameters, query: queryParameters, - body: ModelVulnerabilityScanTriggerReqToJSON(requestParameters.modelVulnerabilityScanTriggerReq), + body: ModelStopScanRequestToJSON(requestParameters.modelStopScanRequest), }, initOverrides); return new runtime.VoidApiResponse(response); diff --git a/deepfence_frontend/apps/dashboard/src/api/generated/models/IngestersCloudResource.ts b/deepfence_frontend/apps/dashboard/src/api/generated/models/IngestersCloudResource.ts index 235a96fece..a28a151950 100644 --- a/deepfence_frontend/apps/dashboard/src/api/generated/models/IngestersCloudResource.ts +++ b/deepfence_frontend/apps/dashboard/src/api/generated/models/IngestersCloudResource.ts @@ -85,6 +85,24 @@ export interface IngestersCloudResource { * @memberof IngestersCloudResource */ cloud_provider?: string; + /** + * + * @type {string} + * @memberof IngestersCloudResource + */ + cluster_arn?: string; + /** + * + * @type {string} + * @memberof IngestersCloudResource + */ + cluster_name?: string; + /** + * + * @type {string} + * @memberof IngestersCloudResource + */ + connectivity?: string; /** * * @type {any} @@ -121,6 +139,12 @@ export interface IngestersCloudResource { * @memberof IngestersCloudResource */ event_notification_configuration?: any | null; + /** + * + * @type {string} + * @memberof IngestersCloudResource + */ + group?: string; /** * * @type {string} @@ -217,6 +241,12 @@ export interface IngestersCloudResource { * @memberof IngestersCloudResource */ is_egress?: boolean; + /** + * + * @type {string} + * @memberof IngestersCloudResource + */ + last_status?: string; /** * * @type {string} @@ -391,6 +421,12 @@ export interface IngestersCloudResource { * @memberof IngestersCloudResource */ target_health_descriptions?: any | null; + /** + * + * @type {string} + * @memberof IngestersCloudResource + */ + task_arn?: string; /** * * @type {any} @@ -477,12 +513,16 @@ export function IngestersCloudResourceFromJSONTyped(json: any, ignoreDiscriminat 'bucket_policy_is_public': !exists(json, 'bucket_policy_is_public') ? undefined : json['bucket_policy_is_public'], 'cidr_ipv4': !exists(json, 'cidr_ipv4') ? undefined : json['cidr_ipv4'], 'cloud_provider': !exists(json, 'cloud_provider') ? undefined : json['cloud_provider'], + 'cluster_arn': !exists(json, 'cluster_arn') ? undefined : json['cluster_arn'], + 'cluster_name': !exists(json, 'cluster_name') ? undefined : json['cluster_name'], + 'connectivity': !exists(json, 'connectivity') ? undefined : json['connectivity'], 'container_definitions': !exists(json, 'container_definitions') ? undefined : json['container_definitions'], 'containers': !exists(json, 'containers') ? undefined : json['containers'], 'create_date': !exists(json, 'create_date') ? undefined : json['create_date'], 'db_cluster_identifier': !exists(json, 'db_cluster_identifier') ? undefined : json['db_cluster_identifier'], 'description': !exists(json, 'description') ? undefined : json['description'], 'event_notification_configuration': !exists(json, 'event_notification_configuration') ? undefined : json['event_notification_configuration'], + 'group': !exists(json, 'group') ? undefined : json['group'], 'group_id': !exists(json, 'group_id') ? undefined : json['group_id'], 'groups': !exists(json, 'groups') ? undefined : json['groups'], 'host_name': !exists(json, 'host_name') ? undefined : json['host_name'], @@ -499,6 +539,7 @@ export function IngestersCloudResourceFromJSONTyped(json: any, ignoreDiscriminat 'instances': !exists(json, 'instances') ? undefined : json['instances'], 'ip_configuration': !exists(json, 'ip_configuration') ? undefined : json['ip_configuration'], 'is_egress': !exists(json, 'is_egress') ? undefined : json['is_egress'], + 'last_status': !exists(json, 'last_status') ? undefined : json['last_status'], 'name': !exists(json, 'name') ? undefined : json['name'], 'network_configuration': !exists(json, 'network_configuration') ? undefined : json['network_configuration'], 'network_interfaces': !exists(json, 'network_interfaces') ? undefined : json['network_interfaces'], @@ -528,6 +569,7 @@ export function IngestersCloudResourceFromJSONTyped(json: any, ignoreDiscriminat 'tags': !exists(json, 'tags') ? undefined : json['tags'], 'target_group_arn': !exists(json, 'target_group_arn') ? undefined : json['target_group_arn'], 'target_health_descriptions': !exists(json, 'target_health_descriptions') ? undefined : json['target_health_descriptions'], + 'task_arn': !exists(json, 'task_arn') ? undefined : json['task_arn'], 'task_definition': !exists(json, 'task_definition') ? undefined : json['task_definition'], 'task_definition_arn': !exists(json, 'task_definition_arn') ? undefined : json['task_definition_arn'], 'user_groups': !exists(json, 'user-groups') ? undefined : json['user-groups'], @@ -560,12 +602,16 @@ export function IngestersCloudResourceToJSON(value?: IngestersCloudResource | nu 'bucket_policy_is_public': value.bucket_policy_is_public, 'cidr_ipv4': value.cidr_ipv4, 'cloud_provider': value.cloud_provider, + 'cluster_arn': value.cluster_arn, + 'cluster_name': value.cluster_name, + 'connectivity': value.connectivity, 'container_definitions': value.container_definitions, 'containers': value.containers, 'create_date': value.create_date, 'db_cluster_identifier': value.db_cluster_identifier, 'description': value.description, 'event_notification_configuration': value.event_notification_configuration, + 'group': value.group, 'group_id': value.group_id, 'groups': value.groups, 'host_name': value.host_name, @@ -582,6 +628,7 @@ export function IngestersCloudResourceToJSON(value?: IngestersCloudResource | nu 'instances': value.instances, 'ip_configuration': value.ip_configuration, 'is_egress': value.is_egress, + 'last_status': value.last_status, 'name': value.name, 'network_configuration': value.network_configuration, 'network_interfaces': value.network_interfaces, @@ -611,6 +658,7 @@ export function IngestersCloudResourceToJSON(value?: IngestersCloudResource | nu 'tags': value.tags, 'target_group_arn': value.target_group_arn, 'target_health_descriptions': value.target_health_descriptions, + 'task_arn': value.task_arn, 'task_definition': value.task_definition, 'task_definition_arn': value.task_definition_arn, 'user-groups': value.user_groups, diff --git a/deepfence_frontend/apps/dashboard/src/api/generated/models/ModelCloudComplianceScanDetails.ts b/deepfence_frontend/apps/dashboard/src/api/generated/models/ModelCloudComplianceScanDetails.ts index f098b15348..2d76faaa1d 100644 --- a/deepfence_frontend/apps/dashboard/src/api/generated/models/ModelCloudComplianceScanDetails.ts +++ b/deepfence_frontend/apps/dashboard/src/api/generated/models/ModelCloudComplianceScanDetails.ts @@ -50,6 +50,12 @@ export interface ModelCloudComplianceScanDetails { * @memberof ModelCloudComplianceScanDetails */ scan_types?: Array | null; + /** + * + * @type {boolean} + * @memberof ModelCloudComplianceScanDetails + */ + stop_requested?: boolean; } /** @@ -75,6 +81,7 @@ export function ModelCloudComplianceScanDetailsFromJSONTyped(json: any, ignoreDi 'benchmarks': !exists(json, 'benchmarks') ? undefined : (json['benchmarks'] === null ? null : (json['benchmarks'] as Array).map(ModelCloudComplianceBenchmarkFromJSON)), 'scan_id': !exists(json, 'scan_id') ? undefined : json['scan_id'], 'scan_types': !exists(json, 'scan_types') ? undefined : json['scan_types'], + 'stop_requested': !exists(json, 'stop_requested') ? undefined : json['stop_requested'], }; } @@ -91,6 +98,7 @@ export function ModelCloudComplianceScanDetailsToJSON(value?: ModelCloudComplian 'benchmarks': value.benchmarks === undefined ? undefined : (value.benchmarks === null ? null : (value.benchmarks as Array).map(ModelCloudComplianceBenchmarkToJSON)), 'scan_id': value.scan_id, 'scan_types': value.scan_types, + 'stop_requested': value.stop_requested, }; } diff --git a/deepfence_frontend/apps/dashboard/src/api/generated/models/ModelContainerImage.ts b/deepfence_frontend/apps/dashboard/src/api/generated/models/ModelContainerImage.ts index 5ec4c48feb..e132104b86 100644 --- a/deepfence_frontend/apps/dashboard/src/api/generated/models/ModelContainerImage.ts +++ b/deepfence_frontend/apps/dashboard/src/api/generated/models/ModelContainerImage.ts @@ -74,6 +74,12 @@ export interface ModelContainerImage { * @memberof ModelContainerImage */ docker_image_virtual_size: string; + /** + * + * @type {string} + * @memberof ModelContainerImage + */ + image_node_id: string; /** * * @type {string} @@ -161,6 +167,7 @@ export function instanceOfModelContainerImage(value: object): boolean { isInstance = isInstance && "docker_image_tag" in value; isInstance = isInstance && "docker_image_tag_list" in value; isInstance = isInstance && "docker_image_virtual_size" in value; + isInstance = isInstance && "image_node_id" in value; isInstance = isInstance && "malware_latest_scan_id" in value; isInstance = isInstance && "malware_scan_status" in value; isInstance = isInstance && "malwares_count" in value; @@ -194,6 +201,7 @@ export function ModelContainerImageFromJSONTyped(json: any, ignoreDiscriminator: 'docker_image_tag': json['docker_image_tag'], 'docker_image_tag_list': json['docker_image_tag_list'], 'docker_image_virtual_size': json['docker_image_virtual_size'], + 'image_node_id': json['image_node_id'], 'malware_latest_scan_id': json['malware_latest_scan_id'], 'malware_scan_status': json['malware_scan_status'], 'malwares_count': json['malwares_count'], @@ -226,6 +234,7 @@ export function ModelContainerImageToJSON(value?: ModelContainerImage | null): a 'docker_image_tag': value.docker_image_tag, 'docker_image_tag_list': value.docker_image_tag_list, 'docker_image_virtual_size': value.docker_image_virtual_size, + 'image_node_id': value.image_node_id, 'malware_latest_scan_id': value.malware_latest_scan_id, 'malware_scan_status': value.malware_scan_status, 'malwares_count': value.malwares_count, diff --git a/deepfence_frontend/apps/dashboard/src/api/generated/models/ModelScanReportFieldsResponse.ts b/deepfence_frontend/apps/dashboard/src/api/generated/models/ModelScanReportFieldsResponse.ts new file mode 100644 index 0000000000..bc415e6fe1 --- /dev/null +++ b/deepfence_frontend/apps/dashboard/src/api/generated/models/ModelScanReportFieldsResponse.ts @@ -0,0 +1,89 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Deepfence ThreatMapper + * Deepfence Runtime API provides programmatic control over Deepfence microservice securing your container, kubernetes and cloud deployments. The API abstracts away underlying infrastructure details like cloud provider, container distros, container orchestrator and type of deployment. This is one uniform API to manage and control security alerts, policies and response to alerts for microservices running anywhere i.e. managed pure greenfield container deployments or a mix of containers, VMs and serverless paradigms like AWS Fargate. + * + * The version of the OpenAPI document: 2.0.0 + * Contact: community@deepfence.io + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * + * @export + * @interface ModelScanReportFieldsResponse + */ +export interface ModelScanReportFieldsResponse { + /** + * + * @type {Array} + * @memberof ModelScanReportFieldsResponse + */ + compliance?: Array | null; + /** + * + * @type {Array} + * @memberof ModelScanReportFieldsResponse + */ + malware?: Array | null; + /** + * + * @type {Array} + * @memberof ModelScanReportFieldsResponse + */ + secret?: Array | null; + /** + * + * @type {Array} + * @memberof ModelScanReportFieldsResponse + */ + vulnerability?: Array | null; +} + +/** + * Check if a given object implements the ModelScanReportFieldsResponse interface. + */ +export function instanceOfModelScanReportFieldsResponse(value: object): boolean { + let isInstance = true; + + return isInstance; +} + +export function ModelScanReportFieldsResponseFromJSON(json: any): ModelScanReportFieldsResponse { + return ModelScanReportFieldsResponseFromJSONTyped(json, false); +} + +export function ModelScanReportFieldsResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): ModelScanReportFieldsResponse { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'compliance': !exists(json, 'compliance') ? undefined : json['compliance'], + 'malware': !exists(json, 'malware') ? undefined : json['malware'], + 'secret': !exists(json, 'secret') ? undefined : json['secret'], + 'vulnerability': !exists(json, 'vulnerability') ? undefined : json['vulnerability'], + }; +} + +export function ModelScanReportFieldsResponseToJSON(value?: ModelScanReportFieldsResponse | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'compliance': value.compliance, + 'malware': value.malware, + 'secret': value.secret, + 'vulnerability': value.vulnerability, + }; +} + diff --git a/deepfence_frontend/apps/dashboard/src/api/generated/models/index.ts b/deepfence_frontend/apps/dashboard/src/api/generated/models/index.ts index 2debe78386..861a470242 100644 --- a/deepfence_frontend/apps/dashboard/src/api/generated/models/index.ts +++ b/deepfence_frontend/apps/dashboard/src/api/generated/models/index.ts @@ -132,6 +132,7 @@ export * from './ModelScanFilter'; export * from './ModelScanInfo'; export * from './ModelScanListReq'; export * from './ModelScanListResp'; +export * from './ModelScanReportFieldsResponse'; export * from './ModelScanResultBasicNode'; export * from './ModelScanResultsActionRequest'; export * from './ModelScanResultsCommon'; diff --git a/deepfence_frontend/apps/dashboard/src/features/integrations/components/IntegrationForm.tsx b/deepfence_frontend/apps/dashboard/src/features/integrations/components/IntegrationForm.tsx index 0d9416fd88..66831d1e7a 100644 --- a/deepfence_frontend/apps/dashboard/src/features/integrations/components/IntegrationForm.tsx +++ b/deepfence_frontend/apps/dashboard/src/features/integrations/components/IntegrationForm.tsx @@ -14,6 +14,7 @@ import { SearchableClusterList } from '@/components/forms/SearchableClusterList' import { SearchableContainerList } from '@/components/forms/SearchableContainerList'; import { SearchableHostList } from '@/components/forms/SearchableHostList'; import { SearchableImageList } from '@/components/forms/SearchableImageList'; +import { FieldSelection } from '@/features/integrations/components/report-form/FieldSelection'; import { SuccessModalContent } from '@/features/settings/components/SuccessModalContent'; import { ScanTypeEnum } from '@/types/common'; @@ -105,6 +106,14 @@ const isUserActivityNotification = (notificationType: string) => { return notificationType && notificationType === 'User Activities'; }; +const isVulnerabilityNotification = (notificationType: string) => { + return notificationType && notificationType === 'Vulnerability'; +}; + +const isJiraIntegration = (integrationType: string) => { + return integrationType && integrationType === IntegrationType.jira; +}; + const API_SCAN_TYPE_MAP: { [key: string]: ScanTypeEnum; } = { @@ -337,6 +346,13 @@ const NotificationType = ({ fieldErrors }: { fieldErrors?: Record ) : null} + {notificationType && + isVulnerabilityNotification(notificationType) && + isJiraIntegration(integrationType) ? ( + + ) : null} ); }; diff --git a/deepfence_frontend/apps/dashboard/src/features/integrations/components/report-form/FieldSelection.tsx b/deepfence_frontend/apps/dashboard/src/features/integrations/components/report-form/FieldSelection.tsx new file mode 100644 index 0000000000..38cdeb7593 --- /dev/null +++ b/deepfence_frontend/apps/dashboard/src/features/integrations/components/report-form/FieldSelection.tsx @@ -0,0 +1,82 @@ +import { useSuspenseQuery } from '@suspensive/react-query'; +import { Suspense, useState } from 'react'; +import { CircleSpinner, Combobox, ComboboxOption } from 'ui-components'; + +import { queries } from '@/queries'; + +export const FieldSelection = ({ + notificationType, +}: { + notificationType: 'vulnerability'; +}) => { + return ( +
+
+
Customize Notification (Optional)
+
+
+ { + /**noop */ + }} + startIcon={} + /> + } + > + + +
+
+ ); +}; + +function useNotificationFields() { + return useSuspenseQuery({ + ...queries.integration.getNotificationFields(), + }); +} + +const FieldSelectionDropdown = ({ + notificationType, +}: { + notificationType: 'vulnerability'; +}) => { + const { data } = useNotificationFields(); + const [selectedFields, setSelectedFields] = useState([]); + const [searchQuery, setSearchQuery] = useState(''); + return ( + setSelectedFields(value)} + onQueryChange={(query) => { + setSearchQuery(query); + }} + getDisplayValue={(items) => { + if (!items.length) return null; + return `${items.length} fields selected`; + }} + > + {data[notificationType as 'vulnerability'] + ?.filter((field) => { + return field.toLowerCase().includes(searchQuery); + }) + .map((field) => { + return ( + + {field} + + ); + })} + + ); +}; diff --git a/deepfence_frontend/apps/dashboard/src/features/integrations/components/useIntegrationTableColumn.tsx b/deepfence_frontend/apps/dashboard/src/features/integrations/components/useIntegrationTableColumn.tsx index b766d19369..f3ab29429e 100644 --- a/deepfence_frontend/apps/dashboard/src/features/integrations/components/useIntegrationTableColumn.tsx +++ b/deepfence_frontend/apps/dashboard/src/features/integrations/components/useIntegrationTableColumn.tsx @@ -148,26 +148,24 @@ export const useIntegrationTableColumn = ( ]; case IntegrationType.jira: return [ - columnHelper.accessor( - (cell) => { - if (isEmpty(cell.config)) { + columnHelper.display({ + id: 'api_token', + header: () => , + minSize: 50, + size: 55, + maxSize: 60, + cell: (cell) => { + if (isEmpty(cell.row.original.config)) { return '-'; } - const isToken = cell.config?.api_token !== undefined; + const isToken = cell.row.original.config?.api_token !== undefined; if (isToken) { return ; } else { return ; } }, - { - id: 'api_token', - header: () => , - minSize: 50, - size: 55, - maxSize: 60, - }, - ), + }), columnHelper.accessor( (cell) => (!isEmpty(cell.config) ? cell.config.issueType : '-'), { diff --git a/deepfence_frontend/apps/dashboard/src/features/integrations/pages/IntegrationAdd.tsx b/deepfence_frontend/apps/dashboard/src/features/integrations/pages/IntegrationAdd.tsx index 731e5b7e50..fe158a5099 100644 --- a/deepfence_frontend/apps/dashboard/src/features/integrations/pages/IntegrationAdd.tsx +++ b/deepfence_frontend/apps/dashboard/src/features/integrations/pages/IntegrationAdd.tsx @@ -25,6 +25,7 @@ import { SuccessModalContent } from '@/features/settings/components/SuccessModal import { invalidateAllQueries, queries } from '@/queries'; import { get403Message } from '@/utils/403'; import { apiWrapper } from '@/utils/api'; +import { getArrayTypeValuesFromFormData } from '@/utils/formData'; import { IntegrationForm, IntegrationType } from '../components/IntegrationForm'; import { IntegrationTable } from '../components/IntegrationTable'; @@ -125,6 +126,7 @@ const getConfigBodyNotificationType = (formData: FormData, integrationType: stri jiraProjectKey: formBody.accessKey, issueType: formBody.task, jiraAssignee: formBody.assigne, + custom_fields: getArrayTypeValuesFromFormData(formData, 'reportingFields'), }; } return { @@ -135,6 +137,7 @@ const getConfigBodyNotificationType = (formData: FormData, integrationType: stri jiraProjectKey: formBody.accessKey, issueType: formBody.task, jiraAssignee: formBody.assigne, + custom_fields: getArrayTypeValuesFromFormData(formData, 'reportingFields'), }; } case IntegrationType.s3: { diff --git a/deepfence_frontend/apps/dashboard/src/queries/integration.tsx b/deepfence_frontend/apps/dashboard/src/queries/integration.tsx index 9c34bc3c69..20ab8da7c2 100644 --- a/deepfence_frontend/apps/dashboard/src/queries/integration.tsx +++ b/deepfence_frontend/apps/dashboard/src/queries/integration.tsx @@ -1,6 +1,10 @@ import { createQueryKeys } from '@lukemorales/query-key-factory'; -import { getIntegrationApiClient, getReportsApiClient } from '@/api/api'; +import { + getCommonApiClient, + getIntegrationApiClient, + getReportsApiClient, +} from '@/api/api'; import { get403Message } from '@/utils/403'; import { apiWrapper } from '@/utils/api'; @@ -52,4 +56,19 @@ export const integrationQueries = createQueryKeys('integration', { }, }; }, + getNotificationFields: () => { + return { + queryKey: ['getNotificationFields'], + queryFn: async () => { + const getReportFields = apiWrapper({ + fn: getCommonApiClient().getScanReportFields, + }); + const reportFieldsResponse = await getReportFields(); + if (!reportFieldsResponse.ok) { + throw reportFieldsResponse.error; + } + return reportFieldsResponse.value; + }, + }; + }, });