Improve fleet control, Crucible ops, and multi-machine identity.
Use hostname-first agent names so the same forged binary on many machines stays distinct at scale. Add WebSocket RTT latency on the roster and Crucible, fleet delete and uninstall flows, live alert config reload, and non-blocking pool setup. Fix Crucible phantom agents after delete, posture scan targeting, and USB portability (config data_dir, LAUNCH sync).
This commit is contained in:
@@ -417,6 +417,55 @@ func EstimateXMRPerDay(hashrate float64) map[string]interface{} {
|
||||
}
|
||||
}
|
||||
|
||||
// DeleteAgent removes an agent record from the database.
|
||||
// If the agent is currently online it is also disconnected (kicked).
|
||||
func (f *FleetHandler) DeleteAgent(w http.ResponseWriter, r *http.Request) {
|
||||
id := chi.URLParam(r, "id")
|
||||
if id == "" {
|
||||
http.Error(w, "missing agent id", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
// Kick live connection first (non-fatal if offline).
|
||||
if f.ws != nil {
|
||||
_ = f.ws.SendToAgent(id, Message{Type: "disconnect", Payload: mustMarshalFleet(map[string]string{"reason": "deleted from roster"})})
|
||||
f.ws.RemoveAgent(id)
|
||||
}
|
||||
if err := f.db.DeleteAgent(id); err != nil {
|
||||
http.Error(w, "delete failed: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(map[string]bool{"success": true})
|
||||
}
|
||||
|
||||
// BulkDeleteAgents deletes multiple agents from the database in one call.
|
||||
func (f *FleetHandler) BulkDeleteAgents(w http.ResponseWriter, r *http.Request) {
|
||||
var req struct {
|
||||
IDs []string `json:"ids"`
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil || len(req.IDs) == 0 {
|
||||
http.Error(w, "ids required", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
deleted := 0
|
||||
for _, id := range req.IDs {
|
||||
if f.ws != nil {
|
||||
_ = f.ws.SendToAgent(id, Message{Type: "disconnect", Payload: mustMarshalFleet(map[string]string{"reason": "deleted from roster"})})
|
||||
f.ws.RemoveAgent(id)
|
||||
}
|
||||
if err := f.db.DeleteAgent(id); err == nil {
|
||||
deleted++
|
||||
}
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(map[string]interface{}{"success": true, "deleted": deleted})
|
||||
}
|
||||
|
||||
func mustMarshalFleet(v interface{}) json.RawMessage {
|
||||
b, _ := json.Marshal(v)
|
||||
return b
|
||||
}
|
||||
|
||||
func parseFloatQuery(r *http.Request, key string, def float64) float64 {
|
||||
v := r.URL.Query().Get(key)
|
||||
if v == "" {
|
||||
|
||||
Reference in New Issue
Block a user