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.