Skip to content

Quickstart

Quickstart

Install

composer require cboxdk/siem

Requires PHP 8.4+ and ext-json (which ships with core PHP). See Requirements.

Build a normalized event

Everything starts with one immutable value object, Cbox\Siem\ValueObjects\SiemEvent:

use Cbox\Siem\Enums\EventCategory;
use Cbox\Siem\Enums\Outcome;
use Cbox\Siem\Enums\Severity;
use Cbox\Siem\ValueObjects\Party;
use Cbox\Siem\ValueObjects\SiemEvent;

$event = new SiemEvent(
    id: 'evt_01HZX',                       // stable, unique
    occurredAt: new DateTimeImmutable(),   // any timezone; normalized to UTC on the wire
    action: 'user-login',                  // short stable slug
    category: EventCategory::Authentication,
    outcome: Outcome::Success,
    severity: Severity::Medium,            // optional, defaults to Info
    actor: new Party('user', '42'),        // optional (type + id)
    target: new Party('session', 'sess_9'),// optional
    sourceIp: '203.0.113.7',               // optional
    message: 'User 42 signed in',          // optional
    context: ['method' => 'password', 'mfa' => true], // already-flattened scalars
);

Only the first five arguments are required. context values must be scalars or null; flattening nested data into dotted keys is your job (see SIEM events).

Format it

Each formatter implements Cbox\Siem\Contracts\StreamFormatter and turns one event into one record string:

use Cbox\Siem\Formatters\CefFormatter;
use Cbox\Siem\Formatters\EcsFormatter;
use Cbox\Siem\Formatters\SplunkHecFormatter;
use Cbox\Siem\Formatters\GelfFormatter;
use Cbox\Siem\Formatters\JsonFormatter;

(new CefFormatter)->format($event);           // ArcSight / syslog CEF line
(new EcsFormatter)->format($event);           // Elastic Common Schema JSON
(new SplunkHecFormatter)->format($event);     // Splunk HEC envelope
(new GelfFormatter('edge-1'))->format($event);// Graylog GELF 1.1 (host = edge-1)
(new JsonFormatter)->format($event);          // generic single-line NDJSON

Every formatter also exposes name() (e.g. cef) and contentType() (e.g. text/plain) for logging and transport.

Format a batch

There is no batch method: map a formatter over your events and let the transport frame them. For NDJSON-style targets that is a newline join:

$formatter = new JsonFormatter;

$body = implode("\n", array_map(
    $formatter->format(...),
    $events,   // iterable<SiemEvent>
));

Deliver it

Delivery is not part of this package. A Cbox\Siem\Contracts\StreamSink receives formatted records and a StreamTarget and ships them — but the only implementation the core provides is Cbox\Siem\Testing\FakeStreamSink, for tests. The real, SSRF-guarded, queued sink lives in cboxdk/laravel-siem.

use Cbox\Siem\Testing\FakeStreamSink;
use Cbox\Siem\ValueObjects\StreamTarget;

$sink = new FakeStreamSink;   // captures instead of sending
$sink->send([$formatter->format($event)], new StreamTarget('splunk-prod', 'opaque-endpoint'));

$sink->assertSentTo('splunk-prod');

Testing your own code

Compose Cbox\Siem\Testing\InteractsWithSiem into a test case for a shared fake sink and a one-line event factory — see Extension points for the formatter-testing seam.