don't close socket after sending and add the close method and related events

This commit is contained in:
nkzawa 2019-10-11 13:19:52 +09:00
parent 0ebf6cb7dc
commit cd7c5e6b2c
3 changed files with 927 additions and 575 deletions

361
index.ts
View File

@ -16,9 +16,12 @@
* @exports CEF * @exports CEF
* @module SyslogPro * @module SyslogPro
*/ */
import EventEmitter from 'events';
import moment from 'moment'; 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 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 import * as tls from 'tls'; // eslint-disable-line no-unused-vars
let dnsPromises = dns.promises; let dnsPromises = dns.promises;
@ -114,7 +117,7 @@ type SyslogOptions = {
* @version 0.0.0 * @version 0.0.0
* @since 0.0.0 * @since 0.0.0
*/ */
export class Syslog { export class Syslog extends EventEmitter {
cef: any; cef: any;
format: string; format: string;
leef: any; leef: any;
@ -124,10 +127,13 @@ export class Syslog {
rfc3164: any; rfc3164: any;
rfc5424: any; rfc5424: any;
target: string; target: string;
tcpSocketPromise: Promise<net.Socket> | null;
tcpTimeout: number; tcpTimeout: number;
tlsServerCerts: (Buffer | string)[]; tlsServerCerts: (Buffer | string)[];
tlsClientCert: Buffer | string; tlsClientCert: Buffer | string;
tlsClientKey: Buffer | string; tlsClientKey: Buffer | string;
tlsSocketPromise: Promise<tls.TLSSocket> | null;
udpSocketPromise: Promise<dgram.Socket> | null;
/** /**
* Construct a new Syslog transport object with user options * Construct a new Syslog transport object with user options
* @public * @public
@ -171,6 +177,7 @@ export class Syslog {
* (Common Event Format) formatting object} * (Common Event Format) formatting object}
*/ */
constructor(options?: SyslogOptions) { constructor(options?: SyslogOptions) {
super();
if (!options) { if (!options) {
options = {}; options = {};
} }
@ -181,7 +188,21 @@ export class Syslog {
this.protocol = options.protocol || 'udp'; this.protocol = options.protocol || 'udp';
this.protocol = this.protocol.toLowerCase(); this.protocol = this.protocol.toLowerCase();
/** @type {number} */ /** @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} */ /** @type {number} */
this.tcpTimeout = options.tcpTimeout || 10000; this.tcpTimeout = options.tcpTimeout || 10000;
if (Array.isArray(options.tlsServerCerts) if (Array.isArray(options.tlsServerCerts)
@ -286,6 +307,23 @@ export class Syslog {
* @throws {Error} - Network Error * @throws {Error} - Network Error
*/ */
async udpMessage(msg) { 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 // Test for target DNS and Address Family (IPv4/6) by looking up the DNS
const dgram = require('dgram'); const dgram = require('dgram');
const dnsOptions = { const dnsOptions = {
@ -293,16 +331,24 @@ export class Syslog {
}; };
const result = await dnsPromises.lookup(this.target, dnsOptions); const result = await dnsPromises.lookup(this.target, dnsOptions);
const udpType = result.family === 4 ? 'udp4' : 'udp6'; const udpType = result.family === 4 ? 'udp4' : 'udp6';
let client = dgram.createSocket(udpType); const socket = dgram.createSocket(udpType);
// Turn msg in to a UTF8 buffer socket.on('close', () => {
let msgBuffer = Buffer.from(msg, 'utf8'); this.onClose();
return new Promise((resolve) => { });
client.send(msgBuffer, this.port, this.target, () => { socket.on('error', (error) => {
client.close(); this.emit('error', error);
resolve(msg); });
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 * Send the Syslog message over TCP
* @private * @private
@ -312,38 +358,76 @@ export class Syslog {
* @throws {Error} - Network Error * @throws {Error} - Network Error
*/ */
async tcpMessage(msg) { 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 net = require('net');
const dnsOptions = {
verbatim: true,
};
const result = await dnsPromises.lookup(this.target, dnsOptions);
const tcpOptions = { const tcpOptions = {
host: this.target, host: this.target,
port: this.port, 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) => { return new Promise((resolve, reject) => {
client.on('end', () => { const removeListeners = () => {
resolve(msg); socket.off('error', onceError);
}); socket.off('timeout', onceTimeout);
client.on('timeout', () => { };
client.end(); const onceError = (error) => {
reject(new Error('TIMEOUT ERROR: Syslog server TCP timeout')); removeListeners();
});
client.on('error', (error) => {
client.destroy();
reject(error); 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 * Send the Syslog message over TLS
* @private * @private
@ -353,6 +437,34 @@ export class Syslog {
* @throws {Error} - Network Error * @throws {Error} - Network Error
*/ */
async tlsMessage(msg) { 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 tls = require('tls');
const tlsOptions: tls.ConnectionOptions = { const tlsOptions: tls.ConnectionOptions = {
host: this.target, host: this.target,
@ -390,25 +502,39 @@ export class Syslog {
tlsOptions.ca = tlsOptionsCerts; tlsOptions.ca = tlsOptionsCerts;
} }
tlsOptions.rejectUnauthorized = this.rejectUnauthorized; 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) => { return new Promise((resolve, reject) => {
client.on('end', () => { const removeListeners = () => {
resolve(msg); socket.off('error', onceError);
}); socket.off('timeout', onceTimeout);
client.on('timeout', () => { };
client.end(); const onceError = (error) => {
reject(new Error('TIMEOUT ERROR: Syslog server TLS timeout')); removeListeners();
});
client.on('error', (error) => {
client.destroy();
reject(error); 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') { if (typeof msg !== 'string') {
throw new Error('TYPE ERROR: Syslog message must be a string'); throw new Error('TYPE ERROR: Syslog message must be a string');
} }
this.protocol = this.protocol.toLowerCase();
if (this.protocol === 'udp') { if (this.protocol === 'udp') {
return this.udpMessage(msg); return this.udpMessage(msg);
} else if (this.protocol === 'tcp') { } else if (this.protocol === 'tcp') {
@ -438,12 +563,68 @@ export class Syslog {
throw new Error(errorMsg); 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. * The base class of RFC formartted syslog messages.
*/ */
export class RFC { abstract class RFC extends Format {
alertColor: number; alertColor: number;
criticalColor: number; criticalColor: number;
emergencyColor: number; emergencyColor: number;
@ -616,7 +797,6 @@ export class RFC3164 extends RFC {
color: boolean; color: boolean;
facility: number; facility: number;
hostname: string; hostname: string;
server: Syslog;
/** /**
* Construct a new RFC3164 formatted Syslog object with user options * Construct a new RFC3164 formatted Syslog object with user options
* @public * @public
@ -678,13 +858,11 @@ export class RFC3164 extends RFC {
} else { } else {
this.extendedColor = false; this.extendedColor = false;
} }
if (options.server) { if (options.server instanceof Syslog) {
if (options.server instanceof Syslog) { /** @private @type {Syslog} */
/** @private @type {Syslog} */ this.server = options.server;
this.server = options.server; } else {
} else { this.server = new Syslog(options.server);
this.server = new Syslog(options.server);
}
} }
if (this.extendedColor) { if (this.extendedColor) {
/** @private @type {number} */ /** @private @type {number} */
@ -796,9 +974,6 @@ export class RFC3164 extends RFC {
* @throws {Error} A standard error object * @throws {Error} A standard error object
*/ */
async send(msg, options) { async send(msg, options) {
if (!this.server) {
this.server = new Syslog();
}
const result = this.buildMessage(msg, options); const result = this.buildMessage(msg, options);
return this.server.send(result); return this.server.send(result);
} }
@ -1024,7 +1199,6 @@ export class RFC5424 extends RFC {
applicationName: string; applicationName: string;
color: boolean; color: boolean;
hostname: string; hostname: string;
server: Syslog;
timestamp: boolean; timestamp: boolean;
timestampMS: boolean; timestampMS: boolean;
timestampTZ: boolean; timestampTZ: boolean;
@ -1105,13 +1279,11 @@ export class RFC5424 extends RFC {
} else { } else {
this.extendedColor = false; this.extendedColor = false;
} }
if (options.server) { if (options.server instanceof Syslog) {
if (options.server instanceof Syslog) { /** @private @type {Syslog} */
/** @private @type {Syslog} */ this.server = options.server;
this.server = options.server; } else {
} else { this.server = new Syslog(options.server);
this.server = new Syslog(options.server);
}
} }
if (this.extendedColor) { if (this.extendedColor) {
/** @private @type {number} */ /** @private @type {number} */
@ -1301,9 +1473,6 @@ export class RFC5424 extends RFC {
* @throws {Error} A standard error object * @throws {Error} A standard error object
*/ */
async send(msg, options) { async send(msg, options) {
if (!this.server) {
this.server = new Syslog();
}
const result = this.buildMessage(msg, options); const result = this.buildMessage(msg, options);
return this.server.send(result); return this.server.send(result);
} }
@ -1511,11 +1680,10 @@ type LEEFOptions = {
* @version 0.0.0 * @version 0.0.0
* @since 0.0.0 * @since 0.0.0
*/ */
export class LEEF { export class LEEF extends Format {
attributes: any; attributes: any;
eventId: string; eventId: string;
product: string; product: string;
server: Syslog;
syslogHeader: boolean; syslogHeader: boolean;
vendor: string; vendor: string;
version: string; version: string;
@ -1541,6 +1709,7 @@ export class LEEF {
* from this class. @see SyslogPro~Syslog * from this class. @see SyslogPro~Syslog
*/ */
constructor(options?: LEEFOptions) { constructor(options?: LEEFOptions) {
super();
options = options || {}; options = options || {};
/** @type {string} */ /** @type {string} */
this.vendor = options.vendor || 'unknown'; this.vendor = options.vendor || 'unknown';
@ -1602,13 +1771,11 @@ export class LEEF {
AttributeLimits: null, AttributeLimits: null,
calCountryOrRegion: null, calCountryOrRegion: null,
}; };
if (options.server) { if (options.server instanceof Syslog) {
if (options.server instanceof Syslog) { /** @private @type {Syslog} */
/** @private @type {Syslog} */ this.server = options.server;
this.server = options.server; } else {
} else { this.server = new Syslog(options.server);
this.server = new Syslog(options.server);
}
} }
} }
/** /**
@ -1638,15 +1805,9 @@ export class LEEF {
/** /**
* @public * @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(options) {
const result = this.buildMessage(); const result = this.buildMessage();
if (!this.server) {
this.server = new Syslog(options);
}
return this.server.send(result); return this.server.send(result);
} }
} }
@ -1677,14 +1838,13 @@ type CEFOptions = {
* @version 0.0.0 * @version 0.0.0
* @since 0.0.0 * @since 0.0.0
*/ */
export class CEF { export class CEF extends Format {
deviceEventClassId: string; deviceEventClassId: string;
deviceProduct: string; deviceProduct: string;
deviceVendor: string; deviceVendor: string;
deviceVersion: string; deviceVersion: string;
extensions: any; extensions: any;
name: string; name: string;
server: Syslog;
severity: string; severity: string;
/** /**
* Construct a new CEF formatting object with user options * Construct a new CEF formatting object with user options
@ -1707,6 +1867,7 @@ export class CEF {
* from this class. @see SyslogPro~Syslog * from this class. @see SyslogPro~Syslog
*/ */
constructor(options?: CEFOptions) { constructor(options?: CEFOptions) {
super();
options = options || {}; options = options || {};
/** @type {string} */ /** @type {string} */
this.deviceVendor = options.deviceVendor || 'Unknown'; this.deviceVendor = options.deviceVendor || 'Unknown';
@ -1880,13 +2041,11 @@ export class CEF {
sourceZoneExternalID: null, sourceZoneExternalID: null,
sourceZoneURI: null, sourceZoneURI: null,
}; };
if (options.server) { if (options.server instanceof Syslog) {
if (options.server instanceof Syslog) { /** @private @type {Syslog} */
/** @private @type {Syslog} */ this.server = options.server;
this.server = options.server; } else {
} else { this.server = new Syslog(options.server as SyslogOptions);
this.server = new Syslog(options.server as SyslogOptions);
}
} }
} }
/** /**
@ -3144,15 +3303,9 @@ export class CEF {
} }
/** /**
* @public * @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(); const result = this.buildMessage();
if (!this.server) {
this.server = new Syslog(options);
}
return this.server.send(result); return this.server.send(result);
} }
} }

858
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -4,88 +4,96 @@ const udp = require('dgram');
const net = require('net'); const net = require('net');
const tls = require('tls'); const tls = require('tls');
const fs = require('fs'); const fs = require('fs');
const dns = require('dns');
let dnsPromises = dns.promises; const noop = () => {};
let udpServer;
let tcpServer;;
let tlsBasicServer;
let tlsAuthServer;
function setupServers () { function setupServers () {
return new Promise ((resolve, reject) => { return Promise.all([
// Load a UDP server new Promise ((resolve, reject) => {
// global.udpServerPort = 8000; // Load a UDP server
this.udpServer = udp.createSocket('udp4'); // global.udpServerPort = 8000;
this.udpServer.bind(global.udpServerPort, () => { udpServer = udp.createSocket('udp6');
// console.log('UDP server running on', global.udpServerPort); udpServer.bind(global.udpServerPort, resolve);
}); udpServer.on('error', reject);
}),
// Load a TCP server
// global.tcpServerPort = 8001; new Promise ((resolve, reject) => {
this.tcpServer = net.createServer((socket) => { // Load a TCP server
socket.on('data', function (data) {}); // global.tcpServerPort = 8001;
socket.on('end', function () {}); tcpServer = net.createServer((socket) => {
}); socket.on('data', function (data) {});
this.tcpServer.listen(global.tcpServerPort, () => { socket.on('end', function () {});
// console.log('TCP server running on', global.tcpServerPort); });
}); tcpServer.listen(global.tcpServerPort, resolve);
tcpServer.on('error', reject);
// Load a basic TLS }),
// global.tlsBasicServerPort = 8002;
const tlsBasicServerOptions = { new Promise ((resolve, reject) => {
key: fs.readFileSync('./tests/jest_test_server_key.pem'), // Load a basic TLS
cert: fs.readFileSync('./tests/jest_test_server_cert.pem'), // global.tlsBasicServerPort = 8002;
handshakeTimeout: 100, const tlsBasicServerOptions = {
requestCert: false, key: fs.readFileSync('./tests/jest_test_server_key.pem'),
rejectUnauthorized: false cert: fs.readFileSync('./tests/jest_test_server_cert.pem'),
}; handshakeTimeout: 100,
this.tlsBasicServer = tls.createServer(tlsBasicServerOptions, (socket) => { requestCert: false,
socket.on('data', function (data) {}); rejectUnauthorized: false
socket.on('end', function() {}); };
}); tlsBasicServer = tls.createServer(tlsBasicServerOptions, (socket) => {
this.tlsBasicServer.listen(global.tlsBasicServerPort, () => { socket.on('data', function (data) {});
// console.log('TLS basic server running on', global.tlsBasicServerPort); socket.on('end', function() {});
}); });
tlsBasicServer.listen(global.tlsBasicServerPort, resolve);
// Load a TLS server with client Cert request tlsBasicServer.on('error', reject);
// global.tlsAuthServerPort = 8003; }),
const tlsAuthServerOptions = {
key: fs.readFileSync('./tests/jest_test_server_key.pem'), new Promise ((resolve, reject) => {
cert: fs.readFileSync('./tests/jest_test_server_cert.pem'), // Load a TLS server with client Cert request
ca: [ fs.readFileSync('./tests/jest_test_client_cert.pem') ], // global.tlsAuthServerPort = 8003;
handshakeTimeout: 100, const tlsAuthServerOptions = {
requestCert: true, key: fs.readFileSync('./tests/jest_test_server_key.pem'),
rejectUnauthorized: true cert: fs.readFileSync('./tests/jest_test_server_cert.pem'),
}; ca: [ fs.readFileSync('./tests/jest_test_client_cert.pem') ],
this.tlsAuthServer = tls.createServer(tlsAuthServerOptions, (socket) => { handshakeTimeout: 100,
socket.on('data', function (data) {}); requestCert: true,
socket.on('end', function() {}); rejectUnauthorized: true
}); };
this.tlsAuthServer.listen(global.tlsAuthServerPort, () => { tlsAuthServer = tls.createServer(tlsAuthServerOptions, (socket) => {
// console.log('TLS auth server running on', global.tlsAuthServerPort); socket.on('data', function (data) {});
}); socket.on('end', function() {});
}); });
tlsAuthServer.listen(global.tlsAuthServerPort, resolve);
tlsAuthServer.on('error', reject);
})
]);
} }
function teardownServers() { function teardownServers() {
return new Promise ((resolve, reject) => { return Promise.all([
this.udpServer.close(() => { new Promise((resolve) => {
// console.log('UDP server closed'); udpServer.close(resolve);
}); }),
this.tcpServer.close(() => { new Promise((resolve) => {
// console.log('TCP server closed'); tcpServer.close(resolve);
}); }),
this.tlsBasicServer.close(() => { new Promise((resolve) => {
// console.log('TLS basic server closed'); tlsBasicServer.close(resolve);
}); }),
this.tlsAuthServer.close(() => { new Promise((resolve) => {
// console.log('TLS auth server closed'); tlsAuthServer.close(resolve);
}); })
}); ]);
} }
beforeAll(() => { beforeAll(async () => {
setupServers().then((result => {})); await setupServers();
}); });
afterAll(() => { afterAll(async () => {
teardownServers().then((result => {})); await teardownServers();
}); });
// CEF Class Tests // CEF Class Tests
@ -154,14 +162,16 @@ describe('CEF Class Tests', () => {
{ {
extensions: { extensions: {
deviceAction: 'block' deviceAction: 'block'
},
server: {
target: '::1',
port:global.udpServerPort
} }
} }
); );
let result = cef.validate(); let result = cef.validate();
result = await cef.send({ result = await cef.send();
target: '::1', await cef.close();
port:global.udpServerPort
});
let validateMsg = 'CEF:0|Unknown|Unknown|Unknown|Unknown|Unknown'; let validateMsg = 'CEF:0|Unknown|Unknown|Unknown|Unknown|Unknown';
validateMsg += '|Unknown|deviceAction=block '; validateMsg += '|Unknown|deviceAction=block ';
expect(result).toBe(validateMsg); expect(result).toBe(validateMsg);
@ -175,9 +185,10 @@ describe('CEF Class Tests', () => {
let cef = new SyslogPro.CEF({ let cef = new SyslogPro.CEF({
server: syslog server: syslog
}); });
syslog.on('error', noop);
expect.assertions(1); expect.assertions(1);
try { try {
await cef.send({}); await cef.send();
} catch (reason) { } catch (reason) {
expect(reason.message).toBe('connect ECONNREFUSED 127.0.0.1:8101'); expect(reason.message).toBe('connect ECONNREFUSED 127.0.0.1:8101');
} }
@ -203,6 +214,7 @@ describe('LEEF Class Tests', () => {
}, },
server: syslog server: syslog
}); });
syslog.on('error', noop);
expect.assertions(1); expect.assertions(1);
try { try {
await leef.send(); await leef.send();
@ -213,6 +225,7 @@ describe('LEEF Class Tests', () => {
test('LEEF Send', async () => { test('LEEF Send', async () => {
let leef = new SyslogPro.LEEF(); let leef = new SyslogPro.LEEF();
const result = await leef.send(); const result = await leef.send();
await leef.close();
expect(result).toBe('LEEF:2.0|unknown|unknown|unknown|unknown|'); expect(result).toBe('LEEF:2.0|unknown|unknown|unknown|unknown|');
}); });
test('LEEF Send with Auth TLS options', async () => { test('LEEF Send with Auth TLS options', async () => {
@ -228,6 +241,7 @@ describe('LEEF Class Tests', () => {
}); });
expect.assertions(1); expect.assertions(1);
const result = await leef.send(); const result = await leef.send();
await leef.close();
expect(result).toBe('LEEF:2.0|unknown|unknown|unknown|unknown|'); expect(result).toBe('LEEF:2.0|unknown|unknown|unknown|unknown|');
}); });
}); });
@ -235,32 +249,46 @@ describe('LEEF Class Tests', () => {
// RFC5424 Class Test // RFC5424 Class Test
describe('RFC5424 Class Tests', () => { describe('RFC5424 Class Tests', () => {
test('RFC5424 Sending critical - debug Severity Messages', async () => { test('RFC5424 Sending critical - debug Severity Messages', async () => {
let rfc5424 = new SyslogPro.RFC5424(); const rfc5424 = new SyslogPro.RFC5424({
let result = await rfc5424.debug('test') server: {
expect(result).toMatch(/<191>1 /); port: global.udpServerPort
result = await rfc5424.log('test'); }
expect(result).toMatch(/<190>1 /); });
result = await rfc5424.info('test'); try {
expect(result).toMatch(/<190>1 /); let result = await rfc5424.debug('test')
result = await rfc5424.note('test'); expect(result).toMatch(/<191>1 /);
expect(result).toMatch(/<189>1 /); result = await rfc5424.log('test');
result = await rfc5424.warn('test'); expect(result).toMatch(/<190>1 /);
expect(result).toMatch(/<188>1 /); result = await rfc5424.info('test');
result = await rfc5424.err('test'); expect(result).toMatch(/<190>1 /);
expect(result).toMatch(/<187>1 /); result = await rfc5424.note('test');
result = await rfc5424.crit('test'); expect(result).toMatch(/<189>1 /);
expect(result).toMatch(/<186>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 () => { 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({ let rfc5424 = new SyslogPro.RFC5424({
server: syslog server: syslog
}); });
expect.assertions(2); expect.assertions(2);
let result = await rfc5424.alert('test') try {
expect(result).toMatch(/<185>1 /); let result = await rfc5424.alert('test')
result = await rfc5424.emer('test') expect(result).toMatch(/<185>1 /);
expect(result).toMatch(/<184>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 () => { test('RFC5424 Send with a bad message type ERROR', async () => {
let rfc5424 = new SyslogPro.RFC5424(); let rfc5424 = new SyslogPro.RFC5424();
@ -295,6 +323,7 @@ describe('RFC5424 Class Tests', () => {
protocol: 'tcp' protocol: 'tcp'
} }
}); });
rfc5424.server.on('error', noop);
expect.assertions(1); expect.assertions(1);
try { try {
await rfc5424.send('hello'); await rfc5424.send('hello');
@ -552,22 +581,30 @@ describe('RFC5424 Class Tests', () => {
// RFC3164 Class Test // RFC3164 Class Test
describe('RFC3164 Class Tests', () => { describe('RFC3164 Class Tests', () => {
test('RFC3164 Sending critical - debug Severity Messages', async () => { 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); expect.assertions(7);
let result = await rfc3164.debug('test'); try {
expect(result).toMatch(/<191>J|F|M|A|S|O|N|D/); let result = await rfc3164.debug('test');
result = await rfc3164.log('test'); expect(result).toMatch(/<191>J|F|M|A|S|O|N|D/);
expect(result).toMatch(/<190>J|F|M|A|S|O|N|D/); result = await rfc3164.log('test');
result = await rfc3164.info('test'); expect(result).toMatch(/<190>J|F|M|A|S|O|N|D/);
expect(result).toMatch(/<190>J|F|M|A|S|O|N|D/); result = await rfc3164.info('test');
result = await rfc3164.note('test'); expect(result).toMatch(/<190>J|F|M|A|S|O|N|D/);
expect(result).toMatch(/<189>J|F|M|A|S|O|N|D/); result = await rfc3164.note('test');
result = await rfc3164.warn('test'); expect(result).toMatch(/<189>J|F|M|A|S|O|N|D/);
expect(result).toMatch(/<188>J|F|M|A|S|O|N|D/); result = await rfc3164.warn('test');
result = await rfc3164.err('test'); expect(result).toMatch(/<188>J|F|M|A|S|O|N|D/);
expect(result).toMatch(/<187>J|F|M|A|S|O|N|D/); result = await rfc3164.err('test');
result = await rfc3164.crit('test') expect(result).toMatch(/<187>J|F|M|A|S|O|N|D/);
expect(result).toMatch(/<186>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 () => { test('RFC3164 Sending TCP emergency - alert Severity Messages', async () => {
let syslog = new SyslogPro.Syslog({ let syslog = new SyslogPro.Syslog({
@ -577,10 +614,14 @@ describe('RFC3164 Class Tests', () => {
let rfc3164 = new SyslogPro.RFC3164({ let rfc3164 = new SyslogPro.RFC3164({
server: syslog server: syslog
}); });
let result = await rfc3164.alert('test'); try {
expect(result).toMatch(/<185>J|F|M|A|S|O|N|D/); let result = await rfc3164.alert('test');
result = await rfc3164.emer('test'); expect(result).toMatch(/<185>J|F|M|A|S|O|N|D/);
expect(result).toMatch(/<184>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 () => { test('RFC3164 Send with a bad message type ERROR', async () => {
let rfc3164 = new SyslogPro.RFC3164(); let rfc3164 = new SyslogPro.RFC3164();
@ -611,6 +652,7 @@ describe('RFC3164 Class Tests', () => {
protocol: 'tcp' protocol: 'tcp'
} }
}); });
rfc3164.server.on('error', noop);
expect.assertions(1); expect.assertions(1);
try { try {
await rfc3164.send('hello'); await rfc3164.send('hello');
@ -760,11 +802,14 @@ describe('Base Syslog Class tests', () => {
protocol: 'udp', protocol: 'udp',
port: global.udpServerPort port: global.udpServerPort
}); });
syslog.on('error', noop);
expect.assertions(1); expect.assertions(1);
try { try {
await syslog.send('test'); await syslog.send('test');
} catch(reason) { } catch(reason) {
expect(reason.message).toBe('getaddrinfo ENOTFOUND noteareal.dns'); expect(reason.message).toBe('getaddrinfo ENOTFOUND noteareal.dns');
} finally {
await syslog.close();
} }
}); });
test('Syslog Send UDP with bad message type Error', async () => { test('Syslog Send UDP with bad message type Error', async () => {
@ -788,6 +833,7 @@ describe('Base Syslog Class tests', () => {
port: global.udpServerPort port: global.udpServerPort
}); });
const result = await syslog.send('test'); const result = await syslog.send('test');
await syslog.close();
expect(result).toBe('test'); expect(result).toBe('test');
}); });
test('Syslog Send TLS with timeout Error', async () => { test('Syslog Send TLS with timeout Error', async () => {
@ -861,6 +907,7 @@ describe('Base Syslog Class tests', () => {
target: 'cloud.positon.org', // Public test server target: 'cloud.positon.org', // Public test server
}); });
const result = await syslog.send('test'); const result = await syslog.send('test');
await syslog.close();
expect(result).toBe('test'); expect(result).toBe('test');
}); });
test('Syslog Send TLS without rejectUnauthorized', async () => { test('Syslog Send TLS without rejectUnauthorized', async () => {
@ -870,6 +917,7 @@ describe('Base Syslog Class tests', () => {
rejectUnauthorized: false rejectUnauthorized: false
}); });
const result = await syslog.send('test'); const result = await syslog.send('test');
await syslog.close();
expect(result).toBe('test'); expect(result).toBe('test');
}); });
test('Syslog Send TCP with DNS Error', async () => { test('Syslog Send TCP with DNS Error', async () => {
@ -879,6 +927,7 @@ describe('Base Syslog Class tests', () => {
port: global.tcpServerPort port: global.tcpServerPort
}); });
expect.assertions(1); expect.assertions(1);
syslog.on('error', noop);
try { try {
await syslog.send('test'); await syslog.send('test');
} catch(reason) { } catch(reason) {