mirror of
https://github.com/misskey-dev/SyslogPro.git
synced 2025-04-29 02:37:18 +09:00
don't close socket after sending and add the close method and related events
This commit is contained in:
parent
0ebf6cb7dc
commit
cd7c5e6b2c
361
index.ts
361
index.ts
@ -16,9 +16,12 @@
|
||||
* @exports CEF
|
||||
* @module SyslogPro
|
||||
*/
|
||||
import EventEmitter from 'events';
|
||||
import moment from 'moment';
|
||||
import * as os from 'os';
|
||||
import * as dgram from 'dgram'; // eslint-disable-line no-unused-vars
|
||||
import * as dns from 'dns';
|
||||
import * as net from 'net'; // eslint-disable-line no-unused-vars
|
||||
import * as os from 'os';
|
||||
import * as tls from 'tls'; // eslint-disable-line no-unused-vars
|
||||
let dnsPromises = dns.promises;
|
||||
|
||||
@ -114,7 +117,7 @@ type SyslogOptions = {
|
||||
* @version 0.0.0
|
||||
* @since 0.0.0
|
||||
*/
|
||||
export class Syslog {
|
||||
export class Syslog extends EventEmitter {
|
||||
cef: any;
|
||||
format: string;
|
||||
leef: any;
|
||||
@ -124,10 +127,13 @@ export class Syslog {
|
||||
rfc3164: any;
|
||||
rfc5424: any;
|
||||
target: string;
|
||||
tcpSocketPromise: Promise<net.Socket> | null;
|
||||
tcpTimeout: number;
|
||||
tlsServerCerts: (Buffer | string)[];
|
||||
tlsClientCert: Buffer | string;
|
||||
tlsClientKey: Buffer | string;
|
||||
tlsSocketPromise: Promise<tls.TLSSocket> | null;
|
||||
udpSocketPromise: Promise<dgram.Socket> | null;
|
||||
/**
|
||||
* Construct a new Syslog transport object with user options
|
||||
* @public
|
||||
@ -171,6 +177,7 @@ export class Syslog {
|
||||
* (Common Event Format) formatting object}
|
||||
*/
|
||||
constructor(options?: SyslogOptions) {
|
||||
super();
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
@ -181,7 +188,21 @@ export class Syslog {
|
||||
this.protocol = options.protocol || 'udp';
|
||||
this.protocol = this.protocol.toLowerCase();
|
||||
/** @type {number} */
|
||||
this.port = options.port || 514;
|
||||
this.port = options.port;
|
||||
if (!this.port) {
|
||||
// defaut port defined on https://tools.ietf.org/html/rfc3195
|
||||
// and https://tools.ietf.org/html/rfc5425
|
||||
if (this.protocol === 'udp') {
|
||||
this.port = 514;
|
||||
} else if (this.protocol === 'tcp') {
|
||||
this.port = 601;
|
||||
} else {
|
||||
this.port = 6514;
|
||||
}
|
||||
}
|
||||
this.tcpSocketPromise = null;
|
||||
this.tlsSocketPromise = null;
|
||||
this.udpSocketPromise = null;
|
||||
/** @type {number} */
|
||||
this.tcpTimeout = options.tcpTimeout || 10000;
|
||||
if (Array.isArray(options.tlsServerCerts)
|
||||
@ -286,6 +307,23 @@ export class Syslog {
|
||||
* @throws {Error} - Network Error
|
||||
*/
|
||||
async udpMessage(msg) {
|
||||
if (!this.udpSocketPromise) {
|
||||
this.udpSocketPromise = this.udpConnect();
|
||||
}
|
||||
const socket = await this.udpSocketPromise;
|
||||
return new Promise((resolve, reject) => {
|
||||
// @ts-ignore
|
||||
socket.send(msg, (err) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(msg);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async udpConnect(): Promise<dgram.Socket> {
|
||||
// Test for target DNS and Address Family (IPv4/6) by looking up the DNS
|
||||
const dgram = require('dgram');
|
||||
const dnsOptions = {
|
||||
@ -293,16 +331,24 @@ export class Syslog {
|
||||
};
|
||||
const result = await dnsPromises.lookup(this.target, dnsOptions);
|
||||
const udpType = result.family === 4 ? 'udp4' : 'udp6';
|
||||
let client = dgram.createSocket(udpType);
|
||||
// Turn msg in to a UTF8 buffer
|
||||
let msgBuffer = Buffer.from(msg, 'utf8');
|
||||
return new Promise((resolve) => {
|
||||
client.send(msgBuffer, this.port, this.target, () => {
|
||||
client.close();
|
||||
resolve(msg);
|
||||
const socket = dgram.createSocket(udpType);
|
||||
socket.on('close', () => {
|
||||
this.onClose();
|
||||
});
|
||||
socket.on('error', (error) => {
|
||||
this.emit('error', error);
|
||||
});
|
||||
return new Promise((resolve, reject) => {
|
||||
socket.connect(this.port, this.target, (err) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(socket);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the Syslog message over TCP
|
||||
* @private
|
||||
@ -312,38 +358,76 @@ export class Syslog {
|
||||
* @throws {Error} - Network Error
|
||||
*/
|
||||
async tcpMessage(msg) {
|
||||
if (!this.tcpSocketPromise) {
|
||||
this.tcpSocketPromise = this.tcpConnect();
|
||||
}
|
||||
const socket = await this.tcpSocketPromise;
|
||||
this.tcpSocketPromise = Promise.resolve(socket);
|
||||
return new Promise((resolve, reject) => {
|
||||
const removeListeners = () => {
|
||||
socket.off('error', onceError);
|
||||
socket.off('timeout', onceTimeout);
|
||||
};
|
||||
const onceError = (error) => {
|
||||
removeListeners();
|
||||
reject(error);
|
||||
};
|
||||
const onceTimeout = () => {
|
||||
removeListeners();
|
||||
reject(new Error('TIMEOUT ERROR: Syslog server TCP timeout'));
|
||||
};
|
||||
socket.write(msg, () => {
|
||||
removeListeners();
|
||||
resolve(msg);
|
||||
});
|
||||
socket.once('error', onceError);
|
||||
socket.once('timeout', onceTimeout);
|
||||
});
|
||||
}
|
||||
|
||||
async tcpConnect(): Promise<net.Socket> {
|
||||
const net = require('net');
|
||||
const dnsOptions = {
|
||||
verbatim: true,
|
||||
};
|
||||
const result = await dnsPromises.lookup(this.target, dnsOptions);
|
||||
const tcpOptions = {
|
||||
host: this.target,
|
||||
port: this.port,
|
||||
family: result.family,
|
||||
};
|
||||
const client = net.createConnection(tcpOptions, () => {
|
||||
// Turn msg in to a UTF8 buffer
|
||||
let msgBuffer = Buffer.from(msg, 'utf8');
|
||||
client.write(msgBuffer, () => {
|
||||
client.end();
|
||||
});
|
||||
});
|
||||
client.setTimeout(this.tcpTimeout);
|
||||
return new Promise((resolve, reject) => {
|
||||
client.on('end', () => {
|
||||
resolve(msg);
|
||||
});
|
||||
client.on('timeout', () => {
|
||||
client.end();
|
||||
reject(new Error('TIMEOUT ERROR: Syslog server TCP timeout'));
|
||||
});
|
||||
client.on('error', (error) => {
|
||||
client.destroy();
|
||||
const removeListeners = () => {
|
||||
socket.off('error', onceError);
|
||||
socket.off('timeout', onceTimeout);
|
||||
};
|
||||
const onceError = (error) => {
|
||||
removeListeners();
|
||||
reject(error);
|
||||
};
|
||||
const onceTimeout = () => {
|
||||
removeListeners();
|
||||
reject(new Error('TIMEOUT ERROR: Syslog server TCP timeout'));
|
||||
};
|
||||
const socket = net.connect(tcpOptions, () => {
|
||||
removeListeners();
|
||||
resolve(socket);
|
||||
});
|
||||
socket.setTimeout(this.tcpTimeout);
|
||||
socket.once('error', onceError);
|
||||
socket.once('timeout', onceTimeout);
|
||||
socket.on('close', () => {
|
||||
this.onClose();
|
||||
});
|
||||
socket.on('end', () => {
|
||||
this.emit('end');
|
||||
});
|
||||
socket.on('error', (error) => {
|
||||
socket.destroy();
|
||||
this.emit('error', error);
|
||||
});
|
||||
socket.on('timeout', () => {
|
||||
socket.end();
|
||||
this.emit('timeout');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the Syslog message over TLS
|
||||
* @private
|
||||
@ -353,6 +437,34 @@ export class Syslog {
|
||||
* @throws {Error} - Network Error
|
||||
*/
|
||||
async tlsMessage(msg) {
|
||||
if (!this.tlsSocketPromise) {
|
||||
this.tlsSocketPromise = this.tlsConnect();
|
||||
}
|
||||
const socket = await this.tlsSocketPromise;
|
||||
this.tlsSocketPromise = Promise.resolve(socket);
|
||||
return new Promise((resolve, reject) => {
|
||||
const removeListeners = () => {
|
||||
socket.off('error', onceError);
|
||||
socket.off('timeout', onceTimeout);
|
||||
};
|
||||
const onceError = (error) => {
|
||||
removeListeners();
|
||||
reject(error);
|
||||
};
|
||||
const onceTimeout = () => {
|
||||
removeListeners();
|
||||
reject(new Error('TIMEOUT ERROR: Syslog server TLS timeout'));
|
||||
};
|
||||
socket.write(msg, () => {
|
||||
removeListeners();
|
||||
resolve(msg);
|
||||
});
|
||||
socket.once('error', onceError);
|
||||
socket.once('timeout', onceTimeout);
|
||||
});
|
||||
}
|
||||
|
||||
async tlsConnect(): Promise<tls.TLSSocket> {
|
||||
const tls = require('tls');
|
||||
const tlsOptions: tls.ConnectionOptions = {
|
||||
host: this.target,
|
||||
@ -390,25 +502,39 @@ export class Syslog {
|
||||
tlsOptions.ca = tlsOptionsCerts;
|
||||
}
|
||||
tlsOptions.rejectUnauthorized = this.rejectUnauthorized;
|
||||
const client = tls.connect(tlsOptions, () => {
|
||||
// Turn msg in to a UTF8 buffer
|
||||
let msgBuffer = Buffer.from(msg, 'utf8');
|
||||
client.write(msgBuffer, () => {
|
||||
client.end();
|
||||
});
|
||||
});
|
||||
client.setTimeout(this.tcpTimeout);
|
||||
return new Promise((resolve, reject) => {
|
||||
client.on('end', () => {
|
||||
resolve(msg);
|
||||
});
|
||||
client.on('timeout', () => {
|
||||
client.end();
|
||||
reject(new Error('TIMEOUT ERROR: Syslog server TLS timeout'));
|
||||
});
|
||||
client.on('error', (error) => {
|
||||
client.destroy();
|
||||
const removeListeners = () => {
|
||||
socket.off('error', onceError);
|
||||
socket.off('timeout', onceTimeout);
|
||||
};
|
||||
const onceError = (error) => {
|
||||
removeListeners();
|
||||
reject(error);
|
||||
};
|
||||
const onceTimeout = () => {
|
||||
removeListeners();
|
||||
reject(new Error('TIMEOUT ERROR: Syslog server TLS timeout'));
|
||||
};
|
||||
const socket = tls.connect(tlsOptions, () => {
|
||||
removeListeners();
|
||||
resolve(socket);
|
||||
});
|
||||
socket.setTimeout(this.tcpTimeout);
|
||||
socket.once('error', onceError);
|
||||
socket.once('timeout', onceTimeout);
|
||||
socket.on('close', () => {
|
||||
this.onClose();
|
||||
});
|
||||
socket.on('end', () => {
|
||||
this.emit('end');
|
||||
});
|
||||
socket.on('error', (error) => {
|
||||
socket.destroy();
|
||||
this.emit('error', error);
|
||||
});
|
||||
socket.on('timeout', () => {
|
||||
socket.end();
|
||||
this.emit('timeout');
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -425,7 +551,6 @@ export class Syslog {
|
||||
if (typeof msg !== 'string') {
|
||||
throw new Error('TYPE ERROR: Syslog message must be a string');
|
||||
}
|
||||
this.protocol = this.protocol.toLowerCase();
|
||||
if (this.protocol === 'udp') {
|
||||
return this.udpMessage(msg);
|
||||
} else if (this.protocol === 'tcp') {
|
||||
@ -438,12 +563,68 @@ export class Syslog {
|
||||
throw new Error(errorMsg);
|
||||
}
|
||||
}
|
||||
|
||||
async close() {
|
||||
if (this.tcpSocketPromise) {
|
||||
let socket;
|
||||
try {
|
||||
socket = await this.tcpSocketPromise;
|
||||
} catch (err) {
|
||||
this.tcpSocketPromise = null;
|
||||
return;
|
||||
}
|
||||
return new Promise((resolve) => {
|
||||
socket.end(resolve);
|
||||
});
|
||||
}
|
||||
|
||||
if (this.tlsSocketPromise) {
|
||||
let socket;
|
||||
try {
|
||||
socket = await this.tlsSocketPromise;
|
||||
} catch (err) {
|
||||
this.tlsSocketPromise = null;
|
||||
return;
|
||||
}
|
||||
return new Promise((resolve) => {
|
||||
socket.end(resolve);
|
||||
});
|
||||
}
|
||||
|
||||
if (this.udpSocketPromise) {
|
||||
let socket;
|
||||
try {
|
||||
socket = await this.udpSocketPromise;
|
||||
} catch (err) {
|
||||
this.udpSocketPromise = null;
|
||||
return;
|
||||
}
|
||||
return new Promise((resolve) => {
|
||||
socket.close(resolve);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async onClose() {
|
||||
this.tcpSocketPromise = null;
|
||||
this.tlsSocketPromise = null;
|
||||
this.udpSocketPromise = null;
|
||||
this.emit('close');
|
||||
}
|
||||
}
|
||||
|
||||
abstract class Format {
|
||||
server: Syslog;
|
||||
|
||||
async close() {
|
||||
return this.server.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The base class of RFC formartted syslog messages.
|
||||
*/
|
||||
export class RFC {
|
||||
abstract class RFC extends Format {
|
||||
alertColor: number;
|
||||
criticalColor: number;
|
||||
emergencyColor: number;
|
||||
@ -616,7 +797,6 @@ export class RFC3164 extends RFC {
|
||||
color: boolean;
|
||||
facility: number;
|
||||
hostname: string;
|
||||
server: Syslog;
|
||||
/**
|
||||
* Construct a new RFC3164 formatted Syslog object with user options
|
||||
* @public
|
||||
@ -678,13 +858,11 @@ export class RFC3164 extends RFC {
|
||||
} else {
|
||||
this.extendedColor = false;
|
||||
}
|
||||
if (options.server) {
|
||||
if (options.server instanceof Syslog) {
|
||||
/** @private @type {Syslog} */
|
||||
this.server = options.server;
|
||||
} else {
|
||||
this.server = new Syslog(options.server);
|
||||
}
|
||||
if (options.server instanceof Syslog) {
|
||||
/** @private @type {Syslog} */
|
||||
this.server = options.server;
|
||||
} else {
|
||||
this.server = new Syslog(options.server);
|
||||
}
|
||||
if (this.extendedColor) {
|
||||
/** @private @type {number} */
|
||||
@ -796,9 +974,6 @@ export class RFC3164 extends RFC {
|
||||
* @throws {Error} A standard error object
|
||||
*/
|
||||
async send(msg, options) {
|
||||
if (!this.server) {
|
||||
this.server = new Syslog();
|
||||
}
|
||||
const result = this.buildMessage(msg, options);
|
||||
return this.server.send(result);
|
||||
}
|
||||
@ -1024,7 +1199,6 @@ export class RFC5424 extends RFC {
|
||||
applicationName: string;
|
||||
color: boolean;
|
||||
hostname: string;
|
||||
server: Syslog;
|
||||
timestamp: boolean;
|
||||
timestampMS: boolean;
|
||||
timestampTZ: boolean;
|
||||
@ -1105,13 +1279,11 @@ export class RFC5424 extends RFC {
|
||||
} else {
|
||||
this.extendedColor = false;
|
||||
}
|
||||
if (options.server) {
|
||||
if (options.server instanceof Syslog) {
|
||||
/** @private @type {Syslog} */
|
||||
this.server = options.server;
|
||||
} else {
|
||||
this.server = new Syslog(options.server);
|
||||
}
|
||||
if (options.server instanceof Syslog) {
|
||||
/** @private @type {Syslog} */
|
||||
this.server = options.server;
|
||||
} else {
|
||||
this.server = new Syslog(options.server);
|
||||
}
|
||||
if (this.extendedColor) {
|
||||
/** @private @type {number} */
|
||||
@ -1301,9 +1473,6 @@ export class RFC5424 extends RFC {
|
||||
* @throws {Error} A standard error object
|
||||
*/
|
||||
async send(msg, options) {
|
||||
if (!this.server) {
|
||||
this.server = new Syslog();
|
||||
}
|
||||
const result = this.buildMessage(msg, options);
|
||||
return this.server.send(result);
|
||||
}
|
||||
@ -1511,11 +1680,10 @@ type LEEFOptions = {
|
||||
* @version 0.0.0
|
||||
* @since 0.0.0
|
||||
*/
|
||||
export class LEEF {
|
||||
export class LEEF extends Format {
|
||||
attributes: any;
|
||||
eventId: string;
|
||||
product: string;
|
||||
server: Syslog;
|
||||
syslogHeader: boolean;
|
||||
vendor: string;
|
||||
version: string;
|
||||
@ -1541,6 +1709,7 @@ export class LEEF {
|
||||
* from this class. @see SyslogPro~Syslog
|
||||
*/
|
||||
constructor(options?: LEEFOptions) {
|
||||
super();
|
||||
options = options || {};
|
||||
/** @type {string} */
|
||||
this.vendor = options.vendor || 'unknown';
|
||||
@ -1602,13 +1771,11 @@ export class LEEF {
|
||||
AttributeLimits: null,
|
||||
calCountryOrRegion: null,
|
||||
};
|
||||
if (options.server) {
|
||||
if (options.server instanceof Syslog) {
|
||||
/** @private @type {Syslog} */
|
||||
this.server = options.server;
|
||||
} else {
|
||||
this.server = new Syslog(options.server);
|
||||
}
|
||||
if (options.server instanceof Syslog) {
|
||||
/** @private @type {Syslog} */
|
||||
this.server = options.server;
|
||||
} else {
|
||||
this.server = new Syslog(options.server);
|
||||
}
|
||||
}
|
||||
/**
|
||||
@ -1638,15 +1805,9 @@ export class LEEF {
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @param {Syslog} [options=false] - A {@link module:SyslogPro~Syslog|
|
||||
* Syslog server connection} that should be used to send messages directly
|
||||
* from this class. @see SyslogPro~Syslog
|
||||
*/
|
||||
async send(options) {
|
||||
const result = this.buildMessage();
|
||||
if (!this.server) {
|
||||
this.server = new Syslog(options);
|
||||
}
|
||||
return this.server.send(result);
|
||||
}
|
||||
}
|
||||
@ -1677,14 +1838,13 @@ type CEFOptions = {
|
||||
* @version 0.0.0
|
||||
* @since 0.0.0
|
||||
*/
|
||||
export class CEF {
|
||||
export class CEF extends Format {
|
||||
deviceEventClassId: string;
|
||||
deviceProduct: string;
|
||||
deviceVendor: string;
|
||||
deviceVersion: string;
|
||||
extensions: any;
|
||||
name: string;
|
||||
server: Syslog;
|
||||
severity: string;
|
||||
/**
|
||||
* Construct a new CEF formatting object with user options
|
||||
@ -1707,6 +1867,7 @@ export class CEF {
|
||||
* from this class. @see SyslogPro~Syslog
|
||||
*/
|
||||
constructor(options?: CEFOptions) {
|
||||
super();
|
||||
options = options || {};
|
||||
/** @type {string} */
|
||||
this.deviceVendor = options.deviceVendor || 'Unknown';
|
||||
@ -1880,13 +2041,11 @@ export class CEF {
|
||||
sourceZoneExternalID: null,
|
||||
sourceZoneURI: null,
|
||||
};
|
||||
if (options.server) {
|
||||
if (options.server instanceof Syslog) {
|
||||
/** @private @type {Syslog} */
|
||||
this.server = options.server;
|
||||
} else {
|
||||
this.server = new Syslog(options.server as SyslogOptions);
|
||||
}
|
||||
if (options.server instanceof Syslog) {
|
||||
/** @private @type {Syslog} */
|
||||
this.server = options.server;
|
||||
} else {
|
||||
this.server = new Syslog(options.server as SyslogOptions);
|
||||
}
|
||||
}
|
||||
/**
|
||||
@ -3144,15 +3303,9 @@ export class CEF {
|
||||
}
|
||||
/**
|
||||
* @public
|
||||
* @param {Syslog} [options=false] - A {@link module:SyslogPro~Syslog|
|
||||
* Syslog server connection} that should be used to send messages directly
|
||||
* from this class. @see SyslogPro~Syslog
|
||||
*/
|
||||
async send(options) {
|
||||
async send() {
|
||||
const result = this.buildMessage();
|
||||
if (!this.server) {
|
||||
this.server = new Syslog(options);
|
||||
}
|
||||
return this.server.send(result);
|
||||
}
|
||||
}
|
||||
|
858
package-lock.json
generated
858
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -4,88 +4,96 @@ const udp = require('dgram');
|
||||
const net = require('net');
|
||||
const tls = require('tls');
|
||||
const fs = require('fs');
|
||||
const dns = require('dns');
|
||||
let dnsPromises = dns.promises;
|
||||
|
||||
const noop = () => {};
|
||||
let udpServer;
|
||||
let tcpServer;;
|
||||
let tlsBasicServer;
|
||||
let tlsAuthServer;
|
||||
|
||||
function setupServers () {
|
||||
return new Promise ((resolve, reject) => {
|
||||
// Load a UDP server
|
||||
// global.udpServerPort = 8000;
|
||||
this.udpServer = udp.createSocket('udp4');
|
||||
this.udpServer.bind(global.udpServerPort, () => {
|
||||
// console.log('UDP server running on', global.udpServerPort);
|
||||
});
|
||||
|
||||
// Load a TCP server
|
||||
// global.tcpServerPort = 8001;
|
||||
this.tcpServer = net.createServer((socket) => {
|
||||
socket.on('data', function (data) {});
|
||||
socket.on('end', function () {});
|
||||
});
|
||||
this.tcpServer.listen(global.tcpServerPort, () => {
|
||||
// console.log('TCP server running on', global.tcpServerPort);
|
||||
});
|
||||
|
||||
// Load a basic TLS
|
||||
// global.tlsBasicServerPort = 8002;
|
||||
const tlsBasicServerOptions = {
|
||||
key: fs.readFileSync('./tests/jest_test_server_key.pem'),
|
||||
cert: fs.readFileSync('./tests/jest_test_server_cert.pem'),
|
||||
handshakeTimeout: 100,
|
||||
requestCert: false,
|
||||
rejectUnauthorized: false
|
||||
};
|
||||
this.tlsBasicServer = tls.createServer(tlsBasicServerOptions, (socket) => {
|
||||
socket.on('data', function (data) {});
|
||||
socket.on('end', function() {});
|
||||
});
|
||||
this.tlsBasicServer.listen(global.tlsBasicServerPort, () => {
|
||||
// console.log('TLS basic server running on', global.tlsBasicServerPort);
|
||||
});
|
||||
|
||||
// Load a TLS server with client Cert request
|
||||
// global.tlsAuthServerPort = 8003;
|
||||
const tlsAuthServerOptions = {
|
||||
key: fs.readFileSync('./tests/jest_test_server_key.pem'),
|
||||
cert: fs.readFileSync('./tests/jest_test_server_cert.pem'),
|
||||
ca: [ fs.readFileSync('./tests/jest_test_client_cert.pem') ],
|
||||
handshakeTimeout: 100,
|
||||
requestCert: true,
|
||||
rejectUnauthorized: true
|
||||
};
|
||||
this.tlsAuthServer = tls.createServer(tlsAuthServerOptions, (socket) => {
|
||||
socket.on('data', function (data) {});
|
||||
socket.on('end', function() {});
|
||||
});
|
||||
this.tlsAuthServer.listen(global.tlsAuthServerPort, () => {
|
||||
// console.log('TLS auth server running on', global.tlsAuthServerPort);
|
||||
});
|
||||
});
|
||||
return Promise.all([
|
||||
new Promise ((resolve, reject) => {
|
||||
// Load a UDP server
|
||||
// global.udpServerPort = 8000;
|
||||
udpServer = udp.createSocket('udp6');
|
||||
udpServer.bind(global.udpServerPort, resolve);
|
||||
udpServer.on('error', reject);
|
||||
}),
|
||||
|
||||
new Promise ((resolve, reject) => {
|
||||
// Load a TCP server
|
||||
// global.tcpServerPort = 8001;
|
||||
tcpServer = net.createServer((socket) => {
|
||||
socket.on('data', function (data) {});
|
||||
socket.on('end', function () {});
|
||||
});
|
||||
tcpServer.listen(global.tcpServerPort, resolve);
|
||||
tcpServer.on('error', reject);
|
||||
}),
|
||||
|
||||
new Promise ((resolve, reject) => {
|
||||
// Load a basic TLS
|
||||
// global.tlsBasicServerPort = 8002;
|
||||
const tlsBasicServerOptions = {
|
||||
key: fs.readFileSync('./tests/jest_test_server_key.pem'),
|
||||
cert: fs.readFileSync('./tests/jest_test_server_cert.pem'),
|
||||
handshakeTimeout: 100,
|
||||
requestCert: false,
|
||||
rejectUnauthorized: false
|
||||
};
|
||||
tlsBasicServer = tls.createServer(tlsBasicServerOptions, (socket) => {
|
||||
socket.on('data', function (data) {});
|
||||
socket.on('end', function() {});
|
||||
});
|
||||
tlsBasicServer.listen(global.tlsBasicServerPort, resolve);
|
||||
tlsBasicServer.on('error', reject);
|
||||
}),
|
||||
|
||||
new Promise ((resolve, reject) => {
|
||||
// Load a TLS server with client Cert request
|
||||
// global.tlsAuthServerPort = 8003;
|
||||
const tlsAuthServerOptions = {
|
||||
key: fs.readFileSync('./tests/jest_test_server_key.pem'),
|
||||
cert: fs.readFileSync('./tests/jest_test_server_cert.pem'),
|
||||
ca: [ fs.readFileSync('./tests/jest_test_client_cert.pem') ],
|
||||
handshakeTimeout: 100,
|
||||
requestCert: true,
|
||||
rejectUnauthorized: true
|
||||
};
|
||||
tlsAuthServer = tls.createServer(tlsAuthServerOptions, (socket) => {
|
||||
socket.on('data', function (data) {});
|
||||
socket.on('end', function() {});
|
||||
});
|
||||
tlsAuthServer.listen(global.tlsAuthServerPort, resolve);
|
||||
tlsAuthServer.on('error', reject);
|
||||
})
|
||||
]);
|
||||
}
|
||||
|
||||
function teardownServers() {
|
||||
return new Promise ((resolve, reject) => {
|
||||
this.udpServer.close(() => {
|
||||
// console.log('UDP server closed');
|
||||
});
|
||||
this.tcpServer.close(() => {
|
||||
// console.log('TCP server closed');
|
||||
});
|
||||
this.tlsBasicServer.close(() => {
|
||||
// console.log('TLS basic server closed');
|
||||
});
|
||||
this.tlsAuthServer.close(() => {
|
||||
// console.log('TLS auth server closed');
|
||||
});
|
||||
});
|
||||
return Promise.all([
|
||||
new Promise((resolve) => {
|
||||
udpServer.close(resolve);
|
||||
}),
|
||||
new Promise((resolve) => {
|
||||
tcpServer.close(resolve);
|
||||
}),
|
||||
new Promise((resolve) => {
|
||||
tlsBasicServer.close(resolve);
|
||||
}),
|
||||
new Promise((resolve) => {
|
||||
tlsAuthServer.close(resolve);
|
||||
})
|
||||
]);
|
||||
}
|
||||
|
||||
beforeAll(() => {
|
||||
setupServers().then((result => {}));
|
||||
beforeAll(async () => {
|
||||
await setupServers();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
teardownServers().then((result => {}));
|
||||
afterAll(async () => {
|
||||
await teardownServers();
|
||||
});
|
||||
|
||||
// CEF Class Tests
|
||||
@ -154,14 +162,16 @@ describe('CEF Class Tests', () => {
|
||||
{
|
||||
extensions: {
|
||||
deviceAction: 'block'
|
||||
},
|
||||
server: {
|
||||
target: '::1',
|
||||
port:global.udpServerPort
|
||||
}
|
||||
}
|
||||
);
|
||||
let result = cef.validate();
|
||||
result = await cef.send({
|
||||
target: '::1',
|
||||
port:global.udpServerPort
|
||||
});
|
||||
result = await cef.send();
|
||||
await cef.close();
|
||||
let validateMsg = 'CEF:0|Unknown|Unknown|Unknown|Unknown|Unknown';
|
||||
validateMsg += '|Unknown|deviceAction=block ';
|
||||
expect(result).toBe(validateMsg);
|
||||
@ -175,9 +185,10 @@ describe('CEF Class Tests', () => {
|
||||
let cef = new SyslogPro.CEF({
|
||||
server: syslog
|
||||
});
|
||||
syslog.on('error', noop);
|
||||
expect.assertions(1);
|
||||
try {
|
||||
await cef.send({});
|
||||
await cef.send();
|
||||
} catch (reason) {
|
||||
expect(reason.message).toBe('connect ECONNREFUSED 127.0.0.1:8101');
|
||||
}
|
||||
@ -203,6 +214,7 @@ describe('LEEF Class Tests', () => {
|
||||
},
|
||||
server: syslog
|
||||
});
|
||||
syslog.on('error', noop);
|
||||
expect.assertions(1);
|
||||
try {
|
||||
await leef.send();
|
||||
@ -213,6 +225,7 @@ describe('LEEF Class Tests', () => {
|
||||
test('LEEF Send', async () => {
|
||||
let leef = new SyslogPro.LEEF();
|
||||
const result = await leef.send();
|
||||
await leef.close();
|
||||
expect(result).toBe('LEEF:2.0|unknown|unknown|unknown|unknown|');
|
||||
});
|
||||
test('LEEF Send with Auth TLS options', async () => {
|
||||
@ -228,6 +241,7 @@ describe('LEEF Class Tests', () => {
|
||||
});
|
||||
expect.assertions(1);
|
||||
const result = await leef.send();
|
||||
await leef.close();
|
||||
expect(result).toBe('LEEF:2.0|unknown|unknown|unknown|unknown|');
|
||||
});
|
||||
});
|
||||
@ -235,32 +249,46 @@ describe('LEEF Class Tests', () => {
|
||||
// RFC5424 Class Test
|
||||
describe('RFC5424 Class Tests', () => {
|
||||
test('RFC5424 Sending critical - debug Severity Messages', async () => {
|
||||
let rfc5424 = new SyslogPro.RFC5424();
|
||||
let result = await rfc5424.debug('test')
|
||||
expect(result).toMatch(/<191>1 /);
|
||||
result = await rfc5424.log('test');
|
||||
expect(result).toMatch(/<190>1 /);
|
||||
result = await rfc5424.info('test');
|
||||
expect(result).toMatch(/<190>1 /);
|
||||
result = await rfc5424.note('test');
|
||||
expect(result).toMatch(/<189>1 /);
|
||||
result = await rfc5424.warn('test');
|
||||
expect(result).toMatch(/<188>1 /);
|
||||
result = await rfc5424.err('test');
|
||||
expect(result).toMatch(/<187>1 /);
|
||||
result = await rfc5424.crit('test');
|
||||
expect(result).toMatch(/<186>1 /);
|
||||
const rfc5424 = new SyslogPro.RFC5424({
|
||||
server: {
|
||||
port: global.udpServerPort
|
||||
}
|
||||
});
|
||||
try {
|
||||
let result = await rfc5424.debug('test')
|
||||
expect(result).toMatch(/<191>1 /);
|
||||
result = await rfc5424.log('test');
|
||||
expect(result).toMatch(/<190>1 /);
|
||||
result = await rfc5424.info('test');
|
||||
expect(result).toMatch(/<190>1 /);
|
||||
result = await rfc5424.note('test');
|
||||
expect(result).toMatch(/<189>1 /);
|
||||
result = await rfc5424.warn('test');
|
||||
expect(result).toMatch(/<188>1 /);
|
||||
result = await rfc5424.err('test');
|
||||
expect(result).toMatch(/<187>1 /);
|
||||
result = await rfc5424.crit('test');
|
||||
expect(result).toMatch(/<186>1 /);
|
||||
} finally {
|
||||
await rfc5424.close();
|
||||
}
|
||||
});
|
||||
test('RFC5424 Sending emergency - alert Severity Messages', async () => {
|
||||
let syslog = new SyslogPro.Syslog();
|
||||
let syslog = new SyslogPro.Syslog({
|
||||
port: global.udpServerPort
|
||||
});
|
||||
let rfc5424 = new SyslogPro.RFC5424({
|
||||
server: syslog
|
||||
});
|
||||
expect.assertions(2);
|
||||
let result = await rfc5424.alert('test')
|
||||
expect(result).toMatch(/<185>1 /);
|
||||
result = await rfc5424.emer('test')
|
||||
expect(result).toMatch(/<184>1 /);
|
||||
try {
|
||||
let result = await rfc5424.alert('test')
|
||||
expect(result).toMatch(/<185>1 /);
|
||||
result = await rfc5424.emer('test')
|
||||
expect(result).toMatch(/<184>1 /);
|
||||
} finally {
|
||||
await rfc5424.close();
|
||||
}
|
||||
});
|
||||
test('RFC5424 Send with a bad message type ERROR', async () => {
|
||||
let rfc5424 = new SyslogPro.RFC5424();
|
||||
@ -295,6 +323,7 @@ describe('RFC5424 Class Tests', () => {
|
||||
protocol: 'tcp'
|
||||
}
|
||||
});
|
||||
rfc5424.server.on('error', noop);
|
||||
expect.assertions(1);
|
||||
try {
|
||||
await rfc5424.send('hello');
|
||||
@ -552,22 +581,30 @@ describe('RFC5424 Class Tests', () => {
|
||||
// RFC3164 Class Test
|
||||
describe('RFC3164 Class Tests', () => {
|
||||
test('RFC3164 Sending critical - debug Severity Messages', async () => {
|
||||
let rfc3164 = new SyslogPro.RFC3164();
|
||||
let rfc3164 = new SyslogPro.RFC3164({
|
||||
server: {
|
||||
port: global.udpServerPort
|
||||
}
|
||||
});
|
||||
expect.assertions(7);
|
||||
let result = await rfc3164.debug('test');
|
||||
expect(result).toMatch(/<191>J|F|M|A|S|O|N|D/);
|
||||
result = await rfc3164.log('test');
|
||||
expect(result).toMatch(/<190>J|F|M|A|S|O|N|D/);
|
||||
result = await rfc3164.info('test');
|
||||
expect(result).toMatch(/<190>J|F|M|A|S|O|N|D/);
|
||||
result = await rfc3164.note('test');
|
||||
expect(result).toMatch(/<189>J|F|M|A|S|O|N|D/);
|
||||
result = await rfc3164.warn('test');
|
||||
expect(result).toMatch(/<188>J|F|M|A|S|O|N|D/);
|
||||
result = await rfc3164.err('test');
|
||||
expect(result).toMatch(/<187>J|F|M|A|S|O|N|D/);
|
||||
result = await rfc3164.crit('test')
|
||||
expect(result).toMatch(/<186>J|F|M|A|S|O|N|D/);
|
||||
try {
|
||||
let result = await rfc3164.debug('test');
|
||||
expect(result).toMatch(/<191>J|F|M|A|S|O|N|D/);
|
||||
result = await rfc3164.log('test');
|
||||
expect(result).toMatch(/<190>J|F|M|A|S|O|N|D/);
|
||||
result = await rfc3164.info('test');
|
||||
expect(result).toMatch(/<190>J|F|M|A|S|O|N|D/);
|
||||
result = await rfc3164.note('test');
|
||||
expect(result).toMatch(/<189>J|F|M|A|S|O|N|D/);
|
||||
result = await rfc3164.warn('test');
|
||||
expect(result).toMatch(/<188>J|F|M|A|S|O|N|D/);
|
||||
result = await rfc3164.err('test');
|
||||
expect(result).toMatch(/<187>J|F|M|A|S|O|N|D/);
|
||||
result = await rfc3164.crit('test')
|
||||
expect(result).toMatch(/<186>J|F|M|A|S|O|N|D/);
|
||||
} finally {
|
||||
await rfc3164.close();
|
||||
}
|
||||
});
|
||||
test('RFC3164 Sending TCP emergency - alert Severity Messages', async () => {
|
||||
let syslog = new SyslogPro.Syslog({
|
||||
@ -577,10 +614,14 @@ describe('RFC3164 Class Tests', () => {
|
||||
let rfc3164 = new SyslogPro.RFC3164({
|
||||
server: syslog
|
||||
});
|
||||
let result = await rfc3164.alert('test');
|
||||
expect(result).toMatch(/<185>J|F|M|A|S|O|N|D/);
|
||||
result = await rfc3164.emer('test');
|
||||
expect(result).toMatch(/<184>J|F|M|A|S|O|N|D/);
|
||||
try {
|
||||
let result = await rfc3164.alert('test');
|
||||
expect(result).toMatch(/<185>J|F|M|A|S|O|N|D/);
|
||||
result = await rfc3164.emer('test');
|
||||
expect(result).toMatch(/<184>J|F|M|A|S|O|N|D/);
|
||||
} finally {
|
||||
await rfc3164.close();
|
||||
}
|
||||
});
|
||||
test('RFC3164 Send with a bad message type ERROR', async () => {
|
||||
let rfc3164 = new SyslogPro.RFC3164();
|
||||
@ -611,6 +652,7 @@ describe('RFC3164 Class Tests', () => {
|
||||
protocol: 'tcp'
|
||||
}
|
||||
});
|
||||
rfc3164.server.on('error', noop);
|
||||
expect.assertions(1);
|
||||
try {
|
||||
await rfc3164.send('hello');
|
||||
@ -760,11 +802,14 @@ describe('Base Syslog Class tests', () => {
|
||||
protocol: 'udp',
|
||||
port: global.udpServerPort
|
||||
});
|
||||
syslog.on('error', noop);
|
||||
expect.assertions(1);
|
||||
try {
|
||||
await syslog.send('test');
|
||||
} catch(reason) {
|
||||
expect(reason.message).toBe('getaddrinfo ENOTFOUND noteareal.dns');
|
||||
} finally {
|
||||
await syslog.close();
|
||||
}
|
||||
});
|
||||
test('Syslog Send UDP with bad message type Error', async () => {
|
||||
@ -788,6 +833,7 @@ describe('Base Syslog Class tests', () => {
|
||||
port: global.udpServerPort
|
||||
});
|
||||
const result = await syslog.send('test');
|
||||
await syslog.close();
|
||||
expect(result).toBe('test');
|
||||
});
|
||||
test('Syslog Send TLS with timeout Error', async () => {
|
||||
@ -861,6 +907,7 @@ describe('Base Syslog Class tests', () => {
|
||||
target: 'cloud.positon.org', // Public test server
|
||||
});
|
||||
const result = await syslog.send('test');
|
||||
await syslog.close();
|
||||
expect(result).toBe('test');
|
||||
});
|
||||
test('Syslog Send TLS without rejectUnauthorized', async () => {
|
||||
@ -870,6 +917,7 @@ describe('Base Syslog Class tests', () => {
|
||||
rejectUnauthorized: false
|
||||
});
|
||||
const result = await syslog.send('test');
|
||||
await syslog.close();
|
||||
expect(result).toBe('test');
|
||||
});
|
||||
test('Syslog Send TCP with DNS Error', async () => {
|
||||
@ -879,6 +927,7 @@ describe('Base Syslog Class tests', () => {
|
||||
port: global.tcpServerPort
|
||||
});
|
||||
expect.assertions(1);
|
||||
syslog.on('error', noop);
|
||||
try {
|
||||
await syslog.send('test');
|
||||
} catch(reason) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user