CrowdStrike Falcon (Event Streams)
Overview
CrowdStrike Falcon is a streaming source that holds a long-lived connection open to the Falcon Event Streams API (/sensors/entities/datafeed/v2) and emits each event as a log record into a Praxis pipeline.
Use it to get detections, incidents, and audit / user-activity events out of Falcon and into your SIEM in near real time. Unlike a polling source, the receiver does not fetch-and-close on a schedule: it keeps the datafeed connection open, reads newline-delimited JSON events as CrowdStrike pushes them, refreshes the session before it expires, and reconnects from the last persisted offset if the stream drops.
This is the Event Streams path, not FDR. Falcon Data Replicator delivers to an S3 bucket plus SQS queue and has no REST endpoint — it is a different integration. Event Streams is the REST feed, and the same API client unlocks it.
Supported types: Logs
Supported platforms: Linux, Windows, macOS
Minimum collector version: 0.3.10
Authentication
| Credential type | Fields |
|---|---|
CrowdStrike (crowdstrike) | client_id, client_secret |
Create the API client in the Falcon console under Support and resources → API clients and keys, and grant it the Event Streams: Read scope. Nothing else is required.
The collector performs the OAuth2 client-credentials exchange itself (POST /oauth2/token) and caches the access token. Your client secret is stored encrypted, masked in the API, and reaches the collector as a credential reference rather than in plaintext.
How the connection works
- Token — OAuth2 client-credentials exchange against
{endpoint}/oauth2/token, cached until shortly before expiry. - Discovery —
GET {endpoint}/sensors/entities/datafeed/v2?appId=<app_id>returns one or more partitions, each with its own datafeed URL and session token. - Stream — one worker per partition holds the datafeed open (
Authorization: Token <session token>) and reads NDJSON events. The HTTP timeout does not apply to this connection. - Refresh — the session is refreshed on the cadence CrowdStrike advertises (
refreshActiveSessionInterval), falling back to 25 minutes if discovery omits it. - Reconnect — on a drop, the worker waits
reconnect_backoff, doubling up toreconnect_max_backoff, then reopens atoffset = <last consumed> + 1.
Basic configuration
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
app_id | string | Yes | none | Names this consumer to CrowdStrike and defines the read-cursor lane. 1–32 characters of [a-zA-Z0-9_-]. See Choosing an App ID. |
endpoint | string (URI) | No | https://api.us-2.crowdstrike.com | Regional Falcon API base used for the token exchange and feed discovery. Must be https. See the region table below. |
persist_offsets | bool | No | true | Checkpoint the per-partition stream offset so restarts resume exactly, instead of falling back to CrowdStrike's approximate server-side checkpoint. See Resumption. |
Falcon API regions
| Cloud | endpoint |
|---|---|
| US-1 | https://api.crowdstrike.com |
| US-2 (default) | https://api.us-2.crowdstrike.com |
| EU-1 | https://api.eu-1.crowdstrike.com |
| US-GOV-1 | https://api.laggar.gcw.crowdstrike.com |
Pick the cloud your Falcon tenant lives in — an API client is only valid in its own region.
advanced
| Parameter | Type | Default | Description |
|---|---|---|---|
timeout | integer (seconds) | 30 | Timeout for the token, discovery and refresh calls. The long-poll stream itself is deliberately not bound by this. |
reconnect_backoff | integer (seconds) | 5 | Initial wait before reconnecting after the stream drops. Doubles on each successive failure. |
reconnect_max_backoff | integer (seconds) | 120 | Ceiling for the reconnect backoff. Must be >= reconnect_backoff. |
tls.insecure_skip_verify | bool | false | Disable TLS server certificate verification. Not recommended in production. |
tls.ca_file | string | none | Custom CA bundle for verifying the Falcon API. |
Choosing an App ID
app_id is not cosmetic — CrowdStrike keys the read cursor to it.
- Keep it stable. Reusing the same
app_idafter a restart or redeploy resumes the feed where it left off. - A new value starts a fresh, independent consumer with its own cursor. Changing
app_idis how you deliberately fork a second copy of the stream; doing it by accident silently re-reads or skips events. - One
app_idper consumer. Two collectors sharing anapp_idcompete for the same feed. If you need the same events in two pipelines, give each its ownapp_id.
Resumption
Each partition carries a monotonic offset. The receiver advances its cursor only after an event has been successfully consumed downstream, then reopens at offset = <last> + 1 after any disconnect.
With Persist Offsets on (the default), Praxis automatically provisions a storage extension for this node under the collector's metadata directory (<collector home>/metadata/crowdstrike_offsets/<node name>). Offsets survive a collector restart, not just a stream drop.
With it off, offsets live in memory only. Stream drops still resume exactly, but a collector restart falls back to CrowdStrike's own server-side checkpoint for the app_id, which is approximate — expect some duplication or a small gap.
An event whose JSON fails to parse is still forwarded downstream (nothing is silently dropped), but it does not advance the cursor, since its offset cannot be trusted.
Output mapping
Each NDJSON event becomes one log record.
| Falcon field | OTel destination |
|---|---|
| (whole event JSON) | LogRecord.Body (string) |
metadata.eventCreationTime (epoch ms) | LogRecord.Timestamp |
| (receive time) | LogRecord.ObservedTimestamp |
metadata.eventType | LogRecord.Attributes["crowdstrike.event_type"] |
| (partition index) | LogRecord.Attributes["crowdstrike.partition"] (int) |
metadata.offset is read for the resume cursor but deliberately not surfaced as an attribute — it is an internal stream position, not meaningful downstream.
Example configuration
{
"app_id": "praxis-prod", // required, 1-32 chars [a-zA-Z0-9_-]
"endpoint": "https://api.us-2.crowdstrike.com", // default: US-2
"persist_offsets": true, // default: true
"advanced": {
"timeout": 30, // default: 30 (control-plane calls only)
"reconnect_backoff": 5, // default: 5
"reconnect_max_backoff": 120, // default: 120
"tls": { "insecure_skip_verify": false }
}
}
Attach a crowdstrike credential to the node; client_id and client_secret are not part of the node config.
Operational notes
- The stream has no timeout.
advanced.timeoutgoverns the token, discovery and refresh calls only. A quiet Falcon tenant holding an idle connection open for hours is normal and is not a stall. - Partitions are CrowdStrike's choice. Discovery may return more than one datafeed resource; the receiver runs a worker per partition automatically. There is nothing to configure.
- Scope failures look like auth failures. An API client without
Event Streams: Readgets a token successfully and then fails at discovery. If the token exchange succeeds but discovery 403s, check the scope before the credentials. - Region mismatch fails at the token step. An API client from another Falcon cloud returns 401 against the wrong
endpoint.
Metrics
| Metric Name | Description |
|---|---|
prx_src_records_received_total{signal="logs"} | Log records emitted, one per Falcon event. |
prx_src_bytes_received_total | Raw NDJSON bytes read from the datafeed. |
prx_src_pipeline_latency_seconds | Arrival → downstream handoff. |
prx_src_errors_total{reason} | Source errors by reason — io for token, discovery, session-refresh and stream failures. |
prx_src_parse_errors_total{parser="json"} | Event whose JSON could not be decoded. It is still forwarded, but does not advance the offset. |
prx_src_records_dropped_total{reason="backpressure"} | Records dropped because the downstream pipeline refused them. |
prx_src_connections_total / _closed_total / _active | One connection per live partition stream. _active is the number of partitions currently streaming; a climbing _total against a flat _active means the feed keeps reconnecting. |