Introduction
Gatekeeper (inqaba-security/gatekeeper) bridges your Laravel application to your Security Operations Center. It turns application-level security signals — logins, registrations, honeypot hits, scanner probes, endpoint abuse, ID enumeration — into normalized Elastic Common Schema (ECS) events and ships them to Microsoft Sentinel, Wazuh, or any syslog/CEF pipeline, with high-severity alerts pushed straight to Slack and Microsoft Teams.
Your WAF and CDN see traffic. Your SIEM sees infrastructure. Neither can see inside your application: which account just failed to log in for the tenth time, which IP is walking through photos/1, photos/2, photos/3, or which "user" filled in a form field that no human can see. Gatekeeper closes that gap.
Laravel app ──> SecurityEvent (ECS + MITRE ATT&CK) ──> queue ──> Sentinel / Wazuh / syslog
▲ │
├── auth events (login, register, lockout, ...) ├── GeoIP enrichment
├── honeypot routes & form honeypots └── Slack / Teams alerts
├── endpoint abuse detection (brute force, scanning)
├── resource enumeration / IDOR probing detection
├── request threat scanner (SQLi / XSS / traversal probes)
├── egress monitoring (outgoing API abuse, spikes, new destinations)
└── Siem::log(...) custom events
Feature overview#
| Feature | What it gives you |
|---|---|
| Normalized events | Every event is an ECS 8.x JSON document with MITRE ATT&CK tactic/technique tags — consistent field names regardless of destination |
| Microsoft Sentinel sink | Azure Monitor Logs Ingestion API (DCE/DCR) or the legacy Data Collector API |
| Wazuh sink | JSON-lines file tailed by the Wazuh agent — Wazuh's recommended pattern for custom app logs |
| Syslog sink | RFC 5424 over UDP/TCP with JSON or CEF payloads |
| Slack & Teams alerting | Webhook alert cards with a per-sink severity floor, so only events worth a human's attention page the channel |
| Auth monitoring | Automatic listeners for Laravel's native authentication events |
| Route honeypots | Decoy endpoints — including parameterized ones like internal/photos/{id} — that log and auto-block attackers |
| Form honeypot | Invisible field + minimum-fill-time Blade component that catches spam bots |
| Endpoint abuse detection | Per-IP thresholds for brute force, forced browsing, and rate-limit hammering |
| Enumeration / IDOR detection | Flags sequential ID scans, abnormal ID breadth, and high miss ratios on parameterized routes |
| Request threat scanner | Passive heuristics for SQLi, XSS, path traversal, command/template/JNDI injection probes |
| Egress monitoring | Watches outgoing HTTP calls for volume spikes, hard-limit breaches, new destinations, and error surges — catches external-API abuse |
| IP blocklist | Cache-backed, TTL'd, CIDR-aware exemptions, fed by detections or managed manually |
| GeoIP enrichment | ECS source.geo.* fields via a local MaxMind database or HTTP driver |
| Queue shipping | Events ship with retries and backoff; failures fall back to the local log so nothing is lost silently |
| Privacy controls | Key-based redaction and optional sha256 pseudonymization of usernames |
Design principles#
Telemetry first, blocking second. Gatekeeper's detections are signals for your SOC, not a web application firewall. Every blocking behaviour (honeypot auto-block, abuse auto-block, scanner rejection) is opt-in configuration. Keep your WAF in front; Gatekeeper gives analysts the application-layer context those layers structurally cannot see.
Never slow a request, never lose an event. Events ship on a dedicated queue, so no user request ever waits on a SIEM network call. Deliveries are retried with backoff, and when every retry fails the event is written to the local Laravel log with its full payload.
One schema, every destination. Whether an analyst is writing KQL in Sentinel or rules in Wazuh, source.ip is source.ip, event.action is event.action, and severity is on the same scale.
Requirements#
- PHP 8.2+
- Laravel 10, 11, 12 or 13
Quick taste#
use Inqaba\Gatekeeper\Facades\Siem;
use Inqaba\Gatekeeper\Events\Severity;
Siem::log('export_download', 'Customer data export downloaded', Severity::High, [
'rows' => 12000,
], $request->user());
<form method="POST" action="/register">
@csrf
<x-siem::honeypot />
...
</form>
Ready? Head to Installation.