2 Commits

Author SHA1 Message Date
f3nris 2d6e097742 fix(rapid7-insightidr): explain the process-tree 404 (v1.9.1)
Running the command on an alert reports `{"error": "HTTP 404", "detail": ""}`.
The API returns 404 with an empty body, so the operator is told a number and
nothing else — and cannot tell a normal answer from a fault.

It is usually normal, and the URL is not at fault: it is built exactly as
get_alert_evidence builds its own, which works. Rapid7 uses the same 404 for
three unrelated situations and does not distinguish them:

  - the alert is not an endpoint detection, so no tree exists. This is the
    common case on a feed of ingress_auth, asset_auth or firewall events;

  - the tree exists in principle but was never generated. The endpoint returns
    the CACHED tree unless force_refresh is set, so an ungenerated tree answers
    404 while its data is there. Retrying with force_refresh=true is the first
    thing to try on an endpoint detection;

  - the key lacks the privilege.

All three are now named in the error, and the force_refresh input says what it
is really for rather than describing it only as a staleness control.

The ingestion path already handled this correctly — it treats 404 as "no tree"
and counts only other statuses as errors — so nothing changes there.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 15:56:23 +02:00
f3nris da44d41555 feat(rapid7-insightidr): add the Alert Triage API commands (v1.1.0)
An ingested investigation carried almost nothing: title, priority, status,
assignee and timestamps. Not a host, not an account, not a command line — so
no entity was ever indexed, and neither the pivot graph nor the AI analysis
had anything to read. Fetching the investigation's alerts did not help: that
endpoint answers with the rule name (already the investigation's title), the
alert source and an alert RRN, and nothing else.

The detection content lives in a different API. The Alert Triage API is served
under /idr/at — its own base, next to /idr/v1 and /idr/v2 — and it is where
the evidence, the actors, the MITRE T-codes and the process trees actually
are. It was missing from this package entirely.

Six read commands:

  search_alerts            POST /alerts/ops/search
  get_alert                GET  /alerts/{rrn}
  get_alert_evidence       GET  /alerts/{rrn}/evidences
  get_alert_actors         GET  /alerts/{rrn}/actors
  get_alert_process_trees  POST /alerts/{rrn}/process_trees/latest
  list_alert_fields        GET  /alerts/2/fields

search_alerts is the one that changes the shape of the feed. It returns full
alert objects — rule with its mitre_tcodes, rule_keys_of_interest, the
AI-suggested disposition, the parent investigation RRN, the status transition
timings and the log entries behind the alert — and its start_time is required
by the API, which makes it a natural incremental watermark. So the alerts can
be read directly, paginated, with no per-investigation fan-out.

Two things worth knowing before using them:

  - field_ids is not optional in practice. The API returns no additional
    fields when it is empty, and those additional fields are where the
    hostnames, accounts and command lines are. Their ids are per-tenant dotted
    paths (process.cmd_line, …), which is what list_alert_fields is for.
    /alerts/fields is deprecated, hence /alerts/2/fields.

  - the whole API is gated on Managed Detection and Response with access to
    the Alerts experience. A key that works on every investigation endpoint
    can still be refused here, so 401 and 403 are reported with that named
    explanation rather than as a bare status code — a licence boundary should
    not read as a bug.

Written against the published OpenAPI spec (SIEM Alerts API 39.10.0); not yet
exercised against a live tenant.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-07 22:31:12 +02:00