Ship logs to IBM QRadar
Use this guide to stream your Audit Logs to IBM QRadar. Firezone delivers events as newline-delimited JSON, one event per line, to a QRadar HTTP Receiver log source.
Step 1: Configure a QRadar HTTP Receiver
- In QRadar, open the Admin tab, choose Log Sources, and add a log source with the HTTP Receiver protocol. On QRadar on Cloud, the receiver runs on your data gateway.
- Set Communication Type to
HTTPs, pick a Listen Port, which defaults to12469, set Message Pattern to\{"type":"so each event in a delivery is parsed separately, and raise Max Payload Length to32767so large events are not split. - Deploy the changes and allow inbound HTTPS from the internet to the listen port.
The receiver must present a TLS certificate from a publicly trusted CA. QRadar's self-signed default will not work. Replace it, or put a TLS-terminating proxy in front of the receiver.
Step 2: Create the Log Sink in Firezone
In the admin portal, go to SettingsLog Sinks, click Add, and select IBM QRadar. Configure the sink:
| Field | Description |
|---|---|
| Name | A name to identify this log sink. |
| Endpoint URL | The public HTTPS URL of the HTTP Receiver, including its listen port, for example https://qradar.example.com:12469. |
| Authorization Header | Optional. Sent as the Authorization header on every delivery, for example Bearer my-secret-token. QRadar's HTTP Receiver ignores it. Set it when a proxy in front of the receiver requires authentication. |
The endpoint URL must be HTTPS, and hostnames that resolve to private or reserved IP addresses are rejected.
Then choose which Log streams to deliver, all four of which are enabled by default, and optionally check Deliver existing logs to backfill logs recorded before the sink was created.
Deliver existing logs can only be selected when you create the sink. It can't be turned on later for an existing sink.
Click Create. Deliveries begin within about a minute.
Delivery format
Firezone POSTs newline-delimited JSON with content type
application/x-ndjson. Each line is
one event with type and log_id guaranteed to appear first. That's what
the \{"type":" Message Pattern keys on to split events:
{
"type": "change",
"log_id": "c0654d20aa1b4a0000000002",
"timestamp": "2026-07-14T09:26:31.114213Z",
"object": "policies",
"operation": "update",
"before": { "id": "0a83588e-…", "description": "Engineering → GitLab" },
"after": {
"id": "0a83588e-…",
"description": "Engineering → GitLab (MFA required)"
},
"subject": {
"actor_id": "e2f6a9c4-…",
"actor_name": "Jamie Admin",
"actor_email": "jamie@company.com",
"actor_type": "account_admin_user",
"auth_provider_id": "9d0c2f4e-…",
"ip": "203.0.113.44",
"ip_region": "US",
"ip_city": "San Francisco",
"ip_lat": 37.7749,
"ip_lon": -122.4194,
"user_agent": "Mozilla/5.0 …"
}
}
{
"type": "session",
"log_id": "53f2c8a91b7e4d20a6c19e04",
"timestamp": "2026-07-14T09:26:31.114213Z",
"context": "client",
"subject": {
"actor_id": "7a1d9e3c-…",
"actor_name": "Riley Engineer",
"actor_email": "riley@company.com",
"actor_type": "account_user",
"auth_provider_id": "9d0c2f4e-…",
"device_id": "2b4d6f8a-…",
"token_id": "c4e6a8b0-…",
"ip": "203.0.113.44",
"ip_region": "US",
"ip_city": "San Francisco",
"ip_lat": 37.7749,
"ip_lon": -122.4194,
"user_agent": "Firezone/1.4.0 (macOS 15.5; arm64)"
}
}
{
"type": "api_request",
"log_id": "a7b3e91c4d208f5a6e1b2c3d",
"timestamp": "2026-07-14T09:26:31.114213Z",
"actor_id": "b8e0c2a4-…",
"api_token_id": "d0f2a4c6-…",
"method": "GET",
"path": "/policies",
"content_length": 0,
"request_id": "F8nMlbf6MUyJZUUABBzB9-yT",
"user_agent": "terraform-provider-firezone/0.4.1",
"ip": "203.0.113.44",
"ip_region": "US",
"ip_city": "San Francisco",
"ip_lat": 37.7749,
"ip_lon": -122.4194
}
Each flow is delivered as two events sharing its log_id. The start event
is suffixed with -s and carries no counters, while the end event is
suffixed with -e and carries the final totals:
{
"type": "flow",
"log_id": "f4e8a2c61b09d735e2a48b17-e",
"timestamp": "2026-07-14T09:26:01.000000Z",
"flow_start": "2026-07-14T09:25:31.000000Z",
"flow_end": "2026-07-14T09:26:01.000000Z",
"last_packet": "2026-07-14T09:26:01.000000Z",
"device_id": "2b4d6f8a-…",
"role": "initiator",
"policy_authorization_id": "6c8e0a2b-…",
"policy_id": "0a83588e-…",
"resource_id": "5c8f6f6e-…",
"resource_name": "GitLab",
"resource_address": "gitlab.company.com",
"actor_id": "7a1d9e3c-…",
"actor_email": "riley@company.com",
"actor_name": "Riley Engineer",
"client_version": "1.4.0",
"device_os_name": "iOS",
"device_os_version": "17.4",
"protocol": "tcp",
"inner_src_ip": "100.64.0.1",
"inner_src_port": 54321,
"inner_dst_ip": "10.0.0.5",
"inner_dst_port": 443,
"outer_src_ip": "203.0.113.10",
"outer_src_port": 51820,
"outer_dst_ip": "198.51.100.5",
"outer_dst_port": 51820,
"domain": "gitlab.company.com",
"rx_packets": 100,
"tx_packets": 80,
"rx_bytes": 102400,
"tx_bytes": 20480
}
How Firezone responds to HTTP status codes
| Response | Behavior |
|---|---|
2xx | The batch is accepted and delivery advances. |
429, 5xx | Retried every minute. If failures persist for 24 hours, the sink is disabled and account admins are emailed. |
413 | The batch is split in half and retried to isolate an oversized event. |
401, 403, 407 | Treated as a configuration error: a proxy in front of the receiver rejected the request, so check the Authorization Header. The sink is disabled immediately. |
Other 4xx or redirect | Treated as a configuration error: the sink is disabled immediately. A redirect usually means the URL is missing the listen port. |
Duplicates and redelivery
Firezone guarantees at-least-once delivery, retrying any batch that isn't
acknowledged rather than risk losing data, so QRadar can occasionally receive
the same event twice. When it does, deduplicate on log_id: flow start and
end events are already suffixed with -s and -e, which makes the log_id
a unique key across all streams.
Recovering a failed sink
A sink showing Warning is retrying automatically, so unless the failures continue there's nothing you need to do. A sink showing Error has stopped delivering and needs attention: fix the cause , commonly an expired TLS certificate, a firewall blocking the listen port, or proxy credentials, then open the sink, click Edit, and click Save to re-enable it. Delivery picks up right where it left off, from the last acknowledged entry, and Deliver Now triggers a delivery immediately if you don't want to wait for the next cycle.
Deleting the sink deletes its delivery state along with it, so re-creating it starts fresh: the new sink delivers logs recorded from its creation onward, plus a full backfill if Deliver existing logs is selected, which re-sends events QRadar may already have.
Need help? See all support options.