Windows Event Collector (WEC)
Synopsis
Creates a Windows Event Collector (WEC) server that accepts event forwarding connections from Windows clients using the WS-Management (WS-Man) protocol. Supports Kerberos/SPNEGO and TLS mutual authentication, subscription-based event filtering, bookmark persistence for resumable collection, SLDC/LZNT1 decompression, and multiple workers for high-throughput scenarios.
Schema
- id: <numeric>
name: <string>
description: <string>
type: wec
tags: <string[]>
pipelines: <pipeline[]>
status: <boolean>
properties:
address: <string>
port: <numeric>
hostname: <string>
reuse: <boolean>
workers: <numeric>
buffer_size: <numeric>
backpressure_policy: <string>
max_active_requests: <numeric>
max_requests_per_socket: <numeric>
use_x_forwarded_for: <boolean>
capture_request_headers: <boolean>
allow_machine_id_mismatch: <boolean>
ip_allowlist_regex: <string>
ip_denylist_regex: <string>
tls:
status: <boolean>
cert_name: <string>
key_name: <string>
client_auth: <numeric>
client_ca_cert_file: <string>
kerberos_keytabs:
- keytab: <string>
spn: <string>
auth:
require_auth: <boolean>
allowed_cert_cns: <string[]>
allowed_cert_sans: <string[]>
subscriptions:
- id: <string>
name: <string>
channel: <string>
query: <string>
content_format: <string>
read_existing_events: <boolean>
send_bookmarks: <boolean>
compress: <boolean>
targets: <string[]>
fields:
- name: <string>
value: <string>
queue:
interval: <numeric>
batch_size: <numeric>
Configuration
The following fields are used to define the device:
Device
| Field | Required | Default | Description |
|---|---|---|---|
id | Y | Unique identifier | |
name | Y | Device name | |
description | N | - | Optional description |
type | Y | Must be wec | |
tags | N | - | Optional tags |
pipelines | N | - | Optional pre-processor pipelines |
status | N | true | Enable/disable the device |
Connection
| Field | Required | Default | Description |
|---|---|---|---|
address | N | "0.0.0.0" | Listen address |
port | Y | Listen port (typically 5985 for HTTP or 5986 for HTTPS) | |
hostname | N | listen address | FQDN advertised to clients in subscription endpoint URIs |
If address is 0.0.0.0, set hostname explicitly to a client-resolvable FQDN.
TLS
| Field | Required | Default | Description |
|---|---|---|---|
tls.status | N | false | Enable TLS encryption |
tls.cert_name | N* | TLS certificate file name (required if TLS enabled) | |
tls.key_name | N* | TLS private key file name (required if TLS enabled) | |
tls.client_auth | N | 0 | TLS client authentication mode (maps to tls.ClientAuthType) |
tls.client_ca_cert_file | N | Path to PEM-encoded CA certificate used to verify client certificates |
* = Conditionally required (only when tls.status: true)
TLS certificate and key files must be placed in the service root directory. Port 5986 is the standard WEF/HTTPS port. Plain HTTP on port 5985 is not recommended for production.
Authentication
| Field | Required | Default | Description |
|---|---|---|---|
auth.require_auth | N | false | Reject unauthenticated requests |
auth.allowed_cert_cns | N | - | List of allowed client certificate Common Names |
auth.allowed_cert_sans | N | - | List of allowed client certificate Subject Alternative Names |
Kerberos / SPNEGO
Multiple keytab entries are supported so a single listener can serve clients enrolled in different Kerberos realms.
| Field | Required | Default | Description |
|---|---|---|---|
kerberos_keytabs[].keytab | N* | Base64-encoded keytab file content | |
kerberos_keytabs[].spn | N* | Service Principal Name, e.g. HTTP/wec.corp.com |
* = Both fields must be provided together per entry. Entries missing either field are skipped with a warning.
Keytab data is provided as base64-encoded bytes so no physical keytab file is required on the host. Each entry in kerberos_keytabs is tried in order; the first entry that successfully authenticates the client wins.
Subscriptions
Each subscription defines a set of events that Windows clients will forward to this collector. Clients receive the list of subscriptions during enumeration and begin forwarding matching events automatically.
| Field | Required | Default | Description |
|---|---|---|---|
subscriptions[].id | Y | Unique subscription identifier (used in endpoint URIs) | |
subscriptions[].name | Y | Human-readable subscription name | |
subscriptions[].channel | Y | Windows event log channel, e.g. Security, System | |
subscriptions[].query | N | * | XPath filter query or full <QueryList> XML block |
subscriptions[].content_format | N | RenderedText | Event content format (RenderedText or Events) |
subscriptions[].read_existing_events | N | false | Read events that existed before the subscription was created |
subscriptions[].send_bookmarks | N | true | Request bookmark payloads from clients for resumable collection |
subscriptions[].compress | N | false | Request SLDC-compressed event batches from clients |
subscriptions[].targets | N | - | DNS name patterns restricting which clients receive this subscription (wildcards supported, empty means all clients) |
Subscription Fields
Per-subscription fields are injected into every event delivered under that subscription. Values prefixed with __subscription. are resolved from subscription metadata at runtime.
| Field | Required | Default | Description |
|---|---|---|---|
subscriptions[].fields[].name | Y | Field name to inject | |
subscriptions[].fields[].value | Y | Static value or __subscription.<key> reference |
Available __subscription.* references: version, subscriptionName, contentFormat, readExistingEvents, heartbeatInterval, batchTimeout, sendBookmarks, compress, locale.
Advanced Configuration
Performance
| Field | Required | Default | Description |
|---|---|---|---|
reuse | N | true | Enable socket address reuse (SO_REUSEADDR) |
workers | N | 4 | Number of concurrent event processing workers |
buffer_size | N | 4096 | Async event channel buffer size (number of event batches) |
backpressure_policy | N | "" | Behavior when the event buffer is full: drop, block, or empty (synchronous fallback) |
max_active_requests | N | 256 | Maximum concurrent in-flight HTTP requests (0 = unlimited) |
max_requests_per_socket | N | 0 | Maximum HTTP requests per TCP connection before close (0 = unlimited) |
IP Filtering
| Field | Required | Default | Description |
|---|---|---|---|
ip_allowlist_regex | N | Regex that client IP must match; non-matching IPs receive 403 | |
ip_denylist_regex | N | Regex that client IP must NOT match; matching IPs receive 403 |
Proxy / Header Handling
| Field | Required | Default | Description |
|---|---|---|---|
use_x_forwarded_for | N | false | Use X-Forwarded-For header to resolve originating client IP |
capture_request_headers | N | false | Attach raw HTTP request headers to each event's client identity |
allow_machine_id_mismatch | N | false | Allow events when the SOAP MachineID does not match the TLS cert CN (logged as a warning when allowed) |
Messages
| Field | Required | Default | Description |
|---|---|---|---|
batch_size | N | 1000 | Number of log records to read per processing batch |
queue.interval | N | 1 | Queue processing interval in seconds |
Details
How WEF Works
Windows Event Forwarding (WEF) uses the WS-Management protocol over HTTP or HTTPS. When a Windows client connects, it sends an Enumerate request to discover available subscriptions. For each matching subscription it receives, the client begins forwarding events in batches. Each batch may include a bookmark that records the client's position in the event log, allowing the server to resume collection from the correct offset after a restart or subscription version change.
The server handles four main WS-Man actions: Enumerate (returns available subscriptions), Subscribe (client acknowledges a subscription), Events (client delivers a batch of events), and Heartbeat (client signals it is still connected but has no new events to deliver).
Subscriptions and Versioning
When a subscription's configuration changes (channel, query, format, etc.), the server automatically bumps its version identifier and invalidates all stored bookmarks for that subscription. Clients detect the version change during their next heartbeat or event delivery and re-subscribe, causing them to replay events from the beginning of the channel or from the point specified by read_existing_events.
Bookmark Persistence
When send_bookmarks is enabled on a subscription, Windows clients include a BookmarkList XML fragment with each event batch. The server validates and stores this bookmark keyed by client identity and subscription ID. On reconnect or version bump, the stored bookmark is sent back to the client in the SubscribeResponse so it can resume forwarding from where it left off.
Compression
When compress is enabled on a subscription, clients compress event batches using the Streaming Lossless Data Compression (SLDC) algorithm (LZNT1 variant). The server automatically detects and decompresses SLDC payloads. A maximum decompressed size of 64 MB is enforced to prevent memory exhaustion.
Client Identity
The server resolves client identity in order of trust: Kerberos principal (highest), TLS certificate CN (verified chain required), SOAP MachineID / X-Machine-Name header (unverified, used for logging only), and remote IP address (fallback). The MachineName field on a client identity is only populated from verified sources (Kerberos or TLS). ReportedMachineName carries the unverified client-supplied value and should not be used for authorization decisions.
MachineID Mismatch
When TLS client certificates are in use, the server compares the hostname portion of the certificate CN against the SOAP MachineID. A mismatch is rejected by default. Set allow_machine_id_mismatch: true to log the mismatch as a warning and allow the request to proceed. Only the short hostname (before the first .) is compared.
Examples
The following are commonly used configuration types.
Basic
A minimal WEC server listening on the standard HTTP port:
Creating a simple WEC server for a Security event subscription... | |
TLS with Kerberos Authentication
Securing the collector with TLS and requiring Kerberos authentication:
Production WEC server with TLS and SPNEGO/Kerberos... | |
Multiple Subscriptions with Filtering
Collecting from multiple channels with XPath queries and target restrictions:
Separate subscriptions per channel with event filtering... | |
High-Volume Processing
Performance tuning for large Windows fleets:
Optimizing for high event throughput with multiple workers and compression... | |
The worker count is automatically capped at the number of available CPU cores.
Subscription Fields
Injecting metadata into every event for downstream enrichment:
Tagging events with subscription context for easier routing... | |
Multi-Realm Kerberos
Serving clients from multiple Kerberos realms with separate keytabs:
Accepting tickets from two different AD domains... | |
Each keytab entry is tried in order. Ensure SPNs are correctly registered in their respective Active Directory domains.
Pipeline Processing
Applying pre-processing pipelines to normalize events before ingestion:
Parsing and normalizing raw Windows event XML... | |