elastic / elastic/integrations

[Salesforce] Add AuraRequest data stream for Lightning UI access monitoring

Open
#20,330 2 comments 0 reactions 1 assignee Claimed by @brijesh-elastic View on GitHub
enhancement Integration:salesforce Team:SDE-Crest Team:Security-Service Integrations
Dominant language
Handlebars
Stars
333
Forks
647
Avg merge
3d 4h
Merged PRs (30d)
209

Description

## Summary

Add a new `aura_request` data stream to the Salesforce integration that collects the **`AuraRequest`** event data — the server-side Aura framework requests that Lightning Experience makes when users load pages, open records, or components fetch data. This is effectively the **record- and component-level access log for the modern Salesforce UI**, and it is a gap in our current SIEM coverage.

## Problem

The `salesforce` package today ships only `login`, `logout`, `apex`, and `setupaudittrail`. There is no visibility into Lightning UI activity, which is where most day-to-day user interaction with records happens. Competing connectors that ingest the full EventLogFile pick up `AuraRequest` automatically; we don't, because our integration collects only a narrow, hardcoded set of event types. Customer demand is documented in #7506 (flags `AuraRequest` as high priority) and the broader security-events requests #15469 and #15659.

## Collection — two poll-based paths (no streaming required)

`AuraRequest` is available through **two API-poll mechanisms**, both compatible with the existing Filebeat `salesforce` input. Neither needs Pub/Sub/streaming.

1. **Primary — EventLogFile** (`event_monitoring_method.event_log_file`): SOQL `SELECT ... FROM EventLogFile WHERE EventType = 'AuraRequest'`, then download the CSV `LogFile`. This mirrors the existing `apex` stream exactly. Broadest edition/API-version support. Batch (hourly/daily).
2. **Optional enhancement — `AuraRequestEventLog` SObject** (`event_monitoring_method.object`, API 61.0+): plain SOQL `query()` against the queryable `AuraRequestEventLog` object (supported calls: `describeSObjects()`, `query()`). Fresher/near-real-time data via the same polling model the integration already uses for `LoginEvent`/`SetupAuditTrail`. Same semantics as the ELF type, CamelCase field names.

## Proposed solution

Add one data stream, `aura_request`, following the existing `apex` stream pattern:

- **Input:** reuse the `salesforce` input with `event_monitoring_method.event_log_file` (primary). Optionally expose the `AuraRequestEventLog` object path for API 61.0+ orgs, normalising its CamelCase fields to the same ECS output.
- **Ingest pipeline:** parse the AuraRequest columns, type-cast timing fields, map to ECS.
- **Field mappings:** `fields.yml` for AuraRequest columns + shared ELF fields.
- **Dashboard:** one Kibana dashboard (mirror Login/Apex): request volume by user, top accessed URIs/pages, requests by source IP, failed/authorization-error requests, guest-user activity.
- **Tests, docs, changelog:** pipeline test with the sample below; README stream section; changelog + minor version bump.

## Fields and ECS mapping

Field list confirmed against the Salesforce Object Reference (Aura Request Event Type, v258.0). Note: this event type has **no** `CONTROLLER`/`METHOD`/`ACTION`/`APP_NAME`/`QUIDDITY` columns — per-action detail is carried in the single compound `ACTION_MESSAGE` string.

| Column | ECS / target field | Notes |
|---|---|---|
| `EVENT_TYPE` | `event.provider` (const `AuraRequest`) | |
| `TIMESTAMP_DERIVED` | `@timestamp` | ISO-8601 |
| `TIMESTAMP` | drop | superseded by derived |
| `REQUEST_ID` | `salesforce.aura.request_id` | correlates events in one transaction |
| `ORGANIZATION_ID` | `salesforce.organization_id` | |
| `USER_ID` / `USER_ID_DERIVED` | `user.id` / `salesforce.user.id_derived` | |
| `CLIENT_IP` | `source.ip` + `related.ip` | guard the literal `Salesforce.com IP` sentinel value |
| `LOGIN_KEY` | `salesforce.aura.login_key` | login-session correlation |
| `SESSION_KEY` | `salesforce.aura.session_key` | |
| `USER_TYPE` | `salesforce.user.type` | `Guest`, `Standard`, … — key for guest-user abuse detection |
| `RUN_TIME` (ms) | `event.duration` (× 1e6 → ns) + `salesforce.aura.run_time_ms` | |
| `CPU_TIME` (ms) | `salesforce.aura.cpu_time_ms` | |
| `DB_TOTAL_TIME` (ns) | `salesforce.aura.db_total_time_ns` | |
| `URI` | `url.path` | usually `/aura` |
| `URI_ID_DERIVED` | `salesforce.aura.uri_id` | the meaningful page ID |
| `REQUEST_METHOD` | `http.request.method` | GET/POST |
| `REQUEST_STATUS` | `event.outcome` | S→success; F/A/N→failure; U/R→unknown |
| `ACTION_MESSAGE` | `salesforce.aura.action_message` | `Method=time;Method=time`; optionally parse to `salesforce.aura.actions[]` |
| `USER_AGENT` | `salesforce.aura.user_agent_code` | **numeric code, NOT a UA string** — do not map to ECS `user_agent.*` |

Static: `event.category: ["web"]`, `event.type: ["access"]`, `event.kind: "event"`, `event.action: "aura-request"`.

The `AuraRequestEventLog` object exposes the same fields in CamelCase (`ActionMessage`, `ClientIp`, `CpuTime`, `DatabaseTotalTime`, `RequestMethod`, `RequestStatus`, `RunTime`, `Timestamp`, `Uri`, `UserAgent`, `UserIdentifier`, `UserType`, …) — normalise to the same ECS output.

## Sample event

No official sample exists (Salesforce's Example cell is empty). Constructed from the confirmed field list with anonymised, format-valid values.

Raw EventLogFile CSV (header + one row):

```csv
"EVENT_TYPE","TIMESTAMP","REQUEST_ID","ORGANIZATION_ID","USER_ID","USER_ID_DERIVED","CLIENT_IP","URI","URI_ID_DERIVED","SESSION_KEY","LOGIN_KEY","RUN_TIME","CPU_TIME","DB_TOTAL_TIME","REQUEST_METHOD","REQUEST_STATUS","ACTION_MESSAGE","USER_AGENT","USER_TYPE","TIMESTAMP_DERIVED"
"AuraRequest","20260715233322.670","3nWgxWbDKWWDIk0FKfF5DV","00D000000000123","00530000009M943","00590000000I1SNIA0","203.0.113.45","/aura","0Ai000000000abcAAM","d7DEq/ANa7nNZZVD","GeJCsym5eyvtEK2I","254","118","41960000","POST","S","AccountController.getAccounts=142;ContactController.getContacts=98","Mozilla","Standard","2026-07-15T23:33:22.670Z"
```

ECS-shaped document after the pipeline:

```json
{
"@timestamp": "2026-07-15T23:33:22.670Z",
"event": { "provider": "AuraRequest", "category": ["web"], "type": ["access"],
"kind": "event", "action": "aura-request", "outcome": "success",
"duration": 254000000 },
"http": { "request": { "method": "POST" } },
"url": { "path": "/aura" },
"source": { "ip": "203.0.113.45" },
"related": { "ip": ["203.0.113.45"], "user": ["00530000009M943"] },
"user": { "id": "00530000009M943" },
"salesforce": {
"organization_id": "00D000000000123",
"user": { "id_derived": "00590000000I1SNIA0", "type": "Standard" },
"aura": {
"request_id": "3nWgxWbDKWWDIk0FKfF5DV",
"session_key": "d7DEq/ANa7nNZZVD", "login_key": "GeJCsym5eyvtEK2I",
"uri_id": "0Ai000000000abcAAM",
"run_time_ms": 254, "cpu_time_ms": 118, "db_total_time_ns": 41960000,
"user_agent_code": "Mozilla",
"action_message": "AccountController.getAccounts=142;ContactController.getContacts=98"
}
}
}
```

## SIEM value

- UI-based data scraping / mass record enumeration through Lightning.
- Guest-user anomalous access (`USER_TYPE=Guest`) — the classic Salesforce Communities public-data exposure class.
- Failed / authorization-error spikes via `REQUEST_STATUS` (F/A/N).
- Recon / abnormal access correlated with a new `CLIENT_IP` or session against Login.
- Per-user access-volume baselining.

## Notes / constraints

- **Licensing:** `AuraRequest` requires the Salesforce **Event Monitoring / Shield** add-on (not in the free-tier ELF set). The `AuraRequestEventLog` object's licensing is undocumented but almost certainly the same — verify against a sandbox. Document this; degrade gracefully.
- **Volume:** Aura requests are high-volume (every Lightning interaction). Document ingest impact; consider a sensible default field set.
- **Latency:** EventLogFile is batch (hours) — forensic/audit-grade, not real-time detection. The `AuraRequestEventLog` object is fresher.
- **Column order is not contractual** and Salesforce can emit undocumented columns — the pipeline must parse by header name, and the mapping should be validated against a real CSV header from a sandbox with Event Monitoring before freezing.
- `USER_AGENT` is a numeric code, not a user-agent string — do not map to ECS `user_agent.*`.

## Out of scope

- Real-Time Event Monitoring / Pub/Sub streaming input (tracked separately).
- ThreatDetection anomaly events.
- Other EventLogFile event types (separate issues).

## Acceptance criteria

- [ ] `aura_request` data stream collects `AuraRequest` via the existing salesforce input (EventLogFile path).
- [ ] Optional `AuraRequestEventLog` object path available for API 61.0+ orgs, normalised to the same ECS.
- [ ] Fields mapped to ECS per the table above; `elastic-package test` (pipeline + system) passing.
- [ ] Kibana dashboard added.
- [ ] README + changelog updated; version bumped.

## References

- #7506, #15469, #15659
- [Aura Request Event Type — Salesforce Object Reference](https://developer.salesforce.com/docs/atlas.en-us.object_reference.meta/object_reference/sforce_api_objects_eventlogfile_lightning_component.htm)
- [AuraRequestEventLog object (API 61.0+, SOQL-queryable)](https://developer.salesforce.com/docs/atlas.en-us.object_reference.meta/api/sforce_api_objects_aurarequesteventlog.htm)
- [EventLogFile Supported Event Types](https://developer.salesforce.com/docs/atlas.en-us.object_reference.meta/object_reference/sforce_api_objects_eventlogfile_supportedeventtypes.htm)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.