diff --git a/deepfence_frontend/apps/dashboard/api-spec.json b/deepfence_frontend/apps/dashboard/api-spec.json index baadea0d78..ddf31c27b2 100644 --- a/deepfence_frontend/apps/dashboard/api-spec.json +++ b/deepfence_frontend/apps/dashboard/api-spec.json @@ -10752,7 +10752,6 @@ "description": { "type": "string" }, "doc_id": { "type": "string" }, "group": { "type": "string" }, - "masked": { "type": "boolean" }, "reason": { "type": "string" }, "region": { "type": "string" }, "resource": { "type": "string" }, @@ -10911,7 +10910,6 @@ "file_sev_score": { "type": "number" }, "file_severity": { "type": "string" }, "image_layer_id": { "type": "string" }, - "masked": { "type": "boolean" }, "meta": { "type": "array", "items": { "type": "string" }, "nullable": true }, "meta_rules": { "$ref": "#/components/schemas/IngestersMetaRules" }, "rule_name": { "type": "string" }, @@ -11076,7 +11074,6 @@ "type": "object", "properties": { "level": { "type": "string" }, "score": { "type": "number" } } }, - "masked": { "type": "boolean" }, "scan_id": { "type": "string" } } }, @@ -12789,6 +12786,7 @@ "type": "object", "properties": { "mask_across_hosts_and_images": { "type": "boolean" }, + "mask_in_this_host_or_image_tags": { "type": "boolean" }, "result_ids": { "type": "array", "items": { "type": "string" }, diff --git a/deepfence_frontend/apps/dashboard/src/api/generated/models/IngestersCloudCompliance.ts b/deepfence_frontend/apps/dashboard/src/api/generated/models/IngestersCloudCompliance.ts index 543ceb08e1..a774ae0610 100644 --- a/deepfence_frontend/apps/dashboard/src/api/generated/models/IngestersCloudCompliance.ts +++ b/deepfence_frontend/apps/dashboard/src/api/generated/models/IngestersCloudCompliance.ts @@ -73,12 +73,6 @@ export interface IngestersCloudCompliance { * @memberof IngestersCloudCompliance */ group?: string; - /** - * - * @type {boolean} - * @memberof IngestersCloudCompliance - */ - masked?: boolean; /** * * @type {string} @@ -163,7 +157,6 @@ export function IngestersCloudComplianceFromJSONTyped(json: any, ignoreDiscrimin 'description': !exists(json, 'description') ? undefined : json['description'], 'doc_id': !exists(json, 'doc_id') ? undefined : json['doc_id'], 'group': !exists(json, 'group') ? undefined : json['group'], - 'masked': !exists(json, 'masked') ? undefined : json['masked'], 'reason': !exists(json, 'reason') ? undefined : json['reason'], 'region': !exists(json, 'region') ? undefined : json['region'], 'resource': !exists(json, 'resource') ? undefined : json['resource'], @@ -194,7 +187,6 @@ export function IngestersCloudComplianceToJSON(value?: IngestersCloudCompliance 'description': value.description, 'doc_id': value.doc_id, 'group': value.group, - 'masked': value.masked, 'reason': value.reason, 'region': value.region, 'resource': value.resource, diff --git a/deepfence_frontend/apps/dashboard/src/api/generated/models/IngestersMalware.ts b/deepfence_frontend/apps/dashboard/src/api/generated/models/IngestersMalware.ts index 240a0a7a0b..6737e6ee31 100644 --- a/deepfence_frontend/apps/dashboard/src/api/generated/models/IngestersMalware.ts +++ b/deepfence_frontend/apps/dashboard/src/api/generated/models/IngestersMalware.ts @@ -56,12 +56,6 @@ export interface IngestersMalware { * @memberof IngestersMalware */ image_layer_id?: string; - /** - * - * @type {boolean} - * @memberof IngestersMalware - */ - masked?: boolean; /** * * @type {Array} @@ -136,7 +130,6 @@ export function IngestersMalwareFromJSONTyped(json: any, ignoreDiscriminator: bo 'file_sev_score': !exists(json, 'file_sev_score') ? undefined : json['file_sev_score'], 'file_severity': !exists(json, 'file_severity') ? undefined : json['file_severity'], 'image_layer_id': !exists(json, 'image_layer_id') ? undefined : json['image_layer_id'], - 'masked': !exists(json, 'masked') ? undefined : json['masked'], 'meta': !exists(json, 'meta') ? undefined : json['meta'], 'meta_rules': !exists(json, 'meta_rules') ? undefined : IngestersMetaRulesFromJSON(json['meta_rules']), 'rule_name': !exists(json, 'rule_name') ? undefined : json['rule_name'], @@ -162,7 +155,6 @@ export function IngestersMalwareToJSON(value?: IngestersMalware | null): any { 'file_sev_score': value.file_sev_score, 'file_severity': value.file_severity, 'image_layer_id': value.image_layer_id, - 'masked': value.masked, 'meta': value.meta, 'meta_rules': IngestersMetaRulesToJSON(value.meta_rules), 'rule_name': value.rule_name, diff --git a/deepfence_frontend/apps/dashboard/src/api/generated/models/IngestersSecret.ts b/deepfence_frontend/apps/dashboard/src/api/generated/models/IngestersSecret.ts index f065be56d2..4ddc7ad042 100644 --- a/deepfence_frontend/apps/dashboard/src/api/generated/models/IngestersSecret.ts +++ b/deepfence_frontend/apps/dashboard/src/api/generated/models/IngestersSecret.ts @@ -62,12 +62,6 @@ export interface IngestersSecret { * @memberof IngestersSecret */ Severity?: IngestersSecretSeverity; - /** - * - * @type {boolean} - * @memberof IngestersSecret - */ - masked?: boolean; /** * * @type {string} @@ -99,7 +93,6 @@ export function IngestersSecretFromJSONTyped(json: any, ignoreDiscriminator: boo 'Match': !exists(json, 'Match') ? undefined : IngestersSecretMatchFromJSON(json['Match']), 'Rule': !exists(json, 'Rule') ? undefined : IngestersSecretRuleFromJSON(json['Rule']), 'Severity': !exists(json, 'Severity') ? undefined : IngestersSecretSeverityFromJSON(json['Severity']), - 'masked': !exists(json, 'masked') ? undefined : json['masked'], 'scan_id': !exists(json, 'scan_id') ? undefined : json['scan_id'], }; } @@ -117,7 +110,6 @@ export function IngestersSecretToJSON(value?: IngestersSecret | null): any { 'Match': IngestersSecretMatchToJSON(value.Match), 'Rule': IngestersSecretRuleToJSON(value.Rule), 'Severity': IngestersSecretSeverityToJSON(value.Severity), - 'masked': value.masked, 'scan_id': value.scan_id, }; } diff --git a/deepfence_frontend/apps/dashboard/src/api/generated/models/ModelScanResultsMaskRequest.ts b/deepfence_frontend/apps/dashboard/src/api/generated/models/ModelScanResultsMaskRequest.ts index ceca56d408..2d2e4c1c94 100644 --- a/deepfence_frontend/apps/dashboard/src/api/generated/models/ModelScanResultsMaskRequest.ts +++ b/deepfence_frontend/apps/dashboard/src/api/generated/models/ModelScanResultsMaskRequest.ts @@ -25,6 +25,12 @@ export interface ModelScanResultsMaskRequest { * @memberof ModelScanResultsMaskRequest */ mask_across_hosts_and_images?: boolean; + /** + * + * @type {boolean} + * @memberof ModelScanResultsMaskRequest + */ + mask_in_this_host_or_image_tags?: boolean; /** * * @type {Array} @@ -82,6 +88,7 @@ export function ModelScanResultsMaskRequestFromJSONTyped(json: any, ignoreDiscri return { 'mask_across_hosts_and_images': !exists(json, 'mask_across_hosts_and_images') ? undefined : json['mask_across_hosts_and_images'], + 'mask_in_this_host_or_image_tags': !exists(json, 'mask_in_this_host_or_image_tags') ? undefined : json['mask_in_this_host_or_image_tags'], 'result_ids': json['result_ids'], 'scan_id': json['scan_id'], 'scan_type': json['scan_type'], @@ -98,6 +105,7 @@ export function ModelScanResultsMaskRequestToJSON(value?: ModelScanResultsMaskRe return { 'mask_across_hosts_and_images': value.mask_across_hosts_and_images, + 'mask_in_this_host_or_image_tags': value.mask_in_this_host_or_image_tags, 'result_ids': value.result_ids, 'scan_id': value.scan_id, 'scan_type': value.scan_type, diff --git a/deepfence_frontend/apps/dashboard/src/features/malwares/components/ResourceDetailModal.tsx b/deepfence_frontend/apps/dashboard/src/features/malwares/components/ResourceDetailModal.tsx new file mode 100644 index 0000000000..605e036fed --- /dev/null +++ b/deepfence_frontend/apps/dashboard/src/features/malwares/components/ResourceDetailModal.tsx @@ -0,0 +1,77 @@ +import { useSuspenseQuery } from '@suspensive/react-query'; +import { + SlidingModal, + SlidingModalCloseButton, + SlidingModalContent, + SlidingModalHeader, +} from 'ui-components'; + +import { TruncatedText } from '@/components/TruncatedText'; +import { + Metadata, + toTopologyMetadataString, +} from '@/features/topology/components/node-details/Metadata'; +import { queries } from '@/queries'; + +const useResourceDetails = ({ nodeId }: { nodeId: string }) => { + return useSuspenseQuery({ + ...queries.lookup.containerImage({ + nodeId: nodeId, + }), + }); +}; +export const ResourceDetailModal = ({ + nodeId, + open, + onClose, +}: { + nodeId: string; + open: boolean; + onClose: React.Dispatch>; +}) => { + const { data } = useResourceDetails({ + nodeId, + }); + + return ( + { + onClose(state); + }} + size="m" + > + + +
+
+ +
+
+
+ +
+ +
+
+
+ ); +}; diff --git a/deepfence_frontend/apps/dashboard/src/features/malwares/pages/MalwareDetailModal.tsx b/deepfence_frontend/apps/dashboard/src/features/malwares/pages/MalwareDetailModal.tsx index 348b75f4a9..724340b03c 100644 --- a/deepfence_frontend/apps/dashboard/src/features/malwares/pages/MalwareDetailModal.tsx +++ b/deepfence_frontend/apps/dashboard/src/features/malwares/pages/MalwareDetailModal.tsx @@ -1,5 +1,5 @@ import { useSuspenseQuery } from '@suspensive/react-query'; -import { Suspense } from 'react'; +import { Suspense, useState } from 'react'; import { useParams, useSearchParams } from 'react-router-dom'; import { Button, @@ -19,7 +19,7 @@ import { CopyLineIcon } from '@/components/icons/common/CopyLine'; import { PopOutIcon } from '@/components/icons/common/PopOut'; import { SeverityBadge } from '@/components/SeverityBadge'; import { MalwareIcon } from '@/components/sideNavigation/icons/Malware'; -import { TruncatedText } from '@/components/TruncatedText'; +import { ResourceDetailModal } from '@/features/malwares/components/ResourceDetailModal'; import { queries } from '@/queries'; import { formatMilliseconds } from '@/utils/date'; import { replacebyUppercaseCharacters } from '@/utils/label'; @@ -134,6 +134,8 @@ const DetailsComponent = () => { data: { data: malwares }, } = useGetMalwareDetails(); + const [showResourceModal, setShowResourceModal] = useState(false); + if (!malwares.length) { return (
@@ -196,8 +198,32 @@ const DetailsComponent = () => {
{malware.resources.map((resource) => { if (!resource.node_id || !resource.node_type) { + return null; + } + if (resource.node_type === 'container_image') { return ( - + <> + }> + {showResourceModal && ( + + )} + + + + ); } let redirectPath = ''; @@ -206,12 +232,6 @@ const DetailsComponent = () => { } else if (resource.node_type === 'container') { redirectPath = `container?containers=${resource.node_id}`; } - if (resource.node_type === 'pod') { - redirectPath = `pod?pods=${resource.name}`; - } - if (resource.node_type === 'kubernetes_cluster') { - redirectPath = `kubernetes_cluster?clusters=${resource.node_id}`; - } return ( { + return useSuspenseQuery({ + ...queries.lookup.containerImage({ + nodeId: nodeId, + }), + }); +}; +export const ResourceDetailModal = ({ + nodeId, + open, + onClose, +}: { + nodeId: string; + open: boolean; + onClose: React.Dispatch>; +}) => { + const { data } = useResourceDetails({ + nodeId, + }); + + return ( + { + onClose(state); + }} + size="m" + > + + +
+
+ +
+
+
+ +
+ +
+
+
+ ); +}; diff --git a/deepfence_frontend/apps/dashboard/src/features/secrets/pages/SecretDetailModal.tsx b/deepfence_frontend/apps/dashboard/src/features/secrets/pages/SecretDetailModal.tsx index 52a882cca0..13a138c22d 100644 --- a/deepfence_frontend/apps/dashboard/src/features/secrets/pages/SecretDetailModal.tsx +++ b/deepfence_frontend/apps/dashboard/src/features/secrets/pages/SecretDetailModal.tsx @@ -1,5 +1,5 @@ import { useSuspenseQuery } from '@suspensive/react-query'; -import { Suspense } from 'react'; +import { Suspense, useState } from 'react'; import { useParams, useSearchParams } from 'react-router-dom'; import { Button, @@ -19,7 +19,7 @@ import { CopyLineIcon } from '@/components/icons/common/CopyLine'; import { PopOutIcon } from '@/components/icons/common/PopOut'; import { SeverityBadge } from '@/components/SeverityBadge'; import { SecretsIcon } from '@/components/sideNavigation/icons/Secrets'; -import { TruncatedText } from '@/components/TruncatedText'; +import { ResourceDetailModal } from '@/features/secrets/components/ResourceDetailModal'; import { queries } from '@/queries'; import { formatMilliseconds } from '@/utils/date'; import { replacebyUppercaseCharacters } from '@/utils/label'; @@ -125,6 +125,8 @@ const DetailsComponent = () => { data: { data: secrets }, } = useGetSecretDetails(); + const [showResourceModal, setShowResourceModal] = useState(false); + if (!secrets.length) { return (
@@ -183,8 +185,32 @@ const DetailsComponent = () => {
{secret.resources.map((resource) => { if (!resource.node_id || !resource.node_type) { + return null; + } + if (resource.node_type === 'container_image') { return ( - + <> + }> + {showResourceModal && ( + + )} + + + + ); } let redirectPath = ''; @@ -193,12 +219,6 @@ const DetailsComponent = () => { } else if (resource.node_type === 'container') { redirectPath = `container?containers=${resource.node_id}`; } - if (resource.node_type === 'pod') { - redirectPath = `pod?pods=${resource.name}`; - } - if (resource.node_type === 'kubernetes_cluster') { - redirectPath = `kubernetes_cluster?clusters=${resource.node_id}`; - } return ( { + return useSuspenseQuery({ + ...queries.lookup.containerImage({ + nodeId: nodeId, + }), + }); +}; +export const ResourceDetailModal = ({ + nodeId, + open, + onClose, +}: { + nodeId: string; + open: boolean; + onClose: React.Dispatch>; +}) => { + const { data } = useResourceDetails({ + nodeId, + }); + + return ( + { + onClose(state); + }} + size="m" + > + + +
+
+ +
+
+
+ +
+ +
+
+
+ ); +}; diff --git a/deepfence_frontend/apps/dashboard/src/features/vulnerabilities/pages/VulnerabilityDetailModal.tsx b/deepfence_frontend/apps/dashboard/src/features/vulnerabilities/pages/VulnerabilityDetailModal.tsx index e1c6d46abf..ef5837fcd1 100644 --- a/deepfence_frontend/apps/dashboard/src/features/vulnerabilities/pages/VulnerabilityDetailModal.tsx +++ b/deepfence_frontend/apps/dashboard/src/features/vulnerabilities/pages/VulnerabilityDetailModal.tsx @@ -1,5 +1,5 @@ import { useSuspenseQuery } from '@suspensive/react-query'; -import { Suspense } from 'react'; +import { Suspense, useState } from 'react'; import { useParams, useSearchParams } from 'react-router-dom'; import { Button, @@ -19,7 +19,7 @@ import { CopyLineIcon } from '@/components/icons/common/CopyLine'; import { PopOutIcon } from '@/components/icons/common/PopOut'; import { CveCVSSScore, SeverityBadge } from '@/components/SeverityBadge'; import { VulnerabilityIcon } from '@/components/sideNavigation/icons/Vulnerability'; -import { TruncatedText } from '@/components/TruncatedText'; +import { ResourceDetailModal } from '@/features/vulnerabilities/components/ResourceDetailModal'; import { queries } from '@/queries'; import { formatMilliseconds } from '@/utils/date'; import { replacebyUppercaseCharacters } from '@/utils/label'; @@ -161,6 +161,8 @@ const DetailsComponent = () => { data: { data: cves }, } = useGetCVEDetails(); + const [showResourceModal, setShowResourceModal] = useState(false); + if (!cves.length) { return (
@@ -225,11 +227,35 @@ const DetailsComponent = () => {
Resources
-
+
{cve.resources.map((resource) => { if (!resource.node_id || !resource.node_type) { + return null; + } + if (resource.node_type === 'container_image') { return ( - + <> + }> + {showResourceModal && ( + + )} + + + + ); } let redirectPath = ''; @@ -238,12 +264,6 @@ const DetailsComponent = () => { } else if (resource.node_type === 'container') { redirectPath = `container?containers=${resource.node_id}`; } - if (resource.node_type === 'pod') { - redirectPath = `pod?pods=${resource.name}`; - } - if (resource.node_type === 'kubernetes_cluster') { - redirectPath = `kubernetes_cluster?clusters=${resource.node_id}`; - } return (