---
name: azion-stream-waf-events-to-a-siem
description: >-
  Create a stream that sends the requests WAF analyzed to your SIEM, in Azion Console or with the Azion API, and confirm the delivery.
---

# Stream WAF events to a SIEM

You can send the events of Web Application Firewall (WAF) to a security information and event management (SIEM) platform from Azion Console or with the Azion API. To send the requests of your applications without WAF data, refer to [Endpoints](/en/documentation/platform/data-stream/endpoints/) and the guide of your endpoint.

A [Data Stream](/en/documentation/platform/data-stream/) stream reads the *WAF Events* data source and shapes each event with the *WAF Event Collector* template. Each log line carries the score the request received, the WAF rules it matched, the attack family, and the action WAF took. For every variable, refer to [WAF Events](/en/documentation/platform/data-stream/data-sources-and-variables/#waf-events).

The example sends the events to an Apache Kafka topic that your SIEM reads. In the stream form, the endpoint is set in the field labeled **Connector**.

---

Select your interface once. The prerequisites and every task below show only that path.

## Prerequisites

- An Azion account with the **Edit Data Stream** permission. For the permissions, refer to [Stream settings](/en/documentation/platform/data-stream/stream-settings/#permissions).
- [Firewall](/en/documentation/platform/firewall/) with WAF on the account, protecting a [workload](/en/documentation/platform/workloads/) that receives requests. To set up WAF, refer to the [WAF quickstart](/en/documentation/platform/firewall/waf/quickstart/).
- An endpoint that your SIEM reads. This guide uses an Apache Kafka cluster, with the host and port of its servers for the initial connection and the name of one topic. For the other endpoints a stream can send to, refer to [Endpoints](/en/documentation/platform/data-stream/endpoints/).

**Console**

- Access to Azion Console. To sign in, refer to [How to access Azion Console](/en/documentation/guides/platform/account-and-billing/how-to-access-azion-console/).

**API**

- A personal token. To create one, refer to [How to manage a personal token](/en/documentation/guides/platform/account-and-billing/personal-tokens/).
- The ID of the workload that WAF protects.
- `curl`.

---

## Create the stream

The stream collects the WAF events of the workload you choose, through a workload filter. Unlike sampling, a workload filter leaves your other streams active.

**Console**

To create the stream in Azion Console:

1. **Open Data Stream**

   Access [Azion Console](https://console.azion.com/) > **Data Stream**.

2. **Select + Stream**

3. **Name the stream**

   In the **General** section, enter a **Name**. For example: `waf-to-siem`.

4. **Select the WAF Events data source**

   In the **Input** section, select *WAF Events* in **Data Source**.

5. **Turn off Sampling**

   In the **Transform** section, turn off **Sampling** while **Option** is still *All Current and Future Workloads*, its starting value. A stream cannot carry sampling and a workload filter together.

6. **Choose the workload**

   In the **Transform** section, set **Option** to *Filter Workloads*. In **Available Workload**, select the workload that WAF protects and move it to **Chosen Workload** with the arrow.

7. **Select the template**

   In the **Render Template** section, select *WAF Event Collector* in **Template**. The **Data Set** field shows the keys of each log line.

8. **Select the endpoint**

   In the **Output** section, select *Apache Kafka* in **Connector**. For another SIEM, select its option, such as *Splunk*, *IBM QRadar*, or *Elasticsearch*, and enter the fields that [Endpoints](/en/documentation/platform/data-stream/endpoints/) lists for it.

9. **Enter the bootstrap servers**

   In **Bootstrap Servers**, enter each server as `host:port`, separated by a comma and no space. For example: `kafka1.example.com:9092,kafka2.example.com:9092`.

10. **Enter the topic**

    In **Kafka Topic**, enter the name of the topic your SIEM reads. For example: `azion.waf`.

11. **(Optional) Turn on TLS**

    Turn on **Enable Transport Layer Security (TLS)** to send the events encrypted. The receiving servers need a certificate from a trusted certificate authority.

12. **Keep the stream active**

    In the **Status** section, keep **Active** turned on.

13. **Select Save**

The Console shows `Your data stream has been created`. The stream appears in the **Data Stream** list with `waf` in the **Source** column and the *Active* status.

**API**

To create the stream with the API, send a `POST` request to `https://api.azion.com/v4/workspace/stream/streams`. Replace `[TOKEN VALUE]` with your personal token, `<workload-id>` with the ID of your workload, and the cluster values with your own:

```bash
curl -X POST 'https://api.azion.com/v4/workspace/stream/streams' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Token [TOKEN VALUE]' \
  -d '{
    "name": "waf-to-siem",
    "active": true,
    "inputs": [
      { "type": "raw_logs", "attributes": { "data_source": "waf" } }
    ],
    "transform": [
      { "type": "filter_workloads", "attributes": { "workloads": [<workload-id>] } },
      { "type": "render_template", "attributes": { "template": 4 } }
    ],
    "outputs": [
      {
        "type": "kafka",
        "attributes": {
          "bootstrap_servers": "kafka1.example.com:9092,kafka2.example.com:9092",
          "kafka_topic": "azion.waf",
          "use_tls": true
        }
      }
    ]
  }'
```

The `waf` data source is *WAF Events* in the Console, and template `4` is *WAF Event Collector*. The API requires `kafka_topic` and `use_tls`: send `true` to encrypt the events with TLS, or `false` to send them unencrypted. A `201` answer carries the stored stream under `data`. Keep its `id`: it identifies the stream in every later request, such as `/v4/workspace/stream/streams/<stream-id>`. For every key of the body, refer to [Stream settings](/en/documentation/platform/data-stream/stream-settings/#stream-object).

Saving the stream checks the format of each field and does not contact the cluster. A wrong server address or topic surfaces only when the stream sends. An activation takes effect after one to two minutes.

---

## Confirm the delivery

[Real-Time Events](/en/documentation/platform/real-time-events/data-sources/#data-stream) records every send of a stream, delivered or not, with the status code the endpoint returned. Send a few requests to the workload that WAF analyzes, then wait about a minute. A stream sends a batch every 60 seconds, or sooner when it reaches 2,000 log lines.

**Console**

To find the sends in Azion Console:

1. **Open Real-Time Events**

   Access [Azion Console](https://console.azion.com/) > **Real-Time Events**.

2. **Select the Data Stream data source**

3. **Read the latest sends**

   Each row is one send. Find the rows whose **Endpoint Type** matches your endpoint, and read their **Status Code**.

A **Status Code** of `200` means the endpoint accepted the batch. **Streamed Lines** gives the number of log lines in the batch.

**API**

To read the sends with the API, query the `dataStreamedEvents` dataset of the Real-Time Events GraphQL API. Replace the dates with a range that covers the activation of the stream:

```bash
curl -X POST 'https://api.azion.com/v4/events/graphql' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Token [TOKEN VALUE]' \
  -d '{"query":"query { dataStreamedEvents(limit: 20, filter: {tsRange: {begin: \"2026-01-01T11:30:00\", end: \"2026-01-01T13:00:00\"}}, orderBy: [ts_DESC]) { ts endpointType statusCode streamedLines dataStreamed } }"}'
```

The API answers `200` with one record for each send, the latest first. For a stream that sends to S3, a record reads as below. Your records carry the type of your endpoint in `endpointType`:

```json
{
  "data": {
    "dataStreamedEvents": [
      {
        "ts": "2026-01-01T12:00:00Z",
        "endpointType": "S3",
        "statusCode": 200,
        "streamedLines": 2,
        "dataStreamed": 2797
      }
    ]
  }
}
```

A `statusCode` of `200` means the endpoint accepted the batch, whose size `streamedLines` gives in log lines and `dataStreamed` in bytes. An empty `dataStreamedEvents` list means the stream has not sent in the range. For every field, refer to [Real-Time Events GraphQL fields](/en/documentation/devtools/graphql/gql-real-time-events-fields/#datastreamedevents-data-stream).

A status other than `200` is the answer of the endpoint, and `503` means Data Stream found the endpoint unavailable. For the causes, refer to [Troubleshoot Data Stream](/en/documentation/platform/data-stream/troubleshooting/).

At the SIEM, each log line carries the keys of the *WAF Event Collector* template. Read these keys to check that the events are the ones WAF analyzed:

- `waf_attack_action` holds the action WAF took, such as `$BLOCK` or `$PASS`.
- `waf_attack_family` holds the class of the infraction, such as `SQL` or `XSS`.
- `waf_score` and `waf_match` hold the score of the request and the infractions it matched.
- `blocked` reads `1` when WAF blocked the request. While `waf_learning` reads `1`, WAF blocks no request.

To correlate these events with the request data of your applications in one log line, use the *Applications* data source with the *Applications + WAF Event Collector* template instead. For the tradeoff, refer to [Best practices for Data Stream](/en/documentation/platform/data-stream/best-practices/#use-the-applications--waf-event-collector-preset-to-feed-a-siem).

---

## Next steps

- [Data sources and variables](/en/documentation/platform/data-stream/data-sources-and-variables.md#waf-events): Read what each variable of the WAF Events data source holds, with an example value.
- [Endpoints](/en/documentation/platform/data-stream/endpoints.md): Find the fields of the endpoint your SIEM reads, with their bounds and API names.
- [Send logs to Apache Kafka](/en/documentation/guides/platform/observability/endpoint-apache-kafka.md): Set the bootstrap servers, the topic, and TLS for an Apache Kafka endpoint.
- [Troubleshoot Data Stream](/en/documentation/platform/data-stream/troubleshooting.md): Find what to change when a send returns a status other than 200.
- [Block attackers automatically from SIEM detections](/en/documentation/use-cases/secure-applications-and-networks/block-attackers-automatically-from-siem-detections.md): A design where the SIEM's detections on these events come back as blocks in a network list.
