@nullbridge/sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/siem.js ADDED
@@ -0,0 +1,92 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * SiemStreamer — stream audit events to external SIEM systems
5
+ * Supports JSON, CEF (ArcSight), and LEEF (IBM QRadar) formats
6
+ */
7
+ class SiemStreamer {
8
+ constructor(config, http) {
9
+ this._config = config;
10
+ this._http = http;
11
+ this._queue = [];
12
+ this._timer = null;
13
+ this._siemCfg = config.siem || {};
14
+ }
15
+
16
+ async start() {
17
+ if (!this._siemCfg.endpoint) {
18
+ console.warn('[NullBridge] SIEM endpoint not configured — streaming disabled');
19
+ return;
20
+ }
21
+
22
+ // Flush to SIEM every 60 seconds
23
+ this._timer = setInterval(() => this.flush(), 60 * 1000);
24
+ if (this._timer.unref) this._timer.unref();
25
+ }
26
+
27
+ /**
28
+ * Queue an event for SIEM streaming
29
+ */
30
+ push(event) {
31
+ const formatted = this._format(event);
32
+ this._queue.push(formatted);
33
+
34
+ // Auto-flush if queue gets large
35
+ if (this._queue.length >= 50) this.flush();
36
+ }
37
+
38
+ /**
39
+ * Flush all queued events to SIEM endpoint
40
+ */
41
+ async flush() {
42
+ if (!this._siemCfg.endpoint || this._queue.length === 0) return;
43
+
44
+ const batch = this._queue.splice(0);
45
+
46
+ try {
47
+ await this._http.post(
48
+ this._siemCfg.endpoint,
49
+ '',
50
+ { events: batch, source: 'nullbridge-sdk', version: '1.0.0' }
51
+ );
52
+ } catch (err) {
53
+ console.warn(`[NullBridge] SIEM flush failed: ${err.message}`);
54
+ // Put events back
55
+ this._queue.unshift(...batch);
56
+ }
57
+ }
58
+
59
+ stop() {
60
+ if (this._timer) clearInterval(this._timer);
61
+ }
62
+
63
+ _format(event) {
64
+ const format = this._siemCfg.format || 'json';
65
+
66
+ switch (format) {
67
+ case 'cef':
68
+ return this._toCEF(event);
69
+ case 'leef':
70
+ return this._toLEEF(event);
71
+ default:
72
+ return { ...event, _source: 'nullbridge', _version: '1.0.0' };
73
+ }
74
+ }
75
+
76
+ // Common Event Format (ArcSight)
77
+ _toCEF(event) {
78
+ const severity = event.outcome === 'blocked' ? 9 : event.outcome === 'failure' ? 6 : 3;
79
+ return `CEF:0|NullBridge|SDK|1.0.0|${event.action}|${event.action}|${severity}|` +
80
+ `agentId=${event.agentId} agentName=${event.agentName} ` +
81
+ `outcome=${event.outcome} ts=${event.timestamp}`;
82
+ }
83
+
84
+ // Log Event Extended Format (IBM QRadar)
85
+ _toLEEF(event) {
86
+ return `LEEF:1.0|NullBridge|SDK|1.0.0|${event.action}|` +
87
+ `agentId=${event.agentId}\tagentName=${event.agentName}\t` +
88
+ `outcome=${event.outcome}\tts=${event.timestamp}`;
89
+ }
90
+ }
91
+
92
+ module.exports = { SiemStreamer };