diff --git a/deepfence_frontend/apps/dashboard/api-spec.json b/deepfence_frontend/apps/dashboard/api-spec.json index 6adf90f4ca..0d275550ff 100644 --- a/deepfence_frontend/apps/dashboard/api-spec.json +++ b/deepfence_frontend/apps/dashboard/api-spec.json @@ -3274,7 +3274,14 @@ } }, "responses": { - "200": { "description": "OK" }, + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/ModelMessageResponse" } + } + } + }, "400": { "description": "Bad Request", "content": { @@ -3423,7 +3430,14 @@ } }, "responses": { - "200": { "description": "OK" }, + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/ModelMessageResponse" } + } + } + }, "400": { "description": "Bad Request", "content": { @@ -3675,7 +3689,14 @@ } }, "responses": { - "200": { "description": "OK" }, + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/ModelMessageResponse" } + } + } + }, "400": { "description": "Bad Request", "content": { @@ -10819,7 +10840,10 @@ "required": ["cloud_provider", "compliance_type"], "type": "object", "properties": { - "cloud_provider": { "enum": ["aws", "gcp", "azure"], "type": "string" }, + "cloud_provider": { + "enum": ["aws", "gcp", "azure", "linux", "kubernetes"], + "type": "string" + }, "compliance_type": { "type": "string" }, "node_id": { "type": "string" } } @@ -11447,6 +11471,7 @@ "filters": { "$ref": "#/components/schemas/ReportersFieldsFilters" }, "id": { "type": "integer" }, "integration_type": { "type": "string" }, + "last_error_msg": { "type": "string" }, "notification_type": { "type": "string" } } }, @@ -11850,6 +11875,7 @@ "properties": { "created_at": { "type": "integer" }, "id": { "type": "integer" }, + "is_syncing": { "type": "boolean" }, "name": { "type": "string" }, "node_id": { "type": "string" }, "non_secret": {}, @@ -12438,15 +12464,16 @@ "properties": { "language": { "enum": [ - "all", "base", "ruby", "python", "javascript", "php", "golang", + "golang-binary", "java", "rust", + "rust-binary", "dotnet" ], "type": "string" @@ -12696,6 +12723,15 @@ "size": { "type": "integer" } } }, + "SearchChainedSearchFilter": { + "required": ["node_filter", "relation_ship"], + "type": "object", + "properties": { + "next_filter": { "nullable": true }, + "node_filter": { "$ref": "#/components/schemas/SearchSearchFilter" }, + "relation_ship": { "type": "string" } + } + }, "SearchNodeCountResp": { "required": [ "cloud_provider", @@ -12766,6 +12802,9 @@ "properties": { "extended_node_filter": { "$ref": "#/components/schemas/SearchSearchFilter" }, "node_filter": { "$ref": "#/components/schemas/SearchSearchFilter" }, + "related_node_filter": { + "$ref": "#/components/schemas/SearchChainedSearchFilter" + }, "window": { "$ref": "#/components/schemas/ModelFetchWindow" } } }, 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 add2407d44..4c7c24b543 100644 --- a/deepfence_frontend/apps/dashboard/src/api/generated/.openapi-generator/FILES +++ b/deepfence_frontend/apps/dashboard/src/api/generated/.openapi-generator/FILES @@ -187,6 +187,7 @@ models/ReportersFieldsFilters.ts models/ReportersMatchFilter.ts models/ReportersOrderFilter.ts models/ReportersOrderSpec.ts +models/SearchChainedSearchFilter.ts models/SearchNodeCountResp.ts models/SearchResultGroup.ts models/SearchResultGroupResp.ts diff --git a/deepfence_frontend/apps/dashboard/src/api/generated/apis/RegistryApi.ts b/deepfence_frontend/apps/dashboard/src/api/generated/apis/RegistryApi.ts index 65437a4475..f1e8dd0a98 100644 --- a/deepfence_frontend/apps/dashboard/src/api/generated/apis/RegistryApi.ts +++ b/deepfence_frontend/apps/dashboard/src/api/generated/apis/RegistryApi.ts @@ -117,13 +117,13 @@ export interface RegistryApiInterface { * @throws {RequiredError} * @memberof RegistryApiInterface */ - addRegistryRaw(requestParameters: AddRegistryRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>; + addRegistryRaw(requestParameters: AddRegistryRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>; /** * Add a new supported registry * Add Registry */ - addRegistry(requestParameters: AddRegistryRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise; + addRegistry(requestParameters: AddRegistryRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise; /** * Add a Google Container registry @@ -135,13 +135,13 @@ export interface RegistryApiInterface { * @throws {RequiredError} * @memberof RegistryApiInterface */ - addRegistryGCRRaw(requestParameters: AddRegistryGCRRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>; + addRegistryGCRRaw(requestParameters: AddRegistryGCRRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>; /** * Add a Google Container registry * Add Google Container Registry */ - addRegistryGCR(requestParameters: AddRegistryGCRRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise; + addRegistryGCR(requestParameters: AddRegistryGCRRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise; /** * count of image tags for a given image and registry @@ -310,13 +310,13 @@ export interface RegistryApiInterface { * @throws {RequiredError} * @memberof RegistryApiInterface */ - updateRegistryRaw(requestParameters: UpdateRegistryRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>; + updateRegistryRaw(requestParameters: UpdateRegistryRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>; /** * Update registry * Update Registry */ - updateRegistry(requestParameters: UpdateRegistryRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise; + updateRegistry(requestParameters: UpdateRegistryRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise; } @@ -329,7 +329,7 @@ export class RegistryApi extends runtime.BaseAPI implements RegistryApiInterface * Add a new supported registry * Add Registry */ - async addRegistryRaw(requestParameters: AddRegistryRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async addRegistryRaw(requestParameters: AddRegistryRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { const queryParameters: any = {}; const headerParameters: runtime.HTTPHeaders = {}; @@ -352,22 +352,23 @@ export class RegistryApi extends runtime.BaseAPI implements RegistryApiInterface body: ModelRegistryAddReqToJSON(requestParameters.modelRegistryAddReq), }, initOverrides); - return new runtime.VoidApiResponse(response); + return new runtime.JSONApiResponse(response, (jsonValue) => ModelMessageResponseFromJSON(jsonValue)); } /** * Add a new supported registry * Add Registry */ - async addRegistry(requestParameters: AddRegistryRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { - await this.addRegistryRaw(requestParameters, initOverrides); + async addRegistry(requestParameters: AddRegistryRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.addRegistryRaw(requestParameters, initOverrides); + return await response.value(); } /** * Add a Google Container registry * Add Google Container Registry */ - async addRegistryGCRRaw(requestParameters: AddRegistryGCRRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async addRegistryGCRRaw(requestParameters: AddRegistryGCRRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { if (requestParameters.name === null || requestParameters.name === undefined) { throw new runtime.RequiredError('name','Required parameter requestParameters.name was null or undefined when calling addRegistryGCR.'); } @@ -428,15 +429,16 @@ export class RegistryApi extends runtime.BaseAPI implements RegistryApiInterface body: formParams, }, initOverrides); - return new runtime.VoidApiResponse(response); + return new runtime.JSONApiResponse(response, (jsonValue) => ModelMessageResponseFromJSON(jsonValue)); } /** * Add a Google Container registry * Add Google Container Registry */ - async addRegistryGCR(requestParameters: AddRegistryGCRRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { - await this.addRegistryGCRRaw(requestParameters, initOverrides); + async addRegistryGCR(requestParameters: AddRegistryGCRRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.addRegistryGCRRaw(requestParameters, initOverrides); + return await response.value(); } /** @@ -830,7 +832,7 @@ export class RegistryApi extends runtime.BaseAPI implements RegistryApiInterface * Update registry * Update Registry */ - async updateRegistryRaw(requestParameters: UpdateRegistryRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async updateRegistryRaw(requestParameters: UpdateRegistryRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { if (requestParameters.registryId === null || requestParameters.registryId === undefined) { throw new runtime.RequiredError('registryId','Required parameter requestParameters.registryId was null or undefined when calling updateRegistry.'); } @@ -857,15 +859,16 @@ export class RegistryApi extends runtime.BaseAPI implements RegistryApiInterface body: ModelRegistryUpdateReqToJSON(requestParameters.modelRegistryUpdateReq), }, initOverrides); - return new runtime.VoidApiResponse(response); + return new runtime.JSONApiResponse(response, (jsonValue) => ModelMessageResponseFromJSON(jsonValue)); } /** * Update registry * Update Registry */ - async updateRegistry(requestParameters: UpdateRegistryRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { - await this.updateRegistryRaw(requestParameters, initOverrides); + async updateRegistry(requestParameters: UpdateRegistryRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.updateRegistryRaw(requestParameters, initOverrides); + return await response.value(); } } diff --git a/deepfence_frontend/apps/dashboard/src/api/generated/models/ModelCloudNodeControlReq.ts b/deepfence_frontend/apps/dashboard/src/api/generated/models/ModelCloudNodeControlReq.ts index 6f3cae31bd..27b7a48018 100644 --- a/deepfence_frontend/apps/dashboard/src/api/generated/models/ModelCloudNodeControlReq.ts +++ b/deepfence_frontend/apps/dashboard/src/api/generated/models/ModelCloudNodeControlReq.ts @@ -46,7 +46,9 @@ export interface ModelCloudNodeControlReq { export const ModelCloudNodeControlReqCloudProviderEnum = { Aws: 'aws', Gcp: 'gcp', - Azure: 'azure' + Azure: 'azure', + Linux: 'linux', + Kubernetes: 'kubernetes' } as const; export type ModelCloudNodeControlReqCloudProviderEnum = typeof ModelCloudNodeControlReqCloudProviderEnum[keyof typeof ModelCloudNodeControlReqCloudProviderEnum]; diff --git a/deepfence_frontend/apps/dashboard/src/api/generated/models/ModelIntegrationListResp.ts b/deepfence_frontend/apps/dashboard/src/api/generated/models/ModelIntegrationListResp.ts index 9b732e1e61..98e6286496 100644 --- a/deepfence_frontend/apps/dashboard/src/api/generated/models/ModelIntegrationListResp.ts +++ b/deepfence_frontend/apps/dashboard/src/api/generated/models/ModelIntegrationListResp.ts @@ -50,6 +50,12 @@ export interface ModelIntegrationListResp { * @memberof ModelIntegrationListResp */ integration_type?: string; + /** + * + * @type {string} + * @memberof ModelIntegrationListResp + */ + last_error_msg?: string; /** * * @type {string} @@ -81,6 +87,7 @@ export function ModelIntegrationListRespFromJSONTyped(json: any, ignoreDiscrimin 'filters': !exists(json, 'filters') ? undefined : ReportersFieldsFiltersFromJSON(json['filters']), 'id': !exists(json, 'id') ? undefined : json['id'], 'integration_type': !exists(json, 'integration_type') ? undefined : json['integration_type'], + 'last_error_msg': !exists(json, 'last_error_msg') ? undefined : json['last_error_msg'], 'notification_type': !exists(json, 'notification_type') ? undefined : json['notification_type'], }; } @@ -98,6 +105,7 @@ export function ModelIntegrationListRespToJSON(value?: ModelIntegrationListResp 'filters': ReportersFieldsFiltersToJSON(value.filters), 'id': value.id, 'integration_type': value.integration_type, + 'last_error_msg': value.last_error_msg, 'notification_type': value.notification_type, }; } diff --git a/deepfence_frontend/apps/dashboard/src/api/generated/models/ModelRegistryListResp.ts b/deepfence_frontend/apps/dashboard/src/api/generated/models/ModelRegistryListResp.ts index 2511b00889..ca022b7f1f 100644 --- a/deepfence_frontend/apps/dashboard/src/api/generated/models/ModelRegistryListResp.ts +++ b/deepfence_frontend/apps/dashboard/src/api/generated/models/ModelRegistryListResp.ts @@ -31,6 +31,12 @@ export interface ModelRegistryListResp { * @memberof ModelRegistryListResp */ id?: number; + /** + * + * @type {boolean} + * @memberof ModelRegistryListResp + */ + is_syncing?: boolean; /** * * @type {string} @@ -84,6 +90,7 @@ export function ModelRegistryListRespFromJSONTyped(json: any, ignoreDiscriminato 'created_at': !exists(json, 'created_at') ? undefined : json['created_at'], 'id': !exists(json, 'id') ? undefined : json['id'], + 'is_syncing': !exists(json, 'is_syncing') ? undefined : json['is_syncing'], 'name': !exists(json, 'name') ? undefined : json['name'], 'node_id': !exists(json, 'node_id') ? undefined : json['node_id'], 'non_secret': !exists(json, 'non_secret') ? undefined : json['non_secret'], @@ -103,6 +110,7 @@ export function ModelRegistryListRespToJSON(value?: ModelRegistryListResp | null 'created_at': value.created_at, 'id': value.id, + 'is_syncing': value.is_syncing, 'name': value.name, 'node_id': value.node_id, 'non_secret': value.non_secret, diff --git a/deepfence_frontend/apps/dashboard/src/api/generated/models/ModelVulnerabilityScanConfigLanguage.ts b/deepfence_frontend/apps/dashboard/src/api/generated/models/ModelVulnerabilityScanConfigLanguage.ts index 9459a39f60..4eb360c68e 100644 --- a/deepfence_frontend/apps/dashboard/src/api/generated/models/ModelVulnerabilityScanConfigLanguage.ts +++ b/deepfence_frontend/apps/dashboard/src/api/generated/models/ModelVulnerabilityScanConfigLanguage.ts @@ -32,15 +32,16 @@ export interface ModelVulnerabilityScanConfigLanguage { * @export */ export const ModelVulnerabilityScanConfigLanguageLanguageEnum = { - All: 'all', Base: 'base', Ruby: 'ruby', Python: 'python', Javascript: 'javascript', Php: 'php', Golang: 'golang', + GolangBinary: 'golang-binary', Java: 'java', Rust: 'rust', + RustBinary: 'rust-binary', Dotnet: 'dotnet' } as const; export type ModelVulnerabilityScanConfigLanguageLanguageEnum = typeof ModelVulnerabilityScanConfigLanguageLanguageEnum[keyof typeof ModelVulnerabilityScanConfigLanguageLanguageEnum]; diff --git a/deepfence_frontend/apps/dashboard/src/api/generated/models/SearchChainedSearchFilter.ts b/deepfence_frontend/apps/dashboard/src/api/generated/models/SearchChainedSearchFilter.ts new file mode 100644 index 0000000000..1ea0173160 --- /dev/null +++ b/deepfence_frontend/apps/dashboard/src/api/generated/models/SearchChainedSearchFilter.ts @@ -0,0 +1,90 @@ +/* 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'; +import type { SearchSearchFilter } from './SearchSearchFilter'; +import { + SearchSearchFilterFromJSON, + SearchSearchFilterFromJSONTyped, + SearchSearchFilterToJSON, +} from './SearchSearchFilter'; + +/** + * + * @export + * @interface SearchChainedSearchFilter + */ +export interface SearchChainedSearchFilter { + /** + * + * @type {any} + * @memberof SearchChainedSearchFilter + */ + next_filter?: any | null; + /** + * + * @type {SearchSearchFilter} + * @memberof SearchChainedSearchFilter + */ + node_filter: SearchSearchFilter; + /** + * + * @type {string} + * @memberof SearchChainedSearchFilter + */ + relation_ship: string; +} + +/** + * Check if a given object implements the SearchChainedSearchFilter interface. + */ +export function instanceOfSearchChainedSearchFilter(value: object): boolean { + let isInstance = true; + isInstance = isInstance && "node_filter" in value; + isInstance = isInstance && "relation_ship" in value; + + return isInstance; +} + +export function SearchChainedSearchFilterFromJSON(json: any): SearchChainedSearchFilter { + return SearchChainedSearchFilterFromJSONTyped(json, false); +} + +export function SearchChainedSearchFilterFromJSONTyped(json: any, ignoreDiscriminator: boolean): SearchChainedSearchFilter { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'next_filter': !exists(json, 'next_filter') ? undefined : json['next_filter'], + 'node_filter': SearchSearchFilterFromJSON(json['node_filter']), + 'relation_ship': json['relation_ship'], + }; +} + +export function SearchChainedSearchFilterToJSON(value?: SearchChainedSearchFilter | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'next_filter': value.next_filter, + 'node_filter': SearchSearchFilterToJSON(value.node_filter), + 'relation_ship': value.relation_ship, + }; +} + diff --git a/deepfence_frontend/apps/dashboard/src/api/generated/models/SearchSearchNodeReq.ts b/deepfence_frontend/apps/dashboard/src/api/generated/models/SearchSearchNodeReq.ts index 8fa096026a..806101667b 100644 --- a/deepfence_frontend/apps/dashboard/src/api/generated/models/SearchSearchNodeReq.ts +++ b/deepfence_frontend/apps/dashboard/src/api/generated/models/SearchSearchNodeReq.ts @@ -19,6 +19,12 @@ import { ModelFetchWindowFromJSONTyped, ModelFetchWindowToJSON, } from './ModelFetchWindow'; +import type { SearchChainedSearchFilter } from './SearchChainedSearchFilter'; +import { + SearchChainedSearchFilterFromJSON, + SearchChainedSearchFilterFromJSONTyped, + SearchChainedSearchFilterToJSON, +} from './SearchChainedSearchFilter'; import type { SearchSearchFilter } from './SearchSearchFilter'; import { SearchSearchFilterFromJSON, @@ -44,6 +50,12 @@ export interface SearchSearchNodeReq { * @memberof SearchSearchNodeReq */ node_filter: SearchSearchFilter; + /** + * + * @type {SearchChainedSearchFilter} + * @memberof SearchSearchNodeReq + */ + related_node_filter?: SearchChainedSearchFilter; /** * * @type {ModelFetchWindow} @@ -75,6 +87,7 @@ export function SearchSearchNodeReqFromJSONTyped(json: any, ignoreDiscriminator: 'extended_node_filter': !exists(json, 'extended_node_filter') ? undefined : SearchSearchFilterFromJSON(json['extended_node_filter']), 'node_filter': SearchSearchFilterFromJSON(json['node_filter']), + 'related_node_filter': !exists(json, 'related_node_filter') ? undefined : SearchChainedSearchFilterFromJSON(json['related_node_filter']), 'window': ModelFetchWindowFromJSON(json['window']), }; } @@ -90,6 +103,7 @@ export function SearchSearchNodeReqToJSON(value?: SearchSearchNodeReq | null): a 'extended_node_filter': SearchSearchFilterToJSON(value.extended_node_filter), 'node_filter': SearchSearchFilterToJSON(value.node_filter), + 'related_node_filter': SearchChainedSearchFilterToJSON(value.related_node_filter), 'window': ModelFetchWindowToJSON(value.window), }; } 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 613a7f2c06..829dc1ec07 100644 --- a/deepfence_frontend/apps/dashboard/src/api/generated/models/index.ts +++ b/deepfence_frontend/apps/dashboard/src/api/generated/models/index.ts @@ -164,6 +164,7 @@ export * from './ReportersFieldsFilters'; export * from './ReportersMatchFilter'; export * from './ReportersOrderFilter'; export * from './ReportersOrderSpec'; +export * from './SearchChainedSearchFilter'; export * from './SearchNodeCountResp'; export * from './SearchResultGroup'; export * from './SearchResultGroupResp'; diff --git a/deepfence_frontend/apps/dashboard/src/components/scan-configure-forms/VulnerabilityScanConfigureForm.tsx b/deepfence_frontend/apps/dashboard/src/components/scan-configure-forms/VulnerabilityScanConfigureForm.tsx index 0331369e5f..13551577a9 100644 --- a/deepfence_frontend/apps/dashboard/src/components/scan-configure-forms/VulnerabilityScanConfigureForm.tsx +++ b/deepfence_frontend/apps/dashboard/src/components/scan-configure-forms/VulnerabilityScanConfigureForm.tsx @@ -15,54 +15,71 @@ import { get403Message } from '@/utils/403'; import { apiWrapper } from '@/utils/api'; import { isNodeTypeARegistryTagType, isNodeTypeARegistryType } from '@/utils/registry'; -const getPackages = () => [ +const binaries = [ { - name: 'OS Packages', + name: 'Golang binary', + dependent: ModelVulnerabilityScanConfigLanguageLanguageEnum.Golang, checked: false, - value: ModelVulnerabilityScanConfigLanguageLanguageEnum.Base, + value: ModelVulnerabilityScanConfigLanguageLanguageEnum.GolangBinary, }, { - name: 'Java', + name: 'Rust binary', + dependent: ModelVulnerabilityScanConfigLanguageLanguageEnum.Rust, checked: false, - value: ModelVulnerabilityScanConfigLanguageLanguageEnum.Java, - }, - { - name: 'Javascript', - checked: false, - value: ModelVulnerabilityScanConfigLanguageLanguageEnum.Javascript, - }, - { - name: 'Rust', - checked: false, - value: ModelVulnerabilityScanConfigLanguageLanguageEnum.Rust, - }, - { - name: 'GoLang', - checked: false, - value: ModelVulnerabilityScanConfigLanguageLanguageEnum.Golang, - }, - { - name: 'Ruby', - checked: false, - value: ModelVulnerabilityScanConfigLanguageLanguageEnum.Ruby, - }, - { - name: 'Python', - checked: false, - value: ModelVulnerabilityScanConfigLanguageLanguageEnum.Python, - }, - { - name: 'PHP', - checked: false, - value: ModelVulnerabilityScanConfigLanguageLanguageEnum.Php, - }, - { - name: 'Dotnet', - checked: false, - value: ModelVulnerabilityScanConfigLanguageLanguageEnum.Dotnet, + value: ModelVulnerabilityScanConfigLanguageLanguageEnum.RustBinary, }, ]; +const getPackages = () => { + return [ + { + name: 'OS Packages', + checked: true, + value: ModelVulnerabilityScanConfigLanguageLanguageEnum.Base, + }, + { + name: 'Java', + checked: false, + value: ModelVulnerabilityScanConfigLanguageLanguageEnum.Java, + }, + { + name: 'Javascript', + checked: false, + value: ModelVulnerabilityScanConfigLanguageLanguageEnum.Javascript, + }, + { + name: 'Rust', + checked: false, + value: ModelVulnerabilityScanConfigLanguageLanguageEnum.Rust, + }, + { + name: 'GoLang', + checked: false, + value: ModelVulnerabilityScanConfigLanguageLanguageEnum.Golang, + }, + { + name: 'Ruby', + checked: false, + value: ModelVulnerabilityScanConfigLanguageLanguageEnum.Ruby, + }, + { + name: 'Python', + checked: false, + value: ModelVulnerabilityScanConfigLanguageLanguageEnum.Python, + }, + { + name: 'PHP', + checked: false, + value: ModelVulnerabilityScanConfigLanguageLanguageEnum.Php, + }, + { + name: 'Dotnet', + checked: false, + value: ModelVulnerabilityScanConfigLanguageLanguageEnum.Dotnet, + }, + ]; +}; + export type VulnerabilityScanConfigureFormProps = { showAdvancedOptions: boolean; data: @@ -105,6 +122,7 @@ export const scanVulnerabilityApiAction = async ({ const imageTag = formData.get('imageTag')?.toString() ?? ''; const packages = formData.getAll('packages'); + const binaries = formData.getAll('binaries'); let filter_in = null; let _nodeType = nodeType; @@ -132,7 +150,24 @@ export const scanVulnerabilityApiAction = async ({ }; } } + let languagesSelected: { + language: ModelVulnerabilityScanConfigLanguageLanguageEnum; + }[] = []; + if (selectAll !== 'all') { + languagesSelected = packages.map((pkg) => ({ + language: pkg as unknown as ModelVulnerabilityScanConfigLanguageLanguageEnum, + })); + if (binaries.length) { + (binaries as ModelVulnerabilityScanConfigLanguageLanguageEnum[]).forEach( + (binary) => { + languagesSelected.push({ + language: binary, + }); + }, + ); + } + } const requestBody: ModelVulnerabilityScanTriggerReq = { filters: { cloud_account_scan_filter: { filter_in: null }, @@ -149,19 +184,18 @@ export const scanVulnerabilityApiAction = async ({ })), scan_config: selectAll === 'all' - ? [ - { - language: ModelVulnerabilityScanConfigLanguageLanguageEnum.All, - }, - ] - : packages.map((pkg) => ({ - language: pkg as unknown as ModelVulnerabilityScanConfigLanguageLanguageEnum, - })), + ? (packages as ModelVulnerabilityScanConfigLanguageLanguageEnum[]).map((name) => { + return { + language: name, + }; + }) + : languagesSelected, }; const startVulnerabilityScanApi = apiWrapper({ fn: getVulnerabilityApiClient().startVulnerabilityScan, }); + const startVulnerabilityScanResponse = await startVulnerabilityScanApi({ modelVulnerabilityScanTriggerReq: requestBody, }); @@ -230,8 +264,16 @@ export const VulnerabilityScanConfigureForm = ({ onCancel, showAdvancedOptions: wantAdvanceOptions, }: VulnerabilityScanConfigureFormProps) => { - const [pkgs, setSelectPackages] = useState(getPackages()); + const [pkgs, setSelectPackages] = useState(() => getPackages()); const [isSelectAll, setIsSelectAll] = useState(false); + const [binaryPkgs, setBinaryPkgs] = useState< + { + dependent: string; + name: string; + checked: boolean; + value: string; + }[] + >([]); const fetcher = useFetcher(); const { state, data: fetcherData } = fetcher; @@ -263,9 +305,14 @@ export const VulnerabilityScanConfigureForm = ({ return pkg; }); setSelectPackages(newPkgs); + setBinaryPkgs(binaries); } else { const newPkgs = pkgs.map((pkg) => { pkg.checked = false; + if (pkg.value === ModelVulnerabilityScanConfigLanguageLanguageEnum.Base) { + pkg.checked = true; + } + setBinaryPkgs([]); return pkg; }); setSelectPackages(newPkgs); @@ -277,18 +324,74 @@ export const VulnerabilityScanConfigureForm = ({ pkg: { name: string; checked: boolean; + value: string; }, checked: boolean, ) => { + let newBinaries: { + name: string; + dependent: string; + checked: boolean; + value: string; + }[] = binaryPkgs; const _newState = pkgs.map((state) => { - if (state.name === pkg.name) { - state.checked = checked; + if (state.value === pkg.value) { + if ( + state.value === pkg.value && + pkg.value === ModelVulnerabilityScanConfigLanguageLanguageEnum.Base + ) { + state.checked = true; + } else { + state.checked = checked; + } + } + + if (state.value === pkg.value) { + const foundBinaryDependent = binaries.find((binary) => { + return binary.dependent === pkg.value; + }); + if (pkg.checked) { + if (foundBinaryDependent) { + // for registry scan include binaries when dependent is included + if (isNodeTypeRegistryType) { + foundBinaryDependent.checked = true; + } + newBinaries.push(foundBinaryDependent); + } + } else { + if (foundBinaryDependent) { + newBinaries = newBinaries.filter((binary) => { + return binary.dependent !== pkg.value; + }); + } + } } return state; }); setSelectPackages(_newState); + setBinaryPkgs(newBinaries); }; + // binaries checkbox + const onBinaryCheckedChange = ( + binary: { + name: string; + dependent: string; + checked: boolean; + value: string; + }, + checked: boolean, + ) => { + const _newState = binaryPkgs.map((state) => { + if (state.value === binary.value) { + state.checked = checked; + } + return state; + }); + setBinaryPkgs(_newState); + }; + const isNodeTypeRegistryType = + data.nodeType === 'registry' || isNodeTypeARegistryType(data.nodeType); return ( + {binaryPkgs.length > 0 ? ( + <> +
+ Select binaries + {!isNodeTypeRegistryType && ( + + (binaries scan will consume higher memory) + + )} +
+
+ {binaryPkgs.map((binary) => { + return ( + { + onBinaryCheckedChange(binary, checked); + }} + /> + ); + })} +
+ + ) : null} {wantAdvanceOptions && ( 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 0e897ce0f5..b766d19369 100644 --- a/deepfence_frontend/apps/dashboard/src/features/integrations/components/useIntegrationTableColumn.tsx +++ b/deepfence_frontend/apps/dashboard/src/features/integrations/components/useIntegrationTableColumn.tsx @@ -1,10 +1,11 @@ import { isEmpty } from 'lodash-es'; import { useMemo } from 'react'; import { useParams } from 'react-router-dom'; -import { createColumnHelper, Dropdown, DropdownItem } from 'ui-components'; +import { createColumnHelper, Dropdown, DropdownItem, Tooltip } from 'ui-components'; import { ModelIntegrationListResp } from '@/api/generated'; import { EllipsisIcon } from '@/components/icons/common/Ellipsis'; +import { ErrorIcon, SuccessIcon } from '@/components/icons/common/ScanStatuses'; import { TruncatedText } from '@/components/TruncatedText'; import { ActionEnumType } from '@/features/integrations/pages/IntegrationAdd'; @@ -473,6 +474,38 @@ export const useIntegrationTableColumn = ( size: 70, maxSize: 75, }), + columnHelper.accessor('last_error_msg', { + cell: (cell) => { + const isError = + cell.row.original?.last_error_msg && + cell.row.original?.last_error_msg?.trim()?.length > 0; + return ( +
+ {isError ? ( + +
+ + + + Error +
+
+ ) : ( +
+ + + + Active +
+ )} +
+ ); + }, + header: () => 'Status', + minSize: 65, + size: 70, + maxSize: 75, + }), ...getDynamicTableColumns(), ]; return columns;