> ## Documentation Index
> Fetch the complete documentation index at: https://docs.casebender.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Splunk

> Bi-directional integration between CaseBender and Splunk (Enterprise Security) for notable/alert ingestion, HEC audit forwarding, and notable close-out sync.

## Overview

The Splunk integration (**INT-001**) provides **bi-directional** synchronization between
CaseBender and Splunk, including **Splunk Enterprise Security (ES)** notable events.

<CardGroup cols={2}>
  <Card title="Inbound Ingestion" icon="arrow-right-to-bracket">
    Splunk notables and alerts are ingested into CaseBender — either **pulled
    automatically** on a schedule via the ES REST search API, or **pushed** from a
    Splunk alert action / webhook — then normalized, enriched with observables,
    and turned into alerts (or cases).
  </Card>

  <Card title="Outbound Sync" icon="arrow-right-from-bracket">
    Case lifecycle events are forwarded to a Splunk index via **HEC**, and when a
    linked case is closed CaseBender can **close the originating ES notable** via
    the REST API with an audit comment.
  </Card>
</CardGroup>

<Tip>
  **Two inbound paths.** Use **alert-action / webhook (push)** if you already
  build Splunk alerts, or **automatic polling (pull)** if you'd rather have
  CaseBender run a saved search on a schedule. Polling requires the Enterprise
  Security REST connection; the webhook path does not.
</Tip>

<Note>
  Outbound HEC uses the **HTTP Event Collector** (default `/services/collector/event`,
  usually port `8088`). Notable pull and close-out use the **management REST API**
  (usually port `8089`). On-prem Splunk commonly uses **self-signed certificates** on
  both — set **Verify SSL** off if needed (see below).
</Note>

## Capabilities

| Capability                     | Direction | Description                                                                                                                |
| ------------------------------ | --------- | -------------------------------------------------------------------------------------------------------------------------- |
| **Notable polling (pull)**     | Inbound   | CaseBender runs your SPL on a schedule via the ES REST search API and ingests results automatically — no Splunk-side setup |
| Alert ingestion (push)         | Inbound   | Splunk alert actions / webhooks post payloads that are normalized into CaseBender alerts                                   |
| Observable extraction          | Inbound   | `src`/`dest`/`user` (and `*_ip`) fields become IP / hostname / user observables                                            |
| Asset extraction               | Inbound   | `host` (and non-IP `dest`) become host assets                                                                              |
| Auto-create cases              | Inbound   | Ingested records can be promoted to Cases automatically (deduped by notable ID)                                            |
| HEC audit forwarding           | Outbound  | Case create/update/close and alert promotion are logged to a Splunk index                                                  |
| Notable close-out (write-back) | Outbound  | On case close, the originating ES notable is set to Closed with a comment via `notable_update`                             |
| Connection test                | Outbound  | Sends a test event to the HEC endpoint                                                                                     |

## Prerequisites

<Steps>
  <Step title="Splunk access">
    A Splunk deployment. For notable pull/close-out you need **Splunk Enterprise
    Security** and a role with the `edit_notable_events` capability. For HEC
    forwarding you need an **HTTP Event Collector** token.
  </Step>

  <Step title="Network egress">
    The CaseBender deployment (and the background poller service, for polling)
    must be able to reach your Splunk **HEC** endpoint (e.g. `:8088`) and, for
    REST features, the **management** endpoint (e.g. `:8089`).
  </Step>

  <Step title="CaseBender administrator role">
    You must be able to create and manage integrations in **Settings → Integrations**.
  </Step>
</Steps>

## Part A — Prepare Splunk

<Steps>
  <Step title="Create an HEC token (for outbound forwarding)">
    In Splunk, go to **Settings → Data inputs → HTTP Event Collector → New Token**.
    Enable HEC globally if it isn't already, choose (or create) a target index, and
    copy the token value.
  </Step>

  <Step title="Create an authentication token (for REST features)">
    For notable **polling** and **close-out**, create a Splunk **authentication
    token** under **Settings → Tokens** (or use a service account for Basic auth).
    The associated role needs `edit_notable_events` to close notables and search
    access to your notable index.
  </Step>
</Steps>

## Part B — Configure the integration in CaseBender

<Steps>
  <Step title="Open the integration catalog">
    Go to **Settings → Integrations → Create**, then choose **Splunk** from the
    **SIEM** category.
  </Step>

  <Step title="Choose a purpose">
    Set `purpose` to **Inbound**, **Outbound**, or **Bidirectional** to show the
    relevant configuration cards.
  </Step>

  <Step title="Configure inbound webhook (push)">
    Copy the **Webhook URL** and generate an **API key** (prefixed `sk_splunk_`).
    In Splunk, add a **Webhook** alert action that posts to the URL with header
    `Authorization: Bearer <API_KEY>`.
  </Step>

  <Step title="Configure the Enterprise Security REST connection (optional)">
    In the **Enterprise Security REST API** card, enter the management URL (e.g.
    `https://splunk:8089`) and credentials:

    | Field                           | Description                                     |
    | ------------------------------- | ----------------------------------------------- |
    | `restUrl`                       | Splunk management URI (usually port 8089)       |
    | `restAuthType`                  | `token` (bearer) or `basic` (username/password) |
    | `restToken`                     | Splunk authentication token (bearer)            |
    | `restUsername` / `restPassword` | Basic-auth credentials                          |

    This connection powers both notable **polling** and **close-out**.
  </Step>

  <Step title="Enable automatic polling (optional)">
    In the **Automatic polling** card, turn on **Enable automatic polling** and set:

    | Option                        | Effect                                                                                |
    | ----------------------------- | ------------------------------------------------------------------------------------- |
    | `pollingEnabled`              | Turn on scheduled pulling of Splunk results                                           |
    | `searchQuery`                 | SPL run each interval, e.g. `` search `notable` `` (must start with `search` or `\|`) |
    | `pollingIntervalMinutes`      | How often to poll (default `5`, range 1–1440)                                         |
    | `pollingInitialLookbackHours` | On first run, import results from within this window (default `24`, range 1–168)      |

    See [Automatic polling](#inbound-automatic-polling) for how it works.
  </Step>

  <Step title="Configure outbound (HEC + notable close)">
    In the **Outbound** card, enter the HEC URL, token, and index, then enable:

    | Option                    | Effect                                                                         |
    | ------------------------- | ------------------------------------------------------------------------------ |
    | `syncCaseUpdates`         | Forward `case_created` / `case_updated` / `alert_promoted` audit events to HEC |
    | `syncCaseClose`           | Forward a `case_closed` audit event to HEC                                     |
    | `closeNotableOnCaseClose` | Close the originating ES **notable** via REST when a linked case is closed     |
    | `autoCreateCases`         | Promote each ingested Splunk record to a **Case** automatically                |
  </Step>

  <Step title="Test the connection">
    Use **Test Connection** to send a test event to the HEC endpoint. If your
    Splunk uses a self-signed certificate, turn **Verify SSL** off.
  </Step>
</Steps>

## Inbound (automatic polling)

With **Automatic polling** enabled, CaseBender periodically runs your SPL through the
Enterprise Security REST search API and ingests the results on its own — **no Splunk-side
alert action or webhook is required**.

### How it works

<Steps>
  <Step title="Scheduled search">
    On each interval (`pollingIntervalMinutes`), CaseBender runs `searchQuery` over the window
    since the last cursor via the streaming export endpoint:

    ```
    POST https://<splunk>:8089/services/search/jobs/export
        search=<your SPL>&earliest_time=<cursor>&latest_time=now&output_mode=json
    ```

    On the very first run there is no cursor, so results from within
    `pollingInitialLookbackHours` are imported.
  </Step>

  <Step title="Cursor + deduplication">
    CaseBender advances a per-integration cursor to the newest result `_time` it has seen, so
    each run only fetches new activity. Results are also **deduplicated by notable `event_id`**
    (falling back to the search `sid`), so a notable is never ingested twice — even if the
    polling window overlaps.
  </Step>

  <Step title="Normalization">
    Each result row is normalized into a CaseBender alert — mapping severity from `urgency`,
    building the title/description, and extracting observables and host assets. The notable
    `event_id` is stamped onto the alert so outbound close-out can find it later.
  </Step>
</Steps>

<Note>
  With **`autoCreateCases` enabled**, each polled notable becomes a **Case** automatically
  (deduplicated by notable ID) — this matches the "pull notable → work it as a case" flow.
  With it disabled, results land in the **Alerts** inbox for manual promotion. Either way the
  Splunk link is preserved so closing the case can close the notable.
</Note>

<Info>
  Polling runs in CaseBender's background poller service. Ensure that service can reach your
  Splunk management endpoint (directly or via your configured proxy). Internal Splunk hosts
  should be listed in `NO_PROXY` on proxy-only networks.
</Info>

## Inbound (webhook / push)

As an alternative (or in addition) to polling, a Splunk **alert action** (or any webhook
sender) can push search results to the CaseBender ingestion endpoint.

### Endpoint

```
POST https://<your-casebender-domain>/api/v1/ingest/splunk
```

Requests are authenticated with an integration **API key** passed as
`Authorization: Bearer <key>` (the `x-api-key` header is also accepted). Splunk webhook API
keys are prefixed with `sk_splunk_`.

### Payload example

Splunk's webhook alert action posts a `result` object plus search metadata:

```bash theme={null}
curl -X POST "https://<your-casebender-domain>/api/v1/ingest/splunk" \
  -H "Authorization: Bearer sk_splunk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "sid": "scheduler__admin__search__RMD5...",
    "search_name": "Threat - Brute Force Access - Rule",
    "results_link": "https://splunk.example.com/app/search/...",
    "app": "SplunkEnterpriseSecuritySuite",
    "result": {
      "event_id": "A1B2C3D4-...",
      "rule_title": "Brute Force Access Behavior Detected",
      "urgency": "high",
      "security_domain": "access",
      "src": "10.0.0.5",
      "dest": "10.0.0.20",
      "user": "jdoe"
    }
  }'
```

A successful request returns HTTP `202 Accepted`:

```json theme={null}
{ "success": true, "messageId": "..." }
```

### Processing pipeline

<Steps>
  <Step title="Ingestion proxy">
    `/api/v1/ingest/splunk` validates the source and forwards the request to the ingestion
    service (`POST /v1/sources/splunk`).
  </Step>

  <Step title="Queue publish">
    The ingestion service authenticates the API key, validates the payload, and publishes the
    record to the processing queue.
  </Step>

  <Step title="Normalization">
    The Splunk processor normalizes the record into a CaseBender alert — mapping severity,
    building the title/description, and extracting observables and host assets.
  </Step>
</Steps>

### Data mapping reference

**Severity mapping** (Splunk `urgency` → CaseBender 1–4):

| Splunk urgency          | CaseBender severity |
| ----------------------- | ------------------- |
| `critical`              | 4                   |
| `high`                  | 3                   |
| `medium`                | 2                   |
| `low` / `informational` | 1                   |

**Observable / asset extraction:**

| Splunk field       | Observable / asset                  |
| ------------------ | ----------------------------------- |
| `src` / `src_ip`   | `ip` or `hostname` observable (IOC) |
| `dest` / `dest_ip` | `ip` or `hostname` observable       |
| `user`             | `user` observable                   |
| `host`             | host asset                          |

**Title** is built from `rule_title` → `search_name` → `alert_name` → `signature` →
`message`. **Tags** applied on ingest include `splunk`, `siem`, `notable` (for ES notables),
`domain:<security_domain>`, and `app:<app>`. Ingested records default to **TLP:2** and
**PAP:2**.

## Outbound: HEC audit forwarding

When enabled with `syncCaseUpdates` / `syncCaseClose`, CaseBender posts JSON audit events to
your HEC endpoint so case activity is searchable in Splunk:

| Event          | HEC `action`             | Gate              |
| -------------- | ------------------------ | ----------------- |
| Case created   | `case_created`           | `syncCaseUpdates` |
| Case updated   | `case_updated`           | `syncCaseUpdates` |
| Alert promoted | `alert_promoted_to_case` | `syncCaseUpdates` |
| Case closed    | `case_closed`            | `syncCaseClose`   |

Events are sent with `source: casebender:case` (or `casebender:alert`) and `sourcetype: _json`
to the configured index.

## Outbound: Closing the Splunk notable (write-back)

When a case is closed in CaseBender, the `case_closed` event is dispatched to the Splunk
handler. If the case is linked to a Splunk notable **and** `closeNotableOnCaseClose` is on,
CaseBender closes the notable through the ES REST API.

### How the linked notable is resolved

The ingest pipeline stamps `splunkEventId` (the notable `event_id`) and the ingesting
integration ID onto each Splunk alert's `customFields`. On case close, the handler collects
those event IDs from the alerts linked to the case, so a case promoted from a polled or
webhook notable resolves automatically — regardless of how it was created.

### What is sent

CaseBender calls the ES `notable_update` endpoint:

```
POST https://<splunk>:8089/services/notable_update
    ruleUIDs=["<event_id>", ...]&status=<code>&comment=<comment>&output_mode=json
```

* `status` defaults to **5 (Closed)** and is configurable via `notableStatusOnClose`.
* `comment` is: `Case <id> closed in CaseBender with resolution: <resolution>`.

The outcome (notables closed, or an error) is written to the case timeline so analysts can
confirm the sync.

<Note>
  `syncCaseClose` (HEC audit event) and `closeNotableOnCaseClose` (REST notable write-back)
  are independent per-integration toggles. Notable write-back requires the Enterprise Security
  REST connection and a role with the `edit_notable_events` capability.
</Note>

## Security considerations

* **Token handling** — HEC tokens and REST tokens/passwords are stored in the integration
  settings; rotate them on your organization's schedule and update the integration when you do.
* **Least privilege** — the REST role only needs search access to your notable index and
  `edit_notable_events`. HEC tokens should target a dedicated index.
* **Webhook keys** — treat the `sk_splunk_` API key as a secret. Rotate it if exposed and
  update the Splunk alert action.
* **TLS** — prefer trusted certificates. If you must use self-signed certs (common on-prem),
  **Verify SSL** can be turned off; the connection is still encrypted but the certificate is
  not validated. Restrict egress to your Splunk HEC and management endpoints.

## Troubleshooting

<AccordionGroup>
  <Accordion title="Test Connection fails or times out">
    Confirm the HEC URL and token, that HEC is enabled, and that CaseBender can reach the HEC
    port (usually `8088`). If Splunk uses a self-signed certificate, turn **Verify SSL** off —
    otherwise the request fails with a certificate error.
  </Accordion>

  <Accordion title="Ingestion returns 401 Unauthorized">
    The `Authorization: Bearer` (or `x-api-key`) header is missing or invalid. Confirm you are
    sending the `sk_splunk_` key that matches the integration's configured webhook API key.
  </Accordion>

  <Accordion title="Polling is enabled but no notables appear">
    Confirm **Enable automatic polling** is on, the **ES REST** connection is filled in, and a
    **search query** is set. Verify the role can run the search and reach the management port
    (usually `8089`), and that there are results newer than the cursor. On first run only
    results within `pollingInitialLookbackHours` are imported. Check the integration's last
    sync status for the specific error.
  </Accordion>

  <Accordion title="Case close doesn't close the Splunk notable">
    Ensure `closeNotableOnCaseClose` is on and the **ES REST** connection is configured with a
    role that has `edit_notable_events`. The case must be linked to a Splunk notable — closing
    a case promoted from a polled/webhook notable resolves the link automatically. Check the
    case timeline for the sync result.
  </Accordion>

  <Accordion title="notable_update returns 403 or 404">
    A `403` means the REST role lacks the `edit_notable_events` capability. A `404` usually
    means the URL isn't the Enterprise Security management endpoint — confirm `restUrl` points
    at Splunk's management port with ES installed.
  </Accordion>

  <Accordion title="Self-signed certificate errors behind a proxy">
    On proxy-only networks, add your internal Splunk host to `NO_PROXY` so the connection goes
    direct, and turn **Verify SSL** off if the cert is self-signed.
  </Accordion>
</AccordionGroup>

## Related documentation

* [Integrations overview](./introduction.mdx)
* [Splunk HTTP Event Collector](https://docs.splunk.com/Documentation/Splunk/latest/Data/UsetheHTTPEventCollector)
* [Splunk ES notable event actions](https://docs.splunk.com/Documentation/ES/latest/User/Triagenotableevents)
