Add tiered LOTL mining onion and fleet recon so agents can fallback across execution tiers while operators see spread and vuln posture in Crucible. Includes triple-onion chain, spread cred graph, and full Go/TS/E2E test validation.
This commit is contained in:
@@ -2,6 +2,7 @@ package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
@@ -57,6 +58,71 @@ func TestListAgentsEmptyArray(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestListAgentsPaginated(t *testing.T) {
|
||||
h := newTestHandler(t)
|
||||
for i := 0; i < 5; i++ {
|
||||
if err := h.db.UpsertAgent(&models.Agent{
|
||||
ID: fmt.Sprintf("agent-%d", i), Name: "n", Status: "online",
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/v1/agents?limit=2&offset=1", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
h.ListAgents(rec, req)
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("status %d body %s", rec.Code, rec.Body.String())
|
||||
}
|
||||
var body struct {
|
||||
Agents []json.RawMessage `json:"agents"`
|
||||
Total int `json:"total"`
|
||||
Limit int `json:"limit"`
|
||||
Offset int `json:"offset"`
|
||||
}
|
||||
if err := json.Unmarshal(rec.Body.Bytes(), &body); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(body.Agents) != 2 || body.Total != 5 || body.Limit != 2 || body.Offset != 1 {
|
||||
t.Fatalf("unexpected paginated body: %+v", body)
|
||||
}
|
||||
}
|
||||
|
||||
func TestListAgentsSubnetFilter(t *testing.T) {
|
||||
h := newTestHandler(t)
|
||||
agents := []struct {
|
||||
id, ip string
|
||||
}{
|
||||
{"subnet-a", "10.0.1.10"},
|
||||
{"subnet-b", "10.0.2.20"},
|
||||
{"subnet-c", "192.168.1.5"},
|
||||
}
|
||||
for _, a := range agents {
|
||||
if err := h.db.UpsertAgent(&models.Agent{
|
||||
ID: a.id, Name: a.id, IP: a.ip, Status: "online",
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/v1/agents?limit=50&subnet=10.0.1.x", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
h.ListAgents(rec, req)
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("status %d body %s", rec.Code, rec.Body.String())
|
||||
}
|
||||
var body struct {
|
||||
Agents []struct {
|
||||
ID string `json:"id"`
|
||||
} `json:"agents"`
|
||||
Total int `json:"total"`
|
||||
}
|
||||
if err := json.Unmarshal(rec.Body.Bytes(), &body); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if body.Total != 1 || len(body.Agents) != 1 || body.Agents[0].ID != "subnet-a" {
|
||||
t.Fatalf("unexpected subnet filter body: %+v", body)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAgentStatsLimitCap(t *testing.T) {
|
||||
h := newTestHandler(t)
|
||||
req := httptest.NewRequest(http.MethodGet, "/agents/missing-agent/stats?limit=5000", nil)
|
||||
|
||||
Reference in New Issue
Block a user