feat(sentinelone): scope threat and alert fetches to given accounts (v1.4.0)

A multi-tenant console returns every account's threats and alerts at once.
get_threats and get_alerts now take an optional account_ids input, passed
through as the accountIds query parameter, so an ingestion can be pinned to
the accounts the SOC actually watches.

The input is optional, so existing instances and running ingestions keep
their current behaviour.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Guillaume BOURGEOIS
2026-08-04 15:56:47 +02:00
parent 144089a099
commit 7efc873867
3 changed files with 7 additions and 2 deletions
+4 -2
View File
@@ -1,8 +1,8 @@
id: sentinelone id: sentinelone
name: SentinelOne name: SentinelOne
version: 1.3.0 version: 1.4.0
description: "SentinelOne Singularity (API v2.1) — endpoint detection & response: triage threats, enrich, isolate/reconnect hosts, mitigate, scan." description: "SentinelOne Singularity (API v2.1) — endpoint detection & response: triage threats, enrich, isolate/reconnect hosts, mitigate, scan."
changelog: "1.3.0 — Exhaustive OCSF mappers: get_threats (38 fields) and get_alerts (58 fields) now cover device, finding, malware, actor/target process, file, registry, network, indicators and container. 1.2.4 — Re-modelled the OCSF mappers to OCSF actor/target semantics: the initiating process maps to actor.* (actor.process, actor.user), and the process/file acted upon maps to the target (process.*, file.*, user.*). 1.2.3 — Expanded the OCSF mappers (get_threats, get_alerts) with more fields: file hashes (sha1/md5), file ext/size, finding/rule ids, confidence, status, parent process and device/user identity. 1.2.2 — Added pre-built OCSF mappers (get_threats, get_alerts) for the mapper library. 1.2.1 — Added test_connection for the instance Test button. 1.2.0 — Added 13 commands: threat-analysis, threat-download-from-cloud, abort-endpoint-scan, endpoint-fetch-logs, fetch-file, get-remote-script-task-status/results, get-service-users, list-installed-singularity-marketplace-applications, update-uam-alert-status/verdict, run-powerquery and create-tag-rule (83 commands total). 1.1.0 — Command names prefixed with 'sentinelone-' (e.g. sentinelone-isolate-agent) for easier toolbox search; command IDs unchanged. 1.0.0 — Initial release: 70 commands covering agents, threats, alerts, blocklist/exclusions, IOCs, STAR rules, Deep Visibility, remote scripts, tags, firewall and network discovery based on the SentinelOne API v2.1." changelog: "1.4.0 — get_threats and get_alerts accept an optional account_ids filter (accountIds), so a multi-tenant console can be scoped to one or more accounts at fetch time. 1.3.0 — Exhaustive OCSF mappers: get_threats (38 fields) and get_alerts (58 fields) now cover device, finding, malware, actor/target process, file, registry, network, indicators and container. 1.2.4 — Re-modelled the OCSF mappers to OCSF actor/target semantics: the initiating process maps to actor.* (actor.process, actor.user), and the process/file acted upon maps to the target (process.*, file.*, user.*). 1.2.3 — Expanded the OCSF mappers (get_threats, get_alerts) with more fields: file hashes (sha1/md5), file ext/size, finding/rule ids, confidence, status, parent process and device/user identity. 1.2.2 — Added pre-built OCSF mappers (get_threats, get_alerts) for the mapper library. 1.2.1 — Added test_connection for the instance Test button. 1.2.0 — Added 13 commands: threat-analysis, threat-download-from-cloud, abort-endpoint-scan, endpoint-fetch-logs, fetch-file, get-remote-script-task-status/results, get-service-users, list-installed-singularity-marketplace-applications, update-uam-alert-status/verdict, run-powerquery and create-tag-rule (83 commands total). 1.1.0 — Command names prefixed with 'sentinelone-' (e.g. sentinelone-isolate-agent) for easier toolbox search; command IDs unchanged. 1.0.0 — Initial release: 70 commands covering agents, threats, alerts, blocklist/exclusions, IOCs, STAR rules, Deep Visibility, remote scripts, tags, firewall and network discovery based on the SentinelOne API v2.1."
category: endpoint category: endpoint
# Per-instance configuration. The scripts build the API base as <url>/web/api/v2.1. # Per-instance configuration. The scripts build the API base as <url>/web/api/v2.1.
@@ -41,6 +41,7 @@ commands:
query: { type: string, description: "Free-text (hash, file, computer name, uuid)" } query: { type: string, description: "Free-text (hash, file, computer name, uuid)" }
threat_ids: { type: string, description: "Comma-separated threat IDs" } threat_ids: { type: string, description: "Comma-separated threat IDs" }
created_after: { type: string, description: "ISO8601 lower bound on createdAt" } created_after: { type: string, description: "ISO8601 lower bound on createdAt" }
account_ids: { type: string, description: "Optional comma-separated account IDs to scope the search to." }
required: [] required: []
outputs_schema: { properties: {} } outputs_schema: { properties: {} }
ingest: ingest:
@@ -289,6 +290,7 @@ commands:
analystVerdict: { type: string, description: "Filter by analyst verdict." } analystVerdict: { type: string, description: "Filter by analyst verdict." }
alert_ids: { type: string, description: "Comma-separated alert IDs." } alert_ids: { type: string, description: "Comma-separated alert IDs." }
site_ids: { type: string, description: "Comma-separated site IDs." } site_ids: { type: string, description: "Comma-separated site IDs." }
account_ids: { type: string, description: "Optional comma-separated account IDs to scope the search to." }
limit: { type: number, description: "Max results (default 100)." } limit: { type: number, description: "Max results (default 100)." }
required: [created_from] required: [created_from]
outputs_schema: { properties: {} } outputs_schema: { properties: {} }
@@ -31,6 +31,7 @@ def main():
"analystVerdict": inputs.get("analystVerdict"), "analystVerdict": inputs.get("analystVerdict"),
"ids": inputs.get("alert_ids"), "ids": inputs.get("alert_ids"),
"siteIds": inputs.get("site_ids"), "siteIds": inputs.get("site_ids"),
"accountIds": inputs.get("account_ids"),
"limit": int(inputs.get("limit") or 100), "limit": int(inputs.get("limit") or 100),
} }
url = base + "/cloud-detection/alerts?" + urllib.parse.urlencode({k: v for k, v in qs.items() if v not in (None, "")}) url = base + "/cloud-detection/alerts?" + urllib.parse.urlencode({k: v for k, v in qs.items() if v not in (None, "")})
@@ -27,6 +27,8 @@ def main():
qs["ids"] = str(inputs["threat_ids"]) qs["ids"] = str(inputs["threat_ids"])
if inputs.get("created_after"): if inputs.get("created_after"):
qs["createdAt__gt"] = str(inputs["created_after"]) qs["createdAt__gt"] = str(inputs["created_after"])
if inputs.get("account_ids"):
qs["accountIds"] = str(inputs["account_ids"])
url = base + "/threats?" + urllib.parse.urlencode(qs) url = base + "/threats?" + urllib.parse.urlencode(qs)
print(json.dumps(request("GET", url, headers))) print(json.dumps(request("GET", url, headers)))