skills: add datto-edr (Datto EDR / Infocyte HUNT) + syncro-rmm memory
New /datto-edr skill — standalone CLI for the Datto EDR REST API (azcomp4587, rebranded Infocyte HUNT, raw-token LoopBack). Live-verified reads across the whole MSP fleet: orgs/sites/agents/detections/sweep + deploy-cmd. Scan/isolate gated behind --confirm (shape-verified, not run against prod). Token vaulted at msp-tools/datto-edr.sops.yaml. Also: reference_syncro_rmm_api_gui_only memory (Syncro RMM policy mgmt is GUI-only) and the guru-rmm submodule pointer bump (Feature 6 EDR research). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -228,9 +228,23 @@ class DattoEDRClient:
|
||||
"alertCount": True, "locationCount": True},
|
||||
}) or []
|
||||
|
||||
def list_locations(self, org_id: Optional[str] = None, limit: int = 500) -> list[dict]:
|
||||
"""List Locations (= client sites). VERIFIED LIVE. This is the per-client
|
||||
grouping that agents belong to (Agent.locationId -> Location.id), and a
|
||||
Location carries organizationId. Org -> Locations -> Agents is the
|
||||
inventory hierarchy."""
|
||||
filt: dict = {"limit": limit, "order": "name ASC",
|
||||
"fields": {"id": True, "name": True, "organizationId": True,
|
||||
"agentCount": True, "activeAgentCount": True,
|
||||
"alertCount": True, "lastScannedOn": True}}
|
||||
if org_id:
|
||||
filt["where"] = {"organizationId": org_id}
|
||||
return self._get("Locations", filt) or []
|
||||
|
||||
def list_targets(self, org_id: Optional[str] = None, limit: int = 500) -> list[dict]:
|
||||
"""List Targets (= target groups / sites). VERIFIED LIVE.
|
||||
Each Target belongs to an Organization via organizationId."""
|
||||
"""List Targets (= SCAN target groups). VERIFIED LIVE. Distinct from
|
||||
Locations: a Target is the scannable unit (POST targets/{id}/scan). Each
|
||||
Target belongs to an Organization via organizationId."""
|
||||
filt: dict = {"limit": limit, "order": "name ASC",
|
||||
"fields": {"id": True, "name": True, "organizationId": True,
|
||||
"agentCount": True, "activeAgentCount": True,
|
||||
@@ -239,16 +253,17 @@ class DattoEDRClient:
|
||||
filt["where"] = {"organizationId": org_id}
|
||||
return self._get("Targets", filt) or []
|
||||
|
||||
def list_agents(self, org_id: Optional[str] = None,
|
||||
target_group_id: Optional[str] = None,
|
||||
def list_agents(self, location_id: Optional[str] = None,
|
||||
location_ids: Optional[list[str]] = None,
|
||||
limit: int = 500) -> list[dict]:
|
||||
"""List Agents (endpoints). VERIFIED LIVE.
|
||||
Filter by deviceGroupId (target group). Org filtering is done by the CLI
|
||||
via the target-group->org map since Agents carry deviceGroupId, not orgId."""
|
||||
"""List Agents (endpoints). VERIFIED LIVE. Filter by locationId (a single
|
||||
site) or location_ids (an org's sites, via LoopBack `inq`)."""
|
||||
filt: dict = {"limit": limit, "order": "hostname ASC"}
|
||||
where: dict = {}
|
||||
if target_group_id:
|
||||
where["deviceGroupId"] = target_group_id
|
||||
if location_id:
|
||||
where["locationId"] = location_id
|
||||
elif location_ids:
|
||||
where["locationId"] = {"inq": location_ids}
|
||||
if where:
|
||||
filt["where"] = where
|
||||
return self._get("Agents", filt) or []
|
||||
|
||||
Reference in New Issue
Block a user