diff --git a/deepfence_agent/tools/apache/scope/probe/docker/reporter.go b/deepfence_agent/tools/apache/scope/probe/docker/reporter.go index 3d98c949db..dcc42ff3d2 100644 --- a/deepfence_agent/tools/apache/scope/probe/docker/reporter.go +++ b/deepfence_agent/tools/apache/scope/probe/docker/reporter.go @@ -51,9 +51,10 @@ func (r *Reporter) Report() (report.Report, error) { return report.MakeReport(), nil } + var imageIDTagMap map[string]basicImage result := report.MakeReport() - result.Container = r.containerTopology(localAddrs) - result.ContainerImage = r.containerImageTopology() + result.ContainerImage, imageIDTagMap = r.containerImageTopology() + result.Container = r.containerTopology(localAddrs, imageIDTagMap) result.Overlay = r.overlayTopology() return result, nil } @@ -73,7 +74,7 @@ func getLocalIPs() ([]string, []net.IP, error) { return ips, addrs, nil } -func (r *Reporter) containerTopology(localAddrs []net.IP) report.Topology { +func (r *Reporter) containerTopology(localAddrs []net.IP, imageIDTagMap map[string]basicImage) report.Topology { result := report.MakeTopology() nodes := []report.TopologyNode{} r.registry.WalkContainers(func(c Container) { @@ -117,6 +118,11 @@ func (r *Reporter) containerTopology(localAddrs []net.IP) report.Topology { if node.Metadata.NodeID == "" { continue } + if basicImageDetails, ok := imageIDTagMap[node.Metadata.DockerImageID]; ok { + node.Metadata.ImageNameWithTag = basicImageDetails.ImageNameWithTag + node.Metadata.ImageName = basicImageDetails.ImageName + node.Metadata.ImageTag = basicImageDetails.ImageTag + } var isInHostNamespace bool node.Sets, isInHostNamespace = networkInfo(node.Metadata.NodeID) tags, ok := containerImageTags[node.Metadata.NodeID] @@ -141,9 +147,16 @@ func (r *Reporter) containerTopology(localAddrs []net.IP) report.Topology { return result } -func (r *Reporter) containerImageTopology() report.Topology { +type basicImage struct { + ImageName string `json:"docker_image_name,omitempty"` + ImageNameWithTag string `json:"docker_image_name_with_tag,omitempty"` + ImageTag string `json:"docker_image_tag,omitempty"` +} + +func (r *Reporter) containerImageTopology() (report.Topology, map[string]basicImage) { result := report.MakeTopology() imageTagsMap := r.registry.GetImageTags() + imageIDTagMap := make(map[string]basicImage) r.registry.WalkImages(func(image docker_client.APIImages) { imageID := trimImageID(image.ID) shortImageID := getShortImageID(imageID) @@ -165,6 +178,11 @@ func (r *Reporter) containerImageTopology() report.Topology { metadata.ImageNameWithTag = imageFullName metadata.ImageName = ImageNameWithoutTag(imageFullName) metadata.ImageTag = ImageNameTag(imageFullName) + imageIDTagMap[imageID] = basicImage{ + ImageName: metadata.ImageName, + ImageNameWithTag: metadata.ImageNameWithTag, + ImageTag: metadata.ImageTag, + } } var tags []string var ok bool @@ -194,7 +212,7 @@ func (r *Reporter) containerImageTopology() report.Topology { }) }) - return result + return result, imageIDTagMap } func (r *Reporter) overlayTopology() report.Topology { diff --git a/deepfence_server/handler/completion.go b/deepfence_server/handler/completion.go index 1364f2e70a..ff5a465aec 100644 --- a/deepfence_server/handler/completion.go +++ b/deepfence_server/handler/completion.go @@ -46,6 +46,10 @@ func (h *Handler) CompleteContainerInfo(w http.ResponseWriter, r *http.Request) genericCompleteInfoHandler[model.Container](w, r, h) } +func (h *Handler) CompleteContainerImageInfo(w http.ResponseWriter, r *http.Request) { + genericCompleteInfoHandler[model.ContainerImage](w, r, h) +} + func genericCompleteInfoHandler[T reporters.Cypherable](w http.ResponseWriter, r *http.Request, h *Handler) { defer r.Body.Close() var req completion.CompletionNodeFieldReq diff --git a/deepfence_server/model/lookup.go b/deepfence_server/model/lookup.go index faffddf04d..4b03e04931 100644 --- a/deepfence_server/model/lookup.go +++ b/deepfence_server/model/lookup.go @@ -217,6 +217,7 @@ type Container struct { Processes []Process `json:"processes" required:"true"` DockerLabels map[string]interface{} `json:"docker_labels" required:"true" nested_json:"true"` HostName string `json:"host_name" required:"true"` + DockerImageNameWithTag string `json:"docker_image_name_with_tag" required:"true"` DockerContainerCommand string `json:"docker_container_command" required:"true"` DockerContainerState string `json:"docker_container_state" required:"true"` DockerContainerStateHuman string `json:"docker_container_state_human" required:"true"` diff --git a/deepfence_server/router/router.go b/deepfence_server/router/router.go index 7cd8a1f863..87de02e6fd 100644 --- a/deepfence_server/router/router.go +++ b/deepfence_server/router/router.go @@ -274,6 +274,7 @@ func SetupRoutes(r *chi.Mux, serverPort string, serveOpenapiDocs bool, ingestC c r.Post("/compliance", dfHandler.CompleteComplianceInfo) r.Post("/pod", dfHandler.CompletePodInfo) r.Post("/container", dfHandler.CompleteContainerInfo) + r.Post("/containerimage", dfHandler.CompleteContainerImageInfo) }) r.Route("/search", func(r chi.Router) {