Skip to main content

wazuhtester

wazuhtester is a Python library and command-line tool for interacting with the Wazuh wazuh-logtest daemon. It handles the Unix-socket wire protocol, daemon sessions, and response parsing so rule and decoder tests do not need to reimplement the framing and JSON envelope.

It was extracted from wazuh-devenv, which consumes the package instead of carrying its own protocol client. See ROADMAP.md for the release and migration sequence.

Installation

Install the package into a Python environment for library use:

python -m pip install wazuhtester

For command-line-only use, pipx is the preferred installation model once the package is published:

pipx install wazuhtester

A local checkout can be installed with:

pipx install --editable .

The package requires Python 3.9+, Linux, and a reachable wazuh-logtest Unix socket from a running Wazuh manager. It does not install or run Wazuh itself. Importing wazuhtester on a non-Linux platform fails immediately with an explicit unsupported-platform error. WSL is supported because Python reports the WSL environment as Linux.

Python API

For a single independent event:

from wazuhtester import LogtestStatus, send_log

response = send_log(
    "Oct 10 10:00:00 host sshd[1234]: "
    "Failed password for root from 1.2.3.4 port 22 ssh2"
)

assert response.status == LogtestStatus.RuleMatch
print(response.rule_id)
print(response.rule_description)

A one-shot send_log() call owns the daemon session it creates and removes it before returning. Supplying an explicit token means the caller owns that existing session, so send_log() does not remove it.

For stateful, frequency, or composite rules, send the sequence in one session:

from wazuhtester import LogtestStatus, send_multiple_logs

logs = [
    "sshd: Failed password for invalid user admin from 1.2.3.4 port 22 ssh2",
    "sshd: Failed password for invalid user admin from 1.2.3.4 port 22 ssh2",
    "sshd: Failed password for invalid user admin from 1.2.3.4 port 22 ssh2",
]

responses = send_multiple_logs(logs)
assert responses[-1].status == LogtestStatus.RuleMatch

For explicit session control, LogtestSession automatically reuses the token returned by the daemon:

from wazuhtester import LogtestResponse, LogtestSession

with LogtestSession() as session:
    first = LogtestResponse(session.process_log("event one"))
    second = LogtestResponse(session.process_log("event two"))

The second request uses the token returned by the first. Exiting the context removes the active daemon session.

CLI

Installing the package exposes the wazuhtester console command. The executable name deliberately does not use wazuh-logtest, which is the name of Wazuh's native tool.

The console-script and module entry points are equivalent:

wazuhtester
python -m wazuhtester

The CLI reads one log record per line from stdin. All records in one invocation share one daemon session, preserving correlation and frequency semantics:

printf '%s\n' \
  'sshd: Failed password for invalid user admin from 1.2.3.4 port 22 ssh2' \
  'sshd: Failed password for invalid user admin from 1.2.3.4 port 22 ssh2' |
  wazuhtester

Useful options:

-l, --location TEXT
-f, --log-format FORMAT
-s, --socket PATH
    --json
    --version
-h, --help

--json emits one JSON object per input record (NDJSON), suitable for shell pipelines:

cat samples.log | wazuhtester --json | jq 'select(.rule_id == "5710")'

A valid event that produces no rule match is still a successful CLI operation. Runtime communication or protocol failures return exit code 1, argparse usage errors return 2, and Ctrl+C returns 130.

Configuring the socket path

By default the client uses:

/var/ossec/queue/sockets/logtest

Override it through the environment:

export WAZUH_LOGTEST_SOCKET=/path/to/logtest.sock

or per call:

from wazuhtester import send_log

send_log("...", socket_path="/path/to/logtest.sock")

Check reachability without sending a log:

from wazuhtester import is_logtest_available

if not is_logtest_available():
    raise SystemExit("wazuh-logtest is not reachable")

pytest plugin

Installing wazuhtester also registers a pytest plugin through the pytest11 entry point. It is deliberately opt-in for daemon availability checks.

  • @pytest.mark.wazuh_logtest marks a test as requiring a live daemon. Marked tests are skipped if the daemon is unavailable.
  • --wazuh-require-logtest, or the wazuh_require_logtest ini option, makes an unavailable daemon fatal for the test session.
  • --wazuh-socket PATH overrides the socket path for the test run.
  • logtest_session provides a LogtestSession and removes its active session during teardown.
  • send_log exposes the high-level one-shot API as a fixture.
import pytest


@pytest.mark.wazuh_logtest
def test_custom_rule(send_log):
    response = send_log("...")
    assert response.rule_id == "100100"

API surface

Name Purpose
send_log(...) Send one event and return a LogtestResponse. A newly created daemon session is cleaned up automatically.
send_multiple_logs(...) Send an ordered sequence in one daemon session and return one response per event.
LogtestSession Lower-level session API. Automatically reuses the current daemon token and supports context-manager cleanup.
LogtestResponse Parsed daemon response with status, decoder, rule, static and dynamic fields. to_dict() returns deterministic JSON-compatible data.
LogtestStatus RuleMatch, Error, NoDecoder, or NoRule.
is_logtest_available(...) Probe the configured Unix socket without sending an event.
get_socket_path() Resolve the socket path, including WAZUH_LOGTEST_SOCKET.
LogtestError hierarchy Distinguish connection, daemon, and protocol failures while preserving compatible builtin base classes.

Development

python -m venv .venv
.venv/bin/pip install -e ".[dev]"
.venv/bin/pytest
.venv/bin/mypy src/wazuhtester

The test suite uses a fake AF_UNIX server that implements the Wazuh logtest framing, so a Wazuh installation is not required for normal package CI.

License

GNU General Public License version 2 only - see LICENSE.

Release files for wazuhtester 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for wazuhtester 0.1.1
File Size Uploaded
wazuhtester-0.1.1.tar.gz 30.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for wazuhtester 0.1.1
File Interpreter ABI Platform
wazuhtester-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 54.3 kB

Release files / wazuhtester-0.1.1.tar.gz

Download URL wazuhtester-0.1.1.tar.gz
Size 30.2 kB
Tags Source
SHA-256 checksum
How to use checksums
6201332b24a52c534a506c0221a50553b871c69b796fb561bb985eade334002c
BLAKE2b-256 checksum
How to use checksums
5bb15b62710a23557883e5501ae57bd45e977a855eda89c78bb982914b855cbd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.

Transparency log

Release files / wazuhtester-0.1.1-py3-none-any.whl

Download URL wazuhtester-0.1.1-py3-none-any.whl
Size 24.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f53726ceffb5a3163c194c34428e37e3e34a16e7fb38d544bd015570ffb91cb6
BLAKE2b-256 checksum
How to use checksums
0918d5a2384bad9030daf3c746f40ff7e15d9c2cc71796e72b538bc6fe6bb879
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page