Show services discovered by site agents as suggested targets

Stores the sanitised list per site, serves it at /sites/{id}/discovered and adds
it to the target picker. Needs a Reef release containing model.DiscoveredService.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
VeillaxandClaude Sonnet 5.5 committed 2026-10-27 16:57:35 -06:00
1 parent 39659f0144
commit 7e429a7be0
6 files changed
+90 -7

No files matched your search

+42
View File
@@ -4,6 +4,7 @@ import (
"errors"
"net"
"net/http"
"net/netip"
"sort"
"strings"
"time"
@@ -291,6 +292,47 @@ func (s *Server) siteContainers(w http.ResponseWriter, r *http.Request, c *orgCt
writeJSON(w, 200, out)
}
// cleanDiscovered keeps what an agent reports as suggestions only if it is well formed: it is shown in
// the dashboard, so lengths are bounded and anything that is not a plain address is dropped.
func cleanDiscovered(in []model.DiscoveredService) []model.DiscoveredService {
out := []model.DiscoveredService{}
clip := func(s string, n int) string {
if len(s) > n {
s = s[:n]
}
return strings.ToValidUTF8(s, "")
}
for _, d := range in {
if len(out) >= 500 {
break
}
if _, err := netip.ParseAddr(d.Host); err != nil || d.Port < 1 || d.Port > 65535 {
continue
}
src := "scan"
if d.Source == "local" {
src = "local"
}
out = append(out, model.DiscoveredService{Host: d.Host, Port: d.Port, Proto: "tcp", Service: clip(d.Service, 20), Detail: clip(d.Detail, 160), Source: src})
}
return out
}
func (s *Server) siteDiscovered(w http.ResponseWriter, r *http.Request, c *orgCtx) {
s.mu.Lock()
defer s.mu.Unlock()
st := s.findSite(r.PathValue("id"))
if st == nil || !s.siteVisible(c, st) {
fail(w, 404, errors.New("no such site"))
return
}
out := s.discovered[st.ID]
if out == nil {
out = []model.DiscoveredService{}
}
writeJSON(w, 200, out)
}
// ---------- domains ----------
func domainsOverlap(a, b string) bool {