Skip to main content

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>
passphrase: <string>
min_tls_version: <string>
max_tls_version: <string>
insecure_skip_verify: <boolean>
is_auth_required: <boolean>
client_ca_cert_name: <string>
kerberos_keytabs:
- kerberos_keytab: <string>
kerberos_spn: <string>
subscriptions:
- id: <string>
name: <string>
channel: <string>
query: <string>
content_format: <string>
read_existing_events: <boolean>
send_bookmarks: <boolean>
fresh_on_reconnect: <boolean>
compress: <boolean>
targets: <string[]>
fields:
- name: <string>
value: <string>
batch_size: <numeric>

Configuration​

The following fields are used to define the device:

Device​

FieldRequiredDefaultDescription
idY-Unique numeric identifier
nameY-Device name
descriptionN-Optional description
typeY-Must be wec
tagsN-Optional tags
pipelinesN-Optional pre-processor pipelines
statusNtrueEnable/disable the device

Connection​

FieldRequiredDefaultDescription
addressN"0.0.0.0"Listen address
portY-Listen port (typically 5985 for HTTP or 5986 for HTTPS)
hostnameNlisten addressFQDN advertised to clients in subscription endpoint URIs
note

If address is 0.0.0.0, set hostname explicitly to a client-resolvable FQDN.

There is no protocol key. tls.status chooses between HTTP and HTTPS: false is HTTP, conventionally on port 5985, and true is HTTPS, conventionally on port 5986. The Protocol select in the web interface writes exactly that. While a device is being created it also moves the port between the two, but only a port that still holds the other protocol's default: a port typed by hand, or the port of a saved device, is left alone.

TLS​

FieldRequiredDefaultDescription
tls.statusNfalseEnable TLS encryption
tls.cert_nameY*cert.pemTLS certificate
tls.key_nameY*key.pemTLS private key
tls.passphraseN-Passphrase for an encrypted private key
tls.min_tls_versionNtls1.2Minimum accepted TLS version (tls1.0, tls1.1, tls1.2, tls1.3)
tls.max_tls_versionN-Maximum accepted TLS version. When unset, the highest mutually supported version is negotiated.
tls.insecure_skip_verifyNfalseHas no effect on this device. It applies only where the Director connects to a server, never to the connections it accepts: a client certificate is checked only through is_auth_required and client_ca_cert_name. Changing it restarts the listener and nothing else.

* = Required when tls.status is true.

note

tls.min_version is a deprecated alias for tls.min_tls_version, honored only when tls.min_tls_version is unset. Use tls.min_tls_version in new configurations.

Mutual TLS is configured through is_auth_required and client_ca_cert_name, described under Authentication below. This device does not use the tls.client_ca_name and tls.client_auth_required keys read by the other listeners.

note

TLS material fields (cert_name, key_name, ca_name, client_ca_name) accept any of the following:

  • File name — resolved relative to the service root directory. Nested paths such as certs/prod/server.pem are supported.
  • Absolute path — honored only if it resolves inside the service root. Any path that escapes the root is refused.
  • Inline PEM content — used verbatim when the value contains -----BEGIN.
  • Environment variable — ${ENV_VAR}.
  • Vault reference — $secret{id=...} or $secret{store=...,ref=...}.
note

Port 5986 is the standard WEF/HTTPS port. Plain HTTP on port 5985 is not recommended for production.

Authentication​

FieldRequiredDefaultDescription
is_auth_requiredNfalseReject unauthenticated requests
client_ca_cert_nameN-CA bundle used to verify client certificates. When unset, the host trust store is used, which is sufficient for domain-joined Windows hosts whose domain CA is already trusted.

Both keys are read at the top level of properties, not under tls.

When is_auth_required is true, how the collector checks a forwarder's Kerberos ticket depends on whether keytabs are configured:

  • With keytabs, the collector checks tickets against them, on any Director. Client certificates are not demanded, because these clients authenticate through SPNEGO in the HTTP Authorization header — requiring a certificate would fail the handshake before Kerberos could negotiate.
  • Without keytabs, the collector checks tickets with Windows SSPI, which uses the Director's own computer account. SSPI exists only on Windows: on any other Director the collector does not start, and reports SSPI authentication is only available on Windows; configure keytab-based authentication instead. Over HTTPS the TLS layer also demands a client certificate from every forwarder, checked against client_ca_cert_name or the system trust store, and the handshake fails without one.

The web interface asks this under Kerberos authentication: A keytab or The director's computer account. A keytab is required when it is the chosen method.

Kerberos / SPNEGO​

Multiple keytab entries are supported so a single listener can serve clients enrolled in different Kerberos realms.

FieldRequiredDefaultDescription
kerberos_keytabs[].kerberos_keytabN*Base64-encoded keytab file content
kerberos_keytabs[].kerberos_spnN*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.

note

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.

FieldRequiredDefaultDescription
subscriptions[].idYUnique subscription identifier (used in endpoint URIs)
subscriptions[].nameYHuman-readable subscription name
subscriptions[].channelYWindows event log channel, e.g. Security, System
subscriptions[].queryY* for every event; a full <QueryList> block, sent as it is; or a bare XPath predicate such as EventID=4624, which the collector wraps as *[System[(…)]]. A complete XPath such as *[System[(Level=1)]] is wrapped a second time and matches nothing. < and > are refused outside a <QueryList>, and a query is capped at 32 KB.
subscriptions[].content_formatNRenderedTextEvent content format (RenderedText or Events)
subscriptions[].read_existing_eventsNfalseRead events that existed before the subscription was created
subscriptions[].send_bookmarksNtrueRequest bookmark payloads from clients for resumable collection
subscriptions[].fresh_on_reconnectNfalseWhen a forwarder reconnects, discard its stored bookmark and start from new events instead of resuming where it left off
subscriptions[].compressNfalseRequest SLDC-compressed event batches from clients
subscriptions[].targetsN-DNS name patterns restricting which clients receive this subscription (wildcards supported, empty means all clients)

In the web interface fresh_on_reconnect is After a lost connection, with the options Resume from the last event received and Skip to new events. Skipping is offered only while read_existing_events is false: with the bookmark discarded on every reconnect, a forwarder told to read existing events would start from the beginning of its log, and send the whole log again each time.

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.

FieldRequiredDefaultDescription
subscriptions[].fields[].nameYField name to inject
subscriptions[].fields[].valueYStatic value or __subscription.<key> reference

Available __subscription.* references: version, subscriptionName, contentFormat, readExistingEvents, heartbeatInterval, batchTimeout, sendBookmarks, compress, locale.

Advanced Configuration​

Performance​

FieldRequiredDefaultDescription
reuseNtrueEnable socket address reuse (SO_REUSEADDR)
workersNOne per 8 CPU coresNumber of concurrent event processing workers, never below 1 and reduced further on memory-constrained hosts. Forced to 1 when reuse is false.
buffer_sizeN4096Async event channel buffer size (number of event batches)
backpressure_policyN""Behavior when the event buffer is full: drop, block, or empty (synchronous fallback)
max_active_requestsN256Maximum concurrent in-flight HTTP requests (0 = unlimited)
max_requests_per_socketN0Maximum HTTP requests per TCP connection before close (0 = unlimited)
max_buffer_sizeN128MBIngest buffer admission cap. Also sizes this listener's ingest buffers: 3/8 of this value at start, growing to at most 3x
note

max_buffer_size is the ingest-buffer admission cap, and is distinct from any buffer_size field above, which sizes the network read buffer. Left unset it is 128MB, whose buffers take 48 MiB of heap per listener worker at start and grow to at most 384 MiB as bursts need the room — and with reuse: true a device runs one worker per listener. Size strings are binary, and 32MB and 32MiB are exact synonyms.

See Listener Memory Sizing for the arithmetic, the sizing table, and what happens when the cap is exhausted.

IP Filtering​

FieldRequiredDefaultDescription
ip_allowlist_regexNRegex that client IP must match; non-matching IPs receive 403
ip_denylist_regexNRegex that client IP must NOT match; matching IPs receive 403

Proxy / Header Handling​

FieldRequiredDefaultDescription
use_x_forwarded_forNfalseUse X-Forwarded-For header to resolve originating client IP
capture_request_headersNfalseAttach raw HTTP request headers to each event's client identity
allow_machine_id_mismatchNfalseAllow events when the SOAP MachineID does not match the TLS cert CN (logged as a warning when allowed)

Messages​

FieldRequiredDefaultDescription
batch_sizeN10000Number of log records to read per processing batch
note

queue.interval is a Director service-level setting configured in vmetric.yml and cannot be overridden per device.

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).

Pointing Forwarders at the Collector​

Forwarders find the collector through Group Policy. The web interface shows the value to use as a read-only Forwarder setting (Group Policy) line, built from the protocol, hostname and port, with a copy button:

Server=http://wec01.corp.example.com:5985/wsman/SubscriptionManager/WEC,Refresh=60

Set it under Computer Configuration > Policies > Administrative Templates > Windows Components > Event Forwarding > Configure target Subscription Manager. The path is case-sensitive, and Refresh is how often forwarders check for changed subscriptions, in seconds.

The hostname in that line is the device's hostname, and it must be a name or address forwarders can reach. The web interface's Hostname field refuses a listen, loopback, multicast or broadcast address such as 0.0.0.0, which is right for address but tells a forwarder nothing.

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...

devices:
- id: 1
name: basic_wec
type: wec
properties:
port: 5985
hostname: wec.corp.com
subscriptions:
- id: security-events
name: Security Events
channel: Security
query: "*"

TLS with Kerberos Authentication​

Securing the collector with TLS and requiring Kerberos authentication:

Production WEC server with TLS and SPNEGO/Kerberos...

devices:
- id: 2
name: secure_wec
type: wec
properties:
port: 5986
hostname: wec.corp.com
tls:
status: true
cert_name: wec.crt
key_name: wec.key
is_auth_required: true
kerberos_keytabs:
- kerberos_keytab: "${KEYTAB_BASE64}"
kerberos_spn: "HTTP/wec.corp.com"
subscriptions:
- id: security-events
name: Security Events
channel: Security
query: "*"
send_bookmarks: true

Multiple Subscriptions with Filtering​

Collecting from multiple channels with XPath queries and target restrictions:

Separate subscriptions per channel with event filtering...

devices:
- id: 3
name: filtered_wec
type: wec
properties:
port: 5986
hostname: wec.corp.com
tls:
status: true
cert_name: wec.crt
key_name: wec.key
subscriptions:
- id: security-critical
name: Critical Security Events
channel: Security
query: "*[System[(Level=1 or Level=2)]]"
content_format: RenderedText
send_bookmarks: true
targets:
- "*.corp.com"
- id: system-events
name: System Events
channel: System
query: "*"
send_bookmarks: true
- id: app-events
name: Application Events
channel: Application
query: "*"
targets:
- "dc01.corp.com"
- "dc02.corp.com"

High-Volume Processing​

Performance tuning for large Windows fleets:

Optimizing for high event throughput with multiple workers and compression...

devices:
- id: 4
name: performant_wec
type: wec
properties:
port: 5986
hostname: wec.corp.com
tls:
status: true
cert_name: wec.crt
key_name: wec.key
reuse: true
workers: 8
buffer_size: 8192
backpressure_policy: block
max_active_requests: 512
batch_size: 5000
subscriptions:
- id: all-security
name: All Security Events
channel: Security
query: "*"
compress: true
send_bookmarks: true
note

The worker count scales as one worker per 8 CPU cores rather than one per core, and is reduced further on memory-constrained hosts. Setting workers without enabling reuse has no effect: the count is forced to 1, because the workers rely on SO_REUSEPORT to share the listening socket.

Subscription Fields​

Injecting metadata into every event for downstream enrichment:

Tagging events with subscription context for easier routing...

devices:
- id: 5
name: enriched_wec
type: wec
properties:
port: 5986
hostname: wec.corp.com
tls:
status: true
cert_name: wec.crt
key_name: wec.key
subscriptions:
- id: dc-security
name: DC Security Events
channel: Security
query: "*"
send_bookmarks: true
targets:
- "*.dc.corp.com"
fields:
- name: collector_role
value: domain_controller
- name: subscription_name
value: __subscription.subscriptionName
- name: content_format
value: __subscription.contentFormat

Multi-Realm Kerberos​

Serving clients from multiple Kerberos realms with separate keytabs:

Accepting tickets from two different AD domains...

devices:
- id: 6
name: multirealm_wec
type: wec
properties:
port: 5986
hostname: wec.corp.com
tls:
status: true
cert_name: wec.crt
key_name: wec.key
is_auth_required: true
kerberos_keytabs:
- kerberos_keytab: "${KEYTAB_CORP_BASE64}"
kerberos_spn: "HTTP/wec.corp.com"
- kerberos_keytab: "${KEYTAB_PARTNER_BASE64}"
kerberos_spn: "HTTP/wec.corp.com@PARTNER.COM"
subscriptions:
- id: all-security
name: All Security Events
channel: Security
query: "*"
send_bookmarks: true
warning

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...

devices:
- id: 7
name: pipeline_wec
type: wec
pipelines:
- windows_event_parser
- field_normalizer
- timestamp_fixer
properties:
port: 5986
hostname: wec.corp.com
tls:
status: true
cert_name: wec.crt
key_name: wec.key
subscriptions:
- id: security-events
name: Security Events
channel: Security
query: "*"
send_bookmarks: true