diff --git a/Makefile b/Makefile index 637a648dcf..5c8b372494 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ export DEEPFENCE_FARGATE_DIR=$(DEEPFENCE_AGENT_DIR)/fargate export IMAGE_REPOSITORY?=deepfenceio export DF_IMG_TAG?=latest export IS_DEV_BUILD?=false -export VERSION?="2.1.0" +export VERSION?="2.1.1" default: bootstrap console_plugins agent console fargate-local diff --git a/deepfence_agent/fargate/Dockerfile.fargate b/deepfence_agent/fargate/Dockerfile.fargate index 1a7d6d67f9..0b14fea9af 100644 --- a/deepfence_agent/fargate/Dockerfile.fargate +++ b/deepfence_agent/fargate/Dockerfile.fargate @@ -115,7 +115,7 @@ LABEL deepfence.role=system WORKDIR / -COPY fargate/deepfence-agent-bin-2.1.0 /deepfence +COPY fargate/deepfence-agent-bin-2.1.1 /deepfence COPY fargate/deepfence-entry-point-scratch.sh deepfence/usr/local/bin/deepfence-entry-point-scratch.sh COPY --from=builder /tmp/rootfs/bin/curl /deepfence/bin/curl diff --git a/deepfence_agent/tools/apache/scope/probe/host/reporter.go b/deepfence_agent/tools/apache/scope/probe/host/reporter.go index cebe686a68..47113c3172 100644 --- a/deepfence_agent/tools/apache/scope/probe/host/reporter.go +++ b/deepfence_agent/tools/apache/scope/probe/host/reporter.go @@ -10,6 +10,7 @@ import ( "sync" "time" + "github.com/deepfence/ThreatMapper/deepfence_utils/log" dfUtils "github.com/deepfence/df-utils" "github.com/deepfence/df-utils/cloud_metadata" "github.com/weaveworks/scope/report" @@ -107,6 +108,8 @@ func getCloudMetadata(cloudProvider string) (string, cloud_metadata.CloudMetadat func (r *Reporter) updateCloudMetadata(cloudProvider string) { cloudProvider, cloudMetadata := getCloudMetadata(cloudProvider) + log.Info().Msgf("Cloud metadata: %v", cloudMetadata) + r.cloudMeta.mtx.Lock() r.cloudMeta.cloudProvider = cloudProvider r.cloudMeta.cloudMetadata = cloudMetadata diff --git a/deepfence_agent/tools/apache/scope/probe/kubernetes/kubernetes_cluster.go b/deepfence_agent/tools/apache/scope/probe/kubernetes/kubernetes_cluster.go index 50a0507ed9..71897f934e 100644 --- a/deepfence_agent/tools/apache/scope/probe/kubernetes/kubernetes_cluster.go +++ b/deepfence_agent/tools/apache/scope/probe/kubernetes/kubernetes_cluster.go @@ -1,8 +1,10 @@ package kubernetes import ( + "sync" "time" + "github.com/deepfence/ThreatMapper/deepfence_utils/log" "github.com/deepfence/df-utils/cloud_metadata" "github.com/weaveworks/scope/report" ) @@ -10,20 +12,61 @@ import ( // KubernetesClusterResource represents a Kubernetes cluster type KubernetesClusterResource interface { GetNode() report.TopologyNode + GetTopology() report.Topology + Stop() } type kubernetesCluster struct { - cloudProvider string - cloudAccountID string + k8sTopology report.Topology + stopRefresh chan bool + sync.RWMutex } // NewKubernetesClusterResource creates a new Cluster node func NewKubernetesClusterResource() KubernetesClusterResource { - metadata := cloud_metadata.GetCloudMetadata() - return &kubernetesCluster{cloudProvider: metadata.CloudProvider, cloudAccountID: metadata.AccountID} + k8sCluster := kubernetesCluster{stopRefresh: make(chan bool)} + k8sCluster.cacheK8sTopology() + go k8sCluster.refresh() + return &k8sCluster +} + +func (k *kubernetesCluster) Stop() { + k.stopRefresh <- true +} + +func (k *kubernetesCluster) refresh() { + ticker := time.NewTicker(6 * time.Hour) + for { + select { + case <-ticker.C: + k.cacheK8sTopology() + case <-k.stopRefresh: + return + } + } +} + +func (k *kubernetesCluster) cacheK8sTopology() { + k.Lock() + defer k.Unlock() + + k.k8sTopology = report.MakeTopology() + node := k.GetNode() + //cloudProviderNodeId = node.Parents.CloudProvider + k.k8sTopology.AddNode(node) +} + +func (k *kubernetesCluster) GetTopology() report.Topology { + k.RLock() + defer k.RUnlock() + + return k.k8sTopology } func (k *kubernetesCluster) GetNode() report.TopologyNode { + cloudMetadata := cloud_metadata.GetCloudMetadata() + log.Info().Msgf("Cloud metadata: %v", cloudMetadata) + metadata := report.Metadata{ Timestamp: time.Now().UTC().Format(time.RFC3339Nano), NodeID: kubernetesClusterId, @@ -31,14 +74,14 @@ func (k *kubernetesCluster) GetNode() report.TopologyNode { NodeType: report.KubernetesCluster, KubernetesClusterId: kubernetesClusterId, KubernetesClusterName: kubernetesClusterName, - CloudProvider: k.cloudProvider, + CloudProvider: cloudMetadata.CloudProvider, AgentRunning: true, - CloudAccountID: k.cloudAccountID, + CloudAccountID: cloudMetadata.AccountID, } return report.TopologyNode{ Metadata: metadata, Parents: &report.Parent{ - CloudProvider: k.cloudProvider, + CloudProvider: cloudMetadata.CloudProvider, }, } } diff --git a/deepfence_agent/tools/apache/scope/probe/kubernetes/namespace.go b/deepfence_agent/tools/apache/scope/probe/kubernetes/namespace.go index 42897db6d2..356105ad5f 100644 --- a/deepfence_agent/tools/apache/scope/probe/kubernetes/namespace.go +++ b/deepfence_agent/tools/apache/scope/probe/kubernetes/namespace.go @@ -27,7 +27,7 @@ func (ns *namespace) GetNode() report.TopologyNode { return report.TopologyNode{ Metadata: ns.MetaNode(kubernetesClusterId+"-"+ns.Name(), report.Namespace), Parents: &report.Parent{ - CloudProvider: cloudProviderNodeId, + //CloudProvider: cloudProviderNodeId, KubernetesCluster: kubernetesClusterId, }, } diff --git a/deepfence_agent/tools/apache/scope/probe/kubernetes/pod.go b/deepfence_agent/tools/apache/scope/probe/kubernetes/pod.go index 02b6ab54e2..e25c5d93c3 100644 --- a/deepfence_agent/tools/apache/scope/probe/kubernetes/pod.go +++ b/deepfence_agent/tools/apache/scope/probe/kubernetes/pod.go @@ -106,7 +106,7 @@ func (p *pod) GetNode() report.TopologyNode { return report.TopologyNode{ Metadata: metadata, Parents: &report.Parent{ - CloudProvider: cloudProviderNodeId, + //CloudProvider: cloudProviderNodeId, KubernetesCluster: kubernetesClusterId, Host: hostname, Namespace: kubernetesClusterId + "-" + p.GetNamespace(), diff --git a/deepfence_agent/tools/apache/scope/probe/kubernetes/reporter.go b/deepfence_agent/tools/apache/scope/probe/kubernetes/reporter.go index 6cb0db8993..deabceb30a 100644 --- a/deepfence_agent/tools/apache/scope/probe/kubernetes/reporter.go +++ b/deepfence_agent/tools/apache/scope/probe/kubernetes/reporter.go @@ -20,17 +20,16 @@ const ( var ( kubernetesClusterId string kubernetesClusterName string - cloudProviderNodeId string ) // Reporter generate Reports containing Container and ContainerImage topologies type Reporter struct { - client Client - probeID string - probe *probe.Probe - hostID string - nodeName string - k8sClusterTopology report.Topology + client Client + probeID string + probe *probe.Probe + hostID string + nodeName string + kubernetesClusterResource KubernetesClusterResource } // NewReporter makes a new Reporter @@ -39,19 +38,20 @@ func NewReporter(client Client, probeID string, hostID string, probe *probe.Prob kubernetesClusterName = os.Getenv(k8sClusterName) reporter := &Reporter{ - client: client, - probeID: probeID, - probe: probe, - hostID: hostID, - nodeName: nodeName, + client: client, + probeID: probeID, + probe: probe, + hostID: hostID, + nodeName: nodeName, + kubernetesClusterResource: NewKubernetesClusterResource(), } - reporter.k8sClusterTopology = reporter.kubernetesClusterTopology() //client.WatchPods(reporter.podEvent) return reporter } // Stop unregisters controls. func (r *Reporter) Stop() { + r.kubernetesClusterResource.Stop() } // Name of this reporter, for metrics gathering @@ -143,21 +143,13 @@ func (r *Reporter) Report() (report.Report, error) { if err != nil { return result, err } - result.KubernetesCluster.Merge(r.k8sClusterTopology) + result.KubernetesCluster.Merge(r.kubernetesClusterResource.GetTopology()) result.Pod.Merge(podTopology) result.Service.Merge(serviceTopology) result.Namespace.Merge(namespaceTopology) return result, nil } -func (r *Reporter) kubernetesClusterTopology() report.Topology { - result := report.MakeTopology() - node := NewKubernetesClusterResource().GetNode() - cloudProviderNodeId = node.Parents.CloudProvider - result.AddNode(node) - return result -} - func (r *Reporter) serviceTopology() (report.Topology, []Service, error) { var ( result = report.MakeTopology() diff --git a/deepfence_agent/tools/apache/scope/probe/kubernetes/service.go b/deepfence_agent/tools/apache/scope/probe/kubernetes/service.go index cd1376911a..8e8e6b7024 100644 --- a/deepfence_agent/tools/apache/scope/probe/kubernetes/service.go +++ b/deepfence_agent/tools/apache/scope/probe/kubernetes/service.go @@ -75,7 +75,7 @@ func (s *service) GetNode() report.TopologyNode { return report.TopologyNode{ Metadata: metadata, Parents: &report.Parent{ - CloudProvider: cloudProviderNodeId, + //CloudProvider: cloudProviderNodeId, KubernetesCluster: kubernetesClusterId, Namespace: kubernetesClusterId + "-" + s.GetNamespace(), }, diff --git a/deepfence_frontend/apps/dashboard/api-spec.json b/deepfence_frontend/apps/dashboard/api-spec.json index 1bac005608..5e3ec8e04e 100644 --- a/deepfence_frontend/apps/dashboard/api-spec.json +++ b/deepfence_frontend/apps/dashboard/api-spec.json @@ -13678,6 +13678,11 @@ "required": ["node_ids"], "type": "object", "properties": { + "container_names": { + "type": "array", + "items": { "type": "string" }, + "nullable": true + }, "fields_filters": { "$ref": "#/components/schemas/ReportersFieldsFilters" }, "node_ids": { "type": "array", @@ -14107,10 +14112,11 @@ } }, "ModelRegistryImagesReq": { - "required": ["registry_id", "image_filter", "window"], + "required": ["registry_id", "image_filter", "image_stub_filter", "window"], "type": "object", "properties": { "image_filter": { "$ref": "#/components/schemas/ReportersFieldsFilters" }, + "image_stub_filter": { "$ref": "#/components/schemas/ReportersFieldsFilters" }, "registry_id": { "type": "string" }, "window": { "$ref": "#/components/schemas/ModelFetchWindow" } } @@ -15282,7 +15288,12 @@ "type": "object", "properties": { "sbom_format": { - "enum": ["syft-json@11.0.1", "cyclonedx-json@1.5", "spdx-json@2.3"], + "enum": [ + "syft-json@11.0.1", + "cyclonedx-json@1.5", + "spdx-json@2.2", + "spdx-json@2.3" + ], "type": "string" } } diff --git a/deepfence_frontend/apps/dashboard/src/api/generated/models/ModelRegistryImagesReq.ts b/deepfence_frontend/apps/dashboard/src/api/generated/models/ModelRegistryImagesReq.ts index 2208152307..0996e7d57a 100644 --- a/deepfence_frontend/apps/dashboard/src/api/generated/models/ModelRegistryImagesReq.ts +++ b/deepfence_frontend/apps/dashboard/src/api/generated/models/ModelRegistryImagesReq.ts @@ -38,6 +38,12 @@ export interface ModelRegistryImagesReq { * @memberof ModelRegistryImagesReq */ image_filter: ReportersFieldsFilters; + /** + * + * @type {ReportersFieldsFilters} + * @memberof ModelRegistryImagesReq + */ + image_stub_filter: ReportersFieldsFilters; /** * * @type {string} @@ -58,6 +64,7 @@ export interface ModelRegistryImagesReq { export function instanceOfModelRegistryImagesReq(value: object): boolean { let isInstance = true; isInstance = isInstance && "image_filter" in value; + isInstance = isInstance && "image_stub_filter" in value; isInstance = isInstance && "registry_id" in value; isInstance = isInstance && "window" in value; @@ -75,6 +82,7 @@ export function ModelRegistryImagesReqFromJSONTyped(json: any, ignoreDiscriminat return { 'image_filter': ReportersFieldsFiltersFromJSON(json['image_filter']), + 'image_stub_filter': ReportersFieldsFiltersFromJSON(json['image_stub_filter']), 'registry_id': json['registry_id'], 'window': ModelFetchWindowFromJSON(json['window']), }; @@ -90,6 +98,7 @@ export function ModelRegistryImagesReqToJSON(value?: ModelRegistryImagesReq | nu return { 'image_filter': ReportersFieldsFiltersToJSON(value.image_filter), + 'image_stub_filter': ReportersFieldsFiltersToJSON(value.image_stub_filter), 'registry_id': value.registry_id, 'window': ModelFetchWindowToJSON(value.window), }; diff --git a/deepfence_frontend/apps/dashboard/src/api/generated/models/UtilsReportOptions.ts b/deepfence_frontend/apps/dashboard/src/api/generated/models/UtilsReportOptions.ts index f48ba79dea..ec12c13d07 100644 --- a/deepfence_frontend/apps/dashboard/src/api/generated/models/UtilsReportOptions.ts +++ b/deepfence_frontend/apps/dashboard/src/api/generated/models/UtilsReportOptions.ts @@ -34,6 +34,7 @@ export interface UtilsReportOptions { export const UtilsReportOptionsSbomFormatEnum = { SyftJson1101: 'syft-json@11.0.1', CyclonedxJson15: 'cyclonedx-json@1.5', + SpdxJson22: 'spdx-json@2.2', SpdxJson23: 'spdx-json@2.3' } as const; export type UtilsReportOptionsSbomFormatEnum = typeof UtilsReportOptionsSbomFormatEnum[keyof typeof UtilsReportOptionsSbomFormatEnum]; diff --git a/deepfence_frontend/apps/dashboard/src/components/forms/CompareScanInputModal.tsx b/deepfence_frontend/apps/dashboard/src/components/forms/CompareScanInputModal.tsx index 5a677b48af..505f06f90d 100644 --- a/deepfence_frontend/apps/dashboard/src/components/forms/CompareScanInputModal.tsx +++ b/deepfence_frontend/apps/dashboard/src/components/forms/CompareScanInputModal.tsx @@ -136,7 +136,7 @@ const InputForm = ({ valueKey="nodeId" onChange={(data: ISelected) => { setToScanData({ - toScanTime: data.updatedAt, + toScanTime: data.createdAt, toScanId: data.scanId, }); }} @@ -153,7 +153,7 @@ const InputForm = ({ valueKey="nodeId" onChange={(data: ISelected) => { setToScanData({ - toScanTime: data.updatedAt, + toScanTime: data.createdAt, toScanId: data.scanId, }); }} @@ -183,7 +183,7 @@ export const CompareScanInputModal = ({ showDialog: boolean; setShowDialog: React.Dispatch>; scanHistoryData: { - updatedAt: number; + createdAt: number; scanId: string; status: string; }[]; @@ -238,12 +238,12 @@ export const CompareScanInputModal = ({ disabled={!toScanData.toScanTime} onClick={() => { const baseScan = scanHistoryData.find((data) => { - return data.updatedAt === compareInput.baseScanTime; + return data.createdAt === compareInput.baseScanTime; }); setCompareInput({ baseScanId: baseScan?.scanId ?? '', toScanId: toScanData?.toScanId ?? '', - baseScanTime: baseScan?.updatedAt ?? 0, + baseScanTime: baseScan?.createdAt ?? 0, toScanTime: toScanData?.toScanTime ?? 0, showScanTimeModal: false, }); diff --git a/deepfence_frontend/apps/dashboard/src/components/forms/ScanTimeList.tsx b/deepfence_frontend/apps/dashboard/src/components/forms/ScanTimeList.tsx index 95f8422e4d..394dfe0462 100644 --- a/deepfence_frontend/apps/dashboard/src/components/forms/ScanTimeList.tsx +++ b/deepfence_frontend/apps/dashboard/src/components/forms/ScanTimeList.tsx @@ -23,7 +23,7 @@ interface TimeListProps { } export interface ISelected { - updatedAt: number; + createdAt: number; scanId: string; } @@ -91,7 +91,7 @@ const ScanTime = ({ placeholder="Scan time" value={selectedTime as unknown as ISelected} onChange={(value: ISelected) => { - setSelectedTime(value.updatedAt); + setSelectedTime(value.createdAt); onChange?.(value); }} clearAll="Clear" @@ -109,20 +109,21 @@ const ScanTime = ({ return page.data; }) .filter( - (scan) => scan.updatedAt !== skipScanTime && isScanComplete(scan.status), + (scan) => scan.createdAt !== skipScanTime && isScanComplete(scan.status), ) + .reverse() ?.map?.((scan) => { return ( - {formatMilliseconds(scan.updatedAt)} + {formatMilliseconds(scan.createdAt)} ); })} diff --git a/deepfence_frontend/apps/dashboard/src/features/malwares/pages/MalwareScanResults.tsx b/deepfence_frontend/apps/dashboard/src/features/malwares/pages/MalwareScanResults.tsx index f80357ddd1..6c36bb7ca3 100644 --- a/deepfence_frontend/apps/dashboard/src/features/malwares/pages/MalwareScanResults.tsx +++ b/deepfence_frontend/apps/dashboard/src/features/malwares/pages/MalwareScanResults.tsx @@ -585,7 +585,7 @@ const HistoryControls = () => { const [isSubmitting, setIsSubmitting] = useState(false); const { data, fetchStatus } = useScanResults(); const { scanStatusResult } = data; - const { scan_id, node_id, node_type, updated_at, status } = scanStatusResult ?? {}; + const { scan_id, node_id, node_type, created_at, status } = scanStatusResult ?? {}; const { navigate, goBack } = usePageNavigation(); const { downloadScan } = useDownloadScan((state) => { setIsSubmitting(state === 'submitting'); @@ -604,7 +604,7 @@ const HistoryControls = () => { }>({ baseScanId: '', toScanId: '', - baseScanTime: updated_at ?? 0, + baseScanTime: created_at ?? 0, toScanTime: 0, showScanTimeModal: false, }); @@ -625,7 +625,7 @@ const HistoryControls = () => { if (!scan_id || !node_id || !node_type) { throw new Error('Scan Type, Node Type and Node Id are required'); } - if (!updated_at) { + if (!created_at) { return null; } @@ -680,7 +680,7 @@ const HistoryControls = () => { id: item.scanId, isCurrent: item.scanId === scan_id, status: item.status, - timestamp: item.updatedAt, + timestamp: item.createdAt, showScanCompareButton: true, onScanTimeCompareButtonClick: onCompareScanClick, onDeleteClick: (id) => { @@ -704,7 +704,7 @@ const HistoryControls = () => { ); }, }))} - currentTimeStamp={formatMilliseconds(updated_at)} + currentTimeStamp={formatMilliseconds(created_at)} /> {scanIdToDelete && ( @@ -784,7 +784,7 @@ const HistoryControls = () => { onClick={() => { setCompareInput({ ...compareInput, - baseScanTime: updated_at ?? 0, + baseScanTime: created_at ?? 0, showScanTimeModal: true, }); }} diff --git a/deepfence_frontend/apps/dashboard/src/features/malwares/pages/MalwareScans.tsx b/deepfence_frontend/apps/dashboard/src/features/malwares/pages/MalwareScans.tsx index dfa73cf7ed..7223dfda1a 100644 --- a/deepfence_frontend/apps/dashboard/src/features/malwares/pages/MalwareScans.tsx +++ b/deepfence_frontend/apps/dashboard/src/features/malwares/pages/MalwareScans.tsx @@ -78,7 +78,9 @@ export interface FocusableElement { } enum ActionEnumType { - DELETE = 'delete', + DELETE_SCAN = 'delete_scan', + CANCEL_SCAN = 'cancel_scan', + START_SCAN = 'start_scan,', } const DEFAULT_PAGE_SIZE = 10; @@ -109,7 +111,7 @@ const action = async ({ throw new Error('Invalid action'); } - if (actionType === ActionEnumType.DELETE) { + if (actionType === ActionEnumType.DELETE_SCAN) { const resultApi = apiWrapper({ fn: getScanResultsApiClient().bulkDeleteScans, }); @@ -180,7 +182,7 @@ const DeleteConfirmationModal = ({ if ( fetcher.state === 'idle' && fetcher.data?.success && - fetcher.data.action === ActionEnumType.DELETE + fetcher.data.action === ActionEnumType.DELETE_SCAN ) { onDeleteSuccess(); } @@ -219,7 +221,7 @@ const DeleteConfirmationModal = ({ disabled={fetcher.state === 'submitting'} onClick={(e) => { e.preventDefault(); - onDeleteAction(ActionEnumType.DELETE); + onDeleteAction(ActionEnumType.DELETE_SCAN); }} > Delete @@ -247,9 +249,11 @@ const DeleteConfirmationModal = ({ const ActionDropdown = ({ trigger, row, + onTableAction, }: { trigger: React.ReactNode; row: ModelScanInfo; + onTableAction: (row: ModelScanInfo, actionType: ActionEnumType) => void; }) => { const fetcher = useFetcher(); const [open, setOpen] = useState(false); @@ -257,15 +261,13 @@ const ActionDropdown = ({ const { downloadScan } = useDownloadScan((state) => { setIsSubmitting(state === 'submitting'); }); - const [openStopScanModal, setOpenStopScanModal] = useState(false); - const [showDeleteDialog, setShowDeleteDialog] = useState(false); const { scan_id: scanId, node_id: nodeId, node_type: nodeType, status: scanStatus, } = row; - const [showStartScan, setShowStartScan] = useState(false); + const onDownloadAction = useCallback(() => { downloadScan({ scanId, @@ -280,45 +282,6 @@ const ActionDropdown = ({ return ( <> - {openStopScanModal && ( - - )} - - {showDeleteDialog && ( - { - // - }} - /> - )} - {showStartScan && ( - setShowStartScan(false)} - scanOptions={ - { - showAdvancedOptions: true, - scanType: ScanTypeEnum.MalwareScan, - data: { - nodes: [ - { - nodeId, - nodeType, - }, - ], - }, - } as ConfigureScanModalProps['scanOptions'] - } - /> - )} { e.preventDefault(); if (isScanInProgress(scanStatus)) return; - setShowStartScan(true); + onTableAction(row, ActionEnumType.START_SCAN); }} disabled={isScanInProgress(scanStatus) || isScanStopping(scanStatus)} > @@ -351,7 +314,7 @@ const ActionDropdown = ({ { e.preventDefault(); - setOpenStopScanModal(true); + onTableAction(row, ActionEnumType.CANCEL_SCAN); }} disabled={!isScanInProgress(scanStatus)} > @@ -360,7 +323,7 @@ const ActionDropdown = ({ { if (!scanId || !nodeType) return; - setShowDeleteDialog(true); + onTableAction(row, ActionEnumType.DELETE_SCAN); }} > @@ -688,9 +651,11 @@ const Filters = () => { const ScansTable = ({ rowSelectionState, setRowSelectionState, + onTableAction, }: { rowSelectionState: RowSelectionState; setRowSelectionState: React.Dispatch>; + onTableAction: (row: ModelScanInfo, actionType: ActionEnumType) => void; }) => { const [searchParams, setSearchParams] = useSearchParams(); const { data } = useSuspenseQuery({ @@ -729,6 +694,7 @@ const ScansTable = ({ cell: (cell) => ( @@ -783,7 +749,7 @@ const ScansTable = ({ size: 240, maxSize: 250, }), - columnHelper.accessor('updated_at', { + columnHelper.accessor('created_at', { cell: (info) => , header: () => , minSize: 140, @@ -1035,7 +1001,7 @@ const ScansTable = ({ const BulkActions = ({ selectedRows, - setRowSelectionState, + onBulkAction, }: { selectedRows: { scanId: string; @@ -1043,11 +1009,18 @@ const BulkActions = ({ nodeType: string; scanStatus: string; }[]; - setRowSelectionState: React.Dispatch>; + onBulkAction: ( + data: { + scanIdsToCancelScan: string[]; + scanIdsToDeleteScan: string[]; + nodesToStartScan: { + nodeId: string; + nodeType: string; + }[]; + }, + actionType: ActionEnumType, + ) => void; }) => { - const [openStartScan, setOpenStartScan] = useState(false); - const [showDeleteDialog, setShowDeleteDialog] = useState(false); - const [showCancelScanDialog, setShowCancelScanDialog] = useState(false); const nodesToStartScan = useMemo(() => { return selectedRows .filter( @@ -1075,50 +1048,20 @@ const BulkActions = ({ return ( <> - {openStartScan && ( - setOpenStartScan(false)} - onSuccess={() => setRowSelectionState({})} - scanOptions={ - { - showAdvancedOptions: true, - scanType: ScanTypeEnum.MalwareScan, - data: { - nodes: nodesToStartScan, - }, - } as ConfigureScanModalProps['scanOptions'] - } - /> - )} - {showDeleteDialog && ( - { - setRowSelectionState({}); - }} - /> - )} - {showCancelScanDialog ? ( - { - setRowSelectionState({}); - }} - /> - ) : null} @@ -1139,7 +1091,14 @@ const BulkActions = ({ size="sm" disabled={scanIdsToDeleteScan.length === 0} onClick={() => { - setShowDeleteDialog(true); + onBulkAction( + { + scanIdsToCancelScan: [], + scanIdsToDeleteScan, + nodesToStartScan: [], + }, + ActionEnumType.DELETE_SCAN, + ); }} > Delete Scan @@ -1154,9 +1113,12 @@ const MalwareScans = () => { queryKey: queries.malware.scanList._def, }); const [filtersExpanded, setFiltersExpanded] = useState(false); - const [rowSelectionState, setRowSelectionState] = useState({}); + const [openStartScan, setOpenStartScan] = useState(false); + const [showDeleteDialog, setShowDeleteDialog] = useState(false); + const [showCancelScanDialog, setShowCancelScanDialog] = useState(false); + const selectedRows = useMemo< { scanId: string; @@ -1170,8 +1132,116 @@ const MalwareScans = () => { }); }, [rowSelectionState]); + const [rowToAction, setRowToAction] = useState<{ + scanIdsToCancelScan: string[]; + scanIdsToDeleteScan: string[]; + nodesToStartScan: { + nodeId: string; + nodeType: string; + }[]; + }>({ + scanIdsToCancelScan: [], + scanIdsToDeleteScan: [], + nodesToStartScan: [], + }); + + const onTableAction = (row: ModelScanInfo, actionType: string) => { + if (actionType === ActionEnumType.DELETE_SCAN) { + setRowToAction({ + scanIdsToCancelScan: [], + scanIdsToDeleteScan: [row.scan_id], + nodesToStartScan: [], + }); + setShowDeleteDialog(true); + } else if (actionType === ActionEnumType.CANCEL_SCAN) { + setRowToAction({ + scanIdsToCancelScan: [row.scan_id], + scanIdsToDeleteScan: [], + nodesToStartScan: [], + }); + setShowCancelScanDialog(true); + } else if (actionType === ActionEnumType.START_SCAN) { + setRowToAction({ + scanIdsToCancelScan: [], + scanIdsToDeleteScan: [], + nodesToStartScan: [ + { + nodeId: row.node_id, + nodeType: row.node_type, + }, + ], + }); + setOpenStartScan(true); + } + }; + + const onBulkAction = ( + data: { + scanIdsToCancelScan: string[]; + scanIdsToDeleteScan: string[]; + nodesToStartScan: { + nodeId: string; + nodeType: string; + }[]; + }, + actionType: string, + ) => { + setRowToAction({ + scanIdsToCancelScan: data.scanIdsToCancelScan, + scanIdsToDeleteScan: data.scanIdsToDeleteScan, + nodesToStartScan: data.nodesToStartScan, + }); + if (actionType === ActionEnumType.DELETE_SCAN) { + setShowDeleteDialog(true); + } else if (actionType === ActionEnumType.CANCEL_SCAN) { + setShowCancelScanDialog(true); + } else if (actionType === ActionEnumType.START_SCAN) { + setOpenStartScan(true); + } + }; + return (
+ <> + {openStartScan && ( + setOpenStartScan(false)} + onSuccess={() => setRowSelectionState({})} + scanOptions={ + { + showAdvancedOptions: true, + scanType: ScanTypeEnum.MalwareScan, + data: { + nodes: rowToAction?.nodesToStartScan, + }, + } as ConfigureScanModalProps['scanOptions'] + } + /> + )} + {showDeleteDialog && ( + { + setRowSelectionState({}); + }} + /> + )} + {showCancelScanDialog ? ( + { + setRowSelectionState({}); + }} + /> + ) : null} + +
} isLink> @@ -1191,10 +1261,7 @@ const MalwareScans = () => {
- +
diff --git a/deepfence_frontend/apps/dashboard/src/features/postures/pages/Accounts.tsx b/deepfence_frontend/apps/dashboard/src/features/postures/pages/Accounts.tsx index 6df95e923a..da2cbd5282 100644 --- a/deepfence_frontend/apps/dashboard/src/features/postures/pages/Accounts.tsx +++ b/deepfence_frontend/apps/dashboard/src/features/postures/pages/Accounts.tsx @@ -58,7 +58,10 @@ import { PlusIcon } from '@/components/icons/common/Plus'; import { RefreshIcon } from '@/components/icons/common/Refresh'; import { TimesIcon } from '@/components/icons/common/Times'; import { TrashLineIcon } from '@/components/icons/common/TrashLine'; -import { CLOUDS } from '@/components/scan-configure-forms/ComplianceScanConfigureForm'; +import { + CLOUDS, + ComplianceScanConfigureFormProps, +} from '@/components/scan-configure-forms/ComplianceScanConfigureForm'; import { StopScanForm } from '@/components/scan-configure-forms/StopScanForm'; import { ScanStatusBadge } from '@/components/ScanStatusBadge'; import { PostureIcon } from '@/components/sideNavigation/icons/Posture'; @@ -99,14 +102,13 @@ import { usePageNavigation } from '@/utils/usePageNavigation'; import { isUpgradeAvailable } from '@/utils/version'; enum ActionEnumType { - DELETE = 'delete', + DELETE_SCAN = 'delete_scan', REFRESH_ACCOUNT = 'refresh_account', START_SCAN = 'start_scan', + CANCEL_SCAN = 'cancel_scan', } -export const getNodeTypeByProviderName = ( - providerName: string, -): ComplianceScanNodeTypeEnum | undefined => { +const getNodeTypeByProviderName = (providerName: string): ComplianceScanNodeTypeEnum => { switch (providerName) { case 'linux': case 'host': @@ -124,7 +126,7 @@ export const getNodeTypeByProviderName = ( case 'kubernetes': return ComplianceScanNodeTypeEnum.kubernetes_cluster; default: - return; + throw new Error('No matching provider name found'); } }; @@ -154,7 +156,7 @@ const action = async ({ throw new Error('Invalid action'); } - if (actionType === ActionEnumType.DELETE) { + if (actionType === ActionEnumType.DELETE_SCAN) { if (scanIds.length === 0) { throw new Error('Scan ids are required for deletion'); } @@ -181,7 +183,7 @@ const action = async ({ const { message } = await getResponseErrors(result.error); return { success: false, - action: ActionEnumType.DELETE, + action: ActionEnumType.DELETE_SCAN, message, }; } else if (result.error.response.status === 403) { @@ -189,7 +191,7 @@ const action = async ({ return { success: false, message, - action: ActionEnumType.DELETE, + action: ActionEnumType.DELETE_SCAN, }; } throw result.error; @@ -573,7 +575,7 @@ const DeleteConfirmationModal = ({ if ( fetcher.state === 'idle' && fetcher.data?.success && - fetcher.data.action === ActionEnumType.DELETE + fetcher.data.action === ActionEnumType.DELETE_SCAN ) { onSuccess(); } @@ -612,7 +614,7 @@ const DeleteConfirmationModal = ({ disabled={fetcher.state === 'submitting'} onClick={(e) => { e.preventDefault(); - onDeleteAction(ActionEnumType.DELETE); + onDeleteAction(ActionEnumType.DELETE_SCAN); }} > Delete @@ -648,28 +650,22 @@ const ActionDropdown = ({ nodeType?: string; scanType: ScanTypeEnum; row: ModelCloudNodeAccountInfo; - onTableAction: (ids: string[], actionType: ActionEnumType) => void; + onTableAction: (row: ModelCloudNodeAccountInfo, actionType: ActionEnumType) => void; }) => { const fetcher = useFetcher(); - const { - last_scan_id: scanId = '', - node_id: nodeId, - last_scan_status: scanStatus = '', - active, - } = row; + const { last_scan_id: scanId = '', last_scan_status: scanStatus = '', active } = row; const [open, setOpen] = useState(false); const [isSubmitting, setIsSubmitting] = useState(false); const { downloadScan } = useDownloadScan((state) => { setIsSubmitting(state === 'submitting'); }); - const [openStopScanModal, setOpenStopScanModal] = useState(false); - - const [showDeleteDialog, setShowDeleteDialog] = useState(false); const onDownloadAction = useCallback(() => { downloadScan({ scanId, - nodeType: nodeType as UtilsReportFiltersNodeTypeEnum, + nodeType: (nodeType?.toString() === ComplianceScanNodeTypeEnum.kubernetes_cluster + ? 'cluster' + : nodeType) as UtilsReportFiltersNodeTypeEnum, scanType: (scanType as ScanTypeEnum) === ScanTypeEnum.CloudComplianceScan ? UtilsReportFiltersScanTypeEnum.CloudCompliance @@ -681,35 +677,12 @@ const ActionDropdown = ({ if (fetcher.state === 'idle') setOpen(false); }, [fetcher]); - if (!nodeType || !nodeId) { - throw new Error('Node type and Node id are required'); + if (!nodeType) { + throw new Error('Node type is required'); } return ( <> - {openStopScanModal && ( - - )} - {showDeleteDialog && ( - { - // - }} - /> - )} { - if (!nodeId) { - throw new Error('Node id is required to start scan'); - } - onTableAction([nodeId], ActionEnumType.START_SCAN); + onTableAction(row, ActionEnumType.START_SCAN); }} > Start scan @@ -733,7 +703,7 @@ const ActionDropdown = ({ { e.preventDefault(); - setOpenStopScanModal(true); + onTableAction(row, ActionEnumType.CANCEL_SCAN); }} disabled={!isScanInProgress(scanStatus)} > @@ -755,7 +725,7 @@ const ActionDropdown = ({ disabled={!scanId || !nodeType} onClick={() => { if (!scanId || !nodeType) return; - setShowDeleteDialog(true); + onTableAction(row, ActionEnumType.DELETE_SCAN); }} > { - if (!nodeId) { - throw new Error('Account id is required to refresh'); - } - onTableAction([nodeId], ActionEnumType.REFRESH_ACCOUNT); + onTableAction(row, ActionEnumType.REFRESH_ACCOUNT); }} > Refresh account @@ -787,27 +754,53 @@ const ActionDropdown = ({ }; const BulkActions = ({ - onClick, - onDelete, - onRefreshAccount, - onCancelScan, - disableStartScan, - disableCancelScan, - disableDeleteScan, - disableRefreshAccount, + nodeType, + selectedRows, + onBulkAction, }: { - onClick?: React.MouseEventHandler | undefined; - onCancelScan?: React.MouseEventHandler | undefined; - onDelete?: React.MouseEventHandler | undefined; - onRefreshAccount?: React.MouseEventHandler | undefined; - disableStartScan: boolean; - disableCancelScan: boolean; - disableDeleteScan: boolean; - disableRefreshAccount: boolean; + nodeType: ComplianceScanNodeTypeEnum; + selectedRows: { + scanId: string; + nodeId: string; + nodeType: string; + active: boolean; + scanStatus: string; + }[]; + onBulkAction: ( + data: { + scanIdsToCancelScan: string[]; + scanIdsToDeleteScan: string[]; + nodesToStartScan: ComplianceScanConfigureFormProps['data'] | null; + }, + actionType: ActionEnumType, + ) => void; }) => { const { navigate } = usePageNavigation(); const params = useParams(); + const scanIdsToDeleteScan = useMemo(() => { + return selectedRows + .filter((row) => !isNeverScanned(row.scanStatus)) + .map((row) => row.scanId); + }, [selectedRows]); + + const nodeIdsToScan = useMemo(() => { + return selectedRows + .filter( + (node) => + node.active && + !isScanInProgress(node.scanStatus) && + !isScanStopping(node.scanStatus), + ) + .map((node) => node.nodeId); + }, [selectedRows]); + + const scanIdsToCancelScan = useMemo(() => { + return selectedRows + .filter((row) => isScanInProgress(row.scanStatus)) + .map((row) => row.scanId); + }, [selectedRows]); + return ( <> @@ -842,8 +847,17 @@ const BulkActions = ({ color="default" variant="flat" size="sm" - disabled={disableCancelScan} - onClick={onCancelScan} + disabled={scanIdsToCancelScan.length === 0} + onClick={() => + onBulkAction( + { + scanIdsToCancelScan, + scanIdsToDeleteScan: [], + nodesToStartScan: null, + }, + ActionEnumType.CANCEL_SCAN, + ) + } > Cancel scan @@ -852,8 +866,17 @@ const BulkActions = ({ variant="flat" startIcon={} size="sm" - disabled={disableDeleteScan} - onClick={onDelete} + disabled={scanIdsToDeleteScan.length === 0} + onClick={() => + onBulkAction( + { + scanIdsToCancelScan: [], + scanIdsToDeleteScan, + nodesToStartScan: null, + }, + ActionEnumType.DELETE_SCAN, + ) + } > Delete scan @@ -861,8 +884,17 @@ const BulkActions = ({ variant="flat" startIcon={} size="sm" - disabled={disableRefreshAccount} - onClick={onRefreshAccount} + disabled={selectedRows.length === 0} + onClick={() => + onBulkAction( + { + scanIdsToCancelScan: [], + scanIdsToDeleteScan: [], + nodesToStartScan: null, + }, + ActionEnumType.REFRESH_ACCOUNT, + ) + } > Refresh account @@ -887,7 +919,7 @@ const AccountTable = ({ scanType: 'ComplianceScan' | 'CloudComplianceScan'; setRowSelectionState: React.Dispatch>; rowSelectionState: RowSelectionState; - onTableAction: (ids: string[], actionType: ActionEnumType) => void; + onTableAction: (row: ModelCloudNodeAccountInfo, actionType: ActionEnumType) => void; }) => { const [searchParams, setSearchParams] = useSearchParams(); const { data } = usePostureAccounts(); @@ -1255,10 +1287,6 @@ const Accounts = () => { const [searchParams] = useSearchParams(); const [rowSelectionState, setRowSelectionState] = useState({}); - const [selectedScanType, setSelectedScanType] = useState< - typeof ScanTypeEnum.ComplianceScan | typeof ScanTypeEnum.CloudComplianceScan - >(); - const [filtersExpanded, setFiltersExpanded] = useState(false); const fetcher = useFetcher(); const routeParams = useParams() as { @@ -1271,7 +1299,7 @@ const Accounts = () => { const [showDeleteDialog, setShowDeleteDialog] = useState(false); const [showCancelScan, setShowCancelScan] = useState(false); - const [nodeIdsToScan, setNodeIdsToScan] = useState([]); + const [openStartScan, setOpenStartScan] = useState(false); const scanType = isNonCloudProvider(routeParams.nodeType) ? ScanTypeEnum.ComplianceScan @@ -1291,50 +1319,85 @@ const Accounts = () => { }); }, [rowSelectionState]); - const nodeIdsToDeleteScan = useMemo(() => { - return selectedRows - .filter((row) => !isNeverScanned(row.scanStatus)) - .map((row) => row.scanId); - }, [selectedRows]); - - const nodeIdsToCancelScan = useMemo(() => { - return selectedRows - .filter((row) => isScanInProgress(row.scanStatus)) - .map((row) => row.scanId); - }, [selectedRows]); - - useEffect(() => { - setNodeIdsToScan( - selectedRows - .filter( - (node) => - node.active && - !isScanInProgress(node.scanStatus) && - !isScanStopping(node.scanStatus), - ) - .map((node) => node.nodeId), - ); - }, [selectedRows]); + const [rowToAction, setRowToAction] = useState<{ + scanIdsToCancelScan: string[]; + scanIdsToDeleteScan: string[]; + nodesToStartScan: ComplianceScanConfigureFormProps['data'] | null; + }>({ + scanIdsToCancelScan: [], + scanIdsToDeleteScan: [], + nodesToStartScan: null, + }); const onTableAction = useCallback( - (nodeIds: string[], actionType: ActionEnumType) => { - if (actionType === ActionEnumType.START_SCAN) { - setNodeIdsToScan(nodeIds); - setSelectedScanType(scanType); + (row: ModelCloudNodeAccountInfo, actionType: ActionEnumType) => { + if (actionType === ActionEnumType.START_SCAN && nodeType) { + setRowToAction({ + scanIdsToCancelScan: [], + scanIdsToDeleteScan: [], + nodesToStartScan: { + nodeIds: [row.node_id!], + nodeType: nodeType, + }, + }); + setOpenStartScan(true); return; } else if (actionType === ActionEnumType.REFRESH_ACCOUNT) { const formData = new FormData(); formData.append('actionType', ActionEnumType.REFRESH_ACCOUNT); - nodeIds.forEach((nodeId) => formData.append('accountId[]', nodeId)); + [row.node_id!].forEach((nodeId) => formData.append('accountId[]', nodeId)); fetcher.submit(formData, { method: 'post', }); return; + } else if (actionType === ActionEnumType.DELETE_SCAN) { + setRowToAction({ + scanIdsToCancelScan: [], + scanIdsToDeleteScan: [row.last_scan_id!], + nodesToStartScan: null, + }); + setShowDeleteDialog(true); + } else if (actionType === ActionEnumType.CANCEL_SCAN) { + setRowToAction({ + scanIdsToCancelScan: [row.last_scan_id!], + scanIdsToDeleteScan: [], + nodesToStartScan: null, + }); + setShowCancelScan(true); } }, [fetcher], ); + const onBulkAction = ( + data: { + scanIdsToCancelScan: string[]; + scanIdsToDeleteScan: string[]; + nodesToStartScan: ComplianceScanConfigureFormProps['data'] | null; + }, + actionType: string, + ) => { + setRowToAction({ + scanIdsToCancelScan: data.scanIdsToCancelScan, + scanIdsToDeleteScan: data.scanIdsToDeleteScan, + nodesToStartScan: data.nodesToStartScan, + }); + if (actionType === ActionEnumType.DELETE_SCAN) { + setShowDeleteDialog(true); + } else if (actionType === ActionEnumType.CANCEL_SCAN) { + setShowCancelScan(true); + } else if (actionType === ActionEnumType.START_SCAN) { + setOpenStartScan(true); + } else if (actionType === ActionEnumType.REFRESH_ACCOUNT) { + const formData = new FormData(); + formData.append('actionType', ActionEnumType.REFRESH_ACCOUNT); + selectedRows.forEach((row) => formData.append('accountId[]', row.nodeId)); + fetcher.submit(formData, { + method: 'post', + }); + } + }; + return (
{!hasOrgCloudAccount(nodeType ?? '') ?
: null} @@ -1342,37 +1405,50 @@ const Accounts = () => { { setRowSelectionState({}); }} /> )} + {openStartScan && ( + setOpenStartScan(false)} + onSuccess={() => setRowSelectionState({})} + scanOptions={ + nodeType && rowToAction.nodesToStartScan + ? { + showAdvancedOptions: true, + scanType, + data: rowToAction.nodesToStartScan, + } + : undefined + } + /> + )} + {showDeleteDialog && ( + { + setRowSelectionState({}); + }} + /> + )}
{ - const formData = new FormData(); - formData.append('actionType', ActionEnumType.REFRESH_ACCOUNT); - selectedRows.forEach((row) => formData.append('accountId[]', row.nodeId)); - fetcher.submit(formData, { - method: 'post', - }); - }} - onClick={() => { - setSelectedScanType(scanType); - }} - onCancelScan={() => { - setShowCancelScan(true); - }} - onDelete={() => { - setShowDeleteDialog(true); - }} + nodeType={nodeType} + onBulkAction={onBulkAction} + selectedRows={selectedRows} />
{filtersExpanded ? : null} - setSelectedScanType(undefined)} - onSuccess={() => setRowSelectionState({})} - scanOptions={ - selectedScanType && nodeType - ? { - showAdvancedOptions: true, - scanType: selectedScanType, - data: { - nodeIds: nodeIdsToScan, - nodeType: nodeType, - }, - } - : undefined - } - /> - }> { />
- {showDeleteDialog && ( - { - setRowSelectionState({}); - }} - /> - )}
); }; diff --git a/deepfence_frontend/apps/dashboard/src/features/postures/pages/PostureCloudScanResults.tsx b/deepfence_frontend/apps/dashboard/src/features/postures/pages/PostureCloudScanResults.tsx index 62d0cf4409..2af4aa6b18 100644 --- a/deepfence_frontend/apps/dashboard/src/features/postures/pages/PostureCloudScanResults.tsx +++ b/deepfence_frontend/apps/dashboard/src/features/postures/pages/PostureCloudScanResults.tsx @@ -584,7 +584,7 @@ const HistoryControls = () => { }); const [openStopScanModal, setOpenStopScanModal] = useState(false); - const { scan_id, node_id, node_type, updated_at, status } = scanStatusResult ?? {}; + const { scan_id, node_id, node_type, created_at, status } = scanStatusResult ?? {}; const [showScanCompareModal, setShowScanCompareModal] = useState(false); @@ -599,7 +599,7 @@ const HistoryControls = () => { }>({ baseScanId: '', toScanId: '', - baseScanTime: updated_at ?? 0, + baseScanTime: created_at ?? 0, toScanTime: 0, showScanTimeModal: false, }); @@ -672,7 +672,7 @@ const HistoryControls = () => { id: item.scanId, isCurrent: item.scanId === scan_id, status: item.status, - timestamp: item.updatedAt, + timestamp: item.createdAt, showScanCompareButton: true, onScanTimeCompareButtonClick: onCompareScanClick, onDeleteClick: (id) => { @@ -697,7 +697,7 @@ const HistoryControls = () => { ); }, }))} - currentTimeStamp={formatMilliseconds(updated_at ?? '')} + currentTimeStamp={formatMilliseconds(created_at ?? '')} /> {scanIdToDelete && ( @@ -777,7 +777,7 @@ const HistoryControls = () => { onClick={() => { setCompareInput({ ...compareInput, - baseScanTime: updated_at ?? 0, + baseScanTime: created_at ?? 0, showScanTimeModal: true, }); }} diff --git a/deepfence_frontend/apps/dashboard/src/features/postures/pages/PostureScanResults.tsx b/deepfence_frontend/apps/dashboard/src/features/postures/pages/PostureScanResults.tsx index d469423898..f0750cf373 100644 --- a/deepfence_frontend/apps/dashboard/src/features/postures/pages/PostureScanResults.tsx +++ b/deepfence_frontend/apps/dashboard/src/features/postures/pages/PostureScanResults.tsx @@ -574,7 +574,7 @@ const HistoryControls = () => { const { data, fetchStatus } = useScanResults(); const { nodeType = '' } = useParams(); const { scanStatusResult } = data; - const { scan_id, node_id, node_type, updated_at, status } = scanStatusResult ?? {}; + const { scan_id, node_id, node_type, created_at, status } = scanStatusResult ?? {}; const { navigate, goBack } = usePageNavigation(); const { downloadScan } = useDownloadScan((state) => { setIsSubmitting(state === 'submitting'); @@ -594,7 +594,7 @@ const HistoryControls = () => { }>({ baseScanId: '', toScanId: '', - baseScanTime: updated_at ?? 0, + baseScanTime: created_at ?? 0, toScanTime: 0, showScanTimeModal: false, }); @@ -667,7 +667,7 @@ const HistoryControls = () => { id: item.scanId, isCurrent: item.scanId === scan_id, status: item.status, - timestamp: item.updatedAt, + timestamp: item.createdAt, showScanCompareButton: true, onScanTimeCompareButtonClick: onCompareScanClick, onDeleteClick: (id) => { @@ -692,7 +692,7 @@ const HistoryControls = () => { ); }, }))} - currentTimeStamp={formatMilliseconds(updated_at ?? '')} + currentTimeStamp={formatMilliseconds(created_at ?? '')} /> {scanIdToDelete && ( @@ -772,7 +772,7 @@ const HistoryControls = () => { onClick={() => { setCompareInput({ ...compareInput, - baseScanTime: updated_at ?? 0, + baseScanTime: created_at ?? 0, showScanTimeModal: true, }); }} diff --git a/deepfence_frontend/apps/dashboard/src/features/registries/pages/RegistryAccounts.tsx b/deepfence_frontend/apps/dashboard/src/features/registries/pages/RegistryAccounts.tsx index dadd7031b0..c1ccfda053 100644 --- a/deepfence_frontend/apps/dashboard/src/features/registries/pages/RegistryAccounts.tsx +++ b/deepfence_frontend/apps/dashboard/src/features/registries/pages/RegistryAccounts.tsx @@ -308,7 +308,9 @@ const Header = () => {
- {isFetching ? : null} + {isFetching ? ( + + ) : null}
); diff --git a/deepfence_frontend/apps/dashboard/src/features/secrets/pages/SecretScanResults.tsx b/deepfence_frontend/apps/dashboard/src/features/secrets/pages/SecretScanResults.tsx index 61262756b2..9ef61199bc 100644 --- a/deepfence_frontend/apps/dashboard/src/features/secrets/pages/SecretScanResults.tsx +++ b/deepfence_frontend/apps/dashboard/src/features/secrets/pages/SecretScanResults.tsx @@ -584,7 +584,7 @@ const HistoryControls = () => { const [isSubmitting, setIsSubmitting] = useState(false); const { data, fetchStatus } = useScanResults(); const { scanStatusResult } = data; - const { scan_id, node_id, node_type, updated_at, status } = scanStatusResult ?? {}; + const { scan_id, node_id, node_type, created_at, status } = scanStatusResult ?? {}; const { navigate, goBack } = usePageNavigation(); const { downloadScan } = useDownloadScan((state) => { setIsSubmitting(state === 'submitting'); @@ -604,7 +604,7 @@ const HistoryControls = () => { }>({ baseScanId: '', toScanId: '', - baseScanTime: updated_at ?? 0, + baseScanTime: created_at ?? 0, toScanTime: 0, showScanTimeModal: false, }); @@ -625,7 +625,7 @@ const HistoryControls = () => { if (!scan_id || !node_id || !node_type) { throw new Error('Scan Type, Node Type and Node Id are required'); } - if (!updated_at) { + if (!created_at) { return null; } const onCompareScanClick = (baseScanTime: number) => { @@ -679,7 +679,7 @@ const HistoryControls = () => { id: item.scanId, isCurrent: item.scanId === scan_id, status: item.status, - timestamp: item.updatedAt, + timestamp: item.createdAt, showScanCompareButton: true, onScanTimeCompareButtonClick: onCompareScanClick, onDeleteClick: (id) => { @@ -703,7 +703,7 @@ const HistoryControls = () => { ); }, }))} - currentTimeStamp={formatMilliseconds(updated_at)} + currentTimeStamp={formatMilliseconds(created_at)} /> {scanIdToDelete && ( @@ -783,7 +783,7 @@ const HistoryControls = () => { onClick={() => { setCompareInput({ ...compareInput, - baseScanTime: updated_at ?? 0, + baseScanTime: created_at ?? 0, showScanTimeModal: true, }); }} diff --git a/deepfence_frontend/apps/dashboard/src/features/secrets/pages/SecretScans.tsx b/deepfence_frontend/apps/dashboard/src/features/secrets/pages/SecretScans.tsx index 60ddc1fde6..cbe0fe1d4a 100644 --- a/deepfence_frontend/apps/dashboard/src/features/secrets/pages/SecretScans.tsx +++ b/deepfence_frontend/apps/dashboard/src/features/secrets/pages/SecretScans.tsx @@ -78,7 +78,9 @@ export interface FocusableElement { } enum ActionEnumType { - DELETE = 'delete', + DELETE_SCAN = 'delete_scan', + CANCEL_SCAN = 'cancel_scan', + START_SCAN = 'start_scan,', } const DEFAULT_PAGE_SIZE = 10; @@ -109,7 +111,7 @@ const action = async ({ throw new Error('Invalid action'); } - if (actionType === ActionEnumType.DELETE) { + if (actionType === ActionEnumType.DELETE_SCAN) { const resultApi = apiWrapper({ fn: getScanResultsApiClient().bulkDeleteScans, }); @@ -180,7 +182,7 @@ const DeleteConfirmationModal = ({ if ( fetcher.state === 'idle' && fetcher.data?.success && - fetcher.data.action === ActionEnumType.DELETE + fetcher.data.action === ActionEnumType.DELETE_SCAN ) { onDeleteSuccess(); } @@ -219,7 +221,7 @@ const DeleteConfirmationModal = ({ disabled={fetcher.state === 'submitting'} onClick={(e) => { e.preventDefault(); - onDeleteAction(ActionEnumType.DELETE); + onDeleteAction(ActionEnumType.DELETE_SCAN); }} > Delete @@ -247,9 +249,11 @@ const DeleteConfirmationModal = ({ const ActionDropdown = ({ trigger, row, + onTableAction, }: { trigger: React.ReactNode; row: ModelScanInfo; + onTableAction: (row: ModelScanInfo, actionType: ActionEnumType) => void; }) => { const fetcher = useFetcher(); const [open, setOpen] = useState(false); @@ -257,15 +261,12 @@ const ActionDropdown = ({ const { downloadScan } = useDownloadScan((state) => { setIsSubmitting(state === 'submitting'); }); - const [openStopScanModal, setOpenStopScanModal] = useState(false); - const [showDeleteDialog, setShowDeleteDialog] = useState(false); const { scan_id: scanId, node_id: nodeId, node_type: nodeType, status: scanStatus, } = row; - const [showStartScan, setShowStartScan] = useState(false); const onDownloadAction = useCallback(() => { downloadScan({ @@ -281,47 +282,6 @@ const ActionDropdown = ({ return ( <> - {openStopScanModal && ( - - )} - - {showDeleteDialog && ( - { - // - }} - /> - )} - - {showStartScan && ( - setShowStartScan(false)} - scanOptions={ - { - showAdvancedOptions: true, - scanType: ScanTypeEnum.SecretScan, - data: { - nodes: [ - { - nodeId, - nodeType, - }, - ], - }, - } as ConfigureScanModalProps['scanOptions'] - } - /> - )} - { e.preventDefault(); if (isScanInProgress(scanStatus)) return; - setShowStartScan(true); + onTableAction(row, ActionEnumType.START_SCAN); }} disabled={isScanInProgress(scanStatus) || isScanStopping(scanStatus)} > @@ -354,7 +314,7 @@ const ActionDropdown = ({ { e.preventDefault(); - setOpenStopScanModal(true); + onTableAction(row, ActionEnumType.CANCEL_SCAN); }} disabled={!isScanInProgress(scanStatus)} > @@ -364,7 +324,7 @@ const ActionDropdown = ({ className="text-sm" onClick={() => { if (!scanId || !nodeType) return; - setShowDeleteDialog(true); + onTableAction(row, ActionEnumType.DELETE_SCAN); }} disabled={!scanId || !nodeType} > @@ -692,9 +652,11 @@ const Filters = () => { const ScansTable = ({ rowSelectionState, setRowSelectionState, + onTableAction, }: { rowSelectionState: RowSelectionState; setRowSelectionState: React.Dispatch>; + onTableAction: (row: ModelScanInfo, actionType: ActionEnumType) => void; }) => { const [searchParams, setSearchParams] = useSearchParams(); const { data } = useSuspenseQuery({ @@ -732,6 +694,7 @@ const ScansTable = ({ cell: (cell) => ( @@ -786,7 +749,7 @@ const ScansTable = ({ size: 240, maxSize: 250, }), - columnHelper.accessor('updated_at', { + columnHelper.accessor('created_at', { cell: (info) => , header: () => , minSize: 140, @@ -1039,7 +1002,7 @@ const ScansTable = ({ const BulkActions = ({ selectedRows, - setRowSelectionState, + onBulkAction, }: { selectedRows: { scanId: string; @@ -1047,11 +1010,18 @@ const BulkActions = ({ nodeType: string; scanStatus: string; }[]; - setRowSelectionState: React.Dispatch>; + onBulkAction: ( + data: { + scanIdsToCancelScan: string[]; + scanIdsToDeleteScan: string[]; + nodesToStartScan: { + nodeId: string; + nodeType: string; + }[]; + }, + actionType: ActionEnumType, + ) => void; }) => { - const [openStartScan, setOpenStartScan] = useState(false); - const [showDeleteDialog, setShowDeleteDialog] = useState(false); - const [showCancelScanDialog, setShowCancelScanDialog] = useState(false); const nodesToStartScan = useMemo(() => { return selectedRows .filter( @@ -1079,52 +1049,20 @@ const BulkActions = ({ return ( <> - {openStartScan && ( - setOpenStartScan(false)} - onSuccess={() => setRowSelectionState({})} - scanOptions={ - { - showAdvancedOptions: true, - scanType: ScanTypeEnum.SecretScan, - data: { - nodes: nodesToStartScan, - }, - } as ConfigureScanModalProps['scanOptions'] - } - /> - )} - - {showDeleteDialog && ( - { - setRowSelectionState({}); - }} - /> - )} - {showCancelScanDialog ? ( - { - setRowSelectionState({}); - }} - /> - ) : null} - @@ -1145,7 +1092,14 @@ const BulkActions = ({ size="sm" disabled={scanIdsToDeleteScan.length === 0} onClick={() => { - setShowDeleteDialog(true); + onBulkAction( + { + scanIdsToCancelScan: [], + scanIdsToDeleteScan, + nodesToStartScan: [], + }, + ActionEnumType.DELETE_SCAN, + ); }} > Delete Scan @@ -1163,6 +1117,9 @@ const SecretScans = () => { }); const [rowSelectionState, setRowSelectionState] = useState({}); + const [openStartScan, setOpenStartScan] = useState(false); + const [showDeleteDialog, setShowDeleteDialog] = useState(false); + const [showCancelScanDialog, setShowCancelScanDialog] = useState(false); const selectedRows = useMemo< { @@ -1177,8 +1134,115 @@ const SecretScans = () => { }); }, [rowSelectionState]); + const [rowToAction, setRowToAction] = useState<{ + scanIdsToCancelScan: string[]; + scanIdsToDeleteScan: string[]; + nodesToStartScan: { + nodeId: string; + nodeType: string; + }[]; + }>({ + scanIdsToCancelScan: [], + scanIdsToDeleteScan: [], + nodesToStartScan: [], + }); + + const onTableAction = (row: ModelScanInfo, actionType: string) => { + if (actionType === ActionEnumType.DELETE_SCAN) { + setRowToAction({ + scanIdsToCancelScan: [], + scanIdsToDeleteScan: [row.scan_id], + nodesToStartScan: [], + }); + setShowDeleteDialog(true); + } else if (actionType === ActionEnumType.CANCEL_SCAN) { + setRowToAction({ + scanIdsToCancelScan: [row.scan_id], + scanIdsToDeleteScan: [], + nodesToStartScan: [], + }); + setShowCancelScanDialog(true); + } else if (actionType === ActionEnumType.START_SCAN) { + setRowToAction({ + scanIdsToCancelScan: [], + scanIdsToDeleteScan: [], + nodesToStartScan: [ + { + nodeId: row.node_id, + nodeType: row.node_type, + }, + ], + }); + setOpenStartScan(true); + } + }; + + const onBulkAction = ( + data: { + scanIdsToCancelScan: string[]; + scanIdsToDeleteScan: string[]; + nodesToStartScan: { + nodeId: string; + nodeType: string; + }[]; + }, + actionType: string, + ) => { + setRowToAction({ + scanIdsToCancelScan: data.scanIdsToCancelScan, + scanIdsToDeleteScan: data.scanIdsToDeleteScan, + nodesToStartScan: data.nodesToStartScan, + }); + if (actionType === ActionEnumType.DELETE_SCAN) { + setShowDeleteDialog(true); + } else if (actionType === ActionEnumType.CANCEL_SCAN) { + setShowCancelScanDialog(true); + } else if (actionType === ActionEnumType.START_SCAN) { + setOpenStartScan(true); + } + }; + return (
+ <> + {openStartScan && ( + setOpenStartScan(false)} + onSuccess={() => setRowSelectionState({})} + scanOptions={ + { + showAdvancedOptions: true, + scanType: ScanTypeEnum.SecretScan, + data: { + nodes: rowToAction?.nodesToStartScan, + }, + } as ConfigureScanModalProps['scanOptions'] + } + /> + )} + {showDeleteDialog && ( + { + setRowSelectionState({}); + }} + /> + )} + {showCancelScanDialog ? ( + { + setRowSelectionState({}); + }} + /> + ) : null} +
} isLink> @@ -1198,10 +1262,7 @@ const SecretScans = () => {
- +
diff --git a/deepfence_frontend/apps/dashboard/src/features/settings/pages/UserManagement.tsx b/deepfence_frontend/apps/dashboard/src/features/settings/pages/UserManagement.tsx index 861e4fecc2..67c622e906 100644 --- a/deepfence_frontend/apps/dashboard/src/features/settings/pages/UserManagement.tsx +++ b/deepfence_frontend/apps/dashboard/src/features/settings/pages/UserManagement.tsx @@ -68,6 +68,7 @@ enum ActionEnumType { INVITE_USER = 'inviteUser', EDIT_USER = 'editUser', RESET_API_KEY = 'resetAPIKey', + DELETE_USER = 'delete_user', } const useListUsers = () => { @@ -283,29 +284,14 @@ const action = async ({ request }: ActionFunctionArgs): Promise => { const ActionDropdown = ({ user, trigger, + onTableAction, }: { user: ModelUser; trigger: React.ReactNode; + onTableAction: (row: ModelUser, action: ActionEnumType) => void; }) => { - const [showDeleteDialog, setShowDeleteDialog] = useState(false); - const [showEditUserForm, setShowEditUserForm] = useState(false); - return ( <> - {showDeleteDialog && user.id && ( - - )} - {showEditUserForm && ( - - )} { - setShowEditUserForm(true); + onTableAction(user, ActionEnumType.EDIT_USER); }} > Edit { - setShowDeleteDialog(true); + onTableAction(user, ActionEnumType.DELETE_USER); }} className="dark:text-status-error dark:hover:text-[#C45268]" > @@ -763,7 +749,11 @@ const APITokenComponent = () => { ); }; -const UsersTable = () => { +const UsersTable = ({ + onTableAction, +}: { + onTableAction: (row: ModelUser, action: ActionEnumType) => void; +}) => { const columnHelper = createColumnHelper(); const columns = useMemo(() => { const columns = [ @@ -777,6 +767,7 @@ const UsersTable = () => { return (
@@ -892,9 +883,37 @@ const InviteButton = ({ }; const UserManagement = () => { const [openInviteUserForm, setOpenInviteUserForm] = useState(false); + const [showDeleteDialog, setShowDeleteDialog] = useState(false); + const [showEditUserForm, setShowEditUserForm] = useState(false); + + const [user, setUser] = useState(); + + const onTableAction = (row: ModelUser, action: ActionEnumType) => { + if (action === ActionEnumType.EDIT_USER) { + setUser(row); + setShowEditUserForm(true); + } else if (action === ActionEnumType.DELETE_USER) { + setUser(row); + setShowDeleteDialog(true); + } + }; return (
+ {showDeleteDialog && user?.id && ( + + )} + {showEditUserForm && ( + + )} {openInviteUserForm && ( { /> } > - +
diff --git a/deepfence_frontend/apps/dashboard/src/features/topology/data-components/node-details/Host.tsx b/deepfence_frontend/apps/dashboard/src/features/topology/data-components/node-details/Host.tsx index e5f7c4ef36..a348e6c3de 100644 --- a/deepfence_frontend/apps/dashboard/src/features/topology/data-components/node-details/Host.tsx +++ b/deepfence_frontend/apps/dashboard/src/features/topology/data-components/node-details/Host.tsx @@ -97,7 +97,7 @@ export const Host = (props: HostModalProps) => { - +
} > diff --git a/deepfence_frontend/apps/dashboard/src/features/vulnerabilities/pages/VulnerabilityScanResults.tsx b/deepfence_frontend/apps/dashboard/src/features/vulnerabilities/pages/VulnerabilityScanResults.tsx index e0a8bb2b79..02f731c5bf 100644 --- a/deepfence_frontend/apps/dashboard/src/features/vulnerabilities/pages/VulnerabilityScanResults.tsx +++ b/deepfence_frontend/apps/dashboard/src/features/vulnerabilities/pages/VulnerabilityScanResults.tsx @@ -546,7 +546,7 @@ const HistoryControls = () => { const [isSubmitting, setIsSubmitting] = useState(false); const { data, fetchStatus } = useScanResults(); const { scanStatusResult } = data; - const { scan_id, node_id, node_type, updated_at, status, node_name } = + const { scan_id, node_id, node_type, created_at, status, node_name } = scanStatusResult ?? {}; const { navigate, goBack } = usePageNavigation(); const { downloadScan } = useDownloadScan((state) => { @@ -567,7 +567,7 @@ const HistoryControls = () => { }>({ baseScanId: '', toScanId: '', - baseScanTime: updated_at ?? 0, + baseScanTime: created_at ?? 0, toScanTime: 0, showScanTimeModal: false, }); @@ -588,7 +588,7 @@ const HistoryControls = () => { if (!scan_id || !node_id || !node_type) { throw new Error('Scan Type, Node Type and Node Id are required'); } - if (!updated_at) { + if (!created_at) { return null; } @@ -644,7 +644,7 @@ const HistoryControls = () => { id: item.scanId, isCurrent: item.scanId === scan_id, status: item.status, - timestamp: item.updatedAt, + timestamp: item.createdAt, showScanCompareButton: true, onScanTimeCompareButtonClick: onCompareScanClick, onDeleteClick: (id) => { @@ -668,7 +668,7 @@ const HistoryControls = () => { ); }, }))} - currentTimeStamp={formatMilliseconds(updated_at)} + currentTimeStamp={formatMilliseconds(created_at)} /> {scanIdToDelete && ( @@ -751,7 +751,7 @@ const HistoryControls = () => { onClick={() => { setCompareInput({ ...compareInput, - baseScanTime: updated_at ?? 0, + baseScanTime: created_at ?? 0, showScanTimeModal: true, }); }} diff --git a/deepfence_frontend/apps/dashboard/src/features/vulnerabilities/pages/VulnerabilityScans.tsx b/deepfence_frontend/apps/dashboard/src/features/vulnerabilities/pages/VulnerabilityScans.tsx index c5c60ea68d..c8dbf9b230 100644 --- a/deepfence_frontend/apps/dashboard/src/features/vulnerabilities/pages/VulnerabilityScans.tsx +++ b/deepfence_frontend/apps/dashboard/src/features/vulnerabilities/pages/VulnerabilityScans.tsx @@ -80,7 +80,9 @@ export interface FocusableElement { } enum ActionEnumType { - DELETE = 'delete', + DELETE_SCAN = 'delete_scan', + CANCEL_SCAN = 'cancel_scan', + START_SCAN = 'start_scan,', } const DEFAULT_PAGE_SIZE = 10; @@ -101,7 +103,7 @@ const action = async ({ if (!actionType || scanIds.length === 0) { throw new Error('Action type and scan id is required'); } - if (actionType === ActionEnumType.DELETE) { + if (actionType === ActionEnumType.DELETE_SCAN) { const resultApi = apiWrapper({ fn: getScanResultsApiClient().bulkDeleteScans, }); @@ -172,7 +174,7 @@ const DeleteConfirmationModal = ({ if ( fetcher.state === 'idle' && fetcher.data?.success && - fetcher.data.action === ActionEnumType.DELETE + fetcher.data.action === ActionEnumType.DELETE_SCAN ) { onDeleteSuccess(); } @@ -211,7 +213,7 @@ const DeleteConfirmationModal = ({ disabled={fetcher.state === 'submitting'} onClick={(e) => { e.preventDefault(); - onDeleteAction(ActionEnumType.DELETE); + onDeleteAction(ActionEnumType.DELETE_SCAN); }} > Delete @@ -239,15 +241,15 @@ const DeleteConfirmationModal = ({ const ActionDropdown = ({ trigger, row, + onTableAction, }: { trigger: React.ReactNode; row: ModelScanInfo; + onTableAction: (row: ModelScanInfo, actionType: ActionEnumType) => void; }) => { const fetcher = useFetcher(); const [open, setOpen] = useState(false); - const [openStopScanModal, setOpenStopScanModal] = useState(false); const [isSubmitting, setIsSubmitting] = useState(false); - const [showDeleteDialog, setShowDeleteDialog] = useState(false); const { scan_id: scanId, node_id: nodeId, @@ -256,8 +258,6 @@ const ActionDropdown = ({ status: scanStatus, } = row; - const [showStartScan, setShowStartScan] = useState(false); - const [selectedNode, setSelectedNode] = useState<{ nodeName: string; nodeType: string; @@ -295,47 +295,6 @@ const ActionDropdown = ({ return ( <> - {openStopScanModal && ( - - )} - - {showDeleteDialog && ( - { - // - }} - /> - )} - - {showStartScan && ( - setShowStartScan(false)} - scanOptions={ - { - showAdvancedOptions: true, - scanType: ScanTypeEnum.VulnerabilityScan, - data: { - nodes: [ - { - nodeId, - nodeType, - }, - ], - }, - } as ConfigureScanModalProps['scanOptions'] - } - /> - )} - {selectedNode ? ( { e.preventDefault(); if (isScanInProgress(scanStatus)) return; - setShowStartScan(true); + onTableAction(row, ActionEnumType.START_SCAN); }} disabled={isScanInProgress(scanStatus) || isScanStopping(scanStatus)} > @@ -393,7 +352,7 @@ const ActionDropdown = ({ { e.preventDefault(); - setOpenStopScanModal(true); + onTableAction(row, ActionEnumType.CANCEL_SCAN); }} disabled={!isScanInProgress(scanStatus)} > @@ -403,7 +362,7 @@ const ActionDropdown = ({ { if (!scanId || !nodeType) return; - setShowDeleteDialog(true); + onTableAction(row, ActionEnumType.DELETE_SCAN); }} disabled={!scanId || !nodeType} > @@ -427,9 +386,11 @@ const ActionDropdown = ({ const ScansTable = ({ rowSelectionState, setRowSelectionState, + onTableAction, }: { rowSelectionState: RowSelectionState; setRowSelectionState: React.Dispatch>; + onTableAction: (row: ModelScanInfo, actionType: ActionEnumType) => void; }) => { const [searchParams, setSearchParams] = useSearchParams(); const { data } = useSuspenseQuery({ @@ -469,6 +430,7 @@ const ScansTable = ({ cell: (cell) => ( @@ -523,7 +485,7 @@ const ScansTable = ({ size: 240, maxSize: 250, }), - columnHelper.accessor('updated_at', { + columnHelper.accessor('created_at', { cell: (info) => , header: () => , minSize: 140, @@ -1105,7 +1067,7 @@ const Filters = () => { const BulkActions = ({ selectedRows, - setRowSelectionState, + onBulkAction, }: { selectedRows: { scanId: string; @@ -1113,11 +1075,18 @@ const BulkActions = ({ nodeType: string; scanStatus: string; }[]; - setRowSelectionState: React.Dispatch>; + onBulkAction: ( + data: { + scanIdsToCancelScan: string[]; + scanIdsToDeleteScan: string[]; + nodesToStartScan: { + nodeId: string; + nodeType: string; + }[]; + }, + actionType: ActionEnumType, + ) => void; }) => { - const [openStartScan, setOpenStartScan] = useState(false); - const [showDeleteDialog, setShowDeleteDialog] = useState(false); - const [showCancelScanDialog, setShowCancelScanDialog] = useState(false); const nodesToStartScan = useMemo(() => { return selectedRows .filter( @@ -1145,56 +1114,20 @@ const BulkActions = ({ return ( <> - {openStartScan && ( - { - setOpenStartScan(false); - }} - onSuccess={() => { - setRowSelectionState({}); - }} - scanOptions={ - { - showAdvancedOptions: true, - scanType: ScanTypeEnum.VulnerabilityScan, - data: { - nodes: nodesToStartScan, - }, - } as ConfigureScanModalProps['scanOptions'] - } - /> - )} - - {showDeleteDialog && ( - { - setRowSelectionState({}); - }} - /> - )} - {showCancelScanDialog ? ( - { - setRowSelectionState({}); - }} - /> - ) : null} -
diff --git a/deepfence_frontend/apps/dashboard/src/queries/common.ts b/deepfence_frontend/apps/dashboard/src/queries/common.ts index a2fd4b9bf5..4c7f45d429 100644 --- a/deepfence_frontend/apps/dashboard/src/queries/common.ts +++ b/deepfence_frontend/apps/dashboard/src/queries/common.ts @@ -90,7 +90,7 @@ export const commonQueries = createQueryKeys('common', { return { data: (result.value.scans_info ?? []).slice(0, size)?.map((res) => { return { - updatedAt: res.updated_at, + createdAt: res.created_at, scanId: res.scan_id, status: res.status, nodeName: res.node_name, diff --git a/deepfence_frontend/apps/dashboard/src/queries/registry.tsx b/deepfence_frontend/apps/dashboard/src/queries/registry.tsx index f9979ec179..5157560342 100644 --- a/deepfence_frontend/apps/dashboard/src/queries/registry.tsx +++ b/deepfence_frontend/apps/dashboard/src/queries/registry.tsx @@ -235,6 +235,21 @@ export const registryQueries = createQueryKeys('registry', { queryFn: async () => { const imageTagsRequest: ModelRegistryImagesReq = { image_filter: { + compare_filter: [], + match_filter: { + filter_in: {}, + }, + order_filter: { + order_fields: [], + }, + contains_filter: { + filter_in: {}, + }, + not_contains_filter: { + filter_in: {}, + }, + }, + image_stub_filter: { compare_filter: [], match_filter: { filter_in: {}, diff --git a/deepfence_frontend/packages/ui-components/src/components/spinner/CircleSpinner.tsx b/deepfence_frontend/packages/ui-components/src/components/spinner/CircleSpinner.tsx index 7c28a05a18..2019eac3e8 100644 --- a/deepfence_frontend/packages/ui-components/src/components/spinner/CircleSpinner.tsx +++ b/deepfence_frontend/packages/ui-components/src/components/spinner/CircleSpinner.tsx @@ -18,9 +18,18 @@ const spinnerCVA = cva(['animate-spin dark:text-bg-side-panel fill-accent-accent }, }); -export const CircleSpinner = ({ size = 'md', className }: CircleSpinnerProps) => { +export const CircleSpinner = ({ + size = 'md', + className, + ...props +}: CircleSpinnerProps) => { return ( -
+
- - - - + + + + - + + {{ range $i, $v := $value.ScanResults }} - - - + + + - + + {{ end }}
No.StatusCategoryTest NumberNo.StatusCategoryTest Number DescriptionCheck TypeCheck TypeResource
{{ add1 $i }}{{ $v.Status }}{{ $v.TestCategory }}{{ add1 $i }}{{ $v.Status }}{{ $v.TestCategory }} {{ $v.TestNumber }} {{ trunc 80 $v.TestInfo }}{{ $v.ComplianceCheckType }}{{ $v.ComplianceCheckType }}{{ $v.Resource }}
diff --git a/deepfence_worker/tasks/reports/xlsx.go b/deepfence_worker/tasks/reports/xlsx.go index 826e062165..134acba86d 100644 --- a/deepfence_worker/tasks/reports/xlsx.go +++ b/deepfence_worker/tasks/reports/xlsx.go @@ -62,12 +62,13 @@ var ( "G1": "masked", "H1": "node_id", "I1": "node_name", - "J1": "node_type", - "K1": "status", - "L1": "test_category", - "M1": "test_desc", - "N1": "test_info", - "O1": "test_number", + "J1": "resource", + "K1": "node_type", + "L1": "status", + "M1": "test_category", + "N1": "test_desc", + "O1": "test_info", + "P1": "test_number", } ) @@ -303,6 +304,7 @@ func complianceXLSX(ctx context.Context, params utils.ReportParams) (string, err c.Masked, c.ComplianceNodeID, nodeScanData.ScanInfo.NodeName, + c.Resource, c.ComplianceNodeType, c.Status, c.TestCategory, @@ -354,6 +356,7 @@ func cloudComplianceXLSX(ctx context.Context, params utils.ReportParams) (string c.Masked, c.NodeID, data.ScanInfo.NodeName, + c.Resource, c.ComplianceCheckType, c.Status, c.Type, diff --git a/deployment-scripts/docker-compose.yml b/deployment-scripts/docker-compose.yml index d0a46a9f34..59edfcd030 100644 --- a/deployment-scripts/docker-compose.yml +++ b/deployment-scripts/docker-compose.yml @@ -48,7 +48,7 @@ services: deepfence-postgres: container_name: deepfence-postgres - image: ${IMAGE_REPOSITORY:-deepfenceio}/deepfence_postgres_ce:${DF_IMG_TAG:-2.1.0} + image: ${IMAGE_REPOSITORY:-deepfenceio}/deepfence_postgres_ce:${DF_IMG_TAG:-2.1.1} ulimits: core: 0 restart: unless-stopped @@ -63,7 +63,7 @@ services: deepfence-redis: container_name: deepfence-redis - image: ${IMAGE_REPOSITORY:-deepfenceio}/deepfence_redis_ce:${DF_IMG_TAG:-2.1.0} + image: ${IMAGE_REPOSITORY:-deepfenceio}/deepfence_redis_ce:${DF_IMG_TAG:-2.1.1} ulimits: core: 0 restart: unless-stopped @@ -78,7 +78,7 @@ services: deepfence-neo4j: container_name: deepfence-neo4j - image: ${IMAGE_REPOSITORY:-deepfenceio}/deepfence_neo4j_ce:${DF_IMG_TAG:-2.1.0} + image: ${IMAGE_REPOSITORY:-deepfenceio}/deepfence_neo4j_ce:${DF_IMG_TAG:-2.1.1} ulimits: core: 0 @@ -110,7 +110,7 @@ services: deepfence-console-agent: container_name: deepfence-console-agent - image: ${IMAGE_REPOSITORY:-deepfenceio}/deepfence_agent_ce:${DF_IMG_TAG:-2.1.0} + image: ${IMAGE_REPOSITORY:-deepfenceio}/deepfence_agent_ce:${DF_IMG_TAG:-2.1.1} ulimits: core: 0 deploy: @@ -143,7 +143,7 @@ services: deepfence-router: container_name: deepfence-router - image: ${IMAGE_REPOSITORY:-deepfenceio}/deepfence_router_ce:${DF_IMG_TAG:-2.1.0} + image: ${IMAGE_REPOSITORY:-deepfenceio}/deepfence_router_ce:${DF_IMG_TAG:-2.1.1} ulimits: core: 0 networks: @@ -165,7 +165,7 @@ services: # this service can be commented in case S3 is used deepfence-file-server: container_name: deepfence-file-server - image: ${IMAGE_REPOSITORY:-deepfenceio}/deepfence_file_server_ce:${DF_IMG_TAG:-2.1.0} + image: ${IMAGE_REPOSITORY:-deepfenceio}/deepfence_file_server_ce:${DF_IMG_TAG:-2.1.1} ulimits: core: 0 networks: @@ -186,7 +186,7 @@ services: deepfence-server: container_name: deepfence-server - image: ${IMAGE_REPOSITORY:-deepfenceio}/deepfence_server_ce:${DF_IMG_TAG:-2.1.0} + image: ${IMAGE_REPOSITORY:-deepfenceio}/deepfence_server_ce:${DF_IMG_TAG:-2.1.1} ulimits: core: 0 tmpfs: @@ -216,7 +216,7 @@ services: deepfence-worker: container_name: deepfence-worker - image: ${IMAGE_REPOSITORY:-deepfenceio}/deepfence_worker_ce:${DF_IMG_TAG:-2.1.0} + image: ${IMAGE_REPOSITORY:-deepfenceio}/deepfence_worker_ce:${DF_IMG_TAG:-2.1.1} ulimits: core: 0 restart: unless-stopped @@ -238,7 +238,7 @@ services: # deepfence-worker-2: # container_name: deepfence-worker-2 - # image: ${IMAGE_REPOSITORY:-deepfenceio}/deepfence_worker_ce:${DF_IMG_TAG:-2.1.0} + # image: ${IMAGE_REPOSITORY:-deepfenceio}/deepfence_worker_ce:${DF_IMG_TAG:-2.1.1} # ulimits: # core: 0 # restart: unless-stopped @@ -259,7 +259,7 @@ services: # deepfence-worker-3: # container_name: deepfence-worker-3 - # image: ${IMAGE_REPOSITORY:-deepfenceio}/deepfence_worker_ce:${DF_IMG_TAG:-2.1.0} + # image: ${IMAGE_REPOSITORY:-deepfenceio}/deepfence_worker_ce:${DF_IMG_TAG:-2.1.1} # ulimits: # core: 0 # restart: unless-stopped @@ -280,7 +280,7 @@ services: deepfence-scheduler: container_name: deepfence-scheduler - image: ${IMAGE_REPOSITORY:-deepfenceio}/deepfence_worker_ce:${DF_IMG_TAG:-2.1.0} + image: ${IMAGE_REPOSITORY:-deepfenceio}/deepfence_worker_ce:${DF_IMG_TAG:-2.1.1} ulimits: core: 0 restart: unless-stopped @@ -302,7 +302,7 @@ services: deepfence-ui: container_name: deepfence-ui - image: ${IMAGE_REPOSITORY:-deepfenceio}/deepfence_ui_ce:${DF_IMG_TAG:-2.1.0} + image: ${IMAGE_REPOSITORY:-deepfenceio}/deepfence_ui_ce:${DF_IMG_TAG:-2.1.1} ulimits: core: 0 networks: @@ -316,7 +316,7 @@ services: max-size: "100m" deepfence-kafka-broker: - image: ${IMAGE_REPOSITORY:-deepfenceio}/deepfence_kafka_broker_ce:${DF_IMG_TAG:-2.1.0} + image: ${IMAGE_REPOSITORY:-deepfenceio}/deepfence_kafka_broker_ce:${DF_IMG_TAG:-2.1.1} hostname: deepfence-kafka-broker container_name: deepfence-kafka-broker # environment: @@ -335,7 +335,7 @@ services: restart: unless-stopped deepfence-ingester: - image: ${IMAGE_REPOSITORY:-deepfenceio}/deepfence_worker_ce:${DF_IMG_TAG:-2.1.0} + image: ${IMAGE_REPOSITORY:-deepfenceio}/deepfence_worker_ce:${DF_IMG_TAG:-2.1.1} hostname: deepfence-ingester container_name: deepfence-ingester ports: @@ -354,7 +354,7 @@ services: restart: unless-stopped deepfence-telemetry: - image: ${IMAGE_REPOSITORY:-deepfenceio}/deepfence_telemetry_ce:${DF_IMG_TAG:-2.1.0} + image: ${IMAGE_REPOSITORY:-deepfenceio}/deepfence_telemetry_ce:${DF_IMG_TAG:-2.1.1} hostname: deepfence-telemetry container_name: deepfence-telemetry ports: diff --git a/deployment-scripts/helm-charts/deepfence-agent/Chart.yaml b/deployment-scripts/helm-charts/deepfence-agent/Chart.yaml index 8713a1e919..320a64c5c1 100644 --- a/deployment-scripts/helm-charts/deepfence-agent/Chart.yaml +++ b/deployment-scripts/helm-charts/deepfence-agent/Chart.yaml @@ -15,9 +15,9 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 2.1.0 +version: 2.1.1 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. -appVersion: 2.1.0 \ No newline at end of file +appVersion: 2.1.1 \ No newline at end of file diff --git a/deployment-scripts/helm-charts/deepfence-agent/values.yaml b/deployment-scripts/helm-charts/deepfence-agent/values.yaml index 6fa190ef3b..dd6fc045dc 100644 --- a/deployment-scripts/helm-charts/deepfence-agent/values.yaml +++ b/deployment-scripts/helm-charts/deepfence-agent/values.yaml @@ -11,7 +11,7 @@ commonLabels: {} global: # this image tag is used every where for agents # to override set tag at agents level - imageTag: 2.1.0 + imageTag: 2.1.1 imagePullSecret: # Specifies whether a image pull secret should be created @@ -27,7 +27,7 @@ imagePullSecret: agent: image: name: deepfenceio/deepfence_agent_ce - # tag: 2.1.0 + # tag: 2.1.1 pullPolicy: Always affinity: {} podLabels: {} @@ -51,7 +51,7 @@ agent: cluster_agent: image: name: deepfenceio/deepfence_cluster_agent_ce - # tag: 2.1.0 + # tag: 2.1.1 pullPolicy: Always affinity: {} podLabels: {} diff --git a/deployment-scripts/helm-charts/deepfence-console/Chart.yaml b/deployment-scripts/helm-charts/deepfence-console/Chart.yaml index fb1215d76f..924fd69dc3 100644 --- a/deployment-scripts/helm-charts/deepfence-console/Chart.yaml +++ b/deployment-scripts/helm-charts/deepfence-console/Chart.yaml @@ -2,5 +2,5 @@ apiVersion: v2 name: deepfence-console description: A Helm chart for Kubernetes type: application -version: 2.1.1 -appVersion: 2.1.0 +version: 2.1.2 +appVersion: 2.1.1 diff --git a/deployment-scripts/helm-charts/deepfence-console/values.yaml b/deployment-scripts/helm-charts/deepfence-console/values.yaml index 09ee9ccd3a..229df7c36a 100644 --- a/deployment-scripts/helm-charts/deepfence-console/values.yaml +++ b/deployment-scripts/helm-charts/deepfence-console/values.yaml @@ -12,7 +12,7 @@ global: imageRepoPrefix: "docker.io" # this image tag is used everywhere for console services # to override set tag at service level - imageTag: 2.1.0 + imageTag: 2.1.1 storageClass: "" serviceAccount: @@ -46,7 +46,7 @@ kafka: repository: deepfenceio/deepfence_kafka_broker_ce pullPolicy: Always # Overrides the image tag whose default is .global.imageTag - # tag: 2.1.0 + # tag: 2.1.1 config: # required, recommended to generate new UUID using kafka-storage tool STORAGE_UUID: hNQ55qppT5GGybF52ZGlOQ @@ -84,7 +84,7 @@ postgres: repository: deepfenceio/deepfence_postgres_ce pullPolicy: Always # Overrides the image tag whose default is .global.imageTag - # tag: 2.1.0 + # tag: 2.1.1 storageClass: "" volumeSize: 50G resources: @@ -113,7 +113,7 @@ redis: repository: deepfenceio/deepfence_redis_ce pullPolicy: Always # Overrides the image tag whose default is .global.imageTag - # tag: 2.1.0 + # tag: 2.1.1 storageClass: "" volumeSize: 30G resources: @@ -147,7 +147,7 @@ fileserver: repository: deepfenceio/deepfence_file_server_ce pullPolicy: Always # Overrides the image tag whose default is .global.imageTag - # tag: 2.1.0 + # tag: 2.1.1 storageClass: "" volumeSize: 100G resources: @@ -205,7 +205,7 @@ neo4j: image: repository: deepfenceio/deepfence_neo4j_ce pullPolicy: Always - # tag: 2.1.0 + # tag: 2.1.1 storageClass: "" volumeSize: 100G resources: @@ -257,7 +257,7 @@ router: repository: deepfenceio/deepfence_router_ce pullPolicy: Always # Overrides the image tag whose default is .global.imageTag - # tag: 2.1.0 + # tag: 2.1.1 forceHttpsRedirect: true podAnnotations: {} podSecurityContext: {} @@ -320,7 +320,7 @@ server: repository: deepfenceio/deepfence_server_ce pullPolicy: Always # Overrides the image tag whose default is .global.imageTag - # tag: 2.1.0 + # tag: 2.1.1 podAnnotations: {} podSecurityContext: {} securityContext: {} @@ -352,7 +352,7 @@ worker: repository: deepfenceio/deepfence_worker_ce pullPolicy: Always # Overrides the image tag whose default is .global.imageTag - # tag: 2.1.0 + # tag: 2.1.1 podAnnotations: {} podSecurityContext: {} securityContext: {} @@ -383,7 +383,7 @@ ingester: repository: deepfenceio/deepfence_worker_ce pullPolicy: Always # Overrides the image tag whose default is .global.imageTag - # tag: 2.1.0 + # tag: 2.1.1 podAnnotations: {} podSecurityContext: {} securityContext: {} @@ -413,7 +413,7 @@ scheduler: repository: deepfenceio/deepfence_worker_ce pullPolicy: Always # Overrides the image tag whose default is .global.imageTag - # tag: 2.1.0 + # tag: 2.1.1 service: type: ClusterIP port: 8080 @@ -438,7 +438,7 @@ ui: repository: deepfenceio/deepfence_ui_ce pullPolicy: Always # Overrides the image tag whose default is .global.imageTag - # tag: 2.1.0 + # tag: 2.1.1 service: type: ClusterIP port: 8081 @@ -487,7 +487,7 @@ console_agents: repository: deepfenceio/deepfence_agent_ce pullPolicy: Always # Overrides the image tag whose default is .global.imageTag - # tag: 2.1.0 + # tag: 2.1.1 resources: requests: cpu: 150m @@ -511,7 +511,7 @@ console_agents: repository: deepfenceio/deepfence_cluster_agent_ce pullPolicy: Always # Overrides the image tag whose default is .global.imageTag - # tag: 2.1.0 + # tag: 2.1.1 resources: requests: cpu: 25m diff --git a/deployment-scripts/helm-charts/deepfence-router/Chart.yaml b/deployment-scripts/helm-charts/deepfence-router/Chart.yaml index 87cbaadaad..956d589582 100644 --- a/deployment-scripts/helm-charts/deepfence-router/Chart.yaml +++ b/deployment-scripts/helm-charts/deepfence-router/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 -appVersion: 2.1.0 +appVersion: 2.1.1 description: Deepfence Router - Helm chart for Kubernetes name: deepfence-router type: application -version: 2.1.0 +version: 2.1.1 diff --git a/deployment-scripts/helm-charts/index.yaml b/deployment-scripts/helm-charts/index.yaml index 3bee71c79c..d446b93445 100644 --- a/deployment-scripts/helm-charts/index.yaml +++ b/deployment-scripts/helm-charts/index.yaml @@ -1,6 +1,16 @@ apiVersion: v1 entries: deepfence-agent: + - apiVersion: v2 + appVersion: 2.1.1 + created: "2024-02-15T18:29:08.99782+05:30" + description: Deepfence Agent - Helm chart for Kubernetes + digest: 31587b4e1e4289408d1b0d01c6e0576b2968c6570d59f4449f262b07146920b9 + name: deepfence-agent + type: application + urls: + - deepfence-agent-2.1.1.tgz + version: 2.1.1 - apiVersion: v2 appVersion: 2.1.0 created: "2024-01-05T11:46:18.061528+05:30" @@ -242,6 +252,16 @@ entries: - deepfence-agent-1.0.0.tgz version: 1.0.0 deepfence-console: + - apiVersion: v2 + appVersion: 2.1.1 + created: "2024-02-15T18:29:08.998944+05:30" + description: A Helm chart for Kubernetes + digest: ec67bdf7ef2b684c846850e367bf957c001e4e8263e7d28357717ece9ca193f1 + name: deepfence-console + type: application + urls: + - deepfence-console-2.1.2.tgz + version: 2.1.2 - apiVersion: v2 appVersion: 2.1.0 created: "2024-02-09T19:10:20.013119+05:30" @@ -483,6 +503,16 @@ entries: - deepfence-console-1.0.0.tgz version: 1.0.0 deepfence-router: + - apiVersion: v2 + appVersion: 2.1.1 + created: "2024-02-15T18:29:08.999254+05:30" + description: Deepfence Router - Helm chart for Kubernetes + digest: 4543c1d2fc9ff07c3c5340962ce86982e8f0df5e9c06134f9ee94244d5f3739b + name: deepfence-router + type: application + urls: + - deepfence-router-2.1.1.tgz + version: 2.1.1 - apiVersion: v2 appVersion: 2.1.0 created: "2024-01-03T23:50:13.482983+05:30" @@ -623,4 +653,4 @@ entries: urls: - deepfence-router-1.0.0.tgz version: 1.0.0 -generated: "2024-02-09T19:10:20.011814+05:30" +generated: "2024-02-15T18:29:08.997283+05:30" diff --git a/deployment-scripts/start-agent.sh b/deployment-scripts/start-agent.sh index ba7fdc0496..d9335f2f1c 100755 --- a/deployment-scripts/start-agent.sh +++ b/deployment-scripts/start-agent.sh @@ -113,7 +113,7 @@ start_agent() { -e DEEPFENCE_KEY="$DEEPFENCE_KEY" \ -e DF_USE_DUMMY_SCOPE="$DF_USE_DUMMY_SCOPE" \ -e DF_USE_FAT_DUMMY_SCOPE="$DF_USE_FAT_DUMMY_SCOPE" \ - "$IMAGE_REPOSITORY"/deepfence_agent_ce:"${DF_IMG_TAG:-2.1.0}" + "$IMAGE_REPOSITORY"/deepfence_agent_ce:"${DF_IMG_TAG:-2.1.1}" } main() { diff --git a/deployment-scripts/start-podman-agent.sh b/deployment-scripts/start-podman-agent.sh index a9ab74e980..b6e689ad25 100755 --- a/deployment-scripts/start-podman-agent.sh +++ b/deployment-scripts/start-podman-agent.sh @@ -111,7 +111,7 @@ start_agent() { -e DEEPFENCE_KEY="$DEEPFENCE_KEY" \ -e DF_USE_DUMMY_SCOPE="$DF_USE_DUMMY_SCOPE" \ -e DF_USE_FAT_DUMMY_SCOPE="$DF_USE_FAT_DUMMY_SCOPE" \ - "$IMAGE_REPOSITORY"/deepfence_agent_ce:"${DF_IMG_TAG:-2.1.0}" + "$IMAGE_REPOSITORY"/deepfence_agent_ce:"${DF_IMG_TAG:-2.1.1}" } main() { diff --git a/docs/vulnerability_feeds/listing.json b/docs/vulnerability_feeds/listing.json index 05e4404d1b..f35d619f6b 100644 --- a/docs/vulnerability_feeds/listing.json +++ b/docs/vulnerability_feeds/listing.json @@ -2,54 +2,54 @@ "available": { "3": [ { - "built": "2024-02-11T01:03:50.412286353Z", + "built": "2024-02-17T01:01:21.489056192Z", "version": 3, - "url": "https://threat-intel.deepfence.io/vulnerability-db/releases/download/threatintel-vuln-v3-2024-02-11_00-49-49/threatintel-vuln-v3-2024-02-11_00-49-49.tar.gz", - "checksum": "89d24cfb0fcbb8c805a437d330bbcac28def62fcc45e6d50049a02033160f8cd" + "url": "https://threat-intel.deepfence.io/vulnerability-db/releases/download/threatintel-vuln-v3-2024-02-17_00-49-16/threatintel-vuln-v3-2024-02-17_00-49-16.tar.gz", + "checksum": "eda499d1c3321d871d15ff221b9dafa2d1df647c0a10979a77b5a4ef3c8b22ef" }, { - "built": "2024-02-12T01:06:13.372673857Z", + "built": "2024-02-18T01:03:55.277960429Z", "version": 3, - "url": "https://threat-intel.deepfence.io/vulnerability-db/releases/download/threatintel-vuln-v3-2024-02-12_00-49-41/threatintel-vuln-v3-2024-02-12_00-49-41.tar.gz", - "checksum": "0fc522b6ecbbf60b64057b194cbf0912114c5dfbd4f18f161f49e049794a1516" + "url": "https://threat-intel.deepfence.io/vulnerability-db/releases/download/threatintel-vuln-v3-2024-02-18_00-49-33/threatintel-vuln-v3-2024-02-18_00-49-33.tar.gz", + "checksum": "73c909c42d7287421ef952dd7420215d82f486370daf7870f2f3b5b16a81b6b5" }, { - "built": "2024-02-13T01:03:12.742305129Z", + "built": "2024-02-19T00:59:42.423015778Z", "version": 3, - "url": "https://threat-intel.deepfence.io/vulnerability-db/releases/download/threatintel-vuln-v3-2024-02-13_00-49-33/threatintel-vuln-v3-2024-02-13_00-49-33.tar.gz", - "checksum": "501e31775326b1a468d2b92bb8ffaed69093ac1e4b57675a12c6f9afe8166c40" + "url": "https://threat-intel.deepfence.io/vulnerability-db/releases/download/threatintel-vuln-v3-2024-02-19_00-49-24/threatintel-vuln-v3-2024-02-19_00-49-24.tar.gz", + "checksum": "4b02a72fd2e67d27b92189e105e2b108870b9e45b95d13ea931c734f95247a84" }, { - "built": "2024-02-14T01:04:05.764394206Z", + "built": "2024-02-20T00:59:24.545374821Z", "version": 3, - "url": "https://threat-intel.deepfence.io/vulnerability-db/releases/download/threatintel-vuln-v3-2024-02-14_00-49-35/threatintel-vuln-v3-2024-02-14_00-49-35.tar.gz", - "checksum": "ba735935ccfbf134d5701b8581935de0f16e0e6565361e99ae21f86476fb2bd6" + "url": "https://threat-intel.deepfence.io/vulnerability-db/releases/download/threatintel-vuln-v3-2024-02-20_00-49-16/threatintel-vuln-v3-2024-02-20_00-49-16.tar.gz", + "checksum": "7449fa6b7593e2c5bef9644e28bb02277c78a25199b1d1750cb43b5e507f77d5" } ], "5": [ { - "built": "2024-02-11T00:35:19.348292208Z", + "built": "2024-02-17T00:39:33.279866383Z", "version": 5, - "url": "https://threat-intel.deepfence.io/vulnerability-db/releases/download/threatintel-vuln-v5-2024-02-11_00-19-16/threatintel-vuln-v5-2024-02-11_00-19-16.tar.gz", - "checksum": "911e408adef2fb023c75ebfe7d638856a3341026b8d4ce2d416360bc89b1a06e" + "url": "https://threat-intel.deepfence.io/vulnerability-db/releases/download/threatintel-vuln-v5-2024-02-17_00-17-06/threatintel-vuln-v5-2024-02-17_00-17-06.tar.gz", + "checksum": "d6a256f177a865252ce46c300f8b574118d5fdafc4f0007c211d0ddd35cb5dc9" }, { - "built": "2024-02-12T00:34:01.26515756Z", + "built": "2024-02-18T00:40:02.467254981Z", "version": 5, - "url": "https://threat-intel.deepfence.io/vulnerability-db/releases/download/threatintel-vuln-v5-2024-02-12_00-18-06/threatintel-vuln-v5-2024-02-12_00-18-06.tar.gz", - "checksum": "c3f0fdcb420b7eb53b852c1cb9f712ba397b750d9cea2134f81c2cab3058b422" + "url": "https://threat-intel.deepfence.io/vulnerability-db/releases/download/threatintel-vuln-v5-2024-02-18_00-18-39/threatintel-vuln-v5-2024-02-18_00-18-39.tar.gz", + "checksum": "de2f693d31611b9d1b370f5b3499f2c6addbd79af6da50394d82e8fc67a88da6" }, { - "built": "2024-02-13T00:35:23.788906872Z", + "built": "2024-02-19T00:35:00.853685106Z", "version": 5, - "url": "https://threat-intel.deepfence.io/vulnerability-db/releases/download/threatintel-vuln-v5-2024-02-13_00-17-44/threatintel-vuln-v5-2024-02-13_00-17-44.tar.gz", - "checksum": "434dae101930ecd7284f15a95cfcaa4ad8def1a641f7885af8ab3790bc18ccb4" + "url": "https://threat-intel.deepfence.io/vulnerability-db/releases/download/threatintel-vuln-v5-2024-02-19_00-17-50/threatintel-vuln-v5-2024-02-19_00-17-50.tar.gz", + "checksum": "ff17baf5f3cfa8cfdfa808007c8370e3d0287ef0a5f03d81758d73f16446bedf" }, { - "built": "2024-02-14T00:32:37.809797265Z", + "built": "2024-02-20T00:35:23.842245243Z", "version": 5, - "url": "https://threat-intel.deepfence.io/vulnerability-db/releases/download/threatintel-vuln-v5-2024-02-14_00-17-06/threatintel-vuln-v5-2024-02-14_00-17-06.tar.gz", - "checksum": "9f4a67443a52f25a59c4adac8a3157d0b6adb1b5f48bcf990774ef61525ea313" + "url": "https://threat-intel.deepfence.io/vulnerability-db/releases/download/threatintel-vuln-v5-2024-02-20_00-16-46/threatintel-vuln-v5-2024-02-20_00-16-46.tar.gz", + "checksum": "c581cf06c2af61a76e7acd736762d0085947895ffe962aa739f3118b847fcc58" } ] }