@iota-big3/sdk-security
Version:
Advanced security features including zero trust, quantum-safe crypto, and ML threat detection
471 lines • 16.4 kB
JavaScript
"use strict";
/**
* SIEM Connector Factory
* Creates connectors for various SIEM platforms
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.SIEMConnectorFactory = void 0;
const events_1 = require("events");
const types_1 = require("./types");
/**
* Base SIEM connector with common functionality
*/
class BaseSIEMConnector extends events_1.EventEmitter {
constructor(config) {
super();
this.connected = false;
this.eventQueue = [];
this.stats = {
eventsSent: 0,
eventsQueued: 0,
errors: 0,
lastError: undefined,
lastConnected: undefined
};
this.config = config;
this.setupBatchProcessing();
}
async sendEvent(event) {
if (!this.config.enabled)
return;
// Apply filters
if (this.shouldFilter(event))
return;
// Add to queue
this.eventQueue.push(event);
this.stats.eventsQueued++;
// Send immediately if batch size reached
if (this.eventQueue.length >= (this.config.batchSize || 100)) {
await this.flush();
}
}
async testConnection() {
try {
await this.connect();
const testEvent = {
version: '1.0',
deviceVendor: 'IOTA Big3',
deviceProduct: 'SDK Security',
deviceVersion: '1.0.0',
signatureId: 'TEST-001',
name: 'Connection Test',
severity: types_1.SIEMSeverity.INFORMATIONAL,
timestamp: new Date(),
eventType: types_1.SIEMEventType.SYSTEM,
message: 'SIEM connection test'
};
await this.sendEvent(testEvent);
return true;
}
catch (error) {
this.handleError(error);
return false;
}
}
getStatus() {
return {
connected: this.connected,
lastConnected: this.stats.lastConnected,
eventsSent: this.stats.eventsSent,
eventsQueued: this.stats.eventsQueued,
errors: this.stats.errors,
lastError: this.stats.lastError
};
}
setupBatchProcessing() {
if (this.config.flushInterval) {
this.batchTimer = setInterval(() => {
this.flush().catch(err => this.handleError(err));
}, this.config.flushInterval);
}
}
async flush() {
if (this.eventQueue.length === 0)
return;
const batch = this.eventQueue.splice(0, this.config.batchSize || 100);
try {
await this.sendBatch(batch);
this.stats.eventsSent += batch.length;
this.stats.eventsQueued = this.eventQueue.length;
}
catch (error) {
// Re-queue failed events
this.eventQueue.unshift(...batch);
this.stats.eventsQueued = this.eventQueue.length;
throw error;
}
}
shouldFilter(event) {
if (!this.config.filters)
return false;
for (const filter of this.config.filters) {
const fieldValue = event[filter.field];
let matches = false;
switch (filter.operator) {
case 'equals':
matches = fieldValue === filter.value;
break;
case 'contains':
matches = String(fieldValue).includes(filter.value);
break;
case 'startsWith':
matches = String(fieldValue).startsWith(filter.value);
break;
case 'endsWith':
matches = String(fieldValue).endsWith(filter.value);
break;
case 'regex':
matches = new RegExp(filter.value).test(String(fieldValue));
break;
case 'in':
matches = filter.value.includes(fieldValue);
break;
case 'notIn':
matches = !filter.value.includes(fieldValue);
break;
}
if (filter.action === 'exclude' && matches)
return true;
if (filter.action === 'include' && !matches)
return true;
}
return false;
}
transformEvent(event) {
if (!this.config.transformation)
return event;
const transform = this.config.transformation;
let transformed = event;
// Apply custom transformer
if (transform.customTransformer) {
transformed = transform.customTransformer(event);
}
// Apply field mapping
if (transform.fieldMapping) {
const mapped = {};
for (const [from, to] of Object.entries(transform.fieldMapping)) {
if (from in transformed) {
mapped[to] = transformed[from];
}
}
transformed = { ...transformed, ...mapped };
}
// Apply enrichment
if (transform.enrichment) {
for (const enrichment of transform.enrichment) {
let value;
switch (enrichment.source) {
case 'ENV':
value = process.env[enrichment.value];
break;
case 'CONFIG':
value = enrichment.value;
break;
case 'FUNCTION':
value = enrichment.value(event);
break;
}
transformed[enrichment.field] = value;
}
}
// Format transformation
switch (transform.format) {
case 'CEF':
return this.formatCEF(transformed);
case 'LEEF':
return this.formatLEEF(transformed);
case 'SYSLOG':
return this.formatSyslog(transformed);
case 'JSON':
default:
return transformed;
}
}
formatCEF(event) {
const header = `CEF:${event.version}|${event.deviceVendor}|${event.deviceProduct}|${event.deviceVersion}|${event.signatureId}|${event.name}|${event.severity}`;
const extensions = Object.entries(event)
.filter(([key]) => !['version', 'deviceVendor', 'deviceProduct', 'deviceVersion', 'signatureId', 'name', 'severity'].includes(key))
.map(([key, value]) => `${key}=${value}`)
.join(' ');
return `${header}|${extensions}`;
}
formatLEEF(event) {
const header = `LEEF:2.0|${event.deviceVendor}|${event.deviceProduct}|${event.deviceVersion}|${event.signatureId}`;
const attributes = Object.entries(event)
.filter(([key]) => !['deviceVendor', 'deviceProduct', 'deviceVersion', 'signatureId'].includes(key))
.map(([key, value]) => `${key}=${value}`)
.join('\t');
return `${header}|${attributes}`;
}
formatSyslog(event) {
const priority = event.severity * 8 + 6; // Default facility 6 (local use)
const timestamp = event.timestamp.toISOString();
const hostname = process.env.HOSTNAME || 'localhost';
const tag = `${event.deviceProduct}[${process.pid}]`;
return `<${priority}>${timestamp} ${hostname} ${tag}: ${event.message}`;
}
handleError(error) {
this.stats.errors++;
this.stats.lastError = error.message;
this.emit('error', error);
}
async dispose() {
if (this.batchTimer) {
clearInterval(this.batchTimer);
}
await this.flush();
await this.disconnect();
}
}
/**
* Splunk SIEM Connector
*/
class SplunkConnector extends BaseSIEMConnector {
get platform() {
return types_1.SIEMPlatform.SPLUNK;
}
async connect() {
// In production, would establish connection to Splunk HEC
this.connected = true;
this.stats.lastConnected = new Date();
this.emit('connected', { platform: this.platform });
}
async disconnect() {
// In production, would close Splunk connection
this.connected = false;
this.emit('disconnected', { platform: this.platform });
}
async sendBatch(events) {
if (!this.connected)
await this.connect();
// Transform events for Splunk
const splunkEvents = events.map(event => ({
time: event.timestamp.getTime() / 1000,
host: event.sourceAddress || process.env.HOSTNAME,
source: event.deviceProduct,
sourcetype: '_json',
event: this.transformEvent(event)
}));
// In production, would send to Splunk HEC endpoint
// For now, simulate sending
await new Promise(resolve => setTimeout(resolve, 10));
this.emit('events:sent', { count: events.length, platform: this.platform });
}
async query(query) {
if (!this.connected)
await this.connect();
// In production, would execute Splunk search
// For now, return mock results
return {
total: 0,
events: []
};
}
}
/**
* Elastic SIEM Connector
*/
class ElasticConnector extends BaseSIEMConnector {
get platform() {
return types_1.SIEMPlatform.ELASTIC;
}
async connect() {
// In production, would establish connection to Elasticsearch
this.connected = true;
this.stats.lastConnected = new Date();
this.emit('connected', { platform: this.platform });
}
async disconnect() {
// In production, would close Elasticsearch connection
this.connected = false;
this.emit('disconnected', { platform: this.platform });
}
async sendBatch(events) {
if (!this.connected)
await this.connect();
// Transform events for Elastic Common Schema (ECS)
const ecsEvents = events.map(event => ({
'@timestamp': event.timestamp,
ecs: { version: '1.12.0' },
event: {
kind: 'event',
category: event.eventType.toLowerCase(),
type: [event.eventType.toLowerCase()],
outcome: event.outcome?.toLowerCase(),
severity: event.severity
},
source: {
ip: event.sourceAddress,
port: event.sourcePort,
user: { name: event.sourceUserName }
},
destination: {
ip: event.destinationAddress,
port: event.destinationPort,
user: { name: event.destinationUserName }
},
user: {
id: event.userId,
name: event.userName
},
message: event.message,
labels: event.customFields
}));
// In production, would bulk index to Elasticsearch
await new Promise(resolve => setTimeout(resolve, 10));
this.emit('events:sent', { count: events.length, platform: this.platform });
}
async query(query) {
if (!this.connected)
await this.connect();
// In production, would execute Elasticsearch query
return {
total: 0,
events: []
};
}
}
/**
* IBM QRadar Connector
*/
class QRadarConnector extends BaseSIEMConnector {
get platform() {
return types_1.SIEMPlatform.QRADAR;
}
async connect() {
// In production, would establish connection to QRadar
this.connected = true;
this.stats.lastConnected = new Date();
this.emit('connected', { platform: this.platform });
}
async disconnect() {
this.connected = false;
this.emit('disconnected', { platform: this.platform });
}
async sendBatch(events) {
if (!this.connected)
await this.connect();
// Transform events for QRadar LEEF format
const leefEvents = events.map(event => this.formatLEEF(event));
// In production, would send to QRadar syslog endpoint
await new Promise(resolve => setTimeout(resolve, 10));
this.emit('events:sent', { count: events.length, platform: this.platform });
}
async query(query) {
if (!this.connected)
await this.connect();
// In production, would execute AQL query
return {
total: 0,
events: []
};
}
}
/**
* Azure Sentinel Connector
*/
class SentinelConnector extends BaseSIEMConnector {
get platform() {
return types_1.SIEMPlatform.SENTINEL;
}
async connect() {
// In production, would authenticate with Azure
this.connected = true;
this.stats.lastConnected = new Date();
this.emit('connected', { platform: this.platform });
}
async disconnect() {
this.connected = false;
this.emit('disconnected', { platform: this.platform });
}
async sendBatch(events) {
if (!this.connected)
await this.connect();
// Transform events for Azure Sentinel
const sentinelEvents = events.map(event => ({
TimeGenerated: event.timestamp,
EventType: event.eventType,
Severity: this.mapSeverityToSentinel(event.severity),
Computer: event.sourceAddress || process.env.HOSTNAME,
UserName: event.userName,
Message: event.message,
...event.customFields
}));
// In production, would send to Log Analytics Data Collector API
await new Promise(resolve => setTimeout(resolve, 10));
this.emit('events:sent', { count: events.length, platform: this.platform });
}
async query(query) {
if (!this.connected)
await this.connect();
// In production, would execute KQL query
return {
total: 0,
events: []
};
}
mapSeverityToSentinel(severity) {
const mapping = {
[types_1.SIEMSeverity.EMERGENCY]: 'High',
[types_1.SIEMSeverity.ALERT]: 'High',
[types_1.SIEMSeverity.CRITICAL]: 'High',
[types_1.SIEMSeverity.ERROR]: 'Medium',
[types_1.SIEMSeverity.WARNING]: 'Medium',
[types_1.SIEMSeverity.NOTICE]: 'Low',
[types_1.SIEMSeverity.INFORMATIONAL]: 'Informational',
[types_1.SIEMSeverity.DEBUG]: 'Informational'
};
return mapping[severity] || 'Informational';
}
}
/**
* SIEM Connector Factory
*/
class SIEMConnectorFactory {
/**
* Create a SIEM connector
*/
static create(config) {
const key = `${config.platform}-${config.endpoint}`;
// Return existing connector if available
if (this.connectors.has(key)) {
return this.connectors.get(key);
}
let connector;
switch (config.platform) {
case types_1.SIEMPlatform.SPLUNK:
connector = new SplunkConnector(config);
break;
case types_1.SIEMPlatform.ELASTIC:
connector = new ElasticConnector(config);
break;
case types_1.SIEMPlatform.QRADAR:
connector = new QRadarConnector(config);
break;
case types_1.SIEMPlatform.SENTINEL:
connector = new SentinelConnector(config);
break;
default:
throw new Error(`Unsupported SIEM platform: ${config.platform}`);
}
this.connectors.set(key, connector);
return connector;
}
/**
* Get all active connectors
*/
static getConnectors() {
return Array.from(this.connectors.values());
}
/**
* Dispose all connectors
*/
static async disposeAll() {
const connectors = Array.from(this.connectors.values());
await Promise.all(connectors.map(c => c.dispose()));
this.connectors.clear();
}
}
exports.SIEMConnectorFactory = SIEMConnectorFactory;
SIEMConnectorFactory.connectors = new Map();
//# sourceMappingURL=siem-connector-factory.js.map