From 00b72a3f5708b8f8c88d9ab1a24286002126873a Mon Sep 17 00:00:00 2001 From: Craig Yamato Date: Tue, 25 Sep 2018 18:23:58 +0000 Subject: [PATCH] Updated Readme --- README.md | 26 +- docs/api.md | 1257 +++++++++ docs/docco/README.md | 2699 +++++++++++++++++++ docs/docco/docco.css | 518 ++++ docs/docco/index.html | 2699 +++++++++++++++++++ docs/docco/public/fonts/aller-bold.eot | Bin 0 -> 29804 bytes docs/docco/public/fonts/aller-bold.ttf | Bin 0 -> 66836 bytes docs/docco/public/fonts/aller-bold.woff | Bin 0 -> 33244 bytes docs/docco/public/fonts/aller-light.eot | Bin 0 -> 29509 bytes docs/docco/public/fonts/aller-light.ttf | Bin 0 -> 68620 bytes docs/docco/public/fonts/aller-light.woff | Bin 0 -> 33124 bytes docs/docco/public/fonts/roboto-black.eot | Bin 0 -> 20702 bytes docs/docco/public/fonts/roboto-black.ttf | Bin 0 -> 44828 bytes docs/docco/public/fonts/roboto-black.woff | Bin 0 -> 24536 bytes docs/docco/public/stylesheets/normalize.css | 375 +++ docs/index.html | 185 +- docs/index.js.html | 67 +- docs/module-SyslogPro-CEF.html | 39 +- docs/module-SyslogPro-LEEF.html | 35 +- docs/module-SyslogPro-RFC3164.html | 77 +- docs/module-SyslogPro-RFC5424.html | 89 +- docs/module-SyslogPro-Syslog.html | 47 +- docs/module-SyslogPro.html | 18 +- index.js | 65 +- jsdoc.json | 25 + jsdoc2md/api.hbs | 22 + package-lock.json | 444 ++- package.json | 14 +- 28 files changed, 8448 insertions(+), 253 deletions(-) create mode 100644 docs/api.md create mode 100644 docs/docco/README.md create mode 100644 docs/docco/docco.css create mode 100644 docs/docco/index.html create mode 100644 docs/docco/public/fonts/aller-bold.eot create mode 100644 docs/docco/public/fonts/aller-bold.ttf create mode 100644 docs/docco/public/fonts/aller-bold.woff create mode 100644 docs/docco/public/fonts/aller-light.eot create mode 100644 docs/docco/public/fonts/aller-light.ttf create mode 100644 docs/docco/public/fonts/aller-light.woff create mode 100755 docs/docco/public/fonts/roboto-black.eot create mode 100755 docs/docco/public/fonts/roboto-black.ttf create mode 100755 docs/docco/public/fonts/roboto-black.woff create mode 100644 docs/docco/public/stylesheets/normalize.css create mode 100644 jsdoc.json create mode 100644 jsdoc2md/api.hbs diff --git a/README.md b/README.md index 486da3c..544f4dc 100644 --- a/README.md +++ b/README.md @@ -18,10 +18,18 @@ Structured Data is also included in the module. All 28 standard CEF Extensions are included in the default CEF class. All 45 standard LEEF Attributes are included in the default LEEF class. It is the goal of this project is for every release to offer full code coverage unit testing and documentation. -[Please see the full documentation for usage and options: + +[Please see the full JSDoc for usage and options: https://cyamato.github.io/SyslogPro/](https://cyamato.github.io/SyslogPro/). -## Installation +### News +* ⚠ Please note that at present, the 0.1.x version of the SDK +[requires Node 10.6 or later](https://github.com/nodejs/LTS). +* This module makes use of [ECMA-262 Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) +and the [DNS Promises API](https://nodejs.org/api/dns.html#dns_dns_promises_api). +* APIs do not support the callback model and only return promises. + +### Installation ```shell npm install --save SyslogPro ``` @@ -110,7 +118,12 @@ https://cyamato.github.io/SyslogPro/](https://cyamato.github.io/SyslogPro/). console.log(error); }); ``` - + +## API +For more details see: +* [JSDoc](https://cyamato.github.io/SyslogPro/) +* [api.md](./docs/api.md) + ## Test ```shell npm test @@ -118,4 +131,9 @@ https://cyamato.github.io/SyslogPro/](https://cyamato.github.io/SyslogPro/). ## Contributing -Please try to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code. \ No newline at end of file +Please try to maintain the existing coding style. Add unit tests for any new or +changed functionality. Lint and test your code. + +* [Repository](https://github.com/cyamato/SyslogPro.git) +* [Bug Reporting](https://github.com/cyamato/SyslogPro/issues) +* [Wiki](https://github.com/cyamato/SyslogPro/wiki) \ No newline at end of file diff --git a/docs/api.md b/docs/api.md new file mode 100644 index 0000000..f96c87e --- /dev/null +++ b/docs/api.md @@ -0,0 +1,1257 @@ +API +========================== + +- back to [README.md](../README.md) + +API convention +== + + + +## SyslogPro +The SyslogPro module for sending syslog messages +Most APIs will return a promise. These APIs can be used using +`then(...)/catch(...)` + +Syslog formating classes can be used as input into a Syslog class to be used +simultatniusly to the same Syslog server. The Syslog Class with a configured +Syslog server target can also be used as the input into each of the formating +classes so that they may run independtly. + +**Version**: 0.1.0 +**Author**: Craig Yamato +**Copyright**: (c) 2018 - Craig Yamato + +* [SyslogPro](#module_SyslogPro) + * [~Syslog](#module_SyslogPro..Syslog) + * [new Syslog([options])](#new_module_SyslogPro..Syslog_new) + * [.target](#module_SyslogPro..Syslog+target) : string + * [.protocol](#module_SyslogPro..Syslog+protocol) : string + * [.port](#module_SyslogPro..Syslog+port) : number + * [.tcpTimeout](#module_SyslogPro..Syslog+tcpTimeout) : number + * [.tlsServerCerts](#module_SyslogPro..Syslog+tlsServerCerts) : Array.<string> + * [.tlsClientCert](#module_SyslogPro..Syslog+tlsClientCert) : string + * [.tlsClientKey](#module_SyslogPro..Syslog+tlsClientKey) : string + * [.format](#module_SyslogPro..Syslog+format) : string + * [.rfc3164](#module_SyslogPro..Syslog+rfc3164) : RFC3164 + * [.rfc5424](#module_SyslogPro..Syslog+rfc5424) : RFC5424 + * [.leef](#module_SyslogPro..Syslog+leef) : LEEF + * [.cef](#module_SyslogPro..Syslog+cef) : CEF + * [~RFC3164](#module_SyslogPro..RFC3164) + * [new RFC3164([options])](#new_module_SyslogPro..RFC3164_new) + * [.color](#module_SyslogPro..RFC3164+color) : boolean + * [.extendedColor](#module_SyslogPro..RFC3164+extendedColor) : boolean + * [.setColor()](#module_SyslogPro..RFC3164+setColor) + * [.buildMessage(msg, [options])](#module_SyslogPro..RFC3164+buildMessage) ⇒ Promise + * [.send(msg, [options])](#module_SyslogPro..RFC3164+send) ⇒ Promise + * [.emergency(msg)](#module_SyslogPro..RFC3164+emergency) ⇒ Promise + * [.emer(msg)](#module_SyslogPro..RFC3164+emer) ⇒ Promise + * [.alert(msg)](#module_SyslogPro..RFC3164+alert) ⇒ Promise + * [.critical(msg)](#module_SyslogPro..RFC3164+critical) ⇒ Promise + * [.crit(msg)](#module_SyslogPro..RFC3164+crit) ⇒ Promise + * [.error(msg)](#module_SyslogPro..RFC3164+error) ⇒ Promise + * [.err(msg)](#module_SyslogPro..RFC3164+err) ⇒ Promise + * [.warning(msg)](#module_SyslogPro..RFC3164+warning) ⇒ Promise + * [.warn(msg)](#module_SyslogPro..RFC3164+warn) ⇒ Promise + * [.notice(msg)](#module_SyslogPro..RFC3164+notice) ⇒ Promise + * [.note(msg)](#module_SyslogPro..RFC3164+note) ⇒ Promise + * [.informational(msg)](#module_SyslogPro..RFC3164+informational) ⇒ Promise + * [.info(msg)](#module_SyslogPro..RFC3164+info) ⇒ Promise + * [.log(msg)](#module_SyslogPro..RFC3164+log) ⇒ Promise + * [.debug(msg)](#module_SyslogPro..RFC3164+debug) ⇒ Promise + * [~RFC5424](#module_SyslogPro..RFC5424) + * [new RFC5424([options])](#new_module_SyslogPro..RFC5424_new) + * [.timestamp](#module_SyslogPro..RFC5424+timestamp) : boolean + * [.timestampUTC](#module_SyslogPro..RFC5424+timestampUTC) : boolean + * [.timestampTZ](#module_SyslogPro..RFC5424+timestampTZ) : boolean + * [.timestampMS](#module_SyslogPro..RFC5424+timestampMS) : boolean + * [.encludeStructuredData](#module_SyslogPro..RFC5424+encludeStructuredData) : boolean + * [.utf8BOM](#module_SyslogPro..RFC5424+utf8BOM) : boolean + * [.color](#module_SyslogPro..RFC5424+color) : boolean + * [.extendedColor](#module_SyslogPro..RFC5424+extendedColor) : boolean + * [.setColor()](#module_SyslogPro..RFC5424+setColor) + * [.buildMessage(msg, [options])](#module_SyslogPro..RFC5424+buildMessage) ⇒ Promise + * [.send(msg)](#module_SyslogPro..RFC5424+send) ⇒ Promise + * [.emergency(msg)](#module_SyslogPro..RFC5424+emergency) ⇒ Promise + * [.emer(msg)](#module_SyslogPro..RFC5424+emer) ⇒ Promise + * [.alert(msg)](#module_SyslogPro..RFC5424+alert) ⇒ Promise + * [.critical(msg)](#module_SyslogPro..RFC5424+critical) ⇒ Promise + * [.crit(msg)](#module_SyslogPro..RFC5424+crit) ⇒ Promise + * [.error(msg)](#module_SyslogPro..RFC5424+error) ⇒ Promise + * [.err(msg)](#module_SyslogPro..RFC5424+err) ⇒ Promise + * [.warning(msg)](#module_SyslogPro..RFC5424+warning) ⇒ Promise + * [.warn(msg)](#module_SyslogPro..RFC5424+warn) ⇒ Promise + * [.notice(msg)](#module_SyslogPro..RFC5424+notice) ⇒ Promise + * [.note(msg)](#module_SyslogPro..RFC5424+note) ⇒ Promise + * [.informational(msg)](#module_SyslogPro..RFC5424+informational) ⇒ Promise + * [.info(msg)](#module_SyslogPro..RFC5424+info) ⇒ Promise + * [.log(msg)](#module_SyslogPro..RFC5424+log) ⇒ Promise + * [.debug(msg)](#module_SyslogPro..RFC5424+debug) ⇒ Promise + * [~LEEF](#module_SyslogPro..LEEF) + * [new LEEF([options])](#new_module_SyslogPro..LEEF_new) + * [.vendor](#module_SyslogPro..LEEF+vendor) : string + * [.product](#module_SyslogPro..LEEF+product) : string + * [.version](#module_SyslogPro..LEEF+version) : string + * [.eventId](#module_SyslogPro..LEEF+eventId) : string + * [.syslogHeader](#module_SyslogPro..LEEF+syslogHeader) : boolean + * [.attrabutes](#module_SyslogPro..LEEF+attrabutes) : object + * [.buildMessage()](#module_SyslogPro..LEEF+buildMessage) ⇒ Promise + * [.send([options])](#module_SyslogPro..LEEF+send) + * [~CEF](#module_SyslogPro..CEF) + * [new CEF([options])](#new_module_SyslogPro..CEF_new) + * [.deviceVendor](#module_SyslogPro..CEF+deviceVendor) : string + * [.deviceProduct](#module_SyslogPro..CEF+deviceProduct) : string + * [.deviceVersion](#module_SyslogPro..CEF+deviceVersion) : string + * [.deviceEventClassId](#module_SyslogPro..CEF+deviceEventClassId) : string + * [.name](#module_SyslogPro..CEF+name) : string + * [.severity](#module_SyslogPro..CEF+severity) : string + * [.extensions](#module_SyslogPro..CEF+extensions) : object + * [.validate()](#module_SyslogPro..CEF+validate) ⇒ Promise + * [.buildMessage()](#module_SyslogPro..CEF+buildMessage) ⇒ Promise + * [.send([options])](#module_SyslogPro..CEF+send) + + + +### SyslogPro~Syslog +A class to work with syslog messages using UDP, TCP, or TLS transport. +There is suport for Syslog message formating RFC-3164, RFC-5424 including +Structured Data, IBM LEEF (Log Event Extended Format), and HP CEF (Common +Event Format). +Syslog formating classes can be used as input into a Syslog class to be used +simultatniusly to the same Syslog server. * + +**Kind**: inner class of [SyslogPro](#module_SyslogPro) +**Requires**: module:moment +**Since**: 0.0.0 +**Version**: 0.0.0 + +* [~Syslog](#module_SyslogPro..Syslog) + * [new Syslog([options])](#new_module_SyslogPro..Syslog_new) + * [.target](#module_SyslogPro..Syslog+target) : string + * [.protocol](#module_SyslogPro..Syslog+protocol) : string + * [.port](#module_SyslogPro..Syslog+port) : number + * [.tcpTimeout](#module_SyslogPro..Syslog+tcpTimeout) : number + * [.tlsServerCerts](#module_SyslogPro..Syslog+tlsServerCerts) : Array.<string> + * [.tlsClientCert](#module_SyslogPro..Syslog+tlsClientCert) : string + * [.tlsClientKey](#module_SyslogPro..Syslog+tlsClientKey) : string + * [.format](#module_SyslogPro..Syslog+format) : string + * [.rfc3164](#module_SyslogPro..Syslog+rfc3164) : RFC3164 + * [.rfc5424](#module_SyslogPro..Syslog+rfc5424) : RFC5424 + * [.leef](#module_SyslogPro..Syslog+leef) : LEEF + * [.cef](#module_SyslogPro..Syslog+cef) : CEF + + + +#### new Syslog([options]) +Construct a new Syslog transport object with user options + + +| Param | Type | Default | Description | +| --- | --- | --- | --- | +| [options] | object | | Options object >>>Transport Configuraton | +| [options.target] | string | "'localhost'" | The IP Address|FQDN of the Syslog Server, this option if set will take prasdents over any target set in a formating object | +| [options.protocol] | string | "'udp'" | L4 transport portocol (udp|tcp|tls), this option if set will take prasdents over any transport set in a formating object | +| [options.port] | number | 514 | IP port, this option if set will take prasdents over any IP Port set in a formating object | +| [options.tcpTimeout] | number | 10000 | Ignored for all other transports, this option if set will take prasdents over any timeout set in a formating object | +| [options.tlsServerCerts] | Array.<string> | | Array of authrized TLS server certificates file locations, this option if set will take prasdents over any certificates set in a formating object | +| [options.tlsClientCert] | string | | Client TLS certificate file location that this client should use, this option if set will take prasdents over any certificates set in a formating object | +| [options.tlsClientKey] | string | | Client TLS key file location that this client should use, this option if set will take prasdents over any certificates set in a formating object >>>Syslog Format Settings | +| [options.format] | string | "'none'" | Valid syslog format options for this module are 'none', 'rfc3164', 'rfc5424', 'leef', 'cef' | +| [options.rfc5424] | RFC3164 | | {@link module:SyslogPro~RFC5424| RFC5424 related settings} | +| [options.rfc5424] | RFC5424 | | {@link module:SyslogPro~RFC5424| RFC5424 related settings} | +| [options.leef] | LEEF | | {@link module:SyslogPro~LEEF|IBM LEEF (Log Event Extended Format) object} | +| [options.cef] | CEF | | {@link module:SyslogPro~CEF|HP CEF (Common Event Format) formating object} | + + + +#### syslog.target : string +**Kind**: instance property of [Syslog](#module_SyslogPro..Syslog) + + +#### syslog.protocol : string +**Kind**: instance property of [Syslog](#module_SyslogPro..Syslog) + + +#### syslog.port : number +**Kind**: instance property of [Syslog](#module_SyslogPro..Syslog) + + +#### syslog.tcpTimeout : number +**Kind**: instance property of [Syslog](#module_SyslogPro..Syslog) + + +#### syslog.tlsServerCerts : Array.<string> +**Kind**: instance property of [Syslog](#module_SyslogPro..Syslog) + + +#### syslog.tlsClientCert : string +**Kind**: instance property of [Syslog](#module_SyslogPro..Syslog) + + +#### syslog.tlsClientKey : string +**Kind**: instance property of [Syslog](#module_SyslogPro..Syslog) + + +#### syslog.format : string +**Kind**: instance property of [Syslog](#module_SyslogPro..Syslog) + + +#### syslog.rfc3164 : RFC3164 +**Kind**: instance property of [Syslog](#module_SyslogPro..Syslog) + + +#### syslog.rfc5424 : RFC5424 +**Kind**: instance property of [Syslog](#module_SyslogPro..Syslog) + + +#### syslog.leef : LEEF +**Kind**: instance property of [Syslog](#module_SyslogPro..Syslog) + + +#### syslog.cef : CEF +**Kind**: instance property of [Syslog](#module_SyslogPro..Syslog) + + +### SyslogPro~RFC3164 +A class to work with RFC3164 formated syslog messages. The meesaging is fully configurabule and Ansi foreground +colors can be added. Both ANSI 8 and ANSI 256 color are fully suported. +Most APIs will return a promise. These APIs can be used using +`then(...)/catch(...)` + +A Syslog class with a configured +Syslog server target can also be used as the input into the formating +classes so that it may run independtly. + +The RFC3164 Syslog logging format is ment to be used as a stream of log data +from a service or applacation. This class is designed to be used in this +fashion where new messages are writen to the class as needed. + +**Kind**: inner class of [SyslogPro](#module_SyslogPro) +**Requires**: module:moment +**Since**: 0.0.0 +**Version**: 0.0.0 + +* [~RFC3164](#module_SyslogPro..RFC3164) + * [new RFC3164([options])](#new_module_SyslogPro..RFC3164_new) + * [.color](#module_SyslogPro..RFC3164+color) : boolean + * [.extendedColor](#module_SyslogPro..RFC3164+extendedColor) : boolean + * [.setColor()](#module_SyslogPro..RFC3164+setColor) + * [.buildMessage(msg, [options])](#module_SyslogPro..RFC3164+buildMessage) ⇒ Promise + * [.send(msg, [options])](#module_SyslogPro..RFC3164+send) ⇒ Promise + * [.emergency(msg)](#module_SyslogPro..RFC3164+emergency) ⇒ Promise + * [.emer(msg)](#module_SyslogPro..RFC3164+emer) ⇒ Promise + * [.alert(msg)](#module_SyslogPro..RFC3164+alert) ⇒ Promise + * [.critical(msg)](#module_SyslogPro..RFC3164+critical) ⇒ Promise + * [.crit(msg)](#module_SyslogPro..RFC3164+crit) ⇒ Promise + * [.error(msg)](#module_SyslogPro..RFC3164+error) ⇒ Promise + * [.err(msg)](#module_SyslogPro..RFC3164+err) ⇒ Promise + * [.warning(msg)](#module_SyslogPro..RFC3164+warning) ⇒ Promise + * [.warn(msg)](#module_SyslogPro..RFC3164+warn) ⇒ Promise + * [.notice(msg)](#module_SyslogPro..RFC3164+notice) ⇒ Promise + * [.note(msg)](#module_SyslogPro..RFC3164+note) ⇒ Promise + * [.informational(msg)](#module_SyslogPro..RFC3164+informational) ⇒ Promise + * [.info(msg)](#module_SyslogPro..RFC3164+info) ⇒ Promise + * [.log(msg)](#module_SyslogPro..RFC3164+log) ⇒ Promise + * [.debug(msg)](#module_SyslogPro..RFC3164+debug) ⇒ Promise + + + +#### new RFC3164([options]) +Construct a new RFC3164 formated Syslog object with user options + + +| Param | Type | Default | Description | +| --- | --- | --- | --- | +| [options] | object | | Options object | +| [options.applacationName] | string | "'NodeJSLogger'" | Applacation | +| [options.hostname] | string | "os.hostname" | The name of this server | +| [options.facility] | number | 23 | Facility code to use sending this message | +| [options.color] | boolean | false | Apply color coding encoding tag with syslog message text | +| [options.extendedColor] | boolean | false | Use the extedned ANSI color set encoding tag with syslog message text | +| [options.colors] | object | | User defended colors for severites | +| [options.colors.emergencyColor] | string | | A RGB Hex coded color in the form of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 Extended) | +| [options.colors.alertColor] | string | | A RGB Hex coded color in the form of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 Extended) | +| [options.colors.criticalColor] | string | | A RGB Hex coded color in the form of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 Extended) | +| [options.colors.errorColor] | string | | A RGB Hex coded color in the form of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 Extended) | +| [options.colors.warningColor] | string | | A RGB Hex coded color in the form of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 Extended) | +| [options.colors.noticeColor] | string | | A RGB Hex coded color in the form of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 Extended) | +| [options.colors.informationalColor] | string | | A RGB Hex coded color in the form of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 Extended) | +| [options.colors.debugColor] | string | | A RGB Hex coded color in the form of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 Extended) | +| [options.server] | Syslog | false | A {@link module:SyslogPro~Syslog| Syslog server connection} that should be used to send messages directly from this class. @see SyslogPro~Syslog | + + + +#### rfC3164.color : boolean +**Kind**: instance property of [RFC3164](#module_SyslogPro..RFC3164) + + +#### rfC3164.extendedColor : boolean +**Kind**: instance property of [RFC3164](#module_SyslogPro..RFC3164) + + +#### rfC3164.setColor() +Sets the color to be used for messages at a set priority + +**Kind**: instance method of [RFC3164](#module_SyslogPro..RFC3164) +**Throws**: + +- Error A standard error object + +**Access**: public + +| Param | Type | Description | +| --- | --- | --- | +| [colors.emergencyColor] | string | A RGB Hex coded color in the form of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 Extended) | +| [colors.alertColor] | string | A RGB Hex coded color in the form of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 Extended) | +| [colors.criticalColor] | string | A RGB Hex coded color in the form of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 Extended) | +| [colors.errorColor] | string | A RGB Hex coded color in the form of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 Extended) | +| [colors.warningColor] | string | A RGB Hex coded color in the form of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 Extended) | +| [colors.noticeColor] | string | A RGB Hex coded color in the form of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 Extended) | +| [colors.informationalColor] | string | A RGB Hex coded color in the form of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 Extended) | +| [colors.debugColor] | string | A RGB Hex coded color in the form of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 Extended) | + + + +#### rfC3164.buildMessage(msg, [options]) ⇒ Promise +Building a formated message. Returns a promise with a formated message + +**Kind**: instance method of [RFC3164](#module_SyslogPro..RFC3164) +**Returns**: Promise - A Syslog formated string acording to the selected RFC +**Throws**: + +- Error A standard error object + +**Access**: public + +| Param | Type | Default | Description | +| --- | --- | --- | --- | +| msg | string | | The Syslog Message | +| [options] | object | | Options object | +| [options.severity] | number | 7 | An array of structure | +| [options.colorCode] | number | 36 | The ANSI color code to use if message coloration is selected | + + + +#### rfC3164.send(msg, [options]) ⇒ Promise +send a RFC5424 formated message. Returns a promise with the formated + message that was sent. If no server connection was defined when the + class was created a defualt Syslog connector will be used. + +**Kind**: instance method of [RFC3164](#module_SyslogPro..RFC3164) +**Returns**: Promise - A Syslog formated string acording to the selected RFC +**Throws**: + +- Error A standard error object + +**Access**: public +**See**: SyslogPro~Syslog + +| Param | Type | Default | Description | +| --- | --- | --- | --- | +| msg | string | | The unformated Syslog message to send | +| [options] | object | | Options object | +| [options.severity] | number | 7 | An array of structure | +| [options.colorCode] | number | 36 | The ANSI color code to use if | + + + +#### rfC3164.emergency(msg) ⇒ Promise +Send a syslog message with a secerity level of 0 (Emergency) + +**Kind**: instance method of [RFC3164](#module_SyslogPro..RFC3164) +**Returns**: Promise - - The formated syslog message sent to the Syslog server +**Throws**: + +- Error - Any bubbled up error + +**Access**: public + +| Param | Type | Description | +| --- | --- | --- | +| msg | string | The emergancy message to send to the Syslog server | + + + +#### rfC3164.emer(msg) ⇒ Promise +Send a syslog message with a secerity level of 0 (Emergency) + +**Kind**: instance method of [RFC3164](#module_SyslogPro..RFC3164) +**Returns**: Promise - - The formated syslog message sent to the Syslog server +**Throws**: + +- Error - Any bubbled up error + +**Access**: public + +| Param | Type | Description | +| --- | --- | --- | +| msg | string | The emergancy message to send to the Syslog server | + + + +#### rfC3164.alert(msg) ⇒ Promise +Send a syslog message with a secerity level of 1 (Alert) + +**Kind**: instance method of [RFC3164](#module_SyslogPro..RFC3164) +**Returns**: Promise - - The formated syslog message sent to the Syslog server +**Throws**: + +- Error - Any bubbled up error + +**Access**: public + +| Param | Type | Description | +| --- | --- | --- | +| msg | string | The alert message to send to the Syslog server | + + + +#### rfC3164.critical(msg) ⇒ Promise +Send a syslog message with a secerity level of 2 (Critical) + +**Kind**: instance method of [RFC3164](#module_SyslogPro..RFC3164) +**Returns**: Promise - - The formated syslog message sent to the Syslog server +**Throws**: + +- Error - Any bubbled up error + +**Access**: public + +| Param | Type | Description | +| --- | --- | --- | +| msg | string | The critical message to send to the Syslog server | + + + +#### rfC3164.crit(msg) ⇒ Promise +Send a syslog message with a secerity level of 2 (Critical) + +**Kind**: instance method of [RFC3164](#module_SyslogPro..RFC3164) +**Returns**: Promise - - The formated syslog message sent to the Syslog server +**Throws**: + +- Error - Any bubbled up error + +**Access**: public + +| Param | Type | Description | +| --- | --- | --- | +| msg | string | The critical message to send to the Syslog server | + + + +#### rfC3164.error(msg) ⇒ Promise +Send a syslog message with a secerity level of 3 (Error) + +**Kind**: instance method of [RFC3164](#module_SyslogPro..RFC3164) +**Returns**: Promise - - The formated syslog message sent to the Syslog server +**Throws**: + +- Error - Any bubbled up error + +**Access**: public + +| Param | Type | Description | +| --- | --- | --- | +| msg | string | The error message to send to the Syslog server | + + + +#### rfC3164.err(msg) ⇒ Promise +Send a syslog message with a secerity level of 3 (Error) + +**Kind**: instance method of [RFC3164](#module_SyslogPro..RFC3164) +**Returns**: Promise - - The formated syslog message sent to the Syslog server +**Throws**: + +- Error - Any bubbled up error + +**Access**: public + +| Param | Type | Description | +| --- | --- | --- | +| msg | string | The error message to send to the Syslog server | + + + +#### rfC3164.warning(msg) ⇒ Promise +Send a syslog message with a secerity level of 4 (Warning) + +**Kind**: instance method of [RFC3164](#module_SyslogPro..RFC3164) +**Returns**: Promise - - The formated syslog message sent to the Syslog server +**Throws**: + +- Error - Any bubbled up error + +**Access**: public + +| Param | Type | Description | +| --- | --- | --- | +| msg | string | The warning message to send to the Syslog server | + + + +#### rfC3164.warn(msg) ⇒ Promise +Send a syslog message with a secerity level of 4 (Warning) + +**Kind**: instance method of [RFC3164](#module_SyslogPro..RFC3164) +**Returns**: Promise - - The formated syslog message sent to the Syslog server +**Throws**: + +- Error - Any bubbled up error + +**Access**: public + +| Param | Type | Description | +| --- | --- | --- | +| msg | string | The warning message to send to the Syslog server | + + + +#### rfC3164.notice(msg) ⇒ Promise +Send a syslog message with a secerity level of 5 (Notice) + +**Kind**: instance method of [RFC3164](#module_SyslogPro..RFC3164) +**Returns**: Promise - - The formated syslog message sent to the Syslog server +**Throws**: + +- Error - Any bubbled up error + +**Access**: public + +| Param | Type | Description | +| --- | --- | --- | +| msg | string | The notice message to send to the Syslog server | + + + +#### rfC3164.note(msg) ⇒ Promise +Send a syslog message with a secerity level of 5 (Notice) + +**Kind**: instance method of [RFC3164](#module_SyslogPro..RFC3164) +**Returns**: Promise - - The formated syslog message sent to the Syslog server +**Throws**: + +- Error - Any bubbled up error + +**Access**: public + +| Param | Type | Description | +| --- | --- | --- | +| msg | string | The notice message to send to the Syslog server | + + + +#### rfC3164.informational(msg) ⇒ Promise +Send a syslog message with a secerity level of 6 (Informational) + +**Kind**: instance method of [RFC3164](#module_SyslogPro..RFC3164) +**Returns**: Promise - - The formated syslog message sent to the Syslog server +**Throws**: + +- Error - Any bubbled up error + +**Access**: public + +| Param | Type | Description | +| --- | --- | --- | +| msg | string | The informational message to send to the Syslog server | + + + +#### rfC3164.info(msg) ⇒ Promise +Send a syslog message with a secerity level of 6 (Informational) + +**Kind**: instance method of [RFC3164](#module_SyslogPro..RFC3164) +**Returns**: Promise - - The formated syslog message sent to the Syslog server +**Throws**: + +- Error - Any bubbled up error + +**Access**: public + +| Param | Type | Description | +| --- | --- | --- | +| msg | string | The informational message to send to the Syslog server | + + + +#### rfC3164.log(msg) ⇒ Promise +Send a syslog message with a secerity level of 6 (Informational) + +**Kind**: instance method of [RFC3164](#module_SyslogPro..RFC3164) +**Returns**: Promise - - The formated syslog message sent to the Syslog server +**Throws**: + +- Error - Any bubbled up error + +**Access**: public + +| Param | Type | Description | +| --- | --- | --- | +| msg | string | The informational message to send to the Syslog server | + + + +#### rfC3164.debug(msg) ⇒ Promise +Send a syslog message with a secerity level of 7 (Debug) + +**Kind**: instance method of [RFC3164](#module_SyslogPro..RFC3164) +**Returns**: Promise - - The formated syslog message sent to the Syslog server +**Throws**: + +- Error - Any bubbled up error + +**Access**: public + +| Param | Type | Description | +| --- | --- | --- | +| msg | string | The debug message to send to the Syslog server | + + + +### SyslogPro~RFC5424 +A class to work with RFC5424 formated syslog messages. The meesaging is fully configurabule and Ansi foreground +colors can be added. Both ANSI 8 and ANSI 256 color are fully suported. +Most APIs will return a promise. These APIs can be used using +`then(...)/catch(...)` + +A Syslog class with a configured +Syslog server target can also be used as the input into the formating +classes so that it may run independtly. + +The RFC5424 Syslog logging format is ment to be used as a stream of log data +from a service or applacation. This class is designed to be used in this +fashion where new messages are writen to the class as needed. + +**Kind**: inner class of [SyslogPro](#module_SyslogPro) +**Requires**: module:moment +**Since**: 0.0.0 +**Version**: 0.0.0 + +* [~RFC5424](#module_SyslogPro..RFC5424) + * [new RFC5424([options])](#new_module_SyslogPro..RFC5424_new) + * [.timestamp](#module_SyslogPro..RFC5424+timestamp) : boolean + * [.timestampUTC](#module_SyslogPro..RFC5424+timestampUTC) : boolean + * [.timestampTZ](#module_SyslogPro..RFC5424+timestampTZ) : boolean + * [.timestampMS](#module_SyslogPro..RFC5424+timestampMS) : boolean + * [.encludeStructuredData](#module_SyslogPro..RFC5424+encludeStructuredData) : boolean + * [.utf8BOM](#module_SyslogPro..RFC5424+utf8BOM) : boolean + * [.color](#module_SyslogPro..RFC5424+color) : boolean + * [.extendedColor](#module_SyslogPro..RFC5424+extendedColor) : boolean + * [.setColor()](#module_SyslogPro..RFC5424+setColor) + * [.buildMessage(msg, [options])](#module_SyslogPro..RFC5424+buildMessage) ⇒ Promise + * [.send(msg)](#module_SyslogPro..RFC5424+send) ⇒ Promise + * [.emergency(msg)](#module_SyslogPro..RFC5424+emergency) ⇒ Promise + * [.emer(msg)](#module_SyslogPro..RFC5424+emer) ⇒ Promise + * [.alert(msg)](#module_SyslogPro..RFC5424+alert) ⇒ Promise + * [.critical(msg)](#module_SyslogPro..RFC5424+critical) ⇒ Promise + * [.crit(msg)](#module_SyslogPro..RFC5424+crit) ⇒ Promise + * [.error(msg)](#module_SyslogPro..RFC5424+error) ⇒ Promise + * [.err(msg)](#module_SyslogPro..RFC5424+err) ⇒ Promise + * [.warning(msg)](#module_SyslogPro..RFC5424+warning) ⇒ Promise + * [.warn(msg)](#module_SyslogPro..RFC5424+warn) ⇒ Promise + * [.notice(msg)](#module_SyslogPro..RFC5424+notice) ⇒ Promise + * [.note(msg)](#module_SyslogPro..RFC5424+note) ⇒ Promise + * [.informational(msg)](#module_SyslogPro..RFC5424+informational) ⇒ Promise + * [.info(msg)](#module_SyslogPro..RFC5424+info) ⇒ Promise + * [.log(msg)](#module_SyslogPro..RFC5424+log) ⇒ Promise + * [.debug(msg)](#module_SyslogPro..RFC5424+debug) ⇒ Promise + + + +#### new RFC5424([options]) +Construct a new RFC5424 formated Syslog object with user options + + +| Param | Type | Default | Description | +| --- | --- | --- | --- | +| [options] | object | | Options object | +| [options.applacationName] | string | "'NodeJSLogger'" | Applacation | +| [options.hostname] | string | "os.hostname" | The name of this server | +| [options.timestamp] | boolean | false | Included a Timestamp | +| [options.timestampUTC] | boolean | false | RFC tandard is for local time | +| [options.timestampMS] | boolean | false | Timestamp with ms resoltuion | +| [options.timestampTZ] | boolean | true | Should the timestamp included timezone | +| [options.encludeStructuredData] | boolean | false | Included any provided structured data | +| [options.utf8BOM] | boolean | true | Included the UTF8 | +| [options.color] | boolean | false | Included the UTF8 | +| [options.extendedColor] | boolean | false | Included the UTF8 encoding tag with syslog message text | +| [options.colors] | object | | User defended colors for severites | +| [options.colors.emergencyColor] | string | | A RGB Hex coded color in the form of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 Extended) | +| [options.colors.alertColor] | string | | A RGB Hex coded color in the form of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 Extended) | +| [options.colors.criticalColor] | string | | A RGB Hex coded color in the form of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 Extended) | +| [options.colors.errorColor] | string | | A RGB Hex coded color in the form of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 Extended) | +| [options.colors.warningColor] | string | | A RGB Hex coded color in the form of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 Extended) | +| [options.colors.noticeColor] | string | | A RGB Hex coded color in the form of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 Extended) | +| [options.colors.informationalColor] | string | | A RGB Hex coded color in the form of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 Extended) | +| [options.colors.debugColor] | string | | A RGB Hex coded color in the form of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 Extended) | +| [options.server] | Syslog | false | A {@link module:SyslogPro~Syslog| Syslog server connection} that should be used to send messages directly from this class. @see SyslogPro~Syslog | + + + +#### rfC5424.timestamp : boolean +**Kind**: instance property of [RFC5424](#module_SyslogPro..RFC5424) + + +#### rfC5424.timestampUTC : boolean +**Kind**: instance property of [RFC5424](#module_SyslogPro..RFC5424) + + +#### rfC5424.timestampTZ : boolean +**Kind**: instance property of [RFC5424](#module_SyslogPro..RFC5424) + + +#### rfC5424.timestampMS : boolean +**Kind**: instance property of [RFC5424](#module_SyslogPro..RFC5424) + + +#### rfC5424.encludeStructuredData : boolean +**Kind**: instance property of [RFC5424](#module_SyslogPro..RFC5424) + + +#### rfC5424.utf8BOM : boolean +**Kind**: instance property of [RFC5424](#module_SyslogPro..RFC5424) + + +#### rfC5424.color : boolean +**Kind**: instance property of [RFC5424](#module_SyslogPro..RFC5424) + + +#### rfC5424.extendedColor : boolean +**Kind**: instance property of [RFC5424](#module_SyslogPro..RFC5424) + + +#### rfC5424.setColor() +Sets the color to be used for messages at a set priority + +**Kind**: instance method of [RFC5424](#module_SyslogPro..RFC5424) +**Throws**: + +- Error A standard error object + +**Access**: public + +| Param | Type | Description | +| --- | --- | --- | +| [colors.emergencyColor] | string | A RGB Hex coded color in the form of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 Extended) | +| [colors.alertColor] | string | A RGB Hex coded color in the form of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 Extended) | +| [colors.criticalColor] | string | A RGB Hex coded color in the form of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 Extended) | +| [colors.errorColor] | string | A RGB Hex coded color in the form of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 Extended) | +| [colors.warningColor] | string | A RGB Hex coded color in the form of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 Extended) | +| [colors.noticeColor] | string | A RGB Hex coded color in the form of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 Extended) | +| [colors.informationalColor] | string | A RGB Hex coded color in the form of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 Extended) | +| [colors.debugColor] | string | A RGB Hex coded color in the form of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 Extended) | + + + +#### rfC5424.buildMessage(msg, [options]) ⇒ Promise +Building a formated message. Returns a promise with a formated message + +**Kind**: instance method of [RFC5424](#module_SyslogPro..RFC5424) +**Returns**: Promise - A Syslog formated string acording to the selected RFC +**Throws**: + +- Error A standard error object + +**Access**: public + +| Param | Type | Default | Description | +| --- | --- | --- | --- | +| msg | string | | The Syslog Message | +| [options] | object | | Options object | +| [options.severity] | number | 7 | An array of structure | +| [options.facility] | number | 23 | Facility code to use sending this message | +| [options.pid] | string | "'-'" | The process id of the service sending this message | +| [options.structuredData] | Array.<string> | | An array of structure data strings conforming to the IETF/IANA defined SD-IDs or IANA registred SMI Network Management Private Enterprise Code SD-ID conforming to the format [name@ parameter=value] | +| [options.colorCode] | number | 36 | The ANSI color code to use if message coloration is selected | + + + +#### rfC5424.send(msg) ⇒ Promise +send a RFC5424 formated message. Returns a promise with the formated + message that was sent. If no server connection was defined when the + class was created a defualt Syslog connector will be used. + +**Kind**: instance method of [RFC5424](#module_SyslogPro..RFC5424) +**Returns**: Promise - A Syslog formated string acording to the selected RFC +**Throws**: + +- Error A standard error object + +**Access**: public +**See**: SyslogPro~Syslog + +| Param | Type | Description | +| --- | --- | --- | +| msg | string | The unformated Syslog message to send | + + + +#### rfC5424.emergency(msg) ⇒ Promise +Send a syslog message with a secerity level of 0 (Emergency) + +**Kind**: instance method of [RFC5424](#module_SyslogPro..RFC5424) +**Returns**: Promise - - The formated syslog message sent to the Syslog server +**Throws**: + +- Error - Any bubbled up error + +**Access**: public + +| Param | Type | Description | +| --- | --- | --- | +| msg | string | The emergancy message to send to the Syslog server | + + + +#### rfC5424.emer(msg) ⇒ Promise +Send a syslog message with a secerity level of 0 (Emergency) + +**Kind**: instance method of [RFC5424](#module_SyslogPro..RFC5424) +**Returns**: Promise - - The formated syslog message sent to the Syslog server +**Throws**: + +- Error - Any bubbled up error + +**Access**: public + +| Param | Type | Description | +| --- | --- | --- | +| msg | string | The emergancy message to send to the Syslog server | + + + +#### rfC5424.alert(msg) ⇒ Promise +Send a syslog message with a secerity level of 1 (Alert) + +**Kind**: instance method of [RFC5424](#module_SyslogPro..RFC5424) +**Returns**: Promise - - The formated syslog message sent to the Syslog server +**Throws**: + +- Error - Any bubbled up error + +**Access**: public + +| Param | Type | Description | +| --- | --- | --- | +| msg | string | The alert message to send to the Syslog server | + + + +#### rfC5424.critical(msg) ⇒ Promise +Send a syslog message with a secerity level of 2 (Critical) + +**Kind**: instance method of [RFC5424](#module_SyslogPro..RFC5424) +**Returns**: Promise - - The formated syslog message sent to the Syslog server +**Throws**: + +- Error - Any bubbled up error + +**Access**: public + +| Param | Type | Description | +| --- | --- | --- | +| msg | string | The critical message to send to the Syslog server | + + + +#### rfC5424.crit(msg) ⇒ Promise +Send a syslog message with a secerity level of 2 (Critical) + +**Kind**: instance method of [RFC5424](#module_SyslogPro..RFC5424) +**Returns**: Promise - - The formated syslog message sent to the Syslog server +**Throws**: + +- Error - Any bubbled up error + +**Access**: public + +| Param | Type | Description | +| --- | --- | --- | +| msg | string | The critical message to send to the Syslog server | + + + +#### rfC5424.error(msg) ⇒ Promise +Send a syslog message with a secerity level of 3 (Error) + +**Kind**: instance method of [RFC5424](#module_SyslogPro..RFC5424) +**Returns**: Promise - - The formated syslog message sent to the Syslog server +**Throws**: + +- Error - Any bubbled up error + +**Access**: public + +| Param | Type | Description | +| --- | --- | --- | +| msg | string | The error message to send to the Syslog server | + + + +#### rfC5424.err(msg) ⇒ Promise +Send a syslog message with a secerity level of 3 (Error) + +**Kind**: instance method of [RFC5424](#module_SyslogPro..RFC5424) +**Returns**: Promise - - The formated syslog message sent to the Syslog server +**Throws**: + +- Error - Any bubbled up error + +**Access**: public + +| Param | Type | Description | +| --- | --- | --- | +| msg | string | The error message to send to the Syslog server | + + + +#### rfC5424.warning(msg) ⇒ Promise +Send a syslog message with a secerity level of 4 (Warning) + +**Kind**: instance method of [RFC5424](#module_SyslogPro..RFC5424) +**Returns**: Promise - - The formated syslog message sent to the Syslog server +**Throws**: + +- Error - Any bubbled up error + +**Access**: public + +| Param | Type | Description | +| --- | --- | --- | +| msg | string | The warning message to send to the Syslog server | + + + +#### rfC5424.warn(msg) ⇒ Promise +Send a syslog message with a secerity level of 4 (Warning) + +**Kind**: instance method of [RFC5424](#module_SyslogPro..RFC5424) +**Returns**: Promise - - The formated syslog message sent to the Syslog server +**Throws**: + +- Error - Any bubbled up error + +**Access**: public + +| Param | Type | Description | +| --- | --- | --- | +| msg | string | The warning message to send to the Syslog server | + + + +#### rfC5424.notice(msg) ⇒ Promise +Send a syslog message with a secerity level of 5 (Notice) + +**Kind**: instance method of [RFC5424](#module_SyslogPro..RFC5424) +**Returns**: Promise - - The formated syslog message sent to the Syslog server +**Throws**: + +- Error - Any bubbled up error + +**Access**: public + +| Param | Type | Description | +| --- | --- | --- | +| msg | string | The notice message to send to the Syslog server | + + + +#### rfC5424.note(msg) ⇒ Promise +Send a syslog message with a secerity level of 5 (Notice) + +**Kind**: instance method of [RFC5424](#module_SyslogPro..RFC5424) +**Returns**: Promise - - The formated syslog message sent to the Syslog server +**Throws**: + +- Error - Any bubbled up error + +**Access**: public + +| Param | Type | Description | +| --- | --- | --- | +| msg | string | The notice message to send to the Syslog server | + + + +#### rfC5424.informational(msg) ⇒ Promise +Send a syslog message with a secerity level of 6 (Informational) + +**Kind**: instance method of [RFC5424](#module_SyslogPro..RFC5424) +**Returns**: Promise - - The formated syslog message sent to the Syslog server +**Throws**: + +- Error - Any bubbled up error + +**Access**: public + +| Param | Type | Description | +| --- | --- | --- | +| msg | string | The informational message to send to the Syslog server | + + + +#### rfC5424.info(msg) ⇒ Promise +Send a syslog message with a secerity level of 6 (Informational) + +**Kind**: instance method of [RFC5424](#module_SyslogPro..RFC5424) +**Returns**: Promise - - The formated syslog message sent to the Syslog server +**Throws**: + +- Error - Any bubbled up error + +**Access**: public + +| Param | Type | Description | +| --- | --- | --- | +| msg | string | The informational message to send to the Syslog server | + + + +#### rfC5424.log(msg) ⇒ Promise +Send a syslog message with a secerity level of 6 (Informational) + +**Kind**: instance method of [RFC5424](#module_SyslogPro..RFC5424) +**Returns**: Promise - - The formated syslog message sent to the Syslog server +**Throws**: + +- Error - Any bubbled up error + +**Access**: public + +| Param | Type | Description | +| --- | --- | --- | +| msg | string | The informational message to send to the Syslog server | + + + +#### rfC5424.debug(msg) ⇒ Promise +Send a syslog message with a secerity level of 7 (Debug) + +**Kind**: instance method of [RFC5424](#module_SyslogPro..RFC5424) +**Returns**: Promise - - The formated syslog message sent to the Syslog server +**Throws**: + +- Error - Any bubbled up error + +**Access**: public + +| Param | Type | Description | +| --- | --- | --- | +| msg | string | The debug message to send to the Syslog server | + + + +### SyslogPro~LEEF +A class to work with IBM LEEF (Log Event Extended Format) messages this form +of system messages are designed to work with security systems. Messages can +be saved to file (Saving to file if not part of this module but a LEEF +formated mesage produced by this module can be saved externaly to it) or +sent via Syslog. +Most APIs will return a promise. These APIs can be used using +`then(...)/catch(...)` + +A Syslog class with a configured Syslog server target can also be used as +the input into the formating classes so that it may run independtly. The +LEEF format is designed to send event data to a SIEM system and should not +be as a logging stream. This class is ment to be used once per message. + +**Kind**: inner class of [SyslogPro](#module_SyslogPro) +**Requires**: module:moment +**Since**: 0.0.0 +**Version**: 0.0.0 + +* [~LEEF](#module_SyslogPro..LEEF) + * [new LEEF([options])](#new_module_SyslogPro..LEEF_new) + * [.vendor](#module_SyslogPro..LEEF+vendor) : string + * [.product](#module_SyslogPro..LEEF+product) : string + * [.version](#module_SyslogPro..LEEF+version) : string + * [.eventId](#module_SyslogPro..LEEF+eventId) : string + * [.syslogHeader](#module_SyslogPro..LEEF+syslogHeader) : boolean + * [.attrabutes](#module_SyslogPro..LEEF+attrabutes) : object + * [.buildMessage()](#module_SyslogPro..LEEF+buildMessage) ⇒ Promise + * [.send([options])](#module_SyslogPro..LEEF+send) + + + +#### new LEEF([options]) +Construct a new LEEF formating object with user options + + +| Param | Type | Default | Description | +| --- | --- | --- | --- | +| [options] | object | | Options object | +| [options.vendor] | string | "'unknown'" | The vendor of the system that genrated the event being reported | +| [options.product] | string | "'unknown'" | The product name of the system that genrated the event being reported | +| [options.version] | string | "'unknown'" | The version name of the system that genrated the event being reported | +| [options.eventId] | string | "'unknown'" | The eventId of the system that genrated the event being reported | +| [options.attrabute] | object | | LEEF message attrabutes which defualts to all base attrabutes with null values, new attrabutes should be added as new elements to this object | +| [options.syslogHeader] | boolean | 'true' | Should the LEEF message include a Syslog header with Timestamp and source | +| [options.server] | Syslog | false | A {@link module:SyslogPro~Syslog| Syslog server connection} that should be used to send messages directly from this class. @see SyslogPro~Syslog | + + + +#### leeF.vendor : string +**Kind**: instance property of [LEEF](#module_SyslogPro..LEEF) + + +#### leeF.product : string +**Kind**: instance property of [LEEF](#module_SyslogPro..LEEF) + + +#### leeF.version : string +**Kind**: instance property of [LEEF](#module_SyslogPro..LEEF) + + +#### leeF.eventId : string +**Kind**: instance property of [LEEF](#module_SyslogPro..LEEF) + + +#### leeF.syslogHeader : boolean +**Kind**: instance property of [LEEF](#module_SyslogPro..LEEF) + + +#### leeF.attrabutes : object +**Kind**: instance property of [LEEF](#module_SyslogPro..LEEF) + + +#### leeF.buildMessage() ⇒ Promise +Build a formated message + +**Kind**: instance method of [LEEF](#module_SyslogPro..LEEF) +**Returns**: Promise - - string with formated message +**Access**: public + + +#### leeF.send([options]) +**Kind**: instance method of [LEEF](#module_SyslogPro..LEEF) +**Access**: public + +| Param | Type | Default | Description | +| --- | --- | --- | --- | +| [options] | Syslog | false | A {@link module:SyslogPro~Syslog| Syslog server connection} that should be used to send messages directly from this class. @see SyslogPro~Syslog | + + + +### SyslogPro~CEF +A class to work with HP CEF (Common Event Format) messages. This form +of system messages are designed to work with security systems. Messages can +be saved to file (Saving to file if not part of this module but a CEF +formated mesage produced by this module can be saved externaly to it) or +sent via Syslog. +Most APIs will return a promise. These APIs can be used using +`then(...)/catch(...)` + +A Syslog class with a configured Syslog server target can also be used as +the input into the formating classes so that it may run independtly. The CEF +format is designed to send event data to a SIEM system and should not be as +a logging stream. This class is ment to be used once per message. + +**Kind**: inner class of [SyslogPro](#module_SyslogPro) +**Requires**: module:moment +**Since**: 0.0.0 +**Version**: 0.0.0 + +* [~CEF](#module_SyslogPro..CEF) + * [new CEF([options])](#new_module_SyslogPro..CEF_new) + * [.deviceVendor](#module_SyslogPro..CEF+deviceVendor) : string + * [.deviceProduct](#module_SyslogPro..CEF+deviceProduct) : string + * [.deviceVersion](#module_SyslogPro..CEF+deviceVersion) : string + * [.deviceEventClassId](#module_SyslogPro..CEF+deviceEventClassId) : string + * [.name](#module_SyslogPro..CEF+name) : string + * [.severity](#module_SyslogPro..CEF+severity) : string + * [.extensions](#module_SyslogPro..CEF+extensions) : object + * [.validate()](#module_SyslogPro..CEF+validate) ⇒ Promise + * [.buildMessage()](#module_SyslogPro..CEF+buildMessage) ⇒ Promise + * [.send([options])](#module_SyslogPro..CEF+send) + + + +#### new CEF([options]) +Construct a new CEF formating object with user options + + +| Param | Type | Default | Description | +| --- | --- | --- | --- | +| [options] | object | | Options object | +| [options.deviceVendor] | string | "'unknown'" | The vendor of the system that genrated the event being reported | +| [options.deviceProduct] | string | "'unknown'" | The product name of the system that genrated the event being reported | +| [options.deviceVersion] | string | "'unknown'" | The version name of the system that genrated the event being reported | +| [options.deviceEventClassId] | string | "'unknown'" | The eventId of the system that genrated the event being reported | +| [options.name] | string | "'unknown'" | Name of the service genrating the notice | +| [options.severity] | string | "'unknown'" | Severity of the notification | +| [options.extensions] | string | "{}" | Any CEF Key=Value extentions | +| [options.server] | Syslog | false | A {@link module:SyslogPro~Syslog| Syslog server connection} that should be used to send messages directly from this class. @see SyslogPro~Syslog | + + + +#### ceF.deviceVendor : string +**Kind**: instance property of [CEF](#module_SyslogPro..CEF) + + +#### ceF.deviceProduct : string +**Kind**: instance property of [CEF](#module_SyslogPro..CEF) + + +#### ceF.deviceVersion : string +**Kind**: instance property of [CEF](#module_SyslogPro..CEF) + + +#### ceF.deviceEventClassId : string +**Kind**: instance property of [CEF](#module_SyslogPro..CEF) + + +#### ceF.name : string +**Kind**: instance property of [CEF](#module_SyslogPro..CEF) + + +#### ceF.severity : string +**Kind**: instance property of [CEF](#module_SyslogPro..CEF) + + +#### ceF.extensions : object +**Kind**: instance property of [CEF](#module_SyslogPro..CEF) + + +#### ceF.validate() ⇒ Promise +Validate this CEF object + +**Kind**: instance method of [CEF](#module_SyslogPro..CEF) +**Returns**: Promise - - True if valadated +**Throws**: + +- Error - First element to fail valadation + +**Access**: public + + +#### ceF.buildMessage() ⇒ Promise +Build a CEF formated string + +**Kind**: instance method of [CEF](#module_SyslogPro..CEF) +**Returns**: Promise - - String with formated message +**Access**: public + + +#### ceF.send([options]) +**Kind**: instance method of [CEF](#module_SyslogPro..CEF) +**Access**: public + +| Param | Type | Default | Description | +| --- | --- | --- | --- | +| [options] | Syslog | false | A {@link module:SyslogPro~Syslog| Syslog server connection} that should be used to send messages directly from this class. @see SyslogPro~Syslog | + + +*docs autogenerated via [jsdoc2md] +(https://github.com/jsdoc2md/jsdoc-to-markdown)* + +## Test +```shell + npm test +``` + +## Contributing + +Please try to maintain the existing coding style. Add unit tests for any new or +changed functionality. Lint and test your code. diff --git a/docs/docco/README.md b/docs/docco/README.md new file mode 100644 index 0000000..2b4032a --- /dev/null +++ b/docs/docco/README.md @@ -0,0 +1,2699 @@ + + + + + + + + +``` +/** Copyright (c) 2018 Craig Yamato */ + +/** + * @fileoverview The SyslogPro module for sending syslog messages + * Most APIs will return a promise. These APIs can be used using + * `then(...)/catch(...)` + * + * Syslog formating classes can be used as input into a Syslog class to be used + * simultatniusly to the same Syslog server. The Syslog Class with a configured + * Syslog server target can also be used as the input into each of the formating + * classes so that they may run independtly. + * @author Craig Yamato + * @copyright (c) 2018 - Craig Yamato + * @version 0.1.0 + * @exports Syslog + * @exports LEEF + * @exports CEF + * @module SyslogPro + */ +"use strict"; +const moment = require('moment'); +const os = require("os"); +const dns = require('dns'); +let dnsPromises = dns.promises; +const fs = require("fs"); + +/** + * Format the ANSI foreground color code from a RGB hex code or ANSI color code + * @private + * @param {string} hex - The color hex code in the form of #FFFFFF or Number of + * the ANSI color code (30-37 Standard & 0-255 Extended) + * @returns {Promise} - The formated ANSI color code + * @throws {Error} - A Format Error + */ +function rgbToAnsi (hex, extendedColor) { + return new Promise((resolve, reject) => { + let colorCode = 0; // Var to hold color code + +``` + + + + + + + +Break HEX Code up into RGB + + + + +``` + const hexParts = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); + if (hexParts || typeof hex === 'number') { + if (typeof hex === 'number') { + if (extendedColor && hex < 256) { + resolve(hex); + } else if ((hex > 29 && hex < 38) || (hex > 89 && hex < 98)) { + resolve(hex); + } else { + reject (new Error('FORMAT ERROR: Color code not in range')); + } + } else { + const r = parseInt(hexParts[1], 16); + const g = parseInt(hexParts[2], 16); + const b = parseInt(hexParts[3], 16); + if (extendedColor) { + if (r === g && g === b) { + +``` + + + + + + + +Gray Scale Color + + + + +``` + if (r < 8) { + colorCode = 16; + } else if (r > 248) { + colorCode = 231; + } else { + colorCode = Math.round(((r - 8) / 247) * 24) + 232; + } + } else { + colorCode = 16 + + (36 * Math.round(r / 255 * 5)) + + (6 * Math.round(g / 255 * 5)) + + Math.round(b / 255 * 5); + } + } else { + colorCode = 30; + const red = r / 255; + const green = g / 255; + const blue = b / 255; + let v = Math.max(red, green, blue) * 100; + v = Math.round(v / 50); + if (v === 1) { + colorCode += ((Math.round(b / 255) << 2) + | (Math.round(g / 255) << 1) + | Math.round(r / 255)); + } + if (v === 2) { + colorCode += 60; + } + } + } + resolve(colorCode); + return; + } else { + reject(new Error('TYPE ERROR: Not in RGB color hex or color code')); + return; + } + }); +} + +/** + * A class to work with syslog messages using UDP, TCP, or TLS transport. + * There is suport for Syslog message formating RFC-3164, RFC-5424 including + * Structured Data, IBM LEEF (Log Event Extended Format), and HP CEF (Common + * Event Format). + * Syslog formating classes can be used as input into a Syslog class to be used + * simultatniusly to the same Syslog server. * + * @requires moment + * @version 0.0.0 + * @since 0.0.0 + */ +class Syslog { + /** + * Construct a new Syslog transport object with user options + * @public + * @version 0.0.0 + * @since 0.0.0 + * @this Syslog + * @param {object} [options] - Options object + * >>>Transport Configuraton + * @param {string} [options.target='localhost'] - The IP Address|FQDN of the + * Syslog Server, this option if set will take prasdents over any target + * set in a formating object + * @param {string} [options.protocol='udp'] - L4 transport portocol + * (udp|tcp|tls), this option if set will take prasdents over any transport + * set in a formating object + * @param {number} [options.port=514] - IP port, this option if set will take + * prasdents over any IP Port set in a formating object + * @param {number} [options.tcpTimeout=10000] - Ignored for all other + * transports, this option if set will take prasdents over any timeout + * set in a formating object + * @param {string[]} [options.tlsServerCerts] - Array of authrized TLS server + * certificates file locations, this option if set will take prasdents + * over any certificates set in a formating object + * @param {string} [options.tlsClientCert] - Client TLS certificate file + * location that this client should use, this option if set will take + * prasdents over any certificates set in a formating object + * @param {string} [options.tlsClientKey] - Client TLS key file + * location that this client should use, this option if set will take + * prasdents over any certificates set in a formating object + * >>>Syslog Format Settings + * @param {string} [options.format='none'] - Valid syslog format options for + * this module are 'none', 'rfc3164', 'rfc5424', 'leef', 'cef' + * @param {RFC3164} [options.rfc5424] - {@link module:SyslogPro~RFC5424| + * RFC5424 related settings} + * @param {RFC5424} [options.rfc5424] - {@link module:SyslogPro~RFC5424| + * RFC5424 related settings} + * @param {LEEF} [options.leef] - {@link module:SyslogPro~LEEF|IBM LEEF + * (Log Event Extended Format) object} + * @param {CEF} [options.cef] - {@link module:SyslogPro~CEF|HP CEF + * (Common Event Format) formating object} + */ + constructor (options) { + this.constructor__ = true; + if (!options) { + options = {}; + } + +``` + + + + + + + +Basic transport setup + + + + +``` + /** @type {string} */ + this.target = options.target || 'localhost'; + /** @type {string} */ + this.protocol = options.protocol || 'udp'; + this.protocol = this.protocol.toLowerCase(); + /** @type {number} */ + this.port = options.port || 514; + /** @type {number} */ + this.tcpTimeout = options.tcpTimeout || 10000; + if ((typeof options.tlsServerCerts === 'object' + && Array.isArray(options.tlsServerCerts)) + || typeof options.tlsServerCerts === 'string') { + this.addTlsServerCerts(options.tlsServerCerts); + } else { + /** @type {string[]} */ + this.tlsServerCerts = []; + } + if (options.tlsClientCert) { + /** @type {string} */ + this.tlsClientCert = options.tlsClientCert; + } + if (options.tlsClientKey) { + /** @type {string} */ + this.tlsClientKey = options.tlsClientKey; + } + +``` + + + + + + + +Syslog Format + + + + +``` + if (typeof options.format === 'string') { + /** @type {string} */ + this.format = options.format.toLowerCase(); + } else { + this.format = options.format || 'none'; + } + if (options.rfc3164) { + if (options.rfc3164.constructor__) { + /** @type {RFC3164} */ + this.rfc3164 = options.rfc3164; + } else { + this.rfc3164 = new RFC3164(options); + } + } + if (options.rfc5424) { + if (options.rfc5424.constructor__) { + /** @type {RFC5424} */ + this.rfc5424 = options.rfc5424; + } else { + this.rfc5424 = new RFC5424(options); + } + } + if (options.leef) { + if (options.leef.constructor__) { + /** @type {LEEF} */ + this.leef = options.leef; + } else { + this.leef = new LEEF(options); + } + } + if (options.cef) { + if (options.cef.constructor__) { + /** @type {CEF} */ + this.cef = options.cef; + } else { + this.cef = new CEF(options); + } + } + if (this.format === 'rfc3164' && !this.rfc3164) { + this.rfc3164 = new RFC3164(); + } + if (this.format === 'rfc5424' && !this.rfc5424) { + this.rfc5424 = new RFC5424(); + } + if (this.format === 'leef' && !this.leef) { + this.leef = new LEEF(); + } + if (this.format === 'cef' && !this.cef) { + this.cef = new CEF(); + } + } + + /** + * Add a TLS server certificate which can be used to authentacat the server + * this syslog client is connecting too. This function will valadate the + * input as a file location straing and add it to an array of certificates + * @private + * @version 0.0.0 + * @since 0.0.0 + * @param {string|string[]} certs - File location of the certificate(s) + * @returns {Promise} - True + * @throws {Error} - A Type Error + */ + addTlsServerCerts (certs) { + return new Promise((resolve, reject) => { + if (typeof certs === 'object' && Array.isArray(certs)) { + /** @private @type {string[]} */ + this.tlsServerCerts = certs; + } else if (typeof certs === 'string') { + this.tlsServerCerts = [certs]; + } else { + let errMsg = 'TYPE ERROR: Server Cert file loctions shoudl be a string'; + errMsg += ' or array of strings'; + reject(new Error(errMsg)); + } + resolve(true); + }); + } + /** + * Send the Syslog message over UDP + * @private + * @param {string} msg - The formated Syslog Message + * @returns {Promise} - The Syslog formated string sent + * @throws {Error} - Network Error + */ + udpMessage (msg) { + return new Promise((resolve, reject) => { + const dgram = require('dgram');// Test for target DNS and Address Family (IPv4/6) by looking up the DNS + const dnsOptions = { + verbatim: true + }; + dnsPromises.lookup(this.target, dnsOptions) + .then((result) => { + 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'); + client.send(msgBuffer, this.port, this.target, (error) => { + client.close(); + resolve(msg); + }); + }) + .catch((error) => { + reject(error); // Reject out of the sendMessage function promise + }); + }); + } + /** + * Send the Syslog message over TCP + * @private + * @param {string} msg - The formated Syslog Message + * @returns {Promise} - The Syslog formated string sent + * @throws {Error} - Timeout error for TCP and TLS connections + * @throws {Error} - Network Error + */ + tcpMessage (msg) { + return new Promise((resolve, reject) => { + const net = require('net'); + const dnsOptions = { + verbatim: true + }; + dnsPromises.lookup(this.target, dnsOptions) + .then((result) => { + 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); + 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(); + reject(error); + }); + }) + .catch((error) => { + reject(error); + }); + }); + } + /** + * Send the Syslog message over TLS + * @private + * @param {string} msg - The formated Syslog Message + * @returns {Promise} - The Syslog formated string sent + * @throws {Error} - Timeout error for TCP and TLS connections + * @throws {Error} - Network Error + */ + tlsMessage (msg) { + return new Promise((resolve, reject) => { + const tls = require('tls'); + const tlsOptions = { + host: this.target, + port: this.port, + }; + +``` + + + + + + + +Load client cert and key if requested + + + + +``` + if (typeof this.tlsClientKey === 'string' + && typeof this.tlsClientCert === 'string') { + tlsOptions.key = fs.readFileSync(this.tlsClientKey); + tlsOptions.cert = fs.readFileSync(this.tlsClientCert); + } else if (typeof this.tlsClientKey !== 'string' + && typeof this.tlsClientKey !== 'undefined') { + let errMsg = 'TYPE ERROR: TLS Client Key is not a file'; + errMsg += 'location string'; + reject(new Error(errMsg)); + return; + } else if (typeof this.tlsClientCert !== 'string' + && typeof this.tlsClientCert !== 'undefined') { + let errMsg = 'TYPE ERROR: TLS Client Cert is not a file'; + errMsg += 'location string'; + reject(new Error(errMsg)); + return; + } + +``` + + + + + + + +Load any server certs if provided + + + + +``` + let tlsCerts = this.tlsServerCerts.length; + if (tlsCerts > 0) { + let tlsOptionsCerts = []; + for (let certIndex=0; certIndex { + +``` + + + + + + + +Turn msg in to a UTF8 buffer + + + + +``` + let msgBuffer = Buffer.from(msg, 'utf8'); + client.write(msgBuffer, () => { + client.end(); + }); + }); + client.setTimeout(this.tcpTimeout); + +``` + + + + + + + +client.on('data', (data) => {}); + + + + +``` + 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(); + reject(error); + }); + }); + } + /** + * Send the Syslog message to the selected target Syslog server using the + * selected transport. + * @private + * @param {string} msg - The formated Syslog Message + * @returns {Promise} - The Syslog formated string sent + * @throws {Error} - Timeout error for TCP and TLS connections + * @throws {Error} - Network Error + */ + send (msg) { + return new Promise((resolve, reject) => { + if (typeof msg !== 'string') { + reject(new Error("TYPE ERROR: Syslog message must be a string")); + return; + } + this.protocol = this.protocol.toLowerCase(); + if (this.protocol === 'udp') { + this.udpMessage(msg) + .then((result) => { + resolve(result); + }) + .catch((reson) => { + reject(reson); + }); + } else if (this.protocol === 'tcp') { + this.tcpMessage(msg) + .then((result) => { + resolve(result); + }) + .catch((reson) => { + reject(reson); + }); + } else if (this.protocol === 'tls') { + this.tlsMessage(msg) + .then((result) => { + resolve(result); + }) + .catch((reson) => { + reject(reson); + }); + } else { + let errorMsg = 'FORMAT ERROR: Protocol not reconized, should be '; + errorMsg += 'udp|tcp|tls'; + reject(new Error(errorMsg)); + } + }); + } +} + +/** + * A class to work with RFC3164 formated syslog messages. The meesaging is fully configurabule and Ansi foreground + * colors can be added. Both ANSI 8 and ANSI 256 color are fully suported. + * Most APIs will return a promise. These APIs can be used using + * `then(...)/catch(...)` + * + * A Syslog class with a configured + * Syslog server target can also be used as the input into the formating + * classes so that it may run independtly. + * + * The RFC3164 Syslog logging format is ment to be used as a stream of log data + * from a service or applacation. This class is designed to be used in this + * fashion where new messages are writen to the class as needed. + * @requires moment + * @version 0.0.0 + * @since 0.0.0 + */ +class RFC3164 { + /** + * Construct a new RFC3164 formated Syslog object with user options + * @public + * @this RFC3164 + * @param {object} [options] - Options object + * @param {string} [options.applacationName='NodeJSLogger'] - Applacation + * @param {string} [options.hostname=os.hostname] - The name of this server + * @param {number} [options.facility=23] - Facility code to use sending this + * message + * @param {boolean} [options.color=false] - Apply color coding encoding tag + * with syslog message text + * @param {boolean} [options.extendedColor=false] - Use the extedned ANSI + * color set encoding tag with syslog message text + * @param {object} [options.colors] - User defended colors for + * severites + * @param {string} [options.colors.emergencyColor] - A RGB Hex coded color in the form + * of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 + * Extended) + * @param {string} [options.colors.alertColor] - A RGB Hex coded color in the form + * of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 + * Extended) + * @param {string} [options.colors.criticalColor] - A RGB Hex coded color in the form + * of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 + * Extended) + * @param {string} [options.colors.errorColor] - A RGB Hex coded color in the form + * of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 + * Extended) + * @param {string} [options.colors.warningColor] - A RGB Hex coded color in the form + * of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 + * Extended) + * @param {string} [options.colors.noticeColor] - A RGB Hex coded color in the form + * of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 + * Extended) + * @param {string} [options.colors.informationalColor] - A RGB Hex coded color in the form + * of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 + * Extended) + * @param {string} [options.colors.debugColor] - A RGB Hex coded color in the form + * of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 + * Extended) + * @param {Syslog} [options.server=false] - A {@link module:SyslogPro~Syslog| + * Syslog server connection} that should be used to send messages directly + * from this class. @see SyslogPro~Syslog + */ + constructor (options) { + /** @private @type {boolean} */ + this.constructor__ = true; + options = options || {}; + this.hostname = options.hostname || os.hostname(); + this.applacationName = options.applacationName || ''; + this.facility = options.facility || 23; + if (options.color) { + /** @type {boolean} */ + this.color = true; + } else { + this.color = false; + } + if (options.extendedColor) { + /** @type {boolean} */ + this.extendedColor = true; + } else { + this.extendedColor = false; + } + if (options.server) { + if (!options.server.constructor__) { + /** @private @type {Syslog} */ + this.server = new Syslog(options.server); + } else { + this.server = options.server; + } + } + if (this.extendedColor) { + /** @private @type {number} */ + this.emergencyColor = 1; // Red foreground color + /** @private @type {number} */ + this.alertColor = 202; // Dark Orange foreground color + /** @private @type {number} */ + this.criticalColor = 208; // Orange foreground color + /** @private @type {number} */ + this.errorColor = 178; // Light Orange foreground color + /** @private @type {number} */ + this.warningColor = 226; // Yellow foreground color + /** @private @type {number} */ + this.noticeColor = 117; // Light Blue foreground color + /** @private @type {number} */ + this.informationalColor = 45; // Blue foreground color + /** @private @type {number} */ + this.debugColor = 27; // Dark Blue foreground color + } else { + this.emergencyColor = 31; // Red foreground color + this.alertColor = 31; // Red foreground color + this.criticalColor = 31; // Red foreground color + this.errorColor = 33; // Yellow foreground color + this.warningColor = 33; // Yellow foreground color + this.noticeColor = 36; // Blue foreground color + this.informationalColor = 36; // Blue foreground color + this.debugColor = 34; // Dark Blue foreground color + } + if (typeof options.colors === 'object') { + this.setColor(options.colors, this.extendedColor); + } + } + /** + * Sets the color to be used for messages at a set priority + * @public + * @param {string} [colors.emergencyColor] - A RGB Hex coded color in the form + * of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 + * Extended) + * @param {string} [colors.alertColor] - A RGB Hex coded color in the form + * of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 + * Extended) + * @param {string} [colors.criticalColor] - A RGB Hex coded color in the form + * of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 + * Extended) + * @param {string} [colors.errorColor] - A RGB Hex coded color in the form + * of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 + * Extended) + * @param {string} [colors.warningColor] - A RGB Hex coded color in the form + * of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 + * Extended) + * @param {string} [colors.noticeColor] - A RGB Hex coded color in the form + * of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 + * Extended) + * @param {string} [colors.informationalColor] - A RGB Hex coded color in the form + * of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 + * Extended) + * @param {string} [colors.debugColor] - A RGB Hex coded color in the form + * of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 + * Extended) + * @throws {Error} A standard error object + */ + setColor (colors, extendedColor) { + return new Promise((resolve, reject) => { + let colorPromises = []; + if (colors.emergencyColor) { + colorPromises.push( + new Promise((resolve,reject) => { + rgbToAnsi(colors.emergencyColor, this.extendedColor) + .then((result) => { + this.emergencyColor = result; + resolve(true); + }) + .catch((reson) => { + reson.message = 'TYPE ERROR: '; + reson.message += 'emergencyColor'; + reson.message += ' Not in RGB color hex or color code'; + reject(reson); + }); + })); + } + if (colors.alertColor) { + colorPromises.push( + new Promise((resolve,reject) => { + rgbToAnsi(colors.alertColor, this.extendedColor) + .then((result) => { + this.alertColor = result; + resolve(true); + }) + .catch((reson) => { + reson.message = 'TYPE ERROR: '; + reson.message += 'alertColor'; + reson.message += ' Not in RGB color hex or color code'; + reject(reson); + }); + })); + } + if (colors.criticalColor) { + colorPromises.push( + new Promise((resolve,reject) => { + rgbToAnsi(colors.criticalColor, this.extendedColor) + .then((result) => { + this.criticalColor = result; + resolve(true); + }) + .catch((reson) => { + reson.message = 'TYPE ERROR: '; + reson.message += 'criticalColor'; + reson.message += ' Not in RGB color hex or color code'; + reject(reson); + }); + })); + } + if (colors.errorColor) { + colorPromises.push( + new Promise((resolve,reject) => { + rgbToAnsi(colors.errorColor, this.extendedColor) + .then((result) => { + this.errorColor = result; + resolve(true); + }) + .catch((reson) => { + reson.message = 'TYPE ERROR: '; + reson.message += 'errorColor'; + reson.message += ' Not in RGB color hex or color code'; + reject(reson); + }); + })); + } + if (colors.warningColor) { + colorPromises.push( + new Promise((resolve,reject) => { + rgbToAnsi(colors.warningColor, this.extendedColor) + .then((result) => { + this.warningColor = result; + resolve(true); + }) + .catch((reson) => { + reson.message = 'TYPE ERROR: '; + reson.message += 'warningColor'; + reson.message += ' Not in RGB color hex or color code'; + reject(reson); + }); + })); + } + if (colors.noticeColor) { + colorPromises.push( + new Promise((resolve,reject) => { + rgbToAnsi(colors.noticeColor, this.extendedColor) + .then((result) => { + this.noticeColor = result; + resolve(true); + }) + .catch((reson) => { + reson.message = 'TYPE ERROR: '; + reson.message += 'noticeColor'; + reson.message += ' Not in RGB color hex or color code'; + reject(reson); + }); + })); + } + if (colors.informationalColor) { + colorPromises.push( + new Promise((resolve,reject) => { + rgbToAnsi(colors.informationalColor, this.extendedColor) + .then((result) => { + this.informationalColor = result; + resolve(true); + }) + .catch((reson) => { + reson.message = 'TYPE ERROR: '; + reson.message += 'informationalColor'; + reson.message += ' Not in RGB color hex or color code'; + reject(reson); + }); + })); + } + if (colors.debugColor) { + colorPromises.push( + new Promise((resolve,reject) => { + rgbToAnsi(colors.debugColor, this.extendedColor) + .then((result) => { + this.debugColor = result; + resolve(true); + }) + .catch((reson) => { + reson.message = 'TYPE ERROR: '; + reson.message += 'debugColor'; + reson.message += ' Not in RGB color hex or color code'; + reject(reson); + }); + })); + } + Promise.all(colorPromises) + .then((results) => { + resolve(true); + }) + .catch((reson) => { + reject(reson); + }); + }); + } + /** + * Building a formated message. Returns a promise with a formated message + * @public + * @param {string} msg - The Syslog Message + * @param {object} [options] - Options object + * @param {number} [options.severity=7] - An array of structure + * @param {number} [options.colorCode=36] - The ANSI color code to use if + * message coloration is selected + * @returns {Promise} A Syslog formated string acording to the selected RFC + * @throws {Error} A standard error object + */ + buildMessage (msg, options) { + return new Promise((resolve, reject) => { + options = options || {}; + let severity = typeof options.severity === 'number' ? + options.severity : 6; + if (typeof msg !== 'string' || options.msgSeverity > 7) { + let errMsg = 'FORMAT ERROR: Syslog message must be a string'; + errMsg += ' msgSeverity must be a number between 0 and 7'; + reject(new Error(errMsg)); + return; + } + let fmtMsg = ''; // Formated Syslog message string var + const newLine = '\n'; + const newLineRegEx = /(\r|\n|(\r\n))/; + const escapeCode = '\u001B'; + const resetColor = '\u001B[0m'; + +``` + + + + + + + +The PRI is common to both RFC formats + + + + +``` + const pri = (this.facility * 8) + severity; + +``` + + + + + + + +Remove any newline character + + + + +``` + msg = msg.replace(newLineRegEx, ''); + +``` + + + + + + + +Add requested color + + + + +``` + if (this.color) { + options.msgColor = options.msgColor || 36; + let colorCode = '['; + if (this.extendedColor) { + colorCode += '38;5;'; // Extended 256 Colors ANSI Code + } + if (typeof options.msgColor === 'number') { + colorCode += options.msgColor; + colorCode += 'm'; // ANSI Color Closer + } else { + colorCode = '[39m'; // Use terminal's defualt color + } + msg = escapeCode + colorCode + msg + resetColor; + } + +``` + + + + + + + +RegEx to find a leading 0 in the day of a DateTime for RFC3164 +RFC3164 uses BSD timeformat + + + + +``` + const rfc3164DateRegEx = /((A|D|F|J|M|N|O|S)(a|c|e|p|o|u)(b|c|g|l|n|p|r|t|v|y)\s)0(\d\s\d\d:\d\d:\d\d)/; + const timestamp = moment() + .format('MMM DD hh:mm:ss') + .replace(rfc3164DateRegEx, '$1 $5'); + +``` + + + + + + + +Build message + + + + +``` + fmtMsg = '<' + pri + '>'; + fmtMsg += timestamp; + fmtMsg += ' ' + this.hostname; + fmtMsg += ' ' + this.applacationName; + fmtMsg += ' ' + msg; + fmtMsg += newLine; + resolve(fmtMsg); + }); + } + /** + * send a RFC5424 formated message. Returns a promise with the formated + * message that was sent. If no server connection was defined when the + * class was created a defualt Syslog connector will be used. + * @see SyslogPro~Syslog + * @public + * @param {string} msg - The unformated Syslog message to send + * @param {object} [options] - Options object + * @param {number} [options.severity=7] - An array of structure + * @param {number} [options.colorCode=36] - The ANSI color code to use if + * @returns {Promise} A Syslog formated string acording to the selected RFC + * @throws {Error} A standard error object + */ + send (msg, options) { + return new Promise((resolve, reject) => { + if (!this.server) { + this.server = new Syslog(); + } + this.buildMessage(msg, options) + .then((result) => { + this.server.send(result) + .then((sendResult) => { + resolve(sendResult); + }) + .catch((error) => { + reject(error); + }); + }) + .catch((error) => { + reject(error); + }); + }); + } + /** + * Send a syslog message with a secerity level of 0 (Emergency) + * @public + * @param {string} msg - The emergancy message to send to the Syslog server + * @returns {Promise} - The formated syslog message sent to the Syslog server + * @throws {Error} - Any bubbled up error + */ + emergency (msg) { + return this.send(msg, { + severity: 0, + colorCode: this.emergencyColor + }); + } + /** + * Send a syslog message with a secerity level of 0 (Emergency) + * @public + * @param {string} msg - The emergancy message to send to the Syslog server + * @returns {Promise} - The formated syslog message sent to the Syslog server + * @throws {Error} - Any bubbled up error + */ + emer (msg) { + return this.emergency(msg); + } + /** + * Send a syslog message with a secerity level of 1 (Alert) + * @public + * @param {string} msg - The alert message to send to the Syslog server + * @returns {Promise} - The formated syslog message sent to the Syslog server + * @throws {Error} - Any bubbled up error + */ + alert (msg) { + return this.send(msg, { + severity: 1, + colorCode: this.alertColor + }); + } + /** + * Send a syslog message with a secerity level of 2 (Critical) + * @public + * @param {string} msg - The critical message to send to the Syslog server + * @returns {Promise} - The formated syslog message sent to the Syslog server + * @throws {Error} - Any bubbled up error + */ + critical (msg) { + return this.send(msg, { + severity: 2, + colorCode: this.criticalColor + }); + } + /** + * Send a syslog message with a secerity level of 2 (Critical) + * @public + * @param {string} msg - The critical message to send to the Syslog server + * @returns {Promise} - The formated syslog message sent to the Syslog server + * @throws {Error} - Any bubbled up error + */ + crit (msg) { + return this.critical(msg); + } + /** + * Send a syslog message with a secerity level of 3 (Error) + * @public + * @param {string} msg - The error message to send to the Syslog server + * @returns {Promise} - The formated syslog message sent to the Syslog server + * @throws {Error} - Any bubbled up error + */ + error (msg) { + return this.send(msg, { + severity: 3, + colorCode: this.errorColor + }); + } + /** + * Send a syslog message with a secerity level of 3 (Error) + * @public + * @param {string} msg - The error message to send to the Syslog server + * @returns {Promise} - The formated syslog message sent to the Syslog server + * @throws {Error} - Any bubbled up error + */ + err (msg) { + return this.error(msg); + } + /** + * Send a syslog message with a secerity level of 4 (Warning) + * @public + * @param {string} msg - The warning message to send to the Syslog server + * @returns {Promise} - The formated syslog message sent to the Syslog server + * @throws {Error} - Any bubbled up error + */ + warning (msg) { + return this.send(msg, { + severity: 4, + colorCode: this.warningColor + }); + } + /** + * Send a syslog message with a secerity level of 4 (Warning) + * @public + * @param {string} msg - The warning message to send to the Syslog server + * @returns {Promise} - The formated syslog message sent to the Syslog server + * @throws {Error} - Any bubbled up error + */ + warn (msg) { + return this.warning(msg); + } + /** + * Send a syslog message with a secerity level of 5 (Notice) + * @public + * @param {string} msg - The notice message to send to the Syslog server + * @returns {Promise} - The formated syslog message sent to the Syslog server + * @throws {Error} - Any bubbled up error + */ + notice (msg) { + return this.send(msg, { + severity: 5, + colorCode: this.noticeColor + }); + } + /** + * Send a syslog message with a secerity level of 5 (Notice) + * @public + * @param {string} msg - The notice message to send to the Syslog server + * @returns {Promise} - The formated syslog message sent to the Syslog server + * @throws {Error} - Any bubbled up error + */ + note (msg) { + return this.notice(msg); + } + /** + * Send a syslog message with a secerity level of 6 (Informational) + * @public + * @param {string} msg - The informational message to send to the Syslog server + * @returns {Promise} - The formated syslog message sent to the Syslog server + * @throws {Error} - Any bubbled up error + */ + informational (msg) { + return this.send(msg, { + severity: 6, + colorCode: this.informationalColor + }); + } + /** + * Send a syslog message with a secerity level of 6 (Informational) + * @public + * @param {string} msg - The informational message to send to the Syslog server + * @returns {Promise} - The formated syslog message sent to the Syslog server + * @throws {Error} - Any bubbled up error + */ + info (msg) { + return this.informational(msg); + } + /** + * Send a syslog message with a secerity level of 6 (Informational) + * @public + * @param {string} msg - The informational message to send to the Syslog server + * @returns {Promise} - The formated syslog message sent to the Syslog server + * @throws {Error} - Any bubbled up error + */ + log (msg) { + return this.informational(msg); + } + /** + * Send a syslog message with a secerity level of 7 (Debug) + * @public + * @param {string} msg - The debug message to send to the Syslog server + * @returns {Promise} - The formated syslog message sent to the Syslog server + * @throws {Error} - Any bubbled up error + */ + debug (msg) { + return this.send(msg, { + severity: 7, + colorCode: this.debugColor + }); + } +} + +/** + * A class to work with RFC5424 formated syslog messages. The meesaging is fully configurabule and Ansi foreground + * colors can be added. Both ANSI 8 and ANSI 256 color are fully suported. + * Most APIs will return a promise. These APIs can be used using + * `then(...)/catch(...)` + * + * A Syslog class with a configured + * Syslog server target can also be used as the input into the formating + * classes so that it may run independtly. + * + * The RFC5424 Syslog logging format is ment to be used as a stream of log data + * from a service or applacation. This class is designed to be used in this + * fashion where new messages are writen to the class as needed. + * @requires moment + * @version 0.0.0 + * @since 0.0.0 + */ +class RFC5424 { + /** + * Construct a new RFC5424 formated Syslog object with user options + * @public + * @this RFC5424 + * @param {object} [options] - Options object + * @param {string} [options.applacationName='NodeJSLogger'] - Applacation + * @param {string} [options.hostname=os.hostname] - The name of this server + * @param {boolean} [options.timestamp=false] - Included a Timestamp + * @param {boolean} [options.timestampUTC=false] - RFC tandard is for + * local time + * @param {boolean} [options.timestampMS=false] - Timestamp with ms + * resoltuion + * @param {boolean} [options.timestampTZ=true] - Should the timestamp + * included timezone + * @param {boolean} [options.encludeStructuredData=false] - Included + * any provided structured data + * @param {boolean} [options.utf8BOM=true] - Included the UTF8 + * @param {boolean} [options.color=false] - Included the UTF8 + * @param {boolean} [options.extendedColor=false] - Included the UTF8 + * encoding tag with syslog message text + * @param {object} [options.colors] - User defended colors for + * severites + * @param {string} [options.colors.emergencyColor] - A RGB Hex coded color in the form + * of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 + * Extended) + * @param {string} [options.colors.alertColor] - A RGB Hex coded color in the form + * of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 + * Extended) + * @param {string} [options.colors.criticalColor] - A RGB Hex coded color in the form + * of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 + * Extended) + * @param {string} [options.colors.errorColor] - A RGB Hex coded color in the form + * of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 + * Extended) + * @param {string} [options.colors.warningColor] - A RGB Hex coded color in the form + * of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 + * Extended) + * @param {string} [options.colors.noticeColor] - A RGB Hex coded color in the form + * of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 + * Extended) + * @param {string} [options.colors.informationalColor] - A RGB Hex coded color in the form + * of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 + * Extended) + * @param {string} [options.colors.debugColor] - A RGB Hex coded color in the form + * of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 + * Extended) + * @param {Syslog} [options.server=false] - A {@link module:SyslogPro~Syslog| + * Syslog server connection} that should be used to send messages directly + * from this class. @see SyslogPro~Syslog + */ + constructor (options) { + /** @private @type {boolean} */ + this.constructor__ = true; + options = options || {}; + this.hostname = options.hostname || os.hostname(); + this.applacationName = options.applacationName || ''; + if (typeof options.timestamp === 'undefined' || options.timestamp) { + /** @type {boolean} */ + this.timestamp = true; + } else { + this.timestamp = false; + } + if (options.timestampUTC) { + /** @type {boolean} */ + this.timestampUTC = true; + } else { + this.timestampUTC = false; + } + if (typeof options.timestampTZ === 'undefined' || options.timestampTZ) { + /** @type {boolean} */ + this.timestampTZ = true; + } else { + this.timestampTZ = false; + } + if (options.timestampMS) { + /** @type {boolean} */ + this.timestampMS = true; + } else { + this.timestampMS = false; + } + if (options.encludeStructuredData) { + /** @type {boolean} */ + this.encludeStructuredData = true; + } else { + this.encludeStructuredData = false; + } + if (typeof options.utf8BOM === 'undefined' || options.utf8BOM) { + /** @type {boolean} */ + this.utf8BOM = true; + } else { + this.utf8BOM = false; + } + if (options.color) { + /** @type {boolean} */ + this.color = true; + } else { + this.color = false; + } + if (options.extendedColor) { + /** @type {boolean} */ + this.extendedColor = true; + } else { + this.extendedColor = false; + } + if (options.server) { + if (!options.server.constructor__) { + /** @private @type {Syslog} */ + this.server = new Syslog(options.server); + } else { + this.server = options.server; + } + } + if (this.extendedColor) { + /** @private @type {number} */ + this.emergencyColor = 1; // Red foreground color + /** @private @type {number} */ + this.alertColor = 202; // Dark Orange foreground color + /** @private @type {number} */ + this.criticalColor = 208; // Orange foreground color + /** @private @type {number} */ + this.errorColor = 178; // Light Orange foreground color + /** @private @type {number} */ + this.warningColor = 226; // Yellow foreground color + /** @private @type {number} */ + this.noticeColor = 117; // Light Blue foreground color + /** @private @type {number} */ + this.informationalColor = 45; // Blue foreground color + /** @private @type {number} */ + this.debugColor = 27; // Dark Blue foreground color + } else { + this.emergencyColor = 31; // Red foreground color + this.alertColor = 31; // Red foreground color + this.criticalColor = 31; // Red foreground color + this.errorColor = 33; // Yellow foreground color + this.warningColor = 33; // Yellow foreground color + this.noticeColor = 36; // Blue foreground color + this.informationalColor = 36; // Blue foreground color + this.debugColor = 34; // Dark Blue foreground color + } + if (typeof options.colors === 'object') { + this.setColor(options.colors, this.extendedColor); + } + } + /** + * Sets the color to be used for messages at a set priority + * @public + * @param {string} [colors.emergencyColor] - A RGB Hex coded color in the form + * of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 + * Extended) + * @param {string} [colors.alertColor] - A RGB Hex coded color in the form + * of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 + * Extended) + * @param {string} [colors.criticalColor] - A RGB Hex coded color in the form + * of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 + * Extended) + * @param {string} [colors.errorColor] - A RGB Hex coded color in the form + * of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 + * Extended) + * @param {string} [colors.warningColor] - A RGB Hex coded color in the form + * of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 + * Extended) + * @param {string} [colors.noticeColor] - A RGB Hex coded color in the form + * of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 + * Extended) + * @param {string} [colors.informationalColor] - A RGB Hex coded color in the form + * of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 + * Extended) + * @param {string} [colors.debugColor] - A RGB Hex coded color in the form + * of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 + * Extended) + * @throws {Error} A standard error object + */ + setColor (colors, extendedColor) { + return new Promise((resolve, reject) => { + let colorPromises = []; + if (colors.emergencyColor) { + colorPromises.push( + new Promise((resolve,reject) => { + rgbToAnsi(colors.emergencyColor, this.extendedColor) + .then((result) => { + this.emergencyColor = result; + resolve(true); + }) + .catch((reson) => { + reson.message = 'TYPE ERROR: '; + reson.message += 'emergencyColor'; + reson.message += ' Not in RGB color hex or color code'; + reject(reson); + }); + })); + } + if (colors.alertColor) { + colorPromises.push( + new Promise((resolve,reject) => { + rgbToAnsi(colors.alertColor, this.extendedColor) + .then((result) => { + this.alertColor = result; + resolve(true); + }) + .catch((reson) => { + reson.message = 'TYPE ERROR: '; + reson.message += 'alertColor'; + reson.message += ' Not in RGB color hex or color code'; + reject(reson); + }); + })); + } + if (colors.criticalColor) { + colorPromises.push( + new Promise((resolve,reject) => { + rgbToAnsi(colors.criticalColor, this.extendedColor) + .then((result) => { + this.criticalColor = result; + resolve(true); + }) + .catch((reson) => { + reson.message = 'TYPE ERROR: '; + reson.message += 'criticalColor'; + reson.message += ' Not in RGB color hex or color code'; + reject(reson); + }); + })); + } + if (colors.errorColor) { + colorPromises.push( + new Promise((resolve,reject) => { + rgbToAnsi(colors.errorColor, this.extendedColor) + .then((result) => { + this.errorColor = result; + resolve(true); + }) + .catch((reson) => { + reson.message = 'TYPE ERROR: '; + reson.message += 'errorColor'; + reson.message += ' Not in RGB color hex or color code'; + reject(reson); + }); + })); + } + if (colors.warningColor) { + colorPromises.push( + new Promise((resolve,reject) => { + rgbToAnsi(colors.warningColor, this.extendedColor) + .then((result) => { + this.warningColor = result; + resolve(true); + }) + .catch((reson) => { + reson.message = 'TYPE ERROR: '; + reson.message += 'warningColor'; + reson.message += ' Not in RGB color hex or color code'; + reject(reson); + }); + })); + } + if (colors.noticeColor) { + colorPromises.push( + new Promise((resolve,reject) => { + rgbToAnsi(colors.noticeColor, this.extendedColor) + .then((result) => { + this.noticeColor = result; + resolve(true); + }) + .catch((reson) => { + reson.message = 'TYPE ERROR: '; + reson.message += 'noticeColor'; + reson.message += ' Not in RGB color hex or color code'; + reject(reson); + }); + })); + } + if (colors.informationalColor) { + colorPromises.push( + new Promise((resolve,reject) => { + rgbToAnsi(colors.informationalColor, this.extendedColor) + .then((result) => { + this.informationalColor = result; + resolve(true); + }) + .catch((reson) => { + reson.message = 'TYPE ERROR: '; + reson.message += 'informationalColor'; + reson.message += ' Not in RGB color hex or color code'; + reject(reson); + }); + })); + } + if (colors.debugColor) { + colorPromises.push( + new Promise((resolve,reject) => { + rgbToAnsi(colors.debugColor, this.extendedColor) + .then((result) => { + this.debugColor = result; + resolve(true); + }) + .catch((reson) => { + reson.message = 'TYPE ERROR: '; + reson.message += 'debugColor'; + reson.message += ' Not in RGB color hex or color code'; + reject(reson); + }); + })); + } + Promise.all(colorPromises) + .then((results) => { + resolve(true); + }) + .catch((reson) => { + reject(reson); + }); + }); + } + /** + * Building a formated message. Returns a promise with a formated message + * @public + * @param {string} msg - The Syslog Message + * @param {object} [options] - Options object + * @param {number} [options.severity=7] - An array of structure + * @param {number} [options.facility=23] - Facility code to use sending this + * message + * @param {string} [options.pid='-'] - The process id of the service sending + * this message + * @param {string[]} [options.structuredData] - An array of structure + * data strings conforming to the IETF/IANA defined SD-IDs or IANA + * registred SMI Network Management Private Enterprise Code SD-ID + * conforming to the format + * [name@ parameter=value] + * @param {number} [options.colorCode=36] - The ANSI color code to use if + * message coloration is selected + * @returns {Promise} A Syslog formated string acording to the selected RFC + * @throws {Error} A standard error object + */ + buildMessage (msg, options) { + return new Promise((resolve, reject) => { + options = options || {}; + let severity = typeof options.severity === 'number' ? + options.severity : 6; + if (typeof msg !== 'string' || options.severity > 7) { + let errMsg = 'FORMAT ERROR: Syslog message must be a string'; + errMsg += ' msgSeverity must be a number between 0 and 7'; + reject(new Error(errMsg)); + return; + } + let facility = options.facility || 23; + let pid = options.pid || '-'; + let id = options.id || '-'; + let msgStructuredData = options.msgStructuredData || []; + let fmtMsg = ''; // Formated Syslog message string var + const newLine = '\n'; + const newLineRegEx = /(\r|\n|(\r\n))/; + const escapeCode = '\u001B'; + const resetColor = '\u001B[0m'; + +``` + + + + + + + +The PRI is common to both RFC formats + + + + +``` + const pri = (facility * 8) + severity; + +``` + + + + + + + +Remove any newline character + + + + +``` + msg = msg.replace(newLineRegEx, ''); + +``` + + + + + + + +Add requested color + + + + +``` + if (this.color) { + options.msgColor = options.msgColor || 36; + let colorCode = '['; + if (this.extendedColor) { + colorCode += '38;5;'; // Extended 256 Colors ANSI Code + } + if (typeof options.msgColor === 'number') { + colorCode += options.msgColor; + colorCode += 'm'; // ANSI Color Closer + } else { + colorCode = '[39m'; // Use terminal's defualt color + } + msg = escapeCode + colorCode + msg + resetColor; + } + +``` + + + + + + + +RFC5424 timestamp formating + + + + +``` + let timestamp = '-'; + if (this.timestamp) { + let timeQuality = '[timeQuality'; + if (this.timestampUTC) { + timeQuality += ' tzKnown=1'; + if (this.timestampMS) { + if (this.timestampTZ) { + timestamp = moment().utc().format('YYYY-MM-DDThh:mm:ss.SSSSSSZ'); + } else { + timestamp = moment().utc().format('YYYY-MM-DDThh:mm:ss.SSSSSS'); + } + } else { + if (this.timestampTZ) { + timestamp = moment().utc().format('YYYY-MM-DDThh:mm:ssZ'); + } else { + timestamp = moment().utc().format('YYYY-MM-DDThh:mm:ss'); + } + } + } else { + if (this.timestampTZ) { + timeQuality += ' tzKnown=1'; + if (this.timestampMS) { + timeQuality += ' isSynced=1'; + timeQuality += ' syncAccuracy=0'; + timestamp = moment().format('YYYY-MM-DDThh:mm:ss.SSSSSSZ'); + } else { + timestamp = moment().format('YYYY-MM-DDThh:mm:ssZ'); + } + } else { + timeQuality += ' tzKnown=0'; + if (this.timestampMS) { + timeQuality += ' isSynced=1'; + timeQuality += ' syncAccuracy=0'; + timestamp = moment().format('YYYY-MM-DDThh:mm:ss.SSSSSS'); + } else { + timestamp = moment().format('YYYY-MM-DDThh:mm:ss'); + } + } + } + timeQuality += ']'; + msgStructuredData.push(timeQuality); + } + +``` + + + + + + + +Build Structured Data string + + + + +``` + let structuredData = '-'; + const sdElementCount = msgStructuredData.length; + if (this.encludeStructuredData && sdElementCount > 0) { + let sdElementNames = []; + let sdElements = []; + const sdElementNameRegEx = /(\[)(\S*)(\s|\])/; + +``` + + + + + + + +Loop to drop duplicates of the same SD Element name + + + + +``` + for (let elementIndex=0; + elementIndex'; + fmtMsg += '1'; // Version number + fmtMsg += ' ' + timestamp; + fmtMsg += ' ' + this.hostname; + fmtMsg += ' ' + this.applacationName; + fmtMsg += ' ' + pid; + fmtMsg += ' ' + id; + fmtMsg += ' ' + structuredData; + if (this.utf8BOM) { + fmtMsg += ' BOM' + msg; + } else { + fmtMsg += ' ' + msg; + } + fmtMsg += newLine; + resolve(fmtMsg); + }); + } + /** + * send a RFC5424 formated message. Returns a promise with the formated + * message that was sent. If no server connection was defined when the + * class was created a defualt Syslog connector will be used. + * @see SyslogPro~Syslog + * @public + * @param {string} msg - The unformated Syslog message to send + * @returns {Promise} A Syslog formated string acording to the selected RFC + * @throws {Error} A standard error object + */ + send (msg, options) { + return new Promise((resolve, reject) => { + if (!this.server) { + this.server = new Syslog(); + } + this.buildMessage(msg, options) + .then((result) => { + this.server.send(result) + .then((sendResult) => { + resolve(sendResult); + }) + .catch((error) => { + reject(error); + }); + }) + .catch((error) => { + reject(error); + }); + }); + } + /** + * Send a syslog message with a secerity level of 0 (Emergency) + * @public + * @param {string} msg - The emergancy message to send to the Syslog server + * @returns {Promise} - The formated syslog message sent to the Syslog server + * @throws {Error} - Any bubbled up error + */ + emergency (msg) { + return this.send(msg, { + severity: 0, + colorCode: this.emergencyColor + }); + } + /** + * Send a syslog message with a secerity level of 0 (Emergency) + * @public + * @param {string} msg - The emergancy message to send to the Syslog server + * @returns {Promise} - The formated syslog message sent to the Syslog server + * @throws {Error} - Any bubbled up error + */ + emer (msg) { + return this.emergency(msg); + } + /** + * Send a syslog message with a secerity level of 1 (Alert) + * @public + * @param {string} msg - The alert message to send to the Syslog server + * @returns {Promise} - The formated syslog message sent to the Syslog server + * @throws {Error} - Any bubbled up error + */ + alert (msg) { + return this.send(msg, { + severity: 1, + colorCode: this.alertColor + }); + } + /** + * Send a syslog message with a secerity level of 2 (Critical) + * @public + * @param {string} msg - The critical message to send to the Syslog server + * @returns {Promise} - The formated syslog message sent to the Syslog server + * @throws {Error} - Any bubbled up error + */ + critical (msg) { + return this.send(msg, { + severity: 2, + colorCode: this.criticalColor + }); + } + /** + * Send a syslog message with a secerity level of 2 (Critical) + * @public + * @param {string} msg - The critical message to send to the Syslog server + * @returns {Promise} - The formated syslog message sent to the Syslog server + * @throws {Error} - Any bubbled up error + */ + crit (msg) { + return this.critical(msg); + } + /** + * Send a syslog message with a secerity level of 3 (Error) + * @public + * @param {string} msg - The error message to send to the Syslog server + * @returns {Promise} - The formated syslog message sent to the Syslog server + * @throws {Error} - Any bubbled up error + */ + error (msg) { + return this.send(msg, { + severity: 3, + colorCode: this.errorColor + }); + } + /** + * Send a syslog message with a secerity level of 3 (Error) + * @public + * @param {string} msg - The error message to send to the Syslog server + * @returns {Promise} - The formated syslog message sent to the Syslog server + * @throws {Error} - Any bubbled up error + */ + err (msg) { + return this.error(msg); + } + /** + * Send a syslog message with a secerity level of 4 (Warning) + * @public + * @param {string} msg - The warning message to send to the Syslog server + * @returns {Promise} - The formated syslog message sent to the Syslog server + * @throws {Error} - Any bubbled up error + */ + warning (msg) { + return this.send(msg, { + severity: 4, + colorCode: this.warningColor + }); + } + /** + * Send a syslog message with a secerity level of 4 (Warning) + * @public + * @param {string} msg - The warning message to send to the Syslog server + * @returns {Promise} - The formated syslog message sent to the Syslog server + * @throws {Error} - Any bubbled up error + */ + warn (msg) { + return this.warning(msg); + } + /** + * Send a syslog message with a secerity level of 5 (Notice) + * @public + * @param {string} msg - The notice message to send to the Syslog server + * @returns {Promise} - The formated syslog message sent to the Syslog server + * @throws {Error} - Any bubbled up error + */ + notice (msg) { + return this.send(msg, { + severity: 5, + colorCode: this.noticeColor + }); + } + /** + * Send a syslog message with a secerity level of 5 (Notice) + * @public + * @param {string} msg - The notice message to send to the Syslog server + * @returns {Promise} - The formated syslog message sent to the Syslog server + * @throws {Error} - Any bubbled up error + */ + note (msg) { + return this.notice(msg); + } + /** + * Send a syslog message with a secerity level of 6 (Informational) + * @public + * @param {string} msg - The informational message to send to the Syslog server + * @returns {Promise} - The formated syslog message sent to the Syslog server + * @throws {Error} - Any bubbled up error + */ + informational (msg) { + return this.send(msg, { + severity: 6, + colorCode: this.informationalColor + }); + } + /** + * Send a syslog message with a secerity level of 6 (Informational) + * @public + * @param {string} msg - The informational message to send to the Syslog server + * @returns {Promise} - The formated syslog message sent to the Syslog server + * @throws {Error} - Any bubbled up error + */ + info (msg) { + return this.informational(msg); + } + /** + * Send a syslog message with a secerity level of 6 (Informational) + * @public + * @param {string} msg - The informational message to send to the Syslog server + * @returns {Promise} - The formated syslog message sent to the Syslog server + * @throws {Error} - Any bubbled up error + */ + log (msg) { + return this.informational(msg); + } + /** + * Send a syslog message with a secerity level of 7 (Debug) + * @public + * @param {string} msg - The debug message to send to the Syslog server + * @returns {Promise} - The formated syslog message sent to the Syslog server + * @throws {Error} - Any bubbled up error + */ + debug (msg) { + return this.send(msg, { + severity: 7, + colorCode: this.debugColor + }); + } +} + +/** + * A class to work with IBM LEEF (Log Event Extended Format) messages this form + * of system messages are designed to work with security systems. Messages can + * be saved to file (Saving to file if not part of this module but a LEEF + * formated mesage produced by this module can be saved externaly to it) or + * sent via Syslog. + * Most APIs will return a promise. These APIs can be used using + * `then(...)/catch(...)` + * + * A Syslog class with a configured Syslog server target can also be used as + * the input into the formating classes so that it may run independtly. The + * LEEF format is designed to send event data to a SIEM system and should not + * be as a logging stream. This class is ment to be used once per message. + * @requires moment + * @version 0.0.0 + * @since 0.0.0 + */ +class LEEF { + /** + * Construct a new LEEF formating object with user options + * @public + * @param {object} [options] - Options object + * @param {string} [options.vendor='unknown'] - The vendor of the system that + * genrated the event being reported + * @param {string} [options.product='unknown'] - The product name of the + * system that genrated the event being reported + * @param {string} [options.version='unknown'] - The version name of the + * system that genrated the event being reported + * @param {string} [options.eventId='unknown'] - The eventId of the + * system that genrated the event being reported + * @param {object} [options.attrabute] - LEEF message attrabutes which + * defualts to all base attrabutes with null values, new attrabutes should + * be added as new elements to this object + * @param {boolean} [options.syslogHeader='true'] - Should the LEEF message + * include a Syslog header with Timestamp and source + * @param {Syslog} [options.server=false] - A {@link module:SyslogPro~Syslog| + * Syslog server connection} that should be used to send messages directly + * from this class. @see SyslogPro~Syslog + */ + constructor (options) { + /** @private @type {boolean} */ + this.constructor__ = true; + options = options || {}; + /** @type {string} */ + this.vendor = options.vendor || 'unknown'; + /** @type {string} */ + this.product = options.product || 'unknown'; + /** @type {string} */ + this.version = options.version || 'unknown'; + /** @type {string} */ + this.eventId = options.eventId || 'unknown'; + /** @type {boolean} */ + this.syslogHeader = typeof options.syslogHeader === 'boolean' + ? options.syslogHeader : true; + /** @type {object} */ + this.attrabutes = options.attrabutes || { + cat: null, + devTime: null, + devTimeFormat: null, + proto: null, + sev: null, + src: null, + dst: null, + srcPort: null, + dstPort: null, + srcPreNAT: null, + dstPreNAT: null, + srcPostNAT: null, + dstPostNAT: null, + usrName: null, + srcMAC: null, + dstMAC: null, + srcPreNATPort: null, + dstPreNATPort: null, + srcPostNATPort: null, + dstPostNATPort: null, + identSrc: null, + identHostName: null, + identNetBios: null, + identGrpName: null, + identMAC: null, + vSrc: null, + vSrcName: null, + accountName: null, + srcBytes: null, + dstBytes: null, + srcPackets: null, + dstPackets: null, + totalPackets: null, + role: null, + realm: null, + policy: null, + resource: null, + url: null, + groupID: null, + domain: null, + isLoginEvent: null, + isLogoutEvent: null, + identSecondlp: null, + calLanguage: null, + AttributeLimits: null, + calCountryOrRegion: null, + }; + if (options.server) { + if (options.server.constructor__) { + /** @private @type {Syslog} */ + this.server = options.server; + } else { + this.server = new Syslog(options.server); + } + } + } + /** + *Build a formated message + * @public + * @return {Promise} - string with formated message + */ + buildMessage () { + return new Promise((resolve, reject) => { + let fmtMsg = 'LEEF:2.0'; + fmtMsg += '|' + this.vendor; + fmtMsg += '|' + this.product; + fmtMsg += '|' + this.version; + fmtMsg += '|' + this.eventId; + fmtMsg += '|'; + + +``` + + + + + + + +Build LEEF Attrabuites + + + + +``` + const Tab = '\x09'; + const leefAttribs = Object.entries(this.attrabutes); + const leefAttribsLen = leefAttribs.length; + for (let attrib = 0; attrib < leefAttribsLen; attrib++) { + if (leefAttribs[attrib][1] !== null) { + fmtMsg += leefAttribs[attrib][0] + '=' + leefAttribs[attrib][1] + Tab; + } + } + resolve(fmtMsg); + }); + } + + /** + * @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 + */ + send (options) { + return new Promise((resolve, reject) => { + this.buildMessage() + .then((result) => { + if (!this.server) { + this.server = new Syslog(options); + } + this.server.send(result) + .then((sendResult) => { + resolve(sendResult); + }) + .catch((reson) => { + reject(reson); + }); + }); + }); + } +} + +/** + * A class to work with HP CEF (Common Event Format) messages. This form + * of system messages are designed to work with security systems. Messages can + * be saved to file (Saving to file if not part of this module but a CEF + * formated mesage produced by this module can be saved externaly to it) or + * sent via Syslog. + * Most APIs will return a promise. These APIs can be used using + * `then(...)/catch(...)` + * + * A Syslog class with a configured Syslog server target can also be used as + * the input into the formating classes so that it may run independtly. The CEF + * format is designed to send event data to a SIEM system and should not be as + * a logging stream. This class is ment to be used once per message. + * @requires moment + * @version 0.0.0 + * @since 0.0.0 + */ +class CEF { + /** + * Construct a new CEF formating object with user options + * @public + * @param {object} [options] - Options object + * @param {string} [options.deviceVendor='unknown'] - The vendor of the system + * that genrated the event being reported + * @param {string} [options.deviceProduct='unknown'] - The product name of the + * system that genrated the event being reported + * @param {string} [options.deviceVersion='unknown'] - The version name of the + * system that genrated the event being reported + * @param {string} [options.deviceEventClassId='unknown'] - The eventId of the + * system that genrated the event being reported + * @param {string} [options.name='unknown'] - Name of the service genrating + * the notice + * @param {string} [options.severity='unknown'] - Severity of the notification + * @param {string} [options.extensions={}] - Any CEF Key=Value extentions + * @param {Syslog} [options.server=false] - A {@link module:SyslogPro~Syslog| + * Syslog server connection} that should be used to send messages directly + * from this class. @see SyslogPro~Syslog + */ + constructor (options) { + /** @private @type {boolean} */ + this.constructor__ = true; + options = options || {}; + /** @type {string} */ + this.deviceVendor = options.deviceVendor || 'Unknown'; + /** @type {string} */ + this.deviceProduct = options.deviceProduct || 'Unknown'; + /** @type {string} */ + this.deviceVersion = options.deviceVersion || 'Unknown'; + /** @type {string} */ + this.deviceEventClassId = options.deviceEventClassId || 'Unknown'; + /** @type {string} */ + this.name = options.name || 'Unknown'; + /** @type {string} */ + this.severity = options.severity || 'Unknown'; + /** @type {object} */ + this.extensions = options.extensions || { + 'deviceAction': null, + 'applicationProtocol': null, + 'deviceCustomIPv6Address1': null, + 'deviceCustomIPv6 Address1Label': null, + 'deviceCustomIPv6Address3': null, + 'deviceCustomIPv6Address3 Label': null, + 'deviceCustomIPv6 Address4': null, + 'deviceCustomIPv6 Address4Label': null, + 'deviceEventCategory': null, + 'deviceCustomFloatingPoint1': null, + 'deviceCustom FloatingPoint1Label': null, + 'deviceCustomFloatingPoint2': null, + 'deviceCustomFloatingPoint2 Label': null, + 'deviceCustomFloatingPoint3': null, + 'deviceCustom FloatingPoint3Label': null, + 'deviceCustomFloatingPoint4': null, + 'deviceCustom FloatingPoint4Label': null, + 'deviceCustomNumber1': null, + 'deviceCustomNumber1Label': null, + 'DeviceCustomNumber2': null, + 'deviceCustomNumber2Label': null, + 'deviceCustomNumber3': null, + 'deviceCustomNumber3Label': null, + 'baseEventCount': null, + 'deviceCustomString1': null, + 'deviceCustomString1Label': null, + 'deviceCustomString2': null, + 'deviceCustomString2Label': null, + 'deviceCustomString3': null, + 'deviceCustomString3Label': null, + 'deviceCustomString4': null, + 'deviceCustomString4Label': null, + 'deviceCustomString5': null, + 'deviceCustomString5Label': null, + 'deviceCustomString6': null, + 'deviceCustomString6Label': null, + 'destinationDnsDomain': null, + 'destinationServiceName': null, + 'destinationTranslated Address': null, + 'destinationTranslatedPort': null, + 'deviceCustomDate1': null, + 'deviceCustomDate1Label': null, + 'deviceCustomDate2': null, + 'deviceCustomDate2Label': null, + 'deviceDirection': null, + 'deviceDnsDomain': null, + 'deviceExternalId': null, + 'deviceFacility': null, + 'deviceInboundInterface': null, + 'deviceNtDomain': null, + 'deviceOutboundInterface': null, + 'devicePayloadId': null, + 'deviceProcessName': null, + 'deviceTranslatedAddress': null, + 'destinationHostName': null, + 'destinationMacAddress': null, + 'destinationNtDomain': null, + 'destinationProcessId': null, + 'destinationUserPrivileges': null, + 'destinationProcessName': null, + 'destinationPort': null, + 'destinationAddress': null, + 'deviceTimeZone': null, + 'destinationUserId': null, + 'destinationUserName': null, + 'deviceAddress': null, + 'deviceHostName': null, + 'deviceMacAddress': null, + 'deviceProcessId': null, + 'endTime': null, + 'externalId': null, + 'fileCreateTime': null, + 'fileHash': null, + 'fileId': null, + 'fileModificationTime': null, + 'filePath': null, + 'filePermission': null, + 'fileType': null, + 'flexDate1': null, + 'flexDate1Label': null, + 'flexString1': null, + 'flexString1Label': null, + 'flexString2': null, + 'flexString2Label': null, + 'filename': null, + 'fileSize': null, + 'bytesIn': null, + 'message': null, + 'oldFileCreateTime': null, + 'oldFileHash': null, + 'oldFileId': null, + 'oldFileModificationTime': null, + 'oldFileName': null, + 'oldFilePath': null, + 'oldFileSize': null, + 'oldFileType': null, + 'bytesOut': null, + 'eventOutcome': null, + 'transportProtocol': null, + 'Reason': null, + 'requestUrl': null, + 'requestClientApplication': null, + 'requestContext': null, + 'requestCookies': null, + 'requestMethod': null, + 'deviceReceiptTime': null, + 'sourceHostName': null, + 'sourceMacAddress': null, + 'sourceNtDomain': null, + 'sourceDnsDomain': null, + 'sourceServiceName': null, + 'sourceTranslatedAddress': null, + 'sourceTranslatedPort': null, + 'sourceProcessId': null, + 'sourceUserPrivileges': null, + 'sourceProcessName': null, + 'sourcePort': null, + 'sourceAddress': null, + 'startTime': null, + 'sourceUserId': null, + 'sourceUserName': null, + 'type': null, + 'agentDnsDomain': null, + 'agentNtDomain': null, + 'agentTranslatedAddress': null, + 'agentTranslatedZone ExternalID': null, + 'agentTranslatedZoneURI': null, + 'agentZoneExternalID': null, + 'agentZoneURI': null, + 'agentAddress': null, + 'agentHostName': null, + 'agentId': null, + 'agentMacAddress': null, + 'agentReceiptTime': null, + 'agentType': null, + 'agentTimeZone': null, + 'agentVersion': null, + 'customerExternalID': null, + 'customerURI': null, + 'destinationTranslated ZoneExternalID': null, + 'destinationTranslated ZoneURI': null, + 'destinationZoneExternalID': null, + 'destinationZoneURI': null, + 'deviceTranslatedZone ExternalID': null, + 'deviceTranslatedZoneURI': null, + 'deviceZoneExternalID': null, + 'deviceZoneURI': null, + 'destinationGeoLatitude': null, + 'destinationGeoLongitude': null, + 'eventId': null, + 'rawEvent': null, + 'sourceGeoLatitude': null, + 'sourceGeoLongitude': null, + 'sourceTranslatedZone ExternalID': null, + 'sourceTranslatedZoneURI': null, + 'sourceZoneExternalID': null, + 'sourceZoneURI': null, + }; + if (options.server) { + if (options.server.constructor__) { + /** @private @type {Syslog} */ + this.server = options.server; + } else { + this.server = new Syslog(options.server); + } + } + } + /** + * Validate this CEF object + * @public + * @return {Promise} - True if valadated + * @throws {Error} - First element to fail valadation + */ + validate () { + return new Promise ((resolve, reject) => { + const Extensions = { + 'deviceAction': {key: 'act', type:'String', len:63, discription: 'Action taken by the device.'}, + 'applicationProtocol': {key: 'app', type:'String', len:31, discription: 'Application level protocol, example values are HTTP, HTTPS, SSHv2, Telnet, POP, IMPA, IMAPS, and so on.'}, + 'deviceCustomIPv6Address1': {key: 'c6a1', type:'String', len:null, discription: 'One of four IPv6 address fields available to map fields that do not apply to any other in this dictionary. TIP: See the guidelines under “User-Defined Extensions” for tips on using these fields.'}, + 'deviceCustomIPv6 Address1Label': {key: 'c6a1Label', type:'String', len:1023, discription: 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.'}, + 'deviceCustomIPv6Address3': {key: 'c6a3', type:'String', len:null, discription: 'One of four IPv6 address fields available to map fields that do not apply to any other in this dictionary. TIP: See the guidelines under “User-Defined Extensions” for tips on using these fields.'}, + 'deviceCustomIPv6Address3 Label': {key: 'c6a3Label', type:'String', len:1023, discription: 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.'}, + 'deviceCustomIPv6 Address4': {key: 'c6a4', type:'String', len:null, discription: 'One of four IPv6 address fields available to map fields that do not apply to any other in this dictionary. TIP: See the guidelines under “User-Defined Extensions” for tips on using these fields.'}, + 'deviceCustomIPv6 Address4Label': {key: 'C6a4Label', type:'String', len:1023, discription: 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.'}, + 'deviceEventCategory': {key: 'cat', type:'String', len:1023, discription: 'Represents the category assigned by the originating device. Devices often use their own categorization schema to classify event. Example: “/Monitor/Disk/Read”'}, + 'deviceCustomFloatingPoint1': {key: 'cfp1', type:'Number', len:null, discription: 'One of four floating point fields available to map fields that do not apply to any other in this dictionary.'}, + 'deviceCustom FloatingPoint1Label': {key: 'cfp1Label', type:'String', len:1023, discription: 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.'}, + 'deviceCustomFloatingPoint2': {key: 'cfp2', type:'Number', len:null, discription: 'One of four floating point fields available to map fields that do not apply to any other in this dictionary.'}, + 'deviceCustomFloatingPoint2 Label': {key: 'cfp2Label', type:'String', len:1023, discription: 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.'}, + 'deviceCustomFloatingPoint3': {key: 'cfp3', type:'Number', len:null, discription: 'One of four floating point fields available to map fields that do not apply to any other in this dictionary.'}, + 'deviceCustom FloatingPoint3Label': {key: 'cfp3Label', type:'String', len:1023, discription: 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.'}, + 'deviceCustomFloatingPoint4': {key: 'cfp4', type:'Number', len:null, discription: 'One of four floating point fields available to map fields that do not apply to any other in this dictionary.'}, + 'deviceCustom FloatingPoint4Label': {key: 'cfp4Label', type:'String', len:1023, discription: 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.'}, + 'deviceCustomNumber1': {key: 'cn1', type:'Number', len:null, discription: 'One of three number fields available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible.'}, + 'deviceCustomNumber1Label': {key: 'cn1Label', type:'String', len:1023, discription: 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.'}, + 'DeviceCustomNumber2': {key: 'cn2', type:'Number', len:null, discription: 'One of three number fields available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible.'}, + 'deviceCustomNumber2Label': {key: 'cn2Label', type:'String', len:1023, discription: 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.'}, + 'deviceCustomNumber3': {key: 'cn3', type:'Number', len:null, discription: 'One of three number fields available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible.'}, + 'deviceCustomNumber3Label': {key: 'cn3Label', type:'String', len:1023, discription: 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.'}, + 'baseEventCount': {key: 'cnt', type:'Number', len:null, discription: 'A count associated with this event. How many times was this same event observed? Count can be omitted if it is 1.'}, + 'deviceCustomString1': {key: 'cs1', type:'String', len:4000, discription: 'One of six strings available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible. TIP: See the guidelines under “User-Defined Extensions” for tips on using these fields.'}, + 'deviceCustomString1Label': {key: 'cs1Label', type:'String', len:1023, discription: 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.'}, + 'deviceCustomString2': {key: 'cs2', type:'String', len:4000, discription: 'One of six strings available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible. TIP: See the guidelines under “User-Defined Extensions” for tips on using these fields.'}, + 'deviceCustomString2Label': {key: 'cs2Label', type:'String', len:1023, discription: 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.'}, + 'deviceCustomString3': {key: 'cs3', type:'String', len:4000, discription: 'One of six strings available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible. TIP: See the guidelines under “User-Defined Extensions” for tips on using these fields.'}, + 'deviceCustomString3Label': {key: 'cs3Label', type:'String', len:1023, discription: 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.'}, + 'deviceCustomString4': {key: 'cs4', type:'String', len:4000, discription: 'One of six strings available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible. TIP: See the guidelines under “User-Defined Extensions” for tips on using these fields.'}, + 'deviceCustomString4Label': {key: 'cs4Label', type:'String', len:1023, discription: 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.'}, + 'deviceCustomString5': {key: 'cs5', type:'String', len:4000, discription: 'One of six strings available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible. TIP: See the guidelines under “User-Defined Extensions” for tips on using these fields.'}, + 'deviceCustomString5Label': {key: 'cs5Label', type:'String', len:1023, discription: 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.'}, + 'deviceCustomString6': {key: 'cs6', type:'String', len:4000, discription: 'One of six strings available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible. TIP: See the guidelines under “User-Defined Extensions” for tips on using these fields.'}, + 'deviceCustomString6Label': {key: 'cs6Label', type:'String', len:1023, discription: 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.'}, + 'destinationDnsDomain': {key: 'destination DnsDomain', type:'String', len:255, discription: 'The DNS domain part of the complete fully qualified domain name (FQDN).'}, + 'destinationServiceName': {key: 'destination ServiceName', type:'String', len:1023, discription: 'The service targeted by this event. Example: “sshd”'}, + 'destinationTranslated Address': {key: 'Destination Translated Address', type:'String', len:null, discription: 'Identifies the translated destination that the event refers to in an IP network. The format is an IPv4 address. Example: “192.168.10.1”'}, + 'destinationTranslatedPort': {key: 'Destination TranslatedPort', type:'Number', len:null, discription: 'Port after it was translated; for example, a firewall. Valid port numbers are 0 to 65535.'}, + 'deviceCustomDate1': {key: 'deviceCustom Date1', type:'String', len:null, discription: 'One of two timestamp fields available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible. TIP: See the guidelines under “User-Defined Extensions” for tips on using these fields.'}, + 'deviceCustomDate1Label': {key: 'deviceCustom Date1Label', type:'String', len:1023, discription: 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.'}, + 'deviceCustomDate2': {key: 'deviceCustom Date2', type:'String', len:null, discription: 'One of two timestamp fields available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible. TIP: See the guidelines under “User-Defined Extensions” for tips on using these fields.'}, + 'deviceCustomDate2Label': {key: 'deviceCustom Date2Label', type:'String', len:1023, discription: 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.'}, + 'deviceDirection': {key: 'deviceDirection', type:'Number', len:null, discription: 'Any information about what direction the observed communication has taken. The following values are supported: “0” for inbound or “1” for outbound'}, + 'deviceDnsDomain': {key: 'deviceDns Domain', type:'String', len:255, discription: 'The DNS domain part of the complete fully qualified domain name (FQDN).'}, + 'deviceExternalId': {key: 'device ExternalId', type:'String', len:255, discription: 'A name that uniquely identifies the device generating this event.'}, + 'deviceFacility': {key: 'deviceFacility', type:'String', len:1023, discription: 'The facility generating this event. For example, Syslog has an explicit facility associated with every event.'}, + 'deviceInboundInterface': {key: 'deviceInbound Interface', type:'String', len:128, discription: 'Interface on which the packet or data entered the device.'}, + 'deviceNtDomain': {key: 'deviceNt Domain', type:'String', len:255, discription: 'The Windows domain name of the device address.'}, + 'deviceOutboundInterface': {key: 'Device Outbound Interface', type:'String', len:128, discription: 'Interface on which the packet or data left the device.'}, + 'devicePayloadId': {key: 'Device PayloadId', type:'String', len:128, discription: 'Unique identifier for the payload associated with the event.'}, + 'deviceProcessName': {key: 'deviceProcess Name', type:'String', len:1023, discription: 'Process name associated with the event. An example might be the process generating the syslog entry in UNIX.'}, + 'deviceTranslatedAddress': {key: 'device Translated Address', type:'String', len:null, discription: 'Identifies the translated device address that the event refers to in an IP network. The format is an IPv4 address. Example: “192.168.10.1”'}, + 'destinationHostName': {key: 'dhost', type:'String', len:1023, discription: 'Identifies the destination that an event refers to in an IP network. The format should be a fully qualified domain name (FQDN) associated with the destination node, when a node is available. Examples: “host.domain.com” or “host”.'}, + 'destinationMacAddress': {key: 'dmac', type:'String', len:null, discription: 'Six colon-seperated hexadecimal numbers. Example: “00:0D:60:AF:1B:61”'}, + 'destinationNtDomain': {key: 'dntdom', type:'String', len:255, discription: 'The Windows domain name of the destination address.'}, + 'destinationProcessId': {key: 'dpid', type:'Number', len:null, discription: 'Provides the ID of the destination process associated with the event. For example, if an event contains process ID 105, “105” is the process ID.'}, + 'destinationUserPrivileges': {key: 'dpriv', type:'String', len:1023, discription: 'The typical values are “Administrator”, “User”, and “Guest”. This identifies the destination user’s privileges. In UNIX, for example, activity executed on the root user would be identified with destinationUser Privileges of “Administrator”.'}, + 'destinationProcessName': {key: 'dproc', type:'String', len:1023, discription: 'The name of the event’s destination process. Example: “telnetd” or “sshd”.'}, + 'destinationPort': {key: 'dpt', type:'Number', len:null, discription: 'The valid port numbers are between 0 and 65535.'}, + 'destinationAddress': {key: 'dst', type:'String', len:null, discription: 'Identifies the destination address that the event refers to in an IP network. The format is an IPv4 address. Example: “192.168.10.1”'}, + 'deviceTimeZone': {key: 'dtz', type:'String', len:255, discription: 'The timezone for the device generating the event.'}, + 'destinationUserId': {key: 'duid', type:'String', len:1023, discription: 'Identifies the destination user by ID. For example, in UNIX, the root user is generally associated with user ID 0.'}, + 'destinationUserName': {key: 'duser', type:'String', len:1023, discription: 'Identifies the destination user by name. This is the user associated with the event’s destination. Email addresses are often mapped into the UserName fields. The recipient is a candidate to put into this field.'}, + 'deviceAddress': {key: 'dvc', type:'String', len:null, discription: 'Identifies the device address that an event refers to in an IP network. The format is an IPv4 address. Example: “192.168.10.1”.'}, + 'deviceHostName': {key: 'dvchost', type:'String', len:100, discription: 'The format should be a fully qualified domain name (FQDN) associated with the device node, when a node is available. Example: “host.domain.com” or “host”.'}, + 'deviceMacAddress': {key: 'dvcmac', type:'String', len:null, discription: 'Six colon-separated hexadecimal numbers. Example: “00:0D:60:AF:1B:61”'}, + 'deviceProcessId': {key: 'dvcpid', type:'Number', len:null, discription: 'Provides the ID of the process on the device generating the event.'}, + 'endTime': {key: 'end', type:'String', len:null, discription: 'The time at which the activity related to the event ended. The format is MMM dd yyyy HH:mm:ss or milliseconds since epoch (Jan 1st1970). An example would be reporting the end of a session.'}, + 'externalId': {key: 'externalId', type:'String', len:40, discription: 'The ID used by an originating device. They are usually increasing numbers, associated with events.'}, + 'fileCreateTime': {key: 'fileCreateTime', type:'String', len:null, discription: 'Time when the file was created.'}, + 'fileHash': {key: 'fileHash', type:'String', len:255, discription: 'Hash of a file.'}, + 'fileId': {key: 'fileId', type:'String', len:1023, discription: 'An ID associated with a file could be the inode.'}, + 'fileModificationTime': {key: 'fileModification Time', type:'String', len:null, discription: 'Time when the file was last modified.'}, + 'filePath': {key: 'filePath', type:'String', len:1023, discription: 'Full path to the file, including file name itself. Example: C:\Program Files \WindowsNT\Accessories\ wordpad.exe or /usr/bin/zip'}, + 'filePermission': {key: 'filePermission', type:'String', len:1023, discription: 'Permissions of the file.'}, + 'fileType': {key: 'fileType', type:'String', len:1023, discription: 'Type of file (pipe, socket, etc.)'}, + 'flexDate1': {key: 'flexDate1', type:'String', len:null, discription: 'A timestamp field available to map a timestamp that does not apply to any other defined timestamp field in this dictionary. Use all flex fields sparingly and seek a more specific, dictionary supplied field when possible. These fields are typically reserved for customer use and should not be set by vendors unless necessary.'}, + 'flexDate1Label': {key: 'flexDate1Label', type:'String', len:128, discription: 'The label field is a string and describes the purpose of the flex field.'}, + 'flexString1': {key: 'flexString1', type:'String', len:1023, discription: 'One of four floating point fields available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible. These fields are typically reserved for customer use and should not be set by vendors unless necessary.'}, + 'flexString1Label': {key: 'flexString1 Label', type:'String', len:128, discription: 'The label field is a string and describes the purpose of the flex field.'}, + 'flexString2': {key: 'flexString2', type:'String', len:1023, discription: 'One of four floating point fields available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible. These fields are typically reserved for customer use and should not be set by vendors unless necessary.'}, + 'flexString2Label': {key: 'flex String2Label', type:'String', len:128, discription: 'The label field is a string and describes the purpose of the flex field.'}, + 'filename': {key: 'fname', type:'String', len:1023, discription: 'Name of the file only (without its path).'}, + 'fileSize': {key: 'fsize', type:'Number', len:null, discription: 'Size of the file.'}, + 'bytesIn': {key: 'in', type:'Number', len:null, discription: 'Number of bytes transferred inbound, relative to the source to destination relationship, meaning that data was flowing from source to destination.'}, + 'message': {key: 'msg', type:'String', len:1023, discription: 'An arbitrary message giving more details about the event. Multi-line entries can be produced by using \n as the new line separator.'}, + 'oldFileCreateTime': {key: 'oldFileCreate Time', type:'String', len:null, discription: 'Time when old file was created.'}, + 'oldFileHash': {key: 'oldFileHash', type:'String', len:255, discription: 'Hash of the old file.'}, + 'oldFileId': {key: 'oldFileId', type:'String', len:1023, discription: 'An ID associated with the old file could be the inode.'}, + 'oldFileModificationTime': {key: 'oldFile Modification Time', type:'String', len:null, discription: 'Time when old file was last modified.'}, + 'oldFileName': {key: 'oldFileName', type:'String', len:1023, discription: 'Name of the old file.'}, + 'oldFilePath': {key: 'oldFilePath', type:'String', len:1023, discription: 'Full path to the old fiWindowsNT\Accessories le, including the file name itself. Examples: c:\Program Files\wordpad.exe or /usr/bin/zip'}, + 'oldFileSize': {key: 'oldFileSize', type:'Number', len:null, discription: 'Size of the old file.'}, + 'oldFileType': {key: 'oldFileType', type:'String', len:1023, discription: 'Type of the old file (pipe, socket, etc.)'}, + 'bytesOut': {key: 'out', type:'Number', len:null, discription: 'Number of bytes transferred outbound relative to the source to destination relationship. For example, the byte number of data flowing from the destination to the source.'}, + 'eventOutcome': {key: 'outcome', type:'String', len:63, discription: 'Displays the outcome, usually as ‘success’ or ‘failure’.'}, + 'transportProtocol': {key: 'proto', type:'String', len:31, discription: 'Identifies the Layer-4 protocol used. The possible values are protocols such as TCP or UDP.'}, + 'Reason': {key: 'reason', type:'String', len:1023, discription: 'The reason an audit event was generated. For example “badd password” or “unknown user”. This could also be an error or return code. Example: “0x1234”'}, + 'requestUrl': {key: 'request', type:'String', len:1023, discription: 'In the case of an HTTP request, this field contains the URL accessed. The URL should contain the protocol as well. Example: “http://www/secure.com”'}, + 'requestClientApplication': {key: 'requestClient Application', type:'String', len:1023, discription: 'The User-Agent associated with the request.'}, + 'requestContext': {key: 'requestContext', type:'String', len:2048, discription: 'Description of the content from which the request originated (for example, HTTP Referrer)'}, + 'requestCookies': {key: 'requestCookies', type:'String', len:1023, discription: 'Cookies associated with the request.'}, + 'requestMethod': {key: 'requestMethod', type:'String', len:1023, discription: 'The method used to access a URL. Possible values: “POST”, “GET”, etc.'}, + 'deviceReceiptTime': {key: 'rt', type:'String', len:null, discription: 'The time at which the event related to the activity was received. The format is MMM dd yyyy HH:mm:ss or milliseconds since epoch (Jan 1st 1970)'}, + 'sourceHostName': {key: 'shost', type:'String', len:1023, discription: 'Identifies the source that an event refers to in an IP network. The format should be a fully qualified domain name (DQDN) associated with the source node, when a mode is available. Examples: “host” or “host.domain.com”.'}, + 'sourceMacAddress': {key: 'smac', type:'String', len:null, discription: 'Six colon-separated hexadecimal numbers. Example: “00:0D:60:AF:1B:61”'}, + 'sourceNtDomain': {key: 'sntdom', type:'String', len:255, discription: 'The Windows domain name for the source address.'}, + 'sourceDnsDomain': {key: 'sourceDns Domain', type:'String', len:255, discription: 'The DNS domain part of the complete fully qualified domain name (FQDN).'}, + 'sourceServiceName': {key: 'source ServiceName', type:'String', len:1023, discription: 'The service that is responsible for generating this event.'}, + 'sourceTranslatedAddress': {key: 'source Translated Address', type:'String', len:null, discription: 'Identifies the translated source that the event refers to in an IP network. The format is an IPv4 address. Example: “192.168.10.1”.'}, + 'sourceTranslatedPort': {key: 'source TranslatedPort', type:'Number', len:null, discription: 'A port number after being translated by, for example, a firewall. Valid port numbers are 0 to 65535.'}, + 'sourceProcessId': {key: 'spid', type:'Number', len:null, discription: 'The ID of the source process associated with the event.'}, + 'sourceUserPrivileges': {key: 'spriv', type:'String', len:1023, discription: 'The typical values are “Administrator”, “User”, and “Guest”. It identifies the source user’s privileges. In UNIX, for example, activity executed by the root user would be identified with “Administrator”.'}, + 'sourceProcessName': {key: 'sproc', type:'String', len:1023, discription: 'The name of the event’s source process.'}, + 'sourcePort': {key: 'spt', type:'Number', len:null, discription: 'The valid port numbers are 0 to 65535.'}, + 'sourceAddress': {key: 'src', type:'String', len:null, discription: 'Identifies the source that an event refers to in an IP network. The format is an IPv4 address. Example: “192.168.10.1”.'}, + 'startTime': {key: 'start', type:'String', len:null, discription: 'The time when the activity the event referred to started. The format is MMM dd yyyy HH:mm:ss or milliseconds since epoch (Jan 1st 1970)'}, + 'sourceUserId': {key: 'suid', type:'String', len:1023, discription: 'Identifies the source user by ID. This is the user associated with the source of the event. For example, in UNIX, the root user is generally associated with user ID 0.'}, + 'sourceUserName': {key: 'suser', type:'String', len:1023, discription: 'Identifies the source user by name. Email addresses are also mapped into the UserName fields. The sender is a candidate to put into this field.'}, + 'type': {key: 'type', type:'Number', len:null, discription: '0 means base event, 1 means aggregated, 2 means correlation, and 3 means action. This field can be omitted for base events (type 0).'}, + 'agentDnsDomain': {key: 'agentDns Domain', type:'String', len:255, discription: 'The DNS domain name of the ArcSight connector that processed the event.'}, + 'agentNtDomain': {key: 'agentNtDomain', type:'String', len:255, discription: ''}, + 'agentTranslatedAddress': {key: 'agentTranslated Address', type:'String', len:null, discription: ''}, + 'agentTranslatedZone ExternalID': {key: 'agentTranslated ZoneExternalID', type:'String', len:200, discription: ''}, + 'agentTranslatedZoneURI': {key: 'agentTranslated Zone URI', type:'String', len:2048, discription: ''}, + 'agentZoneExternalID': {key: 'agentZone ExternalID', type:'String', len:200, discription: ''}, + 'agentZoneURI': {key: 'agentZoneURI', type:'String', len:2048, discription: ''}, + 'agentAddress': {key: 'agt', type:'String', len:null, discription: 'The IP address of the ArcSight connector that processed the event.'}, + 'agentHostName': {key: 'ahost', type:'String', len:1023, discription: 'The hostname of the ArcSight connector that processed the event.'}, + 'agentId': {key: 'aid', type:'String', len:40, discription: 'The agent ID of the ArcSight connector that processed the event.'}, + 'agentMacAddress': {key: 'amac', type:'String', len:null, discription: 'The MAC address of the ArcSight connector that processed the event.'}, + 'agentReceiptTime': {key: 'art', type:'String', len:null, discription: 'The time at which information about the event was received by the ArcSight connector.'}, + 'agentType': {key: 'at', type:'String', len:63, discription: 'The agent type of the ArcSight connector that processed the event'}, + 'agentTimeZone': {key: 'atz', type:'String', len:255, discription: 'The agent time zone of the ArcSight connector that processed the event.'}, + 'agentVersion': {key: 'av', type:'String', len:31, discription: 'The version of the ArcSight connector that processed the event.'}, + 'customerExternalID': {key: 'customer ExternalID', type:'String', len:200, discription: ''}, + 'customerURI': {key: 'customerURI', type:'String', len:2048, discription: ''}, + 'destinationTranslated ZoneExternalID': {key: 'destination TranslatedZone ExternalID', type:'String', len:200, discription: ''}, + 'destinationTranslated ZoneURI': {key: 'destination Translated ZoneURI', type:'String', len:2048, discription: 'The URI for the Translated Zone that the destination asset has been assigned to in ArcSight.'}, + 'destinationZoneExternalID': {key: 'destinationZone ExternalID', type:'String', len:200, discription: ''}, + 'destinationZoneURI': {key: 'destinationZone URI', type:'String', len:2048, discription: 'The URI for the Zone that the destination asset has been assigned to in ArcSight.'}, + 'deviceTranslatedZone ExternalID': {key: 'device TranslatedZone ExternalID', type:'String', len:200, discription: ''}, + 'deviceTranslatedZoneURI': {key: 'device TranslatedZone URI', type:'String', len:2048, discription: 'The URI for the Translated Zone that the device asset has been assigned to in ArcSight.'}, + 'deviceZoneExternalID': {key: 'deviceZone ExternalID', type:'String', len:200, discription: ''}, + 'deviceZoneURI': {key: 'deviceZoneURI', type:'String', len:2048, discription: 'Thee URI for the Zone that the device asset has been assigned to in ArcSight.'}, + 'destinationGeoLatitude': {key: 'dlat', type:'Number', len:null, discription: 'The latitudinal value from which the destination’s IP address belongs.'}, + 'destinationGeoLongitude': {key: 'dlong', type:'Number', len:null, discription: 'The longitudinal value from which the destination’s IP address belongs.'}, + 'eventId': {key: 'eventId', type:'Number', len:null, discription: 'This is a unique ID that ArcSight assigns to each event.'}, + 'rawEvent': {key: 'rawEvent', type:'String', len:4000, discription: ''}, + 'sourceGeoLatitude': {key: 'slat', type:'Number', len:null, discription: ''}, + 'sourceGeoLongitude': {key: 'slong', type:'Number', len:null, discription: ''}, + 'sourceTranslatedZone ExternalID': {key: 'source TranslatedZone ExternalID', type:'String', len:200, discription: ''}, + 'sourceTranslatedZoneURI': {key: 'source TranslatedZone URI', type:'String', len:2048, discription: 'The URI for the Translated Zone that the destination asset has been assigned to in ArcSight.'}, + 'sourceZoneExternalID': {key: 'sourceZone ExternalID', type:'String', len:200, discription: ''}, + 'sourceZoneURI': {key: 'sourceZoneURI', type:'String', len:2048, discription: 'The URI for the Zone that the source asset has been assigned to in ArcSight.'}, + }; + if (typeof this.deviceVendor !== 'string' + || typeof this.deviceProduct !== 'string' + || typeof this.deviceVersion !== 'string' + ) { + reject(new Error('TYPE ERROR: CEF Device Info must be a string')); + } + if (this.severity + && ( + ( + typeof this.severity === 'string' + && ( + this.severity !== 'Unknown' + && this.severity !== 'Low' + && this.severity !== 'Medium' + && this.severity !== 'High' + && this.severity !== 'Very-High' + ) + ) + || ( + typeof this.severity === 'number' + && ( + this.severity < 0 + || this.severity > 10 + ) + ) + ) + ) { + reject(new Error('TYPE ERROR: CEF Severity not set correctly')); + } + const cefExts = Object.entries(this.extensions); + const cefExtsLen = cefExts.length; + for (let ext = 0; ext < cefExtsLen; ext++) { + if (cefExts[ext][1] !== null) { + if(Extensions[cefExts[ext][0]]) { + if (typeof cefExts[ext][1] === Extensions[cefExts[ext][0]] + .type + .toLowerCase()) { + if (Extensions[cefExts[ext][0]].len > 0 + && typeof cefExts[ext][1] === 'string' + && cefExts[ext][1].length > Extensions[cefExts[ext][0]].len){ + let errMsg = 'FORMAT ERROR:'; + errMsg += ' CEF Extention Key'; + errMsg += ' ' + cefExts[ext][0]; + errMsg += ' value length is to long;'; + errMsg += ' max length is'; + errMsg += ' ' + Extensions[cefExts[ext][0]].len; + reject(new Error(errMsg)); + } + } else { + let errMsg = 'TYPE ERROR:'; + errMsg += ' CEF Key'; + errMsg += ' ' + cefExts[ext][0]; + errMsg += ' value type was expected to be'; + errMsg += ' ' + Extensions[cefExts[ext][0]].type.toLowerCase(); + reject(new Error(errMsg)); + } + } + } + } + resolve(true); + }); + } + /** + * Build a CEF formated string + * @public + * @return {Promise} - String with formated message + */ + buildMessage () { + return new Promise((resolve, reject) => { + let fmtMsg = 'CEF:0'; + fmtMsg += '|' + this.deviceVendor; + fmtMsg += '|' + this.deviceProduct; + fmtMsg += '|' + this.deviceVersion; + fmtMsg += '|' + this.deviceEventClassId; + fmtMsg += '|' + this.name; + fmtMsg += '|' + this.severity; + fmtMsg += '|'; + + const cefExts = Object.entries(this.extensions); + const cefExtsLen = cefExts.length; + for (let ext = 0; ext < cefExtsLen; ext++) { + if (cefExts[ext][1] !== null) { + fmtMsg += cefExts[ext][0] + '=' + cefExts[ext][1] + ' '; + } + } + resolve(fmtMsg); + }); + } + /** + * @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 + */ + send (options) { + return new Promise((resolve, reject) => { + this.buildMessage() + .then((result) => { + if (!this.server) { + this.server = new Syslog(options); + } + this.server.send(result) + .then((sendResult) => { + resolve(sendResult); + }) + .catch((reson) => { + reject(reson); + }); + }); + }); + } +} + +module.exports = { + RgbToAnsi: rgbToAnsi, + RFC3164: RFC3164, + RFC5424:RFC5424, + LEEF: LEEF, + CEF: CEF, + Syslog: Syslog +}; + +``` + + + + diff --git a/docs/docco/docco.css b/docs/docco/docco.css new file mode 100644 index 0000000..b60f6fa --- /dev/null +++ b/docs/docco/docco.css @@ -0,0 +1,518 @@ +/*--------------------- Typography ----------------------------*/ + +@font-face { + font-family: 'aller-light'; + src: url('public/fonts/aller-light.eot'); + src: url('public/fonts/aller-light.eot?#iefix') format('embedded-opentype'), + url('public/fonts/aller-light.woff') format('woff'), + url('public/fonts/aller-light.ttf') format('truetype'); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'aller-bold'; + src: url('public/fonts/aller-bold.eot'); + src: url('public/fonts/aller-bold.eot?#iefix') format('embedded-opentype'), + url('public/fonts/aller-bold.woff') format('woff'), + url('public/fonts/aller-bold.ttf') format('truetype'); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'roboto-black'; + src: url('public/fonts/roboto-black.eot'); + src: url('public/fonts/roboto-black.eot?#iefix') format('embedded-opentype'), + url('public/fonts/roboto-black.woff') format('woff'), + url('public/fonts/roboto-black.ttf') format('truetype'); + font-weight: normal; + font-style: normal; +} + +/*--------------------- Layout ----------------------------*/ +html { height: 100%; } +body { + font-family: "aller-light"; + font-size: 14px; + line-height: 18px; + color: #30404f; + margin: 0; padding: 0; + height:100%; +} +#container { min-height: 100%; } + +a { + color: #000; +} + +b, strong { + font-weight: normal; + font-family: "aller-bold"; +} + +p { + margin: 15px 0 0px; +} + .annotation ul, .annotation ol { + margin: 25px 0; + } + .annotation ul li, .annotation ol li { + font-size: 14px; + line-height: 18px; + margin: 10px 0; + } + +h1, h2, h3, h4, h5, h6 { + color: #112233; + line-height: 1em; + font-weight: normal; + font-family: "roboto-black"; + text-transform: uppercase; + margin: 30px 0 15px 0; +} + +h1 { + margin-top: 40px; +} +h2 { + font-size: 1.26em; +} + +hr { + border: 0; + background: 1px #ddd; + height: 1px; + margin: 20px 0; +} + +pre, tt, code { + font-size: 12px; line-height: 16px; + font-family: Menlo, Monaco, Consolas, "Lucida Console", monospace; + margin: 0; padding: 0; +} + .annotation pre { + display: block; + margin: 0; + padding: 7px 10px; + background: #fcfcfc; + -moz-box-shadow: inset 0 0 10px rgba(0,0,0,0.1); + -webkit-box-shadow: inset 0 0 10px rgba(0,0,0,0.1); + box-shadow: inset 0 0 10px rgba(0,0,0,0.1); + overflow-x: auto; + } + .annotation pre code { + border: 0; + padding: 0; + background: transparent; + } + + +blockquote { + border-left: 5px solid #ccc; + margin: 0; + padding: 1px 0 1px 1em; +} + .sections blockquote p { + font-family: Menlo, Consolas, Monaco, monospace; + font-size: 12px; line-height: 16px; + color: #999; + margin: 10px 0 0; + white-space: pre-wrap; + } + +ul.sections { + list-style: none; + padding:0 0 5px 0;; + margin:0; +} + +/* + Force border-box so that % widths fit the parent + container without overlap because of margin/padding. + + More Info : http://www.quirksmode.org/css/box.html +*/ +ul.sections > li > div { + -moz-box-sizing: border-box; /* firefox */ + -ms-box-sizing: border-box; /* ie */ + -webkit-box-sizing: border-box; /* webkit */ + -khtml-box-sizing: border-box; /* konqueror */ + box-sizing: border-box; /* css3 */ +} + + +/*---------------------- Jump Page -----------------------------*/ +#jump_to, #jump_page { + margin: 0; + background: white; + -webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777; + -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px; + font: 16px Arial; + cursor: pointer; + text-align: right; + list-style: none; +} + +#jump_to a { + text-decoration: none; +} + +#jump_to a.large { + display: none; +} +#jump_to a.small { + font-size: 22px; + font-weight: bold; + color: #676767; +} + +#jump_to, #jump_wrapper { + position: fixed; + right: 0; top: 0; + padding: 10px 15px; + margin:0; +} + +#jump_wrapper { + display: none; + padding:0; +} + +#jump_to:hover #jump_wrapper { + display: block; +} + +#jump_page_wrapper{ + position: fixed; + right: 0; + top: 0; + bottom: 0; +} + +#jump_page { + padding: 5px 0 3px; + margin: 0 0 25px 25px; + max-height: 100%; + overflow: auto; +} + +#jump_page .source { + display: block; + padding: 15px; + text-decoration: none; + border-top: 1px solid #eee; +} + +#jump_page .source:hover { + background: #f5f5ff; +} + +#jump_page .source:first-child { +} + +/*---------------------- Low resolutions (> 320px) ---------------------*/ +@media only screen and (min-width: 320px) { + .pilwrap { display: none; } + + ul.sections > li > div { + display: block; + padding:5px 10px 0 10px; + } + + ul.sections > li > div.annotation ul, ul.sections > li > div.annotation ol { + padding-left: 30px; + } + + ul.sections > li > div.content { + overflow-x:auto; + -webkit-box-shadow: inset 0 0 5px #e5e5ee; + box-shadow: inset 0 0 5px #e5e5ee; + border: 1px solid #dedede; + margin:5px 10px 5px 10px; + padding-bottom: 5px; + } + + ul.sections > li > div.annotation pre { + margin: 7px 0 7px; + padding-left: 15px; + } + + ul.sections > li > div.annotation p tt, .annotation code { + background: #f8f8ff; + border: 1px solid #dedede; + font-size: 12px; + padding: 0 0.2em; + } +} + +/*---------------------- (> 481px) ---------------------*/ +@media only screen and (min-width: 481px) { + #container { + position: relative; + } + body { + background-color: #F5F5FF; + font-size: 15px; + line-height: 21px; + } + pre, tt, code { + line-height: 18px; + } + p, ul, ol { + margin: 0 0 15px; + } + + + #jump_to { + padding: 5px 10px; + } + #jump_wrapper { + padding: 0; + } + #jump_to, #jump_page { + font: 10px Arial; + text-transform: uppercase; + } + #jump_page .source { + padding: 5px 10px; + } + #jump_to a.large { + display: inline-block; + } + #jump_to a.small { + display: none; + } + + + + #background { + position: absolute; + top: 0; bottom: 0; + width: 350px; + background: #fff; + border-right: 1px solid #e5e5ee; + z-index: -1; + } + + ul.sections > li > div.annotation ul, ul.sections > li > div.annotation ol { + padding-left: 40px; + } + + ul.sections > li { + white-space: nowrap; + } + + ul.sections > li > div { + display: inline-block; + } + + ul.sections > li > div.annotation { + max-width: 350px; + min-width: 350px; + min-height: 5px; + padding: 13px; + overflow-x: hidden; + white-space: normal; + vertical-align: top; + text-align: left; + } + ul.sections > li > div.annotation pre { + margin: 15px 0 15px; + padding-left: 15px; + } + + ul.sections > li > div.content { + padding: 13px; + vertical-align: top; + border: none; + -webkit-box-shadow: none; + box-shadow: none; + } + + .pilwrap { + position: relative; + display: inline; + } + + .pilcrow { + font: 12px Arial; + text-decoration: none; + color: #454545; + position: absolute; + top: 3px; left: -20px; + padding: 1px 2px; + opacity: 0; + -webkit-transition: opacity 0.2s linear; + } + .for-h1 .pilcrow { + top: 47px; + } + .for-h2 .pilcrow, .for-h3 .pilcrow, .for-h4 .pilcrow { + top: 35px; + } + + ul.sections > li > div.annotation:hover .pilcrow { + opacity: 1; + } +} + +/*---------------------- (> 1025px) ---------------------*/ +@media only screen and (min-width: 1025px) { + + body { + font-size: 16px; + line-height: 24px; + } + + #background { + width: 525px; + } + ul.sections > li > div.annotation { + max-width: 525px; + min-width: 525px; + padding: 10px 25px 1px 50px; + } + ul.sections > li > div.content { + padding: 9px 15px 16px 25px; + } +} + +/*---------------------- Syntax Highlighting -----------------------------*/ + +td.linenos { background-color: #f0f0f0; padding-right: 10px; } +span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; } +/* + +github.com style (c) Vasily Polovnyov + +*/ + +pre code { + display: block; padding: 0.5em; + color: #000; + background: #f8f8ff +} + +pre .hljs-comment, +pre .hljs-template_comment, +pre .hljs-diff .hljs-header, +pre .hljs-javadoc { + color: #408080; + font-style: italic +} + +pre .hljs-keyword, +pre .hljs-assignment, +pre .hljs-literal, +pre .hljs-css .hljs-rule .hljs-keyword, +pre .hljs-winutils, +pre .hljs-javascript .hljs-title, +pre .hljs-lisp .hljs-title, +pre .hljs-subst { + color: #954121; + /*font-weight: bold*/ +} + +pre .hljs-number, +pre .hljs-hexcolor { + color: #40a070 +} + +pre .hljs-string, +pre .hljs-tag .hljs-value, +pre .hljs-phpdoc, +pre .hljs-tex .hljs-formula { + color: #219161; +} + +pre .hljs-title, +pre .hljs-id { + color: #19469D; +} +pre .hljs-params { + color: #00F; +} + +pre .hljs-javascript .hljs-title, +pre .hljs-lisp .hljs-title, +pre .hljs-subst { + font-weight: normal +} + +pre .hljs-class .hljs-title, +pre .hljs-haskell .hljs-label, +pre .hljs-tex .hljs-command { + color: #458; + font-weight: bold +} + +pre .hljs-tag, +pre .hljs-tag .hljs-title, +pre .hljs-rules .hljs-property, +pre .hljs-django .hljs-tag .hljs-keyword { + color: #000080; + font-weight: normal +} + +pre .hljs-attribute, +pre .hljs-variable, +pre .hljs-instancevar, +pre .hljs-lisp .hljs-body { + color: #008080 +} + +pre .hljs-regexp { + color: #B68 +} + +pre .hljs-class { + color: #458; + font-weight: bold +} + +pre .hljs-symbol, +pre .hljs-ruby .hljs-symbol .hljs-string, +pre .hljs-ruby .hljs-symbol .hljs-keyword, +pre .hljs-ruby .hljs-symbol .hljs-keymethods, +pre .hljs-lisp .hljs-keyword, +pre .hljs-tex .hljs-special, +pre .hljs-input_number { + color: #990073 +} + +pre .hljs-builtin, +pre .hljs-constructor, +pre .hljs-built_in, +pre .hljs-lisp .hljs-title { + color: #0086b3 +} + +pre .hljs-preprocessor, +pre .hljs-pi, +pre .hljs-doctype, +pre .hljs-shebang, +pre .hljs-cdata { + color: #999; + font-weight: bold +} + +pre .hljs-deletion { + background: #fdd +} + +pre .hljs-addition { + background: #dfd +} + +pre .hljs-diff .hljs-change { + background: #0086b3 +} + +pre .hljs-chunk { + color: #aaa +} + +pre .hljs-tex .hljs-formula { + opacity: 0.5; +} diff --git a/docs/docco/index.html b/docs/docco/index.html new file mode 100644 index 0000000..96292a4 --- /dev/null +++ b/docs/docco/index.html @@ -0,0 +1,2699 @@ + + + + + index.js + + + + + +
+
+ +
    + +
  • +
    +

    index.js

    +
    +
  • + + + +
  • +
    + +
    + +
    + +
    + +
    /** Copyright (c) 2018 Craig Yamato */
    +
    +/**
    + * @fileoverview The SyslogPro module for sending syslog messages
    + * Most APIs will return a promise. These APIs can be used using 
    + * `then(...)/catch(...)`
    + *
    + * Syslog formating classes can be used as input into a Syslog class to be used 
    + * simultatniusly to the same Syslog server.  The Syslog Class with a configured
    + * Syslog server target can also be used as the input into each of the formating 
    + * classes so that they may run independtly.
    + * @author Craig Yamato <craig@kentik.com>
    + * @copyright (c) 2018 - Craig Yamato
    + * @version 0.1.0
    + * @exports Syslog
    + * @exports LEEF
    + * @exports CEF
    + * @module SyslogPro
    + */
    +"use strict";
    +const moment = require('moment');
    +const os = require("os");
    +const dns = require('dns');
    +let dnsPromises = dns.promises;
    +const fs = require("fs");
    +
    +/**
    + * Format the ANSI foreground color code from a RGB hex code or ANSI color code
    + * @private
    + * @param {string} hex - The color hex code in the form of #FFFFFF or Number of
    + *     the ANSI color code (30-37 Standard & 0-255 Extended)
    + * @returns {Promise} - The formated ANSI color code
    + * @throws {Error} - A Format Error
    + */
    +function rgbToAnsi (hex, extendedColor) {
    +  return new Promise((resolve, reject) => {
    +    let colorCode = 0;  // Var to hold color code
    + +
  • + + +
  • +
    + +
    + +
    +

    Break HEX Code up into RGB

    + +
    + +
        const hexParts = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
    +    if (hexParts || typeof hex === 'number') {
    +      if (typeof hex === 'number') {
    +        if (extendedColor && hex < 256) {
    +          resolve(hex);
    +        } else if ((hex > 29 && hex < 38) || (hex > 89 && hex < 98)) {
    +          resolve(hex);
    +        } else {
    +          reject (new Error('FORMAT ERROR: Color code not in range')); 
    +        }
    +      } else {
    +        const r = parseInt(hexParts[1], 16);
    +        const g = parseInt(hexParts[2], 16);
    +        const b = parseInt(hexParts[3], 16);
    +        if (extendedColor) {
    +          if (r === g && g === b) {
    + +
  • + + +
  • +
    + +
    + +
    +

    Gray Scale Color

    + +
    + +
      	        if (r < 8) {
    +  		        colorCode = 16;
    +  	        } else if (r > 248) {
    +  		        colorCode = 231;
    +  	        } else {
    +  	          colorCode = Math.round(((r - 8) / 247) * 24) + 232;
    +  	        }
    +          } else {
    +            colorCode = 16
    +  	            + (36 * Math.round(r / 255 * 5))
    +  	            + (6 * Math.round(g / 255 * 5))
    +  	            + Math.round(b / 255 * 5);
    +          }
    +        } else {
    +          colorCode = 30;
    +          const red = r / 255;
    +          const green = g / 255;
    +          const blue = b / 255;
    +          let v = Math.max(red, green, blue) * 100;
    +          v = Math.round(v / 50);
    +          if (v === 1) {
    +            colorCode += ((Math.round(b / 255) << 2)
    +                | (Math.round(g / 255) << 1)
    +                | Math.round(r / 255));
    +          }
    +          if (v === 2) {
    +            colorCode += 60;
    +          }
    +        }
    +      }
    +      resolve(colorCode);
    +      return;
    +    } else {
    +      reject(new Error('TYPE ERROR: Not in RGB color hex or color code'));
    +      return;
    +    }
    +  });
    +}
    +
    +/**
    + * A class to work with syslog messages using UDP, TCP, or TLS transport.  
    + * There is suport for Syslog message formating RFC-3164, RFC-5424 including 
    + * Structured Data, IBM LEEF (Log Event Extended Format), and HP CEF (Common
    + * Event Format).
    + * Syslog formating classes can be used as input into a Syslog class to be used 
    + * simultatniusly to the same Syslog server. * 
    + * @requires moment
    + * @version 0.0.0
    + * @since 0.0.0
    + */
    +class Syslog {
    +  /**
    +   * Construct a new Syslog transport object with user options 
    +   * @public
    +   * @version 0.0.0
    +   * @since 0.0.0
    +   * @this Syslog
    +   * @param {object} [options] - Options object
    +   * >>>Transport Configuraton
    +   * @param {string} [options.target='localhost'] - The IP Address|FQDN of the 
    +   *    Syslog Server, this option if set will take prasdents over any target 
    +   *    set in a formating object
    +   * @param {string} [options.protocol='udp'] - L4 transport portocol 
    +   *    (udp|tcp|tls), this option if set will take prasdents over any transport 
    +   *    set in a formating object
    +   * @param {number} [options.port=514] - IP port, this option if set will take 
    +   *    prasdents over any IP Port set in a formating object
    +   * @param {number} [options.tcpTimeout=10000] - Ignored for all other 
    +   *    transports, this option if set will take prasdents over any timeout 
    +   *    set in a formating object
    +   * @param {string[]} [options.tlsServerCerts] - Array of authrized TLS server
    +   *    certificates file locations, this option if set will take prasdents 
    +   *    over any certificates set in a formating object
    +   * @param {string} [options.tlsClientCert] - Client TLS certificate file 
    +   *    location that this client should use, this option if set will take 
    +   *    prasdents over any certificates set in a formating object
    +   * @param {string} [options.tlsClientKey] - Client TLS key file 
    +   *    location that this client should use, this option if set will take 
    +   *    prasdents over any certificates set in a formating object
    +   * >>>Syslog Format Settings
    +   * @param {string} [options.format='none'] - Valid syslog format options for 
    +   *    this module are 'none', 'rfc3164', 'rfc5424', 'leef', 'cef'
    +   * @param {RFC3164} [options.rfc5424] - {@link module:SyslogPro~RFC5424|
    +   *    RFC5424 related settings}
    +   * @param {RFC5424} [options.rfc5424] - {@link module:SyslogPro~RFC5424|
    +   *    RFC5424 related settings}
    +   * @param {LEEF} [options.leef] - {@link module:SyslogPro~LEEF|IBM LEEF 
    +   *    (Log Event Extended Format) object} 
    +   * @param {CEF} [options.cef] - {@link module:SyslogPro~CEF|HP CEF 
    +   *    (Common Event Format) formating object} 
    +   */
    +  constructor (options) {
    +    this.constructor__ = true;
    +    if (!options) {
    +      options = {};
    +    }
    + +
  • + + +
  • +
    + +
    + +
    +

    Basic transport setup

    + +
    + +
        /** @type {string} */
    +    this.target = options.target || 'localhost';
    +    /** @type {string} */
    +    this.protocol = options.protocol || 'udp';
    +    this.protocol = this.protocol.toLowerCase();
    +    /** @type {number} */
    +    this.port = options.port || 514;
    +    /** @type {number} */
    +    this.tcpTimeout = options.tcpTimeout || 10000;
    +    if ((typeof options.tlsServerCerts === 'object' 
    +        && Array.isArray(options.tlsServerCerts))
    +        || typeof options.tlsServerCerts === 'string') {
    +      this.addTlsServerCerts(options.tlsServerCerts);  
    +    } else {
    +      /** @type {string[]} */
    +      this.tlsServerCerts = [];
    +    }
    +    if (options.tlsClientCert) {
    +      /** @type {string} */
    +      this.tlsClientCert = options.tlsClientCert; 
    +    }
    +    if (options.tlsClientKey) {
    +      /** @type {string} */
    +      this.tlsClientKey = options.tlsClientKey; 
    +    }
    + +
  • + + +
  • +
    + +
    + +
    +

    Syslog Format

    + +
    + +
        if (typeof options.format === 'string') {
    +      /** @type {string} */
    +      this.format = options.format.toLowerCase();
    +    } else {
    +      this.format = options.format || 'none';
    +    }
    +    if (options.rfc3164) {
    +      if (options.rfc3164.constructor__) {
    +        /** @type {RFC3164} */
    +        this.rfc3164 = options.rfc3164;
    +      } else {
    +        this.rfc3164 = new RFC3164(options);
    +      }
    +    }
    +    if (options.rfc5424) {
    +      if (options.rfc5424.constructor__) {
    +        /** @type {RFC5424} */
    +        this.rfc5424 = options.rfc5424;
    +      } else {
    +        this.rfc5424 = new RFC5424(options);
    +      }
    +    }
    +    if (options.leef) {
    +      if (options.leef.constructor__) {
    +        /** @type {LEEF} */
    +        this.leef = options.leef;
    +      } else {
    +        this.leef = new LEEF(options);
    +      }
    +    }
    +    if (options.cef) {
    +      if (options.cef.constructor__) {
    +        /** @type {CEF} */
    +        this.cef = options.cef;
    +      } else {
    +        this.cef = new CEF(options);
    +      }
    +    }
    +    if (this.format === 'rfc3164' && !this.rfc3164) {
    +      this.rfc3164 = new RFC3164();
    +    }
    +    if (this.format === 'rfc5424' && !this.rfc5424) {
    +      this.rfc5424 = new RFC5424();
    +    }
    +    if (this.format === 'leef' && !this.leef) {
    +      this.leef = new LEEF();
    +    }
    +    if (this.format === 'cef' && !this.cef) {
    +      this.cef = new CEF();
    +    }
    +  }
    +  
    +  /**
    +   * Add a TLS server certificate which can be used to authentacat the server 
    +   * this syslog client is connecting too.  This function will valadate the
    +   * input as a file location straing and add it to an array of certificates
    +   * @private
    +   * @version 0.0.0
    +   * @since 0.0.0
    +   * @param {string|string[]} certs - File location of the certificate(s)
    +   * @returns {Promise} - True
    +   * @throws {Error} - A Type Error
    +   */
    +  addTlsServerCerts (certs) {
    +    return new Promise((resolve, reject) => {
    +      if (typeof certs === 'object' && Array.isArray(certs)) {
    +        /** @private @type {string[]} */
    +        this.tlsServerCerts = certs;
    +      } else if (typeof certs === 'string') {
    +        this.tlsServerCerts = [certs];
    +      } else {
    +        let errMsg = 'TYPE ERROR: Server Cert file loctions shoudl be a string';
    +        errMsg += ' or array of strings';
    +        reject(new Error(errMsg));
    +      }
    +      resolve(true);
    +    });
    +  }
    +  /**
    +   * Send the Syslog message over UDP
    +   * @private
    +   * @param {string} msg - The formated Syslog Message
    +   * @returns {Promise} - The Syslog formated string sent
    +   * @throws {Error} - Network Error
    +   */
    +  udpMessage (msg) {
    +    return new Promise((resolve, reject) => {
    +      const dgram = require('dgram');// Test for target DNS and Address Family (IPv4/6) by looking up the DNS
    +      const dnsOptions = {
    +        verbatim: true
    +      };
    +      dnsPromises.lookup(this.target, dnsOptions)
    +          .then((result) => {
    +            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');
    +            client.send(msgBuffer, this.port, this.target, (error) => {
    +              client.close();
    +              resolve(msg);
    +            });
    +          })
    +          .catch((error) => {
    +            reject(error); // Reject out of the sendMessage function promise
    +          });
    +    });
    +  }
    +  /**
    +   * Send the Syslog message over TCP
    +   * @private
    +   * @param {string} msg - The formated Syslog Message
    +   * @returns {Promise} - The Syslog formated string sent
    +   * @throws {Error} - Timeout error for TCP and TLS connections
    +   * @throws {Error} - Network Error
    +   */
    +  tcpMessage (msg) {
    +    return new Promise((resolve, reject) => {
    +      const net = require('net');
    +      const dnsOptions = {
    +        verbatim: true
    +      };
    +      dnsPromises.lookup(this.target, dnsOptions)
    +          .then((result) => {
    +            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);
    +            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();
    +              reject(error);
    +            });
    +          })
    +          .catch((error) => {
    +            reject(error);
    +          });
    +    });
    +  }
    +  /**
    +   * Send the Syslog message over TLS
    +   * @private
    +   * @param {string} msg - The formated Syslog Message
    +   * @returns {Promise} - The Syslog formated string sent
    +   * @throws {Error} - Timeout error for TCP and TLS connections
    +   * @throws {Error} - Network Error
    +   */
    +  tlsMessage (msg) {
    +    return new Promise((resolve, reject) => {
    +      const tls = require('tls');
    +      const tlsOptions = {
    +        host: this.target,
    +        port: this.port,
    +      };
    + +
  • + + +
  • +
    + +
    + +
    +

    Load client cert and key if requested

    + +
    + +
          if (typeof this.tlsClientKey === 'string' 
    +          && typeof this.tlsClientCert === 'string') {
    +        tlsOptions.key = fs.readFileSync(this.tlsClientKey);
    +        tlsOptions.cert = fs.readFileSync(this.tlsClientCert);      
    +      } else if (typeof this.tlsClientKey !== 'string' 
    +          && typeof this.tlsClientKey !== 'undefined') {
    +        let errMsg = 'TYPE ERROR: TLS Client Key is not a file';
    +        errMsg += 'location string';
    +        reject(new Error(errMsg));
    +        return;
    +      } else if (typeof this.tlsClientCert !== 'string' 
    +          && typeof this.tlsClientCert !== 'undefined') {
    +        let errMsg = 'TYPE ERROR: TLS Client Cert is not a file';
    +        errMsg += 'location string';
    +        reject(new Error(errMsg));
    +        return;
    +      }
    + +
  • + + +
  • +
    + +
    + +
    +

    Load any server certs if provided

    + +
    + +
          let tlsCerts = this.tlsServerCerts.length;
    +      if (tlsCerts > 0) {
    +        let tlsOptionsCerts = [];
    +        for (let certIndex=0; certIndex<tlsCerts; certIndex++) {
    +          if (typeof this.tlsServerCerts[certIndex] !== 'string') {
    +            let errMsg = 'TYPE ERROR: TLS Server Cert is not a file';
    +            errMsg += 'location string';
    +            reject(new Error(errMsg));
    +          }
    +          let cert = fs.readFileSync(this.tlsServerCerts[certIndex]);
    +          tlsOptionsCerts.push(cert);
    +        }
    +        tlsOptions.ca = tlsOptionsCerts;
    +        tlsOptions.rejectUnauthorized = true;
    +      }
    +      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);
    + +
  • + + +
  • +
    + +
    + +
    +

    client.on(‘data’, (data) => {});

    + +
    + +
          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();
    +        reject(error);
    +      });   
    +    });
    +  }
    +  /**
    +   * Send the Syslog message to the selected target Syslog server using the 
    +   * selected transport.
    +   * @private
    +   * @param {string} msg - The formated Syslog Message
    +   * @returns {Promise} - The Syslog formated string sent
    +   * @throws {Error} - Timeout error for TCP and TLS connections
    +   * @throws {Error} - Network Error
    +   */
    +  send (msg) {
    +    return new Promise((resolve, reject) => {
    +      if (typeof msg !== 'string') {
    +        reject(new Error("TYPE ERROR: Syslog message must be a string"));
    +        return;
    +      }
    +      this.protocol = this.protocol.toLowerCase();
    +      if (this.protocol === 'udp') {
    +        this.udpMessage(msg)
    +            .then((result) => {
    +              resolve(result);
    +            })
    +            .catch((reson) => {
    +              reject(reson);
    +            });
    +      } else if (this.protocol === 'tcp') {
    +        this.tcpMessage(msg)
    +            .then((result) => {
    +              resolve(result);
    +            })
    +            .catch((reson) => {
    +              reject(reson);
    +            });
    +      } else if (this.protocol === 'tls') {
    +        this.tlsMessage(msg)
    +            .then((result) => {
    +              resolve(result);
    +            })
    +            .catch((reson) => {
    +              reject(reson);
    +            });
    +      } else {
    +        let errorMsg = 'FORMAT ERROR: Protocol not reconized, should be ';
    +        errorMsg += 'udp|tcp|tls';
    +        reject(new Error(errorMsg));
    +      }
    +    });
    +  }
    +}
    + 
    +/**
    + * A class to work with RFC3164 formated syslog messages. The meesaging is fully configurabule and Ansi foreground 
    + * colors can be added.  Both ANSI 8 and ANSI 256 color are fully suported.
    + * Most APIs will return a promise. These APIs can be used using 
    + * `then(...)/catch(...)`
    + * 
    + * A Syslog class with a configured
    + * Syslog server target can also be used as the input into the formating 
    + * classes so that it may run independtly.
    + * 
    + * The RFC3164 Syslog logging format is ment to be used as a stream of log data 
    + * from a service or applacation. This class is designed to be used in this
    + * fashion where new messages are writen to the class as needed.
    + * @requires moment
    + * @version 0.0.0
    + * @since 0.0.0
    + */
    +class RFC3164 {
    +  /**
    +   * Construct a new RFC3164 formated Syslog object with user options 
    +   * @public
    +   * @this RFC3164
    +   * @param {object} [options] - Options object
    +   * @param {string} [options.applacationName='NodeJSLogger'] - Applacation
    +   * @param {string} [options.hostname=os.hostname] - The name of this server
    +   * @param {number} [options.facility=23] - Facility code to use sending this 
    +   *    message 
    +   * @param {boolean} [options.color=false] - Apply color coding encoding tag 
    +   *    with syslog message text 
    +   * @param {boolean} [options.extendedColor=false] - Use the extedned ANSI 
    +   *    color set encoding tag with syslog message text 
    +   * @param {object} [options.colors] - User defended colors for 
    +   *    severites
    +   * @param {string} [options.colors.emergencyColor] - A RGB Hex coded color in the form 
    +   *    of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 
    +   *    Extended)
    +   * @param {string} [options.colors.alertColor] - A RGB Hex coded color in the form 
    +   *    of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 
    +   *    Extended)
    +   * @param {string} [options.colors.criticalColor] - A RGB Hex coded color in the form 
    +   *    of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 
    +   *    Extended)
    +   * @param {string} [options.colors.errorColor] - A RGB Hex coded color in the form 
    +   *    of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 
    +   *    Extended)
    +   * @param {string} [options.colors.warningColor] - A RGB Hex coded color in the form 
    +   *    of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 
    +   *    Extended)
    +   * @param {string} [options.colors.noticeColor] - A RGB Hex coded color in the form 
    +   *    of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 
    +   *    Extended)
    +   * @param {string} [options.colors.informationalColor] - A RGB Hex coded color in the form 
    +   *    of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 
    +   *    Extended)
    +   * @param {string} [options.colors.debugColor] - A RGB Hex coded color in the form 
    +   *    of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 
    +   *    Extended)
    +   * @param {Syslog} [options.server=false] - A {@link module:SyslogPro~Syslog|
    +   *    Syslog server connection} that should be used to send messages directly 
    +   *    from this class. @see SyslogPro~Syslog
    +   */
    +  constructor (options) {
    +    /** @private @type {boolean} */
    +    this.constructor__ = true;
    +    options = options || {};
    +    this.hostname = options.hostname || os.hostname();
    +    this.applacationName = options.applacationName || '';
    +    this.facility = options.facility || 23;
    +    if (options.color) {
    +      /** @type {boolean} */
    +      this.color = true;
    +    } else {
    +      this.color = false;
    +    }
    +    if (options.extendedColor) {
    +      /** @type {boolean} */
    +      this.extendedColor = true;
    +    } else {
    +      this.extendedColor = false;
    +    }
    +    if (options.server) {
    +      if (!options.server.constructor__) {
    +        /** @private @type {Syslog} */
    +        this.server = new Syslog(options.server);
    +      } else {
    +        this.server = options.server;
    +      }
    +    }
    +    if (this.extendedColor) {
    +      /** @private @type {number} */
    +      this.emergencyColor = 1; // Red foreground color
    +      /** @private @type {number} */
    +      this.alertColor = 202; // Dark Orange foreground color
    +      /** @private @type {number} */
    +      this.criticalColor = 208; // Orange foreground color
    +      /** @private @type {number} */
    +      this.errorColor = 178; // Light Orange foreground color
    +      /** @private @type {number} */
    +      this.warningColor = 226; // Yellow foreground color
    +      /** @private @type {number} */
    +      this.noticeColor = 117; // Light Blue foreground color
    +      /** @private @type {number} */
    +      this.informationalColor = 45; // Blue foreground color
    +      /** @private @type {number} */
    +      this.debugColor = 27; // Dark Blue foreground color
    +    } else {
    +      this.emergencyColor = 31; // Red foreground color
    +      this.alertColor = 31; // Red foreground color
    +      this.criticalColor = 31; // Red foreground color
    +      this.errorColor = 33; // Yellow foreground color
    +      this.warningColor = 33; // Yellow foreground color
    +      this.noticeColor = 36; // Blue foreground color
    +      this.informationalColor = 36; // Blue foreground color
    +      this.debugColor = 34; // Dark Blue foreground color
    +    }
    +    if (typeof options.colors === 'object') {
    +      this.setColor(options.colors, this.extendedColor);
    +    }
    +  }
    +  /**
    +   * Sets the color to be used for messages at a set priority
    +   * @public   
    +   * @param {string} [colors.emergencyColor] - A RGB Hex coded color in the form 
    +   *    of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 
    +   *    Extended)
    +   * @param {string} [colors.alertColor] - A RGB Hex coded color in the form 
    +   *    of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 
    +   *    Extended)
    +   * @param {string} [colors.criticalColor] - A RGB Hex coded color in the form 
    +   *    of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 
    +   *    Extended)
    +   * @param {string} [colors.errorColor] - A RGB Hex coded color in the form 
    +   *    of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 
    +   *    Extended)
    +   * @param {string} [colors.warningColor] - A RGB Hex coded color in the form 
    +   *    of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 
    +   *    Extended)
    +   * @param {string} [colors.noticeColor] - A RGB Hex coded color in the form 
    +   *    of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 
    +   *    Extended)
    +   * @param {string} [colors.informationalColor] - A RGB Hex coded color in the form 
    +   *    of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 
    +   *    Extended)
    +   * @param {string} [colors.debugColor] - A RGB Hex coded color in the form 
    +   *    of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 
    +   *    Extended)
    +   * @throws {Error} A standard error object
    +   */
    +  setColor (colors, extendedColor) {
    +    return new Promise((resolve, reject) => {
    +      let colorPromises = [];
    +      if (colors.emergencyColor) {
    +        colorPromises.push(
    +            new Promise((resolve,reject) => {
    +              rgbToAnsi(colors.emergencyColor, this.extendedColor)
    +                  .then((result) => {
    +                    this.emergencyColor = result;
    +                    resolve(true);
    +                  })
    +                  .catch((reson) => {
    +                    reson.message = 'TYPE ERROR: '; 
    +                    reson.message += 'emergencyColor';
    +                    reson.message += ' Not in RGB color hex or color code';
    +                    reject(reson);
    +                  });
    +        }));
    +      }
    +      if (colors.alertColor) {
    +        colorPromises.push(
    +            new Promise((resolve,reject) => {
    +              rgbToAnsi(colors.alertColor, this.extendedColor)
    +                  .then((result) => {
    +                    this.alertColor = result;
    +                    resolve(true);
    +                  })
    +                  .catch((reson) => {
    +                    reson.message = 'TYPE ERROR: '; 
    +                    reson.message += 'alertColor';
    +                    reson.message += ' Not in RGB color hex or color code';
    +                    reject(reson);
    +                  });
    +        }));
    +      }
    +      if (colors.criticalColor) {
    +        colorPromises.push(
    +            new Promise((resolve,reject) => {
    +              rgbToAnsi(colors.criticalColor, this.extendedColor)
    +                  .then((result) => {
    +                    this.criticalColor = result;
    +                    resolve(true);
    +                  })
    +                  .catch((reson) => {
    +                    reson.message = 'TYPE ERROR: '; 
    +                    reson.message += 'criticalColor';
    +                    reson.message += ' Not in RGB color hex or color code';
    +                    reject(reson);
    +                  });
    +        }));
    +      }
    +      if (colors.errorColor) {
    +        colorPromises.push(
    +            new Promise((resolve,reject) => {
    +              rgbToAnsi(colors.errorColor, this.extendedColor)
    +                  .then((result) => {
    +                    this.errorColor = result;
    +                    resolve(true);
    +                  })
    +                  .catch((reson) => {
    +                    reson.message = 'TYPE ERROR: '; 
    +                    reson.message += 'errorColor';
    +                    reson.message += ' Not in RGB color hex or color code';
    +                    reject(reson);
    +                  });
    +        }));
    +      }
    +      if (colors.warningColor) {
    +        colorPromises.push(
    +            new Promise((resolve,reject) => {
    +              rgbToAnsi(colors.warningColor, this.extendedColor)
    +                  .then((result) => {
    +                    this.warningColor = result;
    +                    resolve(true);
    +                  })
    +                  .catch((reson) => {
    +                    reson.message = 'TYPE ERROR: '; 
    +                    reson.message += 'warningColor';
    +                    reson.message += ' Not in RGB color hex or color code';
    +                    reject(reson);
    +                  });
    +        }));
    +      }
    +      if (colors.noticeColor) {
    +        colorPromises.push(
    +            new Promise((resolve,reject) => {
    +              rgbToAnsi(colors.noticeColor, this.extendedColor)
    +                  .then((result) => {
    +                    this.noticeColor = result;
    +                    resolve(true);
    +                  })
    +                  .catch((reson) => {
    +                    reson.message = 'TYPE ERROR: '; 
    +                    reson.message += 'noticeColor';
    +                    reson.message += ' Not in RGB color hex or color code';
    +                    reject(reson);
    +                  });
    +        }));
    +      }
    +      if (colors.informationalColor) {
    +        colorPromises.push(
    +            new Promise((resolve,reject) => {
    +              rgbToAnsi(colors.informationalColor, this.extendedColor)
    +                  .then((result) => {
    +                    this.informationalColor = result;
    +                    resolve(true);
    +                  })
    +                  .catch((reson) => {
    +                    reson.message = 'TYPE ERROR: '; 
    +                    reson.message += 'informationalColor';
    +                    reson.message += ' Not in RGB color hex or color code';
    +                    reject(reson);
    +                  });
    +        }));
    +      }
    +      if (colors.debugColor) {
    +        colorPromises.push(
    +            new Promise((resolve,reject) => {
    +              rgbToAnsi(colors.debugColor, this.extendedColor)
    +                  .then((result) => {
    +                    this.debugColor = result;
    +                    resolve(true);
    +                  })
    +                  .catch((reson) => {
    +                    reson.message = 'TYPE ERROR: '; 
    +                    reson.message += 'debugColor';
    +                    reson.message += ' Not in RGB color hex or color code';
    +                    reject(reson);
    +                  });
    +        }));
    +      }
    +      Promise.all(colorPromises)
    +          .then((results) => {
    +            resolve(true);
    +          })
    +          .catch((reson) => {
    +            reject(reson);
    +          });
    +    });
    +  }
    +  /**
    +   * Building a formated message.  Returns a promise with a formated message 
    +   * @public
    +   * @param {string} msg - The Syslog Message
    +   * @param {object} [options] - Options object
    +   * @param {number} [options.severity=7] - An array of structure 
    +   * @param {number} [options.colorCode=36] - The ANSI color code to use if 
    +   *    message coloration is selected
    +   * @returns {Promise} A Syslog formated string acording to the selected RFC
    +   * @throws {Error} A standard error object
    +   */
    +  buildMessage (msg, options) {
    +    return new Promise((resolve, reject) => {
    +      options = options || {};
    +      let severity = typeof options.severity === 'number' ? 
    +          options.severity : 6;
    +      if (typeof msg !== 'string' || options.msgSeverity > 7) {
    +        let errMsg = 'FORMAT ERROR: Syslog message must be a string';
    +        errMsg += ' msgSeverity must be a number between 0 and 7';
    +        reject(new Error(errMsg));
    +        return;
    +      }
    +      let fmtMsg = ''; // Formated Syslog message string var
    +      const newLine = '\n';
    +      const newLineRegEx = /(\r|\n|(\r\n))/;
    +      const escapeCode = '\u001B';
    +      const resetColor = '\u001B[0m';
    + +
  • + + +
  • +
    + +
    + +
    +

    The PRI is common to both RFC formats

    + +
    + +
          const pri = (this.facility * 8) + severity;
    + +
  • + + +
  • +
    + +
    + +
    +

    Remove any newline character

    + +
    + +
          msg = msg.replace(newLineRegEx, '');
    + +
  • + + +
  • +
    + +
    + +
    +

    Add requested color

    + +
    + +
          if (this.color) {
    +        options.msgColor = options.msgColor || 36;
    +        let colorCode = '[';
    +        if (this.extendedColor) {
    +          colorCode += '38;5;'; // Extended 256 Colors ANSI Code
    +        }
    +        if (typeof options.msgColor === 'number') {
    +          colorCode += options.msgColor;
    +          colorCode += 'm'; // ANSI Color Closer
    +        } else {
    +          colorCode = '[39m';  // Use terminal's defualt color
    +        }
    +        msg = escapeCode + colorCode + msg + resetColor;
    +      }
    + +
  • + + +
  • +
    + +
    + +
    +

    RegEx to find a leading 0 in the day of a DateTime for RFC3164 +RFC3164 uses BSD timeformat

    + +
    + +
          const rfc3164DateRegEx = /((A|D|F|J|M|N|O|S)(a|c|e|p|o|u)(b|c|g|l|n|p|r|t|v|y)\s)0(\d\s\d\d:\d\d:\d\d)/;
    +      const timestamp = moment()
    +          .format('MMM DD hh:mm:ss')
    +          .replace(rfc3164DateRegEx, '$1 $5');
    + +
  • + + +
  • +
    + +
    + +
    +

    Build message

    + +
    + +
          fmtMsg = '<' + pri + '>';
    +      fmtMsg += timestamp;
    +      fmtMsg += ' ' + this.hostname;
    +      fmtMsg += ' ' + this.applacationName;
    +      fmtMsg += ' ' + msg;
    +      fmtMsg += newLine;
    +      resolve(fmtMsg);
    +    });
    +  }
    +  /**
    +   * send a RFC5424 formated message.  Returns a promise with the formated 
    +   *    message that was sent.  If no server connection was defined when the 
    +   *    class was created a defualt Syslog connector will be used.  
    +   *    @see SyslogPro~Syslog
    +   * @public
    +   * @param {string} msg - The unformated Syslog message to send
    +   * @param {object} [options] - Options object
    +   * @param {number} [options.severity=7] - An array of structure 
    +   * @param {number} [options.colorCode=36] - The ANSI color code to use if 
    +   * @returns {Promise} A Syslog formated string acording to the selected RFC
    +   * @throws {Error} A standard error object
    +   */
    +  send (msg, options) {
    +    return new Promise((resolve, reject) => {
    +      if (!this.server) {
    +        this.server = new Syslog();
    +      }
    +      this.buildMessage(msg, options)
    +        .then((result) => {
    +          this.server.send(result)
    +            .then((sendResult) => {
    +              resolve(sendResult);
    +            })
    +            .catch((error) => {
    +              reject(error);
    +            });
    +        })
    +        .catch((error) => {
    +          reject(error);
    +        });
    +    });
    +  } 
    +  /**
    +   * Send a syslog message with a secerity level of 0 (Emergency)
    +   * @public
    +   * @param {string} msg - The emergancy message to send to the Syslog server
    +   * @returns {Promise} - The formated syslog message sent to the Syslog server
    +   * @throws {Error} - Any bubbled up error
    +   */
    +  emergency (msg) {
    +    return this.send(msg, {
    +      severity: 0, 
    +      colorCode: this.emergencyColor
    +    });
    +  }
    +  /**
    +   * Send a syslog message with a secerity level of 0 (Emergency)
    +   * @public
    +   * @param {string} msg - The emergancy message to send to the Syslog server
    +   * @returns {Promise} - The formated syslog message sent to the Syslog server
    +   * @throws {Error} - Any bubbled up error
    +   */
    +  emer (msg) {
    +    return this.emergency(msg);
    +  }
    +  /**
    +   * Send a syslog message with a secerity level of 1 (Alert)
    +   * @public
    +   * @param {string} msg - The alert message to send to the Syslog server
    +   * @returns {Promise} - The formated syslog message sent to the Syslog server
    +   * @throws {Error} - Any bubbled up error
    +   */
    +  alert (msg) {
    +    return this.send(msg, {
    +      severity: 1, 
    +      colorCode: this.alertColor
    +    });
    +  }
    +  /**
    +   * Send a syslog message with a secerity level of 2 (Critical)
    +   * @public
    +   * @param {string} msg - The critical message to send to the Syslog server
    +   * @returns {Promise} - The formated syslog message sent to the Syslog server
    +   * @throws {Error} - Any bubbled up error
    +   */
    +  critical (msg) {
    +    return this.send(msg, {
    +      severity: 2, 
    +      colorCode: this.criticalColor
    +    });
    +  }
    +  /**
    +   * Send a syslog message with a secerity level of 2 (Critical)
    +   * @public
    +   * @param {string} msg - The critical message to send to the Syslog server
    +   * @returns {Promise} - The formated syslog message sent to the Syslog server
    +   * @throws {Error} - Any bubbled up error
    +   */
    +  crit (msg) {
    +    return this.critical(msg);
    +  }
    +  /**
    +   * Send a syslog message with a secerity level of 3 (Error)
    +   * @public
    +   * @param {string} msg - The error message to send to the Syslog server
    +   * @returns {Promise} - The formated syslog message sent to the Syslog server
    +   * @throws {Error} - Any bubbled up error
    +   */
    +  error (msg) {
    +    return this.send(msg, {
    +      severity: 3, 
    +      colorCode: this.errorColor
    +    });
    +  }
    +  /**
    +   * Send a syslog message with a secerity level of 3 (Error)
    +   * @public
    +   * @param {string} msg - The error message to send to the Syslog server
    +   * @returns {Promise} - The formated syslog message sent to the Syslog server
    +   * @throws {Error} - Any bubbled up error
    +   */
    +  err (msg) {
    +    return this.error(msg);
    +  }
    +  /**
    +   * Send a syslog message with a secerity level of 4 (Warning)
    +   * @public
    +   * @param {string} msg - The warning message to send to the Syslog server
    +   * @returns {Promise} - The formated syslog message sent to the Syslog server
    +   * @throws {Error} - Any bubbled up error
    +   */
    +  warning (msg) {
    +    return this.send(msg, {
    +      severity: 4, 
    +      colorCode: this.warningColor
    +    });
    +  }
    +  /**
    +   * Send a syslog message with a secerity level of 4 (Warning)
    +   * @public
    +   * @param {string} msg - The warning message to send to the Syslog server
    +   * @returns {Promise} - The formated syslog message sent to the Syslog server
    +   * @throws {Error} - Any bubbled up error
    +   */
    +  warn (msg) {
    +    return this.warning(msg);
    +  }
    +  /**
    +   * Send a syslog message with a secerity level of 5 (Notice)
    +   * @public
    +   * @param {string} msg - The notice message to send to the Syslog server
    +   * @returns {Promise} - The formated syslog message sent to the Syslog server
    +   * @throws {Error} - Any bubbled up error
    +   */
    +  notice (msg) {
    +    return this.send(msg, {
    +      severity: 5, 
    +      colorCode: this.noticeColor
    +    });
    +  }
    +  /**
    +   * Send a syslog message with a secerity level of 5 (Notice)
    +   * @public
    +   * @param {string} msg - The notice message to send to the Syslog server
    +   * @returns {Promise} - The formated syslog message sent to the Syslog server
    +   * @throws {Error} - Any bubbled up error
    +   */
    +  note (msg) {
    +    return this.notice(msg);
    +  }
    +  /**
    +   * Send a syslog message with a secerity level of 6 (Informational)
    +   * @public
    +   * @param {string} msg - The informational message to send to the Syslog server
    +   * @returns {Promise} - The formated syslog message sent to the Syslog server
    +   * @throws {Error} - Any bubbled up error
    +   */
    +  informational (msg) {
    +    return this.send(msg, {
    +      severity: 6, 
    +      colorCode: this.informationalColor
    +    });
    +  }
    +  /**
    +   * Send a syslog message with a secerity level of 6 (Informational)
    +   * @public
    +   * @param {string} msg - The informational message to send to the Syslog server
    +   * @returns {Promise} - The formated syslog message sent to the Syslog server
    +   * @throws {Error} - Any bubbled up error
    +   */
    +  info (msg) {
    +    return this.informational(msg);
    +  }
    +  /**
    +   * Send a syslog message with a secerity level of 6 (Informational)
    +   * @public
    +   * @param {string} msg - The informational message to send to the Syslog server
    +   * @returns {Promise} - The formated syslog message sent to the Syslog server
    +   * @throws {Error} - Any bubbled up error
    +   */
    +  log (msg) {
    +    return this.informational(msg);
    +  }
    +  /**
    +   * Send a syslog message with a secerity level of 7 (Debug)
    +   * @public
    +   * @param {string} msg - The debug message to send to the Syslog server
    +   * @returns {Promise} - The formated syslog message sent to the Syslog server
    +   * @throws {Error} - Any bubbled up error
    +   */
    +  debug (msg) {
    +    return this.send(msg, {
    +      severity: 7, 
    +      colorCode: this.debugColor
    +    });
    +  }
    +}
    +
    +/**
    + * A class to work with RFC5424 formated syslog messages. The meesaging is fully configurabule and Ansi foreground 
    + * colors can be added.  Both ANSI 8 and ANSI 256 color are fully suported.
    + * Most APIs will return a promise. These APIs can be used using 
    + * `then(...)/catch(...)`
    + * 
    + * A Syslog class with a configured
    + * Syslog server target can also be used as the input into the formating 
    + * classes so that it may run independtly.
    + * 
    + * The RFC5424 Syslog logging format is ment to be used as a stream of log data 
    + * from a service or applacation. This class is designed to be used in this
    + * fashion where new messages are writen to the class as needed.
    + * @requires moment
    + * @version 0.0.0
    + * @since 0.0.0
    + */
    +class RFC5424 {
    +  /**
    +   * Construct a new RFC5424 formated Syslog object with user options 
    +   * @public
    +   * @this RFC5424
    +   * @param {object} [options] - Options object
    +   * @param {string} [options.applacationName='NodeJSLogger'] - Applacation
    +   * @param {string} [options.hostname=os.hostname] - The name of this server
    +   * @param {boolean} [options.timestamp=false] - Included a Timestamp
    +   * @param {boolean} [options.timestampUTC=false] - RFC tandard is for 
    +   *    local time
    +   * @param {boolean} [options.timestampMS=false] - Timestamp with ms 
    +   *    resoltuion
    +   * @param {boolean} [options.timestampTZ=true] - Should the timestamp
    +   *    included timezone
    +   * @param {boolean} [options.encludeStructuredData=false] - Included 
    +   *    any provided structured data
    +   * @param {boolean} [options.utf8BOM=true] - Included the UTF8 
    +   * @param {boolean} [options.color=false] - Included the UTF8 
    +   * @param {boolean} [options.extendedColor=false] - Included the UTF8 
    +   *    encoding tag with syslog message text 
    +   * @param {object} [options.colors] - User defended colors for 
    +   *    severites
    +   * @param {string} [options.colors.emergencyColor] - A RGB Hex coded color in the form 
    +   *    of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 
    +   *    Extended)
    +   * @param {string} [options.colors.alertColor] - A RGB Hex coded color in the form 
    +   *    of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 
    +   *    Extended)
    +   * @param {string} [options.colors.criticalColor] - A RGB Hex coded color in the form 
    +   *    of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 
    +   *    Extended)
    +   * @param {string} [options.colors.errorColor] - A RGB Hex coded color in the form 
    +   *    of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 
    +   *    Extended)
    +   * @param {string} [options.colors.warningColor] - A RGB Hex coded color in the form 
    +   *    of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 
    +   *    Extended)
    +   * @param {string} [options.colors.noticeColor] - A RGB Hex coded color in the form 
    +   *    of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 
    +   *    Extended)
    +   * @param {string} [options.colors.informationalColor] - A RGB Hex coded color in the form 
    +   *    of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 
    +   *    Extended)
    +   * @param {string} [options.colors.debugColor] - A RGB Hex coded color in the form 
    +   *    of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 
    +   *    Extended)
    +   * @param {Syslog} [options.server=false] - A {@link module:SyslogPro~Syslog|
    +   *    Syslog server connection} that should be used to send messages directly 
    +   *    from this class. @see SyslogPro~Syslog
    +   */
    +  constructor (options) {
    +    /** @private @type {boolean} */
    +    this.constructor__ = true;
    +    options = options || {};
    +    this.hostname = options.hostname || os.hostname();
    +    this.applacationName = options.applacationName || '';
    +    if (typeof options.timestamp === 'undefined' || options.timestamp) {
    +      /** @type {boolean} */
    +      this.timestamp = true;
    +    } else {
    +      this.timestamp = false;
    +    }
    +    if (options.timestampUTC) {
    +      /** @type {boolean} */
    +      this.timestampUTC = true;
    +    } else {
    +      this.timestampUTC = false;
    +    }
    +    if (typeof options.timestampTZ === 'undefined' || options.timestampTZ) {
    +      /** @type {boolean} */
    +      this.timestampTZ = true;
    +    } else {
    +      this.timestampTZ = false;
    +    }
    +    if (options.timestampMS) {
    +      /** @type {boolean} */
    +      this.timestampMS = true;
    +    } else {
    +      this.timestampMS = false;
    +    }
    +    if (options.encludeStructuredData) {
    +      /** @type {boolean} */
    +      this.encludeStructuredData = true;
    +    } else {
    +      this.encludeStructuredData = false;
    +    }
    +    if (typeof options.utf8BOM === 'undefined' || options.utf8BOM) {
    +      /** @type {boolean} */
    +      this.utf8BOM = true;
    +    } else {
    +      this.utf8BOM = false;
    +    }
    +    if (options.color) {
    +      /** @type {boolean} */
    +      this.color = true;
    +    } else {
    +      this.color = false;
    +    }
    +    if (options.extendedColor) {
    +      /** @type {boolean} */
    +      this.extendedColor = true;
    +    } else {
    +      this.extendedColor = false;
    +    }
    +    if (options.server) {
    +      if (!options.server.constructor__) {
    +        /** @private @type {Syslog} */
    +        this.server = new Syslog(options.server);
    +      } else {
    +        this.server = options.server;
    +      }
    +    }
    +    if (this.extendedColor) {
    +      /** @private @type {number} */
    +      this.emergencyColor = 1; // Red foreground color
    +      /** @private @type {number} */
    +      this.alertColor = 202; // Dark Orange foreground color
    +      /** @private @type {number} */
    +      this.criticalColor = 208; // Orange foreground color
    +      /** @private @type {number} */
    +      this.errorColor = 178; // Light Orange foreground color
    +      /** @private @type {number} */
    +      this.warningColor = 226; // Yellow foreground color
    +      /** @private @type {number} */
    +      this.noticeColor = 117; // Light Blue foreground color
    +      /** @private @type {number} */
    +      this.informationalColor = 45; // Blue foreground color
    +      /** @private @type {number} */
    +      this.debugColor = 27; // Dark Blue foreground color
    +    } else {
    +      this.emergencyColor = 31; // Red foreground color
    +      this.alertColor = 31; // Red foreground color
    +      this.criticalColor = 31; // Red foreground color
    +      this.errorColor = 33; // Yellow foreground color
    +      this.warningColor = 33; // Yellow foreground color
    +      this.noticeColor = 36; // Blue foreground color
    +      this.informationalColor = 36; // Blue foreground color
    +      this.debugColor = 34; // Dark Blue foreground color
    +    }
    +    if (typeof options.colors === 'object') {
    +      this.setColor(options.colors, this.extendedColor);
    +    }
    +  }
    +  /**
    +   * Sets the color to be used for messages at a set priority
    +   * @public   
    +   * @param {string} [colors.emergencyColor] - A RGB Hex coded color in the form 
    +   *    of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 
    +   *    Extended)
    +   * @param {string} [colors.alertColor] - A RGB Hex coded color in the form 
    +   *    of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 
    +   *    Extended)
    +   * @param {string} [colors.criticalColor] - A RGB Hex coded color in the form 
    +   *    of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 
    +   *    Extended)
    +   * @param {string} [colors.errorColor] - A RGB Hex coded color in the form 
    +   *    of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 
    +   *    Extended)
    +   * @param {string} [colors.warningColor] - A RGB Hex coded color in the form 
    +   *    of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 
    +   *    Extended)
    +   * @param {string} [colors.noticeColor] - A RGB Hex coded color in the form 
    +   *    of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 
    +   *    Extended)
    +   * @param {string} [colors.informationalColor] - A RGB Hex coded color in the form 
    +   *    of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 
    +   *    Extended)
    +   * @param {string} [colors.debugColor] - A RGB Hex coded color in the form 
    +   *    of #FFFFFF or as or the ANSI color code number (30-37 Standard & 0-255 
    +   *    Extended)
    +   * @throws {Error} A standard error object
    +   */
    +  setColor (colors, extendedColor) {
    +    return new Promise((resolve, reject) => {
    +      let colorPromises = [];
    +      if (colors.emergencyColor) {
    +        colorPromises.push(
    +            new Promise((resolve,reject) => {
    +              rgbToAnsi(colors.emergencyColor, this.extendedColor)
    +                  .then((result) => {
    +                    this.emergencyColor = result;
    +                    resolve(true);
    +                  })
    +                  .catch((reson) => {
    +                    reson.message = 'TYPE ERROR: '; 
    +                    reson.message += 'emergencyColor';
    +                    reson.message += ' Not in RGB color hex or color code';
    +                    reject(reson);
    +                  });
    +        }));
    +      }
    +      if (colors.alertColor) {
    +        colorPromises.push(
    +            new Promise((resolve,reject) => {
    +              rgbToAnsi(colors.alertColor, this.extendedColor)
    +                  .then((result) => {
    +                    this.alertColor = result;
    +                    resolve(true);
    +                  })
    +                  .catch((reson) => {
    +                    reson.message = 'TYPE ERROR: '; 
    +                    reson.message += 'alertColor';
    +                    reson.message += ' Not in RGB color hex or color code';
    +                    reject(reson);
    +                  });
    +        }));
    +      }
    +      if (colors.criticalColor) {
    +        colorPromises.push(
    +            new Promise((resolve,reject) => {
    +              rgbToAnsi(colors.criticalColor, this.extendedColor)
    +                  .then((result) => {
    +                    this.criticalColor = result;
    +                    resolve(true);
    +                  })
    +                  .catch((reson) => {
    +                    reson.message = 'TYPE ERROR: '; 
    +                    reson.message += 'criticalColor';
    +                    reson.message += ' Not in RGB color hex or color code';
    +                    reject(reson);
    +                  });
    +        }));
    +      }
    +      if (colors.errorColor) {
    +        colorPromises.push(
    +            new Promise((resolve,reject) => {
    +              rgbToAnsi(colors.errorColor, this.extendedColor)
    +                  .then((result) => {
    +                    this.errorColor = result;
    +                    resolve(true);
    +                  })
    +                  .catch((reson) => {
    +                    reson.message = 'TYPE ERROR: '; 
    +                    reson.message += 'errorColor';
    +                    reson.message += ' Not in RGB color hex or color code';
    +                    reject(reson);
    +                  });
    +        }));
    +      }
    +      if (colors.warningColor) {
    +        colorPromises.push(
    +            new Promise((resolve,reject) => {
    +              rgbToAnsi(colors.warningColor, this.extendedColor)
    +                  .then((result) => {
    +                    this.warningColor = result;
    +                    resolve(true);
    +                  })
    +                  .catch((reson) => {
    +                    reson.message = 'TYPE ERROR: '; 
    +                    reson.message += 'warningColor';
    +                    reson.message += ' Not in RGB color hex or color code';
    +                    reject(reson);
    +                  });
    +        }));
    +      }
    +      if (colors.noticeColor) {
    +        colorPromises.push(
    +            new Promise((resolve,reject) => {
    +              rgbToAnsi(colors.noticeColor, this.extendedColor)
    +                  .then((result) => {
    +                    this.noticeColor = result;
    +                    resolve(true);
    +                  })
    +                  .catch((reson) => {
    +                    reson.message = 'TYPE ERROR: '; 
    +                    reson.message += 'noticeColor';
    +                    reson.message += ' Not in RGB color hex or color code';
    +                    reject(reson);
    +                  });
    +        }));
    +      }
    +      if (colors.informationalColor) {
    +        colorPromises.push(
    +            new Promise((resolve,reject) => {
    +              rgbToAnsi(colors.informationalColor, this.extendedColor)
    +                  .then((result) => {
    +                    this.informationalColor = result;
    +                    resolve(true);
    +                  })
    +                  .catch((reson) => {
    +                    reson.message = 'TYPE ERROR: '; 
    +                    reson.message += 'informationalColor';
    +                    reson.message += ' Not in RGB color hex or color code';
    +                    reject(reson);
    +                  });
    +        }));
    +      }
    +      if (colors.debugColor) {
    +        colorPromises.push(
    +            new Promise((resolve,reject) => {
    +              rgbToAnsi(colors.debugColor, this.extendedColor)
    +                  .then((result) => {
    +                    this.debugColor = result;
    +                    resolve(true);
    +                  })
    +                  .catch((reson) => {
    +                    reson.message = 'TYPE ERROR: '; 
    +                    reson.message += 'debugColor';
    +                    reson.message += ' Not in RGB color hex or color code';
    +                    reject(reson);
    +                  });
    +        }));
    +      }
    +      Promise.all(colorPromises)
    +          .then((results) => {
    +            resolve(true);
    +          })
    +          .catch((reson) => {
    +            reject(reson);
    +          });
    +    });
    +  }
    +  /**
    +   * Building a formated message.  Returns a promise with a formated message 
    +   * @public
    +   * @param {string} msg - The Syslog Message
    +   * @param {object} [options] - Options object
    +   * @param {number} [options.severity=7] - An array of structure 
    +   * @param {number} [options.facility=23] - Facility code to use sending this 
    +   *    message 
    +   * @param {string} [options.pid='-'] - The process id of the service sending 
    +   *    this message 
    +   * @param {string[]} [options.structuredData] - An array of structure 
    +   *    data strings conforming to the IETF/IANA defined SD-IDs or IANA 
    +   *    registred SMI Network Management Private Enterprise Code SD-ID 
    +   *    conforming to the format 
    +   *    [name@<private enterprise number> parameter=value] 
    +   * @param {number} [options.colorCode=36] - The ANSI color code to use if 
    +   *    message coloration is selected
    +   * @returns {Promise} A Syslog formated string acording to the selected RFC
    +   * @throws {Error} A standard error object
    +   */
    +  buildMessage (msg, options) {
    +    return new Promise((resolve, reject) => {
    +      options = options || {};
    +      let severity = typeof options.severity === 'number' ? 
    +          options.severity : 6;
    +      if (typeof msg !== 'string' || options.severity > 7) {
    +        let errMsg = 'FORMAT ERROR: Syslog message must be a string';
    +        errMsg += ' msgSeverity must be a number between 0 and 7';
    +        reject(new Error(errMsg));
    +        return;
    +      }
    +      let facility = options.facility || 23;
    +      let pid = options.pid || '-';
    +      let id = options.id || '-';
    +      let msgStructuredData = options.msgStructuredData || [];
    +      let fmtMsg = ''; // Formated Syslog message string var
    +      const newLine = '\n';
    +      const newLineRegEx = /(\r|\n|(\r\n))/;
    +      const escapeCode = '\u001B';
    +      const resetColor = '\u001B[0m';
    + +
  • + + +
  • +
    + +
    + +
    +

    The PRI is common to both RFC formats

    + +
    + +
          const pri = (facility * 8) + severity;
    + +
  • + + +
  • +
    + +
    + +
    +

    Remove any newline character

    + +
    + +
          msg = msg.replace(newLineRegEx, '');
    + +
  • + + +
  • +
    + +
    + +
    +

    Add requested color

    + +
    + +
          if (this.color) {
    +        options.msgColor = options.msgColor || 36;
    +        let colorCode = '[';
    +        if (this.extendedColor) {
    +          colorCode += '38;5;'; // Extended 256 Colors ANSI Code
    +        }
    +        if (typeof options.msgColor === 'number') {
    +          colorCode += options.msgColor;
    +          colorCode += 'm'; // ANSI Color Closer
    +        } else {
    +          colorCode = '[39m';  // Use terminal's defualt color
    +        }
    +        msg = escapeCode + colorCode + msg + resetColor;
    +      }
    + +
  • + + +
  • +
    + +
    + +
    +

    RFC5424 timestamp formating

    + +
    + +
          let timestamp = '-';
    +      if (this.timestamp) {
    +        let timeQuality = '[timeQuality';
    +        if (this.timestampUTC) {
    +          timeQuality += ' tzKnown=1';
    +          if (this.timestampMS) {
    +            if (this.timestampTZ) {
    +              timestamp = moment().utc().format('YYYY-MM-DDThh:mm:ss.SSSSSSZ');
    +            } else {
    +              timestamp = moment().utc().format('YYYY-MM-DDThh:mm:ss.SSSSSS');
    +            }
    +          } else {
    +            if (this.timestampTZ) {
    +              timestamp = moment().utc().format('YYYY-MM-DDThh:mm:ssZ');
    +            } else {
    +              timestamp = moment().utc().format('YYYY-MM-DDThh:mm:ss');
    +            }
    +          }
    +        } else {
    +          if (this.timestampTZ) {
    +            timeQuality += ' tzKnown=1';
    +            if (this.timestampMS) {
    +              timeQuality += ' isSynced=1';
    +              timeQuality += ' syncAccuracy=0';
    +              timestamp = moment().format('YYYY-MM-DDThh:mm:ss.SSSSSSZ');
    +            } else {
    +              timestamp = moment().format('YYYY-MM-DDThh:mm:ssZ');
    +            }
    +          } else {
    +            timeQuality += ' tzKnown=0';
    +            if (this.timestampMS) {
    +              timeQuality += ' isSynced=1';
    +              timeQuality += ' syncAccuracy=0';
    +              timestamp = moment().format('YYYY-MM-DDThh:mm:ss.SSSSSS');
    +            } else {
    +              timestamp = moment().format('YYYY-MM-DDThh:mm:ss');
    +            }
    +          }
    +        }
    +        timeQuality += ']';
    +        msgStructuredData.push(timeQuality);
    +      }
    + +
  • + + +
  • +
    + +
    + +
    +

    Build Structured Data string

    + +
    + +
          let structuredData = '-';
    +      const sdElementCount = msgStructuredData.length;
    +      if (this.encludeStructuredData && sdElementCount > 0) {
    +        let sdElementNames = [];
    +        let sdElements = [];
    +        const sdElementNameRegEx = /(\[)(\S*)(\s|\])/;
    + +
  • + + +
  • +
    + +
    + +
    +

    Loop to drop duplicates of the same SD Element name

    + +
    + +
            for (let elementIndex=0; 
    +            elementIndex<sdElementCount; 
    +            elementIndex++) {
    +          let elementName = 
    +            msgStructuredData[elementIndex]
    +            .match(sdElementNameRegEx)[2];
    +          if (!sdElementNames.includes(elementName)) {
    +            sdElementNames.push(elementName);
    +            sdElements.push(msgStructuredData[elementIndex]);
    +          }
    +        }
    +        structuredData = sdElements.join('');
    +      }
    + +
  • + + +
  • +
    + +
    + +
    +

    Build the message

    + +
    + +
          fmtMsg = '<' + pri + '>';
    +      fmtMsg += '1'; // Version number
    +      fmtMsg += ' ' + timestamp;
    +      fmtMsg += ' ' + this.hostname;
    +      fmtMsg += ' ' + this.applacationName;
    +      fmtMsg += ' ' + pid;
    +      fmtMsg += ' ' + id;
    +      fmtMsg += ' ' + structuredData;
    +      if (this.utf8BOM) {
    +        fmtMsg += ' BOM' + msg;
    +      } else {
    +        fmtMsg += ' ' + msg;
    +      }
    +      fmtMsg += newLine;
    +      resolve(fmtMsg);
    +    });
    +  }
    +  /**
    +   * send a RFC5424 formated message.  Returns a promise with the formated 
    +   *    message that was sent.  If no server connection was defined when the 
    +   *    class was created a defualt Syslog connector will be used.  
    +   *    @see SyslogPro~Syslog
    +   * @public
    +   * @param {string} msg - The unformated Syslog message to send
    +   * @returns {Promise} A Syslog formated string acording to the selected RFC
    +   * @throws {Error} A standard error object
    +   */
    +  send (msg, options) {
    +    return new Promise((resolve, reject) => {
    +      if (!this.server) {
    +        this.server = new Syslog();
    +      }
    +      this.buildMessage(msg, options)
    +        .then((result) => {
    +          this.server.send(result)
    +            .then((sendResult) => {
    +              resolve(sendResult);
    +            })
    +            .catch((error) => {
    +              reject(error);
    +            });
    +        })
    +        .catch((error) => {
    +          reject(error);
    +        });
    +    });
    +  }
    +  /**
    +   * Send a syslog message with a secerity level of 0 (Emergency)
    +   * @public
    +   * @param {string} msg - The emergancy message to send to the Syslog server
    +   * @returns {Promise} - The formated syslog message sent to the Syslog server
    +   * @throws {Error} - Any bubbled up error
    +   */
    +  emergency (msg) {
    +    return this.send(msg, {
    +      severity: 0, 
    +      colorCode: this.emergencyColor
    +    });
    +  }
    +  /**
    +   * Send a syslog message with a secerity level of 0 (Emergency)
    +   * @public
    +   * @param {string} msg - The emergancy message to send to the Syslog server
    +   * @returns {Promise} - The formated syslog message sent to the Syslog server
    +   * @throws {Error} - Any bubbled up error
    +   */
    +  emer (msg) {
    +    return this.emergency(msg);
    +  }
    +  /**
    +   * Send a syslog message with a secerity level of 1 (Alert)
    +   * @public
    +   * @param {string} msg - The alert message to send to the Syslog server
    +   * @returns {Promise} - The formated syslog message sent to the Syslog server
    +   * @throws {Error} - Any bubbled up error
    +   */
    +  alert (msg) {
    +    return this.send(msg, {
    +      severity: 1, 
    +      colorCode: this.alertColor
    +    });
    +  }
    +  /**
    +   * Send a syslog message with a secerity level of 2 (Critical)
    +   * @public
    +   * @param {string} msg - The critical message to send to the Syslog server
    +   * @returns {Promise} - The formated syslog message sent to the Syslog server
    +   * @throws {Error} - Any bubbled up error
    +   */
    +  critical (msg) {
    +    return this.send(msg, {
    +      severity: 2, 
    +      colorCode: this.criticalColor
    +    });
    +  }
    +  /**
    +   * Send a syslog message with a secerity level of 2 (Critical)
    +   * @public
    +   * @param {string} msg - The critical message to send to the Syslog server
    +   * @returns {Promise} - The formated syslog message sent to the Syslog server
    +   * @throws {Error} - Any bubbled up error
    +   */
    +  crit (msg) {
    +    return this.critical(msg);
    +  }
    +  /**
    +   * Send a syslog message with a secerity level of 3 (Error)
    +   * @public
    +   * @param {string} msg - The error message to send to the Syslog server
    +   * @returns {Promise} - The formated syslog message sent to the Syslog server
    +   * @throws {Error} - Any bubbled up error
    +   */
    +  error (msg) {
    +    return this.send(msg, {
    +      severity: 3, 
    +      colorCode: this.errorColor
    +    });
    +  }
    +  /**
    +   * Send a syslog message with a secerity level of 3 (Error)
    +   * @public
    +   * @param {string} msg - The error message to send to the Syslog server
    +   * @returns {Promise} - The formated syslog message sent to the Syslog server
    +   * @throws {Error} - Any bubbled up error
    +   */
    +  err (msg) {
    +    return this.error(msg);
    +  }
    +  /**
    +   * Send a syslog message with a secerity level of 4 (Warning)
    +   * @public
    +   * @param {string} msg - The warning message to send to the Syslog server
    +   * @returns {Promise} - The formated syslog message sent to the Syslog server
    +   * @throws {Error} - Any bubbled up error
    +   */
    +  warning (msg) {
    +    return this.send(msg, {
    +      severity: 4, 
    +      colorCode: this.warningColor
    +    });
    +  }
    +  /**
    +   * Send a syslog message with a secerity level of 4 (Warning)
    +   * @public
    +   * @param {string} msg - The warning message to send to the Syslog server
    +   * @returns {Promise} - The formated syslog message sent to the Syslog server
    +   * @throws {Error} - Any bubbled up error
    +   */
    +  warn (msg) {
    +    return this.warning(msg);
    +  }
    +  /**
    +   * Send a syslog message with a secerity level of 5 (Notice)
    +   * @public
    +   * @param {string} msg - The notice message to send to the Syslog server
    +   * @returns {Promise} - The formated syslog message sent to the Syslog server
    +   * @throws {Error} - Any bubbled up error
    +   */
    +  notice (msg) {
    +    return this.send(msg, {
    +      severity: 5, 
    +      colorCode: this.noticeColor
    +    });
    +  }
    +  /**
    +   * Send a syslog message with a secerity level of 5 (Notice)
    +   * @public
    +   * @param {string} msg - The notice message to send to the Syslog server
    +   * @returns {Promise} - The formated syslog message sent to the Syslog server
    +   * @throws {Error} - Any bubbled up error
    +   */
    +  note (msg) {
    +    return this.notice(msg);
    +  }
    +  /**
    +   * Send a syslog message with a secerity level of 6 (Informational)
    +   * @public
    +   * @param {string} msg - The informational message to send to the Syslog server
    +   * @returns {Promise} - The formated syslog message sent to the Syslog server
    +   * @throws {Error} - Any bubbled up error
    +   */
    +  informational (msg) {
    +    return this.send(msg, {
    +      severity: 6, 
    +      colorCode: this.informationalColor
    +    });
    +  }
    +  /**
    +   * Send a syslog message with a secerity level of 6 (Informational)
    +   * @public
    +   * @param {string} msg - The informational message to send to the Syslog server
    +   * @returns {Promise} - The formated syslog message sent to the Syslog server
    +   * @throws {Error} - Any bubbled up error
    +   */
    +  info (msg) {
    +    return this.informational(msg);
    +  }
    +  /**
    +   * Send a syslog message with a secerity level of 6 (Informational)
    +   * @public
    +   * @param {string} msg - The informational message to send to the Syslog server
    +   * @returns {Promise} - The formated syslog message sent to the Syslog server
    +   * @throws {Error} - Any bubbled up error
    +   */
    +  log (msg) {
    +    return this.informational(msg);
    +  }
    +  /**
    +   * Send a syslog message with a secerity level of 7 (Debug)
    +   * @public
    +   * @param {string} msg - The debug message to send to the Syslog server
    +   * @returns {Promise} - The formated syslog message sent to the Syslog server
    +   * @throws {Error} - Any bubbled up error
    +   */
    +  debug (msg) {
    +    return this.send(msg, {
    +      severity: 7, 
    +      colorCode: this.debugColor
    +    });
    +  }
    +}
    + 
    +/**
    + * A class to work with IBM LEEF (Log Event Extended Format) messages this form
    + * of system messages are designed to work with security systems.  Messages can
    + * be saved to file (Saving to file if not part of this module but a LEEF 
    + * formated mesage produced by this module can be saved externaly to it) or 
    + * sent via Syslog. 
    + * Most APIs will return a promise. These APIs can be used using 
    + * `then(...)/catch(...)`
    + * 
    + * A Syslog class with a configured Syslog server target can also be used as 
    + * the input into the formating classes so that it may run independtly. The 
    + * LEEF format is designed to send event data to a SIEM system and should not 
    + * be as a logging stream. This class is ment to be used once per message.
    + * @requires moment
    + * @version 0.0.0
    + * @since 0.0.0
    + */
    +class LEEF {
    +  /**
    +   * Construct a new LEEF formating object with user options
    +   * @public
    +   * @param {object} [options] - Options object
    +   * @param {string} [options.vendor='unknown'] - The vendor of the system that
    +   *    genrated the event being reported
    +   * @param {string} [options.product='unknown'] - The product name of the 
    +   *    system that genrated the event being reported
    +   * @param {string} [options.version='unknown'] - The version name of the 
    +   *    system that genrated the event being reported
    +   * @param {string} [options.eventId='unknown'] - The eventId of the 
    +   *    system that genrated the event being reported
    +   * @param {object} [options.attrabute] - LEEF message attrabutes which 
    +   *    defualts to all base attrabutes with null values, new attrabutes should
    +   *    be added as new elements to this object
    +   * @param {boolean} [options.syslogHeader='true'] - Should the LEEF message 
    +   *    include a Syslog header with Timestamp and source
    +   * @param {Syslog} [options.server=false] - A {@link module:SyslogPro~Syslog|
    +   *    Syslog server connection} that should be used to send messages directly 
    +   *    from this class. @see SyslogPro~Syslog
    +   */
    +  constructor (options) {
    +    /** @private @type {boolean} */
    +    this.constructor__ = true;
    +    options = options || {};
    +    /** @type {string} */
    +    this.vendor = options.vendor || 'unknown';
    +    /** @type {string} */
    +    this.product = options.product || 'unknown';
    +    /** @type {string} */
    +    this.version = options.version || 'unknown';
    +    /** @type {string} */
    +    this.eventId = options.eventId || 'unknown';
    +    /** @type {boolean} */
    +    this.syslogHeader = typeof options.syslogHeader === 'boolean' 
    +        ? options.syslogHeader : true;
    +    /** @type {object} */
    +    this.attrabutes = options.attrabutes || {
    +      cat: null,
    +      devTime: null,
    +      devTimeFormat: null,
    +      proto: null,
    +      sev: null,
    +      src: null,
    +      dst: null,
    +      srcPort: null,
    +      dstPort: null,
    +      srcPreNAT: null,
    +      dstPreNAT: null,
    +      srcPostNAT: null,
    +      dstPostNAT: null,
    +      usrName: null,
    +      srcMAC: null,
    +      dstMAC: null,
    +      srcPreNATPort: null,
    +      dstPreNATPort: null,
    +      srcPostNATPort: null,
    +      dstPostNATPort: null,
    +      identSrc: null,
    +      identHostName: null,
    +      identNetBios: null,
    +      identGrpName: null,
    +      identMAC: null,
    +      vSrc: null,
    +      vSrcName: null,
    +      accountName: null,
    +      srcBytes: null,
    +      dstBytes: null,
    +      srcPackets: null,
    +      dstPackets: null,
    +      totalPackets: null,
    +      role: null,
    +      realm: null,
    +      policy: null,
    +      resource: null,
    +      url: null,
    +      groupID: null,
    +      domain: null,
    +      isLoginEvent: null,
    +      isLogoutEvent: null,
    +      identSecondlp: null,
    +      calLanguage: null,
    +      AttributeLimits: null,
    +      calCountryOrRegion: null,
    +    };
    +    if (options.server) {
    +      if (options.server.constructor__) {
    +        /** @private @type {Syslog} */
    +        this.server = options.server;
    +      } else {
    +        this.server = new Syslog(options.server);
    +      }
    +    }
    +  }
    +  /**
    +   *Build a formated message
    +   * @public
    +   * @return {Promise} - string with formated message
    +   */
    +  buildMessage () {
    +    return new Promise((resolve, reject) => {
    +      let fmtMsg = 'LEEF:2.0';
    +      fmtMsg += '|' + this.vendor;
    +      fmtMsg += '|' + this.product;
    +      fmtMsg += '|' + this.version;
    +      fmtMsg += '|' + this.eventId;
    +      fmtMsg += '|';
    + +
  • + + +
  • +
    + +
    + +
    +

    Build LEEF Attrabuites

    + +
    + +
          const Tab = '\x09';
    +      const leefAttribs = Object.entries(this.attrabutes);
    +      const leefAttribsLen = leefAttribs.length;
    +      for (let attrib = 0; attrib < leefAttribsLen; attrib++) {
    +        if (leefAttribs[attrib][1] !== null) {
    +          fmtMsg += leefAttribs[attrib][0] + '=' + leefAttribs[attrib][1] + Tab;
    +        }
    +      }
    +      resolve(fmtMsg);
    +    });
    +  }
    +  
    +  /**
    +   * @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
    +   */
    +  send (options) {
    +    return new Promise((resolve, reject) => {
    +      this.buildMessage()
    +        .then((result) => {
    +          if (!this.server) {
    +            this.server = new Syslog(options);
    +          }
    +          this.server.send(result)
    +            .then((sendResult) => {
    +              resolve(sendResult);
    +            })
    +            .catch((reson) => {
    +              reject(reson);
    +            });
    +        });
    +    });
    +  }
    +}
    +
    +/**
    + * A class to work with HP CEF (Common Event Format) messages. This form
    + * of system messages are designed to work with security systems.  Messages can
    + * be saved to file (Saving to file if not part of this module but a CEF 
    + * formated mesage produced by this module can be saved externaly to it) or 
    + * sent via Syslog.
    + * Most APIs will return a promise. These APIs can be used using 
    + * `then(...)/catch(...)`
    + * 
    + * A Syslog class with a configured Syslog server target can also be used as 
    + * the input into the formating classes so that it may run independtly. The CEF 
    + * format is designed to send event data to a SIEM system and should not be as 
    + * a logging stream. This class is ment to be used once per message.
    + * @requires moment
    + * @version 0.0.0
    + * @since 0.0.0
    + */
    +class CEF {
    +  /**
    +   * Construct a new CEF formating object with user options 
    +   * @public
    +   * @param {object} [options] - Options object
    +   * @param {string} [options.deviceVendor='unknown'] - The vendor of the system 
    +   *    that genrated the event being reported
    +   * @param {string} [options.deviceProduct='unknown'] - The product name of the 
    +   *    system that genrated the event being reported
    +   * @param {string} [options.deviceVersion='unknown'] - The version name of the 
    +   *    system that genrated the event being reported
    +   * @param {string} [options.deviceEventClassId='unknown'] - The eventId of the 
    +   *    system that genrated the event being reported
    +   * @param {string} [options.name='unknown'] - Name of the service genrating 
    +   *    the notice
    +   * @param {string} [options.severity='unknown'] - Severity of the notification
    +   * @param {string} [options.extensions={}] - Any CEF Key=Value extentions
    +   * @param {Syslog} [options.server=false] - A {@link module:SyslogPro~Syslog|
    +   *    Syslog server connection} that should be used to send messages directly 
    +   *    from this class. @see SyslogPro~Syslog
    +   */
    +  constructor (options) {
    +    /** @private @type {boolean} */
    +    this.constructor__ = true;
    +    options = options || {};
    +    /** @type {string} */
    +    this.deviceVendor = options.deviceVendor || 'Unknown';
    +    /** @type {string} */
    +    this.deviceProduct = options.deviceProduct || 'Unknown';
    +    /** @type {string} */
    +    this.deviceVersion = options.deviceVersion || 'Unknown';
    +    /** @type {string} */
    +    this.deviceEventClassId = options.deviceEventClassId || 'Unknown';
    +    /** @type {string} */
    +    this.name = options.name || 'Unknown';
    +    /** @type {string} */
    +    this.severity = options.severity || 'Unknown';
    +    /** @type {object} */
    +    this.extensions = options.extensions || {
    +      'deviceAction': null,
    +      'applicationProtocol': null,
    +      'deviceCustomIPv6Address1': null,
    +      'deviceCustomIPv6 Address1Label': null,
    +      'deviceCustomIPv6Address3': null,
    +      'deviceCustomIPv6Address3 Label': null,
    +      'deviceCustomIPv6 Address4': null,
    +      'deviceCustomIPv6 Address4Label': null,
    +      'deviceEventCategory': null,
    +      'deviceCustomFloatingPoint1': null,
    +      'deviceCustom FloatingPoint1Label': null,
    +      'deviceCustomFloatingPoint2': null,
    +      'deviceCustomFloatingPoint2 Label': null,
    +      'deviceCustomFloatingPoint3': null,
    +      'deviceCustom FloatingPoint3Label': null,
    +      'deviceCustomFloatingPoint4': null,
    +      'deviceCustom FloatingPoint4Label': null,
    +      'deviceCustomNumber1': null,
    +      'deviceCustomNumber1Label': null,
    +      'DeviceCustomNumber2': null,
    +      'deviceCustomNumber2Label': null,
    +      'deviceCustomNumber3': null,
    +      'deviceCustomNumber3Label': null,
    +      'baseEventCount': null,
    +      'deviceCustomString1': null,
    +      'deviceCustomString1Label': null,
    +      'deviceCustomString2': null,
    +      'deviceCustomString2Label': null,
    +      'deviceCustomString3': null,
    +      'deviceCustomString3Label': null,
    +      'deviceCustomString4': null,
    +      'deviceCustomString4Label': null,
    +      'deviceCustomString5': null,
    +      'deviceCustomString5Label': null,
    +      'deviceCustomString6': null,
    +      'deviceCustomString6Label': null,
    +      'destinationDnsDomain': null,
    +      'destinationServiceName': null,
    +      'destinationTranslated Address': null,
    +      'destinationTranslatedPort': null,
    +      'deviceCustomDate1': null,
    +      'deviceCustomDate1Label': null,
    +      'deviceCustomDate2': null,
    +      'deviceCustomDate2Label': null,
    +      'deviceDirection': null,
    +      'deviceDnsDomain': null,
    +      'deviceExternalId': null,
    +      'deviceFacility': null,
    +      'deviceInboundInterface': null,
    +      'deviceNtDomain': null,
    +      'deviceOutboundInterface': null,
    +      'devicePayloadId': null,
    +      'deviceProcessName': null,
    +      'deviceTranslatedAddress': null,
    +      'destinationHostName': null,
    +      'destinationMacAddress': null,
    +      'destinationNtDomain': null,
    +      'destinationProcessId': null,
    +      'destinationUserPrivileges': null,
    +      'destinationProcessName': null,
    +      'destinationPort': null,
    +      'destinationAddress': null,
    +      'deviceTimeZone': null,
    +      'destinationUserId': null,
    +      'destinationUserName': null,
    +      'deviceAddress': null,
    +      'deviceHostName': null,
    +      'deviceMacAddress': null,
    +      'deviceProcessId': null,
    +      'endTime': null,
    +      'externalId': null,
    +      'fileCreateTime': null,
    +      'fileHash': null,
    +      'fileId': null,
    +      'fileModificationTime': null,
    +      'filePath': null,
    +      'filePermission': null,
    +      'fileType': null,
    +      'flexDate1': null,
    +      'flexDate1Label': null,
    +      'flexString1': null,
    +      'flexString1Label': null,
    +      'flexString2': null,
    +      'flexString2Label': null,
    +      'filename': null,
    +      'fileSize': null,
    +      'bytesIn': null,
    +      'message': null,
    +      'oldFileCreateTime': null,
    +      'oldFileHash': null,
    +      'oldFileId': null,
    +      'oldFileModificationTime': null,
    +      'oldFileName': null,
    +      'oldFilePath': null,
    +      'oldFileSize': null,
    +      'oldFileType': null,
    +      'bytesOut': null,
    +      'eventOutcome': null,
    +      'transportProtocol': null,
    +      'Reason': null,
    +      'requestUrl': null,
    +      'requestClientApplication': null,
    +      'requestContext': null,
    +      'requestCookies': null,
    +      'requestMethod': null,
    +      'deviceReceiptTime': null,
    +      'sourceHostName': null,
    +      'sourceMacAddress': null,
    +      'sourceNtDomain': null,
    +      'sourceDnsDomain': null,
    +      'sourceServiceName': null,
    +      'sourceTranslatedAddress': null,
    +      'sourceTranslatedPort': null,
    +      'sourceProcessId': null,
    +      'sourceUserPrivileges': null,
    +      'sourceProcessName': null,
    +      'sourcePort': null,
    +      'sourceAddress': null,
    +      'startTime': null,
    +      'sourceUserId': null,
    +      'sourceUserName': null,
    +      'type': null,
    +      'agentDnsDomain': null,
    +      'agentNtDomain': null,
    +      'agentTranslatedAddress': null,
    +      'agentTranslatedZone ExternalID': null,
    +      'agentTranslatedZoneURI': null,
    +      'agentZoneExternalID': null,
    +      'agentZoneURI': null,
    +      'agentAddress': null,
    +      'agentHostName': null,
    +      'agentId': null,
    +      'agentMacAddress': null,
    +      'agentReceiptTime': null,
    +      'agentType': null,
    +      'agentTimeZone': null,
    +      'agentVersion': null,
    +      'customerExternalID': null,
    +      'customerURI': null,
    +      'destinationTranslated ZoneExternalID': null,
    +      'destinationTranslated ZoneURI': null,
    +      'destinationZoneExternalID': null,
    +      'destinationZoneURI': null,
    +      'deviceTranslatedZone ExternalID': null,
    +      'deviceTranslatedZoneURI': null,
    +      'deviceZoneExternalID': null,
    +      'deviceZoneURI': null,
    +      'destinationGeoLatitude': null,
    +      'destinationGeoLongitude': null,
    +      'eventId': null,
    +      'rawEvent': null,
    +      'sourceGeoLatitude': null,
    +      'sourceGeoLongitude': null,
    +      'sourceTranslatedZone ExternalID': null,
    +      'sourceTranslatedZoneURI': null,
    +      'sourceZoneExternalID': null,
    +      'sourceZoneURI': null,
    +    };
    +    if (options.server) {
    +      if (options.server.constructor__) {
    +        /** @private @type {Syslog} */
    +        this.server = options.server;
    +      } else {
    +        this.server = new Syslog(options.server);
    +      }
    +    }
    +  }
    +  /**
    +   * Validate this CEF object
    +   * @public
    +   * @return {Promise} - True if valadated
    +   * @throws {Error} - First element to fail valadation
    +   */  
    +  validate () {
    +    return new Promise ((resolve, reject) => {
    +      const Extensions = {
    +        'deviceAction': {key: 'act', type:'String', len:63,  discription: 'Action taken by the device.'},
    +        'applicationProtocol': {key: 'app', type:'String', len:31,  discription: 'Application level protocol, example values are HTTP, HTTPS, SSHv2, Telnet, POP, IMPA, IMAPS, and so on.'},
    +        'deviceCustomIPv6Address1': {key: 'c6a1', type:'String', len:null,  discription: 'One of four IPv6 address fields available to map fields that do not apply to any other in this dictionary. TIP: See the guidelines under “User-Defined Extensions” for tips on using these fields.'},
    +        'deviceCustomIPv6 Address1Label': {key: 'c6a1Label', type:'String', len:1023,  discription: 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.'},
    +        'deviceCustomIPv6Address3': {key: 'c6a3', type:'String', len:null,  discription: 'One of four IPv6 address fields available to map fields that do not apply to any other in this dictionary. TIP: See the guidelines under “User-Defined Extensions” for tips on using these fields.'},
    +        'deviceCustomIPv6Address3 Label': {key: 'c6a3Label', type:'String', len:1023,  discription: 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.'},
    +        'deviceCustomIPv6 Address4': {key: 'c6a4', type:'String', len:null,  discription: 'One of four IPv6 address fields available to map fields that do not apply to any other in this dictionary. TIP: See the guidelines under “User-Defined Extensions” for tips on using these fields.'},
    +        'deviceCustomIPv6 Address4Label': {key: 'C6a4Label', type:'String', len:1023,  discription: 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.'},
    +        'deviceEventCategory': {key: 'cat', type:'String', len:1023,  discription: 'Represents the category assigned by the originating device. Devices often use their own categorization schema to classify event. Example: “/Monitor/Disk/Read”'},
    +        'deviceCustomFloatingPoint1': {key: 'cfp1', type:'Number', len:null,  discription: 'One of four floating point fields available to map fields that do not apply to any other in this dictionary.'},
    +        'deviceCustom FloatingPoint1Label': {key: 'cfp1Label', type:'String', len:1023,  discription: 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.'},
    +        'deviceCustomFloatingPoint2': {key: 'cfp2', type:'Number', len:null,  discription: 'One of four floating point fields available to map fields that do not apply to any other in this dictionary.'},
    +        'deviceCustomFloatingPoint2 Label': {key: 'cfp2Label', type:'String', len:1023,  discription: 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.'},
    +        'deviceCustomFloatingPoint3': {key: 'cfp3', type:'Number', len:null,  discription: 'One of four floating point fields available to map fields that do not apply to any other in this dictionary.'},
    +        'deviceCustom FloatingPoint3Label': {key: 'cfp3Label', type:'String', len:1023,  discription: 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.'},
    +        'deviceCustomFloatingPoint4': {key: 'cfp4', type:'Number', len:null,  discription: 'One of four floating point fields available to map fields that do not apply to any other in this dictionary.'},
    +        'deviceCustom FloatingPoint4Label': {key: 'cfp4Label', type:'String', len:1023,  discription: 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.'},
    +        'deviceCustomNumber1': {key: 'cn1', type:'Number', len:null,  discription: 'One of three number fields available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible.'},
    +        'deviceCustomNumber1Label': {key: 'cn1Label', type:'String', len:1023,  discription: 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.'},
    +        'DeviceCustomNumber2': {key: 'cn2', type:'Number', len:null,  discription: 'One of three number fields available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible.'},
    +        'deviceCustomNumber2Label': {key: 'cn2Label', type:'String', len:1023,  discription: 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.'},
    +        'deviceCustomNumber3': {key: 'cn3', type:'Number', len:null,  discription: 'One of three number fields available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible.'},
    +        'deviceCustomNumber3Label': {key: 'cn3Label', type:'String', len:1023,  discription: 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.'},
    +        'baseEventCount': {key: 'cnt', type:'Number', len:null,  discription: 'A count associated with this event. How many times was this same event observed? Count can be omitted if it is 1.'},
    +        'deviceCustomString1': {key: 'cs1', type:'String', len:4000,  discription: 'One of six strings available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible. TIP: See the guidelines under “User-Defined Extensions” for tips on using these fields.'},
    +        'deviceCustomString1Label': {key: 'cs1Label', type:'String', len:1023,  discription: 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.'},
    +        'deviceCustomString2': {key: 'cs2', type:'String', len:4000,  discription: 'One of six strings available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible. TIP: See the guidelines under “User-Defined Extensions” for tips on using these fields.'},
    +        'deviceCustomString2Label': {key: 'cs2Label', type:'String', len:1023,  discription: 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.'},
    +        'deviceCustomString3': {key: 'cs3', type:'String', len:4000,  discription: 'One of six strings available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible. TIP: See the guidelines under “User-Defined Extensions” for tips on using these fields.'},
    +        'deviceCustomString3Label': {key: 'cs3Label', type:'String', len:1023,  discription: 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.'},
    +        'deviceCustomString4': {key: 'cs4', type:'String', len:4000,  discription: 'One of six strings available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible. TIP: See the guidelines under “User-Defined Extensions” for tips on using these fields.'},
    +        'deviceCustomString4Label': {key: 'cs4Label', type:'String', len:1023,  discription: 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.'},
    +        'deviceCustomString5': {key: 'cs5', type:'String', len:4000,  discription: 'One of six strings available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible. TIP: See the guidelines under “User-Defined Extensions” for tips on using these fields.'},
    +        'deviceCustomString5Label': {key: 'cs5Label', type:'String', len:1023,  discription: 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.'},
    +        'deviceCustomString6': {key: 'cs6', type:'String', len:4000,  discription: 'One of six strings available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible. TIP: See the guidelines under “User-Defined Extensions” for tips on using these fields.'},
    +        'deviceCustomString6Label': {key: 'cs6Label', type:'String', len:1023,  discription: 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.'},
    +        'destinationDnsDomain': {key: 'destination DnsDomain', type:'String', len:255,  discription: 'The DNS domain part of the complete fully qualified domain name (FQDN).'},
    +        'destinationServiceName': {key: 'destination ServiceName', type:'String', len:1023,  discription: 'The service targeted by this event. Example: “sshd”'},
    +        'destinationTranslated Address': {key: 'Destination Translated Address', type:'String', len:null,  discription: 'Identifies the translated destination that the event refers to in an IP network. The format is an IPv4 address. Example: “192.168.10.1”'},
    +        'destinationTranslatedPort': {key: 'Destination TranslatedPort', type:'Number', len:null,  discription: 'Port after it was translated; for example, a firewall. Valid port numbers are 0 to 65535.'},
    +        'deviceCustomDate1': {key: 'deviceCustom Date1', type:'String', len:null,  discription: 'One of two timestamp fields available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible. TIP: See the guidelines under “User-Defined Extensions” for tips on using these fields.'},
    +        'deviceCustomDate1Label': {key: 'deviceCustom Date1Label', type:'String', len:1023,  discription: 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.'},
    +        'deviceCustomDate2': {key: 'deviceCustom Date2', type:'String', len:null,  discription: 'One of two timestamp fields available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible. TIP: See the guidelines under “User-Defined Extensions” for tips on using these fields.'},
    +        'deviceCustomDate2Label': {key: 'deviceCustom Date2Label', type:'String', len:1023,  discription: 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.'},
    +        'deviceDirection': {key: 'deviceDirection', type:'Number', len:null,  discription: 'Any information about what direction the observed communication has taken. The following values are supported: “0” for inbound or “1” for outbound'},
    +        'deviceDnsDomain': {key: 'deviceDns Domain', type:'String', len:255,  discription: 'The DNS domain part of the complete fully qualified domain name (FQDN).'},
    +        'deviceExternalId': {key: 'device ExternalId', type:'String', len:255,  discription: 'A name that uniquely identifies the device generating this event.'},
    +        'deviceFacility': {key: 'deviceFacility', type:'String', len:1023,  discription: 'The facility generating this event. For example, Syslog has an explicit facility associated with every event.'},
    +        'deviceInboundInterface': {key: 'deviceInbound Interface', type:'String', len:128,  discription: 'Interface on which the packet or data entered the device.'},
    +        'deviceNtDomain': {key: 'deviceNt Domain', type:'String', len:255,  discription: 'The Windows domain name of the device address.'},
    +        'deviceOutboundInterface': {key: 'Device Outbound Interface', type:'String', len:128,  discription: 'Interface on which the packet or data left the device.'},
    +        'devicePayloadId': {key: 'Device PayloadId', type:'String', len:128,  discription: 'Unique identifier for the payload associated with the event.'},
    +        'deviceProcessName': {key: 'deviceProcess Name', type:'String', len:1023,  discription: 'Process name associated with the event. An example might be the process generating the syslog entry in UNIX.'},
    +        'deviceTranslatedAddress': {key: 'device Translated Address', type:'String', len:null,  discription: 'Identifies the translated device address that the event refers to in an IP network. The format is an IPv4 address. Example: “192.168.10.1”'},
    +        'destinationHostName': {key: 'dhost', type:'String', len:1023,  discription: 'Identifies the destination that an event refers to in an IP network. The format should be a fully qualified domain name (FQDN) associated with the destination node, when a node is available. Examples: “host.domain.com” or “host”.'},
    +        'destinationMacAddress': {key: 'dmac', type:'String', len:null,  discription: 'Six colon-seperated hexadecimal numbers. Example: “00:0D:60:AF:1B:61”'},
    +        'destinationNtDomain': {key: 'dntdom', type:'String', len:255,  discription: 'The Windows domain name of the destination address.'},
    +        'destinationProcessId': {key: 'dpid', type:'Number', len:null,  discription: 'Provides the ID of the destination process associated with the event. For example, if an event contains process ID 105, “105” is the process ID.'},
    +        'destinationUserPrivileges': {key: 'dpriv', type:'String', len:1023,  discription: 'The typical values are “Administrator”, “User”, and “Guest”. This identifies the destination user’s privileges. In UNIX, for example, activity executed on the root user would be identified with destinationUser Privileges of “Administrator”.'},
    +        'destinationProcessName': {key: 'dproc', type:'String', len:1023,  discription: 'The name of the event’s destination process. Example: “telnetd” or “sshd”.'},
    +        'destinationPort': {key: 'dpt', type:'Number', len:null,  discription: 'The valid port numbers are between 0 and 65535.'},
    +        'destinationAddress': {key: 'dst', type:'String', len:null,  discription: 'Identifies the destination address that the event refers to in an IP network. The format is an IPv4 address. Example: “192.168.10.1”'},
    +        'deviceTimeZone': {key: 'dtz', type:'String', len:255,  discription: 'The timezone for the device generating the event.'},
    +        'destinationUserId': {key: 'duid', type:'String', len:1023,  discription: 'Identifies the destination user by ID. For example, in UNIX, the root user is generally associated with user ID 0.'},
    +        'destinationUserName': {key: 'duser', type:'String', len:1023,  discription: 'Identifies the destination user by name. This is the user associated with the event’s destination. Email addresses are often mapped into the UserName fields. The recipient is a candidate to put into this field.'},
    +        'deviceAddress': {key: 'dvc', type:'String', len:null,  discription: 'Identifies the device address that an event refers to in an IP network. The format is an IPv4 address. Example: “192.168.10.1”.'},
    +        'deviceHostName': {key: 'dvchost', type:'String', len:100,  discription: 'The format should be a fully qualified domain name (FQDN) associated with the device node, when a node is available. Example: “host.domain.com” or “host”.'},
    +        'deviceMacAddress': {key: 'dvcmac', type:'String', len:null,  discription: 'Six colon-separated hexadecimal numbers. Example: “00:0D:60:AF:1B:61”'},
    +        'deviceProcessId': {key: 'dvcpid', type:'Number', len:null,  discription: 'Provides the ID of the process on the device generating the event.'},
    +        'endTime': {key: 'end', type:'String', len:null,  discription: 'The time at which the activity related to the event ended. The format is MMM dd yyyy HH:mm:ss or milliseconds since epoch (Jan 1st1970). An example would be reporting the end of a session.'},
    +        'externalId': {key: 'externalId', type:'String', len:40,  discription: 'The ID used by an originating device. They are usually increasing numbers, associated with events.'},
    +        'fileCreateTime': {key: 'fileCreateTime', type:'String', len:null,  discription: 'Time when the file was created.'},
    +        'fileHash': {key: 'fileHash', type:'String', len:255,  discription: 'Hash of a file.'},
    +        'fileId': {key: 'fileId', type:'String', len:1023,  discription: 'An ID associated with a file could be the inode.'},
    +        'fileModificationTime': {key: 'fileModification Time', type:'String', len:null,  discription: 'Time when the file was last modified.'},
    +        'filePath': {key: 'filePath', type:'String', len:1023,  discription: 'Full path to the file, including file name itself. Example: C:\Program Files \WindowsNT\Accessories\ wordpad.exe or /usr/bin/zip'},
    +        'filePermission': {key: 'filePermission', type:'String', len:1023,  discription: 'Permissions of the file.'},
    +        'fileType': {key: 'fileType', type:'String', len:1023,  discription: 'Type of file (pipe, socket, etc.)'},
    +        'flexDate1': {key: 'flexDate1', type:'String', len:null,  discription: 'A timestamp field available to map a timestamp that does not apply to any other defined timestamp field in this dictionary. Use all flex fields sparingly and seek a more specific, dictionary supplied field when possible. These fields are typically reserved for customer use and should not be set by vendors unless necessary.'},
    +        'flexDate1Label': {key: 'flexDate1Label', type:'String', len:128,  discription: 'The label field is a string and describes the purpose of the flex field.'},
    +        'flexString1': {key: 'flexString1', type:'String', len:1023,  discription: 'One of four floating point fields available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible. These fields are typically reserved for customer use and should not be set by vendors unless necessary.'},
    +        'flexString1Label': {key: 'flexString1 Label', type:'String', len:128,  discription: 'The label field is a string and describes the purpose of the flex field.'},
    +        'flexString2': {key: 'flexString2', type:'String', len:1023,  discription: 'One of four floating point fields available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible. These fields are typically reserved for customer use and should not be set by vendors unless necessary.'},
    +        'flexString2Label': {key: 'flex String2Label', type:'String', len:128,  discription: 'The label field is a string and describes the purpose of the flex field.'},
    +        'filename': {key: 'fname', type:'String', len:1023,  discription: 'Name of the file only (without its path).'},
    +        'fileSize': {key: 'fsize', type:'Number', len:null,  discription: 'Size of the file.'},
    +        'bytesIn': {key: 'in', type:'Number', len:null,  discription: 'Number of bytes transferred inbound, relative to the source to destination relationship, meaning that data was flowing from source to destination.'},
    +        'message': {key: 'msg', type:'String', len:1023,  discription: 'An arbitrary message giving more details about the event. Multi-line entries can be produced by using \n as the new line separator.'},
    +        'oldFileCreateTime': {key: 'oldFileCreate Time', type:'String', len:null,  discription: 'Time when old file was created.'},
    +        'oldFileHash': {key: 'oldFileHash', type:'String', len:255,  discription: 'Hash of the old file.'},
    +        'oldFileId': {key: 'oldFileId', type:'String', len:1023,  discription: 'An ID associated with the old file could be the inode.'},
    +        'oldFileModificationTime': {key: 'oldFile Modification Time', type:'String', len:null,  discription: 'Time when old file was last modified.'},
    +        'oldFileName': {key: 'oldFileName', type:'String', len:1023,  discription: 'Name of the old file.'},
    +        'oldFilePath': {key: 'oldFilePath', type:'String', len:1023,  discription: 'Full path to the old fiWindowsNT\Accessories le, including the file name itself. Examples: c:\Program Files\wordpad.exe or /usr/bin/zip'},
    +        'oldFileSize': {key: 'oldFileSize', type:'Number', len:null,  discription: 'Size of the old file.'},
    +        'oldFileType': {key: 'oldFileType', type:'String', len:1023,  discription: 'Type of the old file (pipe, socket, etc.)'},
    +        'bytesOut': {key: 'out', type:'Number', len:null,  discription: 'Number of bytes transferred outbound relative to the source to destination relationship. For example, the byte number of data flowing from the destination to the source.'},
    +        'eventOutcome': {key: 'outcome', type:'String', len:63,  discription: 'Displays the outcome, usually as ‘success’ or ‘failure’.'},
    +        'transportProtocol': {key: 'proto', type:'String', len:31,  discription: 'Identifies the Layer-4 protocol used. The possible values are protocols such as TCP or UDP.'},
    +        'Reason': {key: 'reason', type:'String', len:1023,  discription: 'The reason an audit event was generated. For example “badd password” or “unknown user”. This could also be an error or return code. Example: “0x1234”'},
    +        'requestUrl': {key: 'request', type:'String', len:1023,  discription: 'In the case of an HTTP request, this field contains the URL accessed. The URL should contain the protocol as well. Example: “http://www/secure.com”'},
    +        'requestClientApplication': {key: 'requestClient Application', type:'String', len:1023,  discription: 'The User-Agent associated with the request.'},
    +        'requestContext': {key: 'requestContext', type:'String', len:2048,  discription: 'Description of the content from which the request originated (for example, HTTP Referrer)'},
    +        'requestCookies': {key: 'requestCookies', type:'String', len:1023,  discription: 'Cookies associated with the request.'},
    +        'requestMethod': {key: 'requestMethod', type:'String', len:1023,  discription: 'The method used to access a URL. Possible values: “POST”, “GET”, etc.'},
    +        'deviceReceiptTime': {key: 'rt', type:'String', len:null,  discription: 'The time at which the event related to the activity was received. The format is MMM dd yyyy HH:mm:ss or milliseconds since epoch (Jan 1st 1970)'},
    +        'sourceHostName': {key: 'shost', type:'String', len:1023,  discription: 'Identifies the source that an event refers to in an IP network. The format should be a fully qualified domain name (DQDN) associated with the source node, when a mode is available. Examples: “host” or “host.domain.com”.'},
    +        'sourceMacAddress': {key: 'smac', type:'String', len:null,  discription: 'Six colon-separated hexadecimal numbers. Example: “00:0D:60:AF:1B:61”'},
    +        'sourceNtDomain': {key: 'sntdom', type:'String', len:255,  discription: 'The Windows domain name for the source address.'},
    +        'sourceDnsDomain': {key: 'sourceDns Domain', type:'String', len:255,  discription: 'The DNS domain part of the complete fully qualified domain name (FQDN).'},
    +        'sourceServiceName': {key: 'source ServiceName', type:'String', len:1023,  discription: 'The service that is responsible for generating this event.'},
    +        'sourceTranslatedAddress': {key: 'source Translated Address', type:'String', len:null,  discription: 'Identifies the translated source that the event refers to in an IP network. The format is an IPv4 address. Example: “192.168.10.1”.'},
    +        'sourceTranslatedPort': {key: 'source TranslatedPort', type:'Number', len:null,  discription: 'A port number after being translated by, for example, a firewall. Valid port numbers are 0 to 65535.'},
    +        'sourceProcessId': {key: 'spid', type:'Number', len:null,  discription: 'The ID of the source process associated with the event.'},
    +        'sourceUserPrivileges': {key: 'spriv', type:'String', len:1023,  discription: 'The typical values are “Administrator”, “User”, and “Guest”. It identifies the source user’s privileges. In UNIX, for example, activity executed by the root user would be identified with “Administrator”.'},
    +        'sourceProcessName': {key: 'sproc', type:'String', len:1023,  discription: 'The name of the event’s source process.'},
    +        'sourcePort': {key: 'spt', type:'Number', len:null,  discription: 'The valid port numbers are 0 to 65535.'},
    +        'sourceAddress': {key: 'src', type:'String', len:null,  discription: 'Identifies the source that an event refers to in an IP network. The format is an IPv4 address. Example: “192.168.10.1”.'},
    +        'startTime': {key: 'start', type:'String', len:null,  discription: 'The time when the activity the event referred to started. The format is MMM dd yyyy HH:mm:ss or milliseconds since epoch (Jan 1st 1970)'},
    +        'sourceUserId': {key: 'suid', type:'String', len:1023,  discription: 'Identifies the source user by ID. This is the user associated with the source of the event. For example, in UNIX, the root user is generally associated with user ID 0.'},
    +        'sourceUserName': {key: 'suser', type:'String', len:1023,  discription: 'Identifies the source user by name. Email addresses are also mapped into the UserName fields. The sender is a candidate to put into this field.'},
    +        'type': {key: 'type', type:'Number', len:null,  discription: '0 means base event, 1 means aggregated, 2 means correlation, and 3 means action. This field can be omitted for base events (type 0).'},
    +        'agentDnsDomain': {key: 'agentDns Domain', type:'String', len:255,  discription: 'The DNS domain name of the ArcSight connector that processed the event.'},
    +        'agentNtDomain': {key: 'agentNtDomain', type:'String', len:255,  discription: ''},
    +        'agentTranslatedAddress': {key: 'agentTranslated Address', type:'String', len:null,  discription: ''},
    +        'agentTranslatedZone ExternalID': {key: 'agentTranslated ZoneExternalID', type:'String', len:200,  discription: ''},
    +        'agentTranslatedZoneURI': {key: 'agentTranslated Zone URI', type:'String', len:2048,  discription: ''},
    +        'agentZoneExternalID': {key: 'agentZone ExternalID', type:'String', len:200,  discription: ''},
    +        'agentZoneURI': {key: 'agentZoneURI', type:'String', len:2048,  discription: ''},
    +        'agentAddress': {key: 'agt', type:'String', len:null,  discription: 'The IP address of the ArcSight connector that processed the event.'},
    +        'agentHostName': {key: 'ahost', type:'String', len:1023,  discription: 'The hostname of the ArcSight connector that processed the event.'},
    +        'agentId': {key: 'aid', type:'String', len:40,  discription: 'The agent ID of the ArcSight connector that processed the event.'},
    +        'agentMacAddress': {key: 'amac', type:'String', len:null,  discription: 'The MAC address of the ArcSight connector that processed the event.'},
    +        'agentReceiptTime': {key: 'art', type:'String', len:null,  discription: 'The time at which information about the event was received by the ArcSight connector.'},
    +        'agentType': {key: 'at', type:'String', len:63,  discription: 'The agent type of the ArcSight connector that processed the event'},
    +        'agentTimeZone': {key: 'atz', type:'String', len:255,  discription: 'The agent time zone of the ArcSight connector that processed the event.'},
    +        'agentVersion': {key: 'av', type:'String', len:31,  discription: 'The version of the ArcSight connector that processed the event.'},
    +        'customerExternalID': {key: 'customer ExternalID', type:'String', len:200,  discription: ''},
    +        'customerURI': {key: 'customerURI', type:'String', len:2048,  discription: ''},
    +        'destinationTranslated ZoneExternalID': {key: 'destination TranslatedZone ExternalID', type:'String', len:200,  discription: ''},
    +        'destinationTranslated ZoneURI': {key: 'destination Translated ZoneURI', type:'String', len:2048,  discription: 'The URI for the Translated Zone that the destination asset has been assigned to in ArcSight.'},
    +        'destinationZoneExternalID': {key: 'destinationZone ExternalID', type:'String', len:200,  discription: ''},
    +        'destinationZoneURI': {key: 'destinationZone URI', type:'String', len:2048,  discription: 'The URI for the Zone that the destination asset has been assigned to in ArcSight.'},
    +        'deviceTranslatedZone ExternalID': {key: 'device TranslatedZone ExternalID', type:'String', len:200,  discription: ''},
    +        'deviceTranslatedZoneURI': {key: 'device TranslatedZone URI', type:'String', len:2048,  discription: 'The URI for the Translated Zone that the device asset has been assigned to in ArcSight.'},
    +        'deviceZoneExternalID': {key: 'deviceZone ExternalID', type:'String', len:200,  discription: ''},
    +        'deviceZoneURI': {key: 'deviceZoneURI', type:'String', len:2048,  discription: 'Thee URI for the Zone that the device asset has been assigned to in ArcSight.'},
    +        'destinationGeoLatitude': {key: 'dlat', type:'Number', len:null,  discription: 'The latitudinal value from which the destination’s IP address belongs.'},
    +        'destinationGeoLongitude': {key: 'dlong', type:'Number', len:null,  discription: 'The longitudinal value from which the destination’s IP address belongs.'},
    +        'eventId': {key: 'eventId', type:'Number', len:null,  discription: 'This is a unique ID that ArcSight assigns to each event.'},
    +        'rawEvent': {key: 'rawEvent', type:'String', len:4000,  discription: ''},
    +        'sourceGeoLatitude': {key: 'slat', type:'Number', len:null,  discription: ''},
    +        'sourceGeoLongitude': {key: 'slong', type:'Number', len:null,  discription: ''},
    +        'sourceTranslatedZone ExternalID': {key: 'source TranslatedZone ExternalID', type:'String', len:200,  discription: ''},
    +        'sourceTranslatedZoneURI': {key: 'source TranslatedZone URI', type:'String', len:2048,  discription: 'The URI for the Translated Zone that the destination asset has been assigned to in ArcSight.'},
    +        'sourceZoneExternalID': {key: 'sourceZone ExternalID', type:'String', len:200,  discription: ''},
    +        'sourceZoneURI': {key: 'sourceZoneURI', type:'String', len:2048,  discription: 'The URI for the Zone that the source asset has been assigned to in ArcSight.'},
    +      };
    +      if (typeof this.deviceVendor !== 'string'
    +          || typeof this.deviceProduct !== 'string'
    +          || typeof this.deviceVersion !== 'string'
    +      ) {
    +        reject(new Error('TYPE ERROR: CEF Device Info must be a string'));
    +      }
    +      if (this.severity
    +          && (
    +            (
    +              typeof this.severity === 'string'
    +              && (
    +                this.severity !== 'Unknown'
    +                && this.severity !== 'Low'
    +                && this.severity !== 'Medium'
    +                && this.severity !== 'High'
    +                && this.severity !== 'Very-High'
    +              )
    +            )
    +            || (
    +              typeof this.severity === 'number'
    +              && (
    +                this.severity < 0
    +                || this.severity > 10
    +              )
    +            )
    +          )
    +      ) {
    +        reject(new Error('TYPE ERROR: CEF Severity not set correctly'));
    +      }
    +      const cefExts = Object.entries(this.extensions);
    +      const cefExtsLen = cefExts.length;
    +      for (let ext = 0; ext < cefExtsLen; ext++) {
    +        if (cefExts[ext][1] !== null) {
    +          if(Extensions[cefExts[ext][0]]) {
    +            if (typeof cefExts[ext][1] === Extensions[cefExts[ext][0]]
    +                .type
    +                .toLowerCase()) {
    +              if (Extensions[cefExts[ext][0]].len > 0
    +                  && typeof cefExts[ext][1] === 'string'
    +                  && cefExts[ext][1].length > Extensions[cefExts[ext][0]].len){
    +                let errMsg = 'FORMAT ERROR:';
    +                errMsg += ' CEF Extention Key';
    +                errMsg += ' ' + cefExts[ext][0];
    +                errMsg += ' value length is to long;';
    +                errMsg += ' max length is';
    +                errMsg += ' ' + Extensions[cefExts[ext][0]].len;
    +                reject(new Error(errMsg));
    +              }
    +            } else {
    +              let errMsg = 'TYPE ERROR:';
    +              errMsg += ' CEF Key';
    +              errMsg += ' ' + cefExts[ext][0];
    +              errMsg += ' value type was expected to be';
    +              errMsg += ' ' + Extensions[cefExts[ext][0]].type.toLowerCase();
    +              reject(new Error(errMsg));
    +            }
    +          }
    +        }
    +      }
    +      resolve(true);
    +    });
    +  }
    +  /**
    +   * Build a CEF formated string
    +   * @public
    +   * @return {Promise} - String with formated message
    +   */    
    +  buildMessage () {
    +    return new Promise((resolve, reject) => {
    +      let fmtMsg = 'CEF:0';
    +      fmtMsg += '|' + this.deviceVendor;
    +      fmtMsg += '|' + this.deviceProduct;
    +      fmtMsg += '|' + this.deviceVersion;
    +      fmtMsg += '|' + this.deviceEventClassId;
    +      fmtMsg += '|' + this.name;
    +      fmtMsg += '|' + this.severity;
    +      fmtMsg += '|';
    +      
    +      const cefExts = Object.entries(this.extensions);
    +      const cefExtsLen = cefExts.length;
    +      for (let ext = 0; ext < cefExtsLen; ext++) {
    +        if (cefExts[ext][1] !== null) {
    +          fmtMsg += cefExts[ext][0] + '=' + cefExts[ext][1] + ' ';
    +        }
    +      }
    +      resolve(fmtMsg);
    +    });
    +  }
    +  /**
    +   * @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
    +   */
    +  send (options) {
    +    return new Promise((resolve, reject) => {
    +      this.buildMessage()
    +        .then((result) => {
    +          if (!this.server) {
    +            this.server = new Syslog(options);
    +          }
    +          this.server.send(result)
    +            .then((sendResult) => {
    +              resolve(sendResult);
    +            })
    +            .catch((reson) => {
    +              reject(reson);
    +            });
    +        });
    +    });
    +  }
    +}
    +
    +module.exports = {
    +  RgbToAnsi: rgbToAnsi,
    +  RFC3164: RFC3164,
    +  RFC5424:RFC5424,
    +  LEEF: LEEF,
    +  CEF: CEF,
    +  Syslog: Syslog
    +};
    + +
  • + +
+
+ + diff --git a/docs/docco/public/fonts/aller-bold.eot b/docs/docco/public/fonts/aller-bold.eot new file mode 100644 index 0000000000000000000000000000000000000000..1b32532a8e40e483069482c3650c3ef22ef16bdd GIT binary patch literal 29804 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 F>VRGqwvGS* literal 0 HcmV?d00001 diff --git a/docs/docco/public/fonts/aller-bold.ttf b/docs/docco/public/fonts/aller-bold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..dc4cc9c27a59ab14fbb7444c6ab35c5b33a034f6 GIT binary patch literal 66836 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%0AAIIsziQtyhPht7#*LdNqb{-ye3^( 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ⅆA*wV|2E?UgaO-298Xthc^!eoT=hLnT61q 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 literal 0 HcmV?d00001 diff --git a/docs/docco/public/fonts/aller-bold.woff b/docs/docco/public/fonts/aller-bold.woff new file mode 100644 index 0000000000000000000000000000000000000000..fa16fd0aba81582de121d833c7bc50e8f1b1b981 GIT binary patch literal 33244 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

--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 q6yXA@F-u0Z~1!1poleYR}~W literal 0 HcmV?d00001 diff --git a/docs/docco/public/fonts/aller-light.eot b/docs/docco/public/fonts/aller-light.eot new file mode 100644 index 0000000000000000000000000000000000000000..40bd654b5fe63501ae64d5673b5aa45051a69e65 GIT binary patch literal 29509 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�y6>nTFX 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 literal 0 HcmV?d00001 diff --git a/docs/docco/public/fonts/roboto-black.eot b/docs/docco/public/fonts/roboto-black.eot new file mode 100755 index 0000000000000000000000000000000000000000..571ed49125910cd6b6b5a9259134dd2e8d37766e GIT binary patch literal 20702 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
~sO?6glRGZi8n^KyFR=i1erVaJp>l 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

  • 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 X3&Ic#E%XNK++i8SYTo{GJ<-1bF1c8o literal 0 HcmV?d00001 diff --git a/docs/docco/public/fonts/roboto-black.woff b/docs/docco/public/fonts/roboto-black.woff new file mode 100755 index 0000000000000000000000000000000000000000..642e5b60f7c662ab5bcf67cfc1089f50bfdd7b00 GIT binary patch literal 24536 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‚ZNmb*+jwao2 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 E0ADU%yZ`_I literal 0 HcmV?d00001 diff --git a/docs/docco/public/stylesheets/normalize.css b/docs/docco/public/stylesheets/normalize.css new file mode 100644 index 0000000..73abb76 --- /dev/null +++ b/docs/docco/public/stylesheets/normalize.css @@ -0,0 +1,375 @@ +/*! normalize.css v2.0.1 | MIT License | git.io/normalize */ + +/* ========================================================================== + HTML5 display definitions + ========================================================================== */ + +/* + * Corrects `block` display not defined in IE 8/9. + */ + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +nav, +section, +summary { + display: block; +} + +/* + * Corrects `inline-block` display not defined in IE 8/9. + */ + +audio, +canvas, +video { + display: inline-block; +} + +/* + * Prevents modern browsers from displaying `audio` without controls. + * Remove excess height in iOS 5 devices. + */ + +audio:not([controls]) { + display: none; + height: 0; +} + +/* + * Addresses styling for `hidden` attribute not present in IE 8/9. + */ + +[hidden] { + display: none; +} + +/* ========================================================================== + Base + ========================================================================== */ + +/* + * 1. Sets default font family to sans-serif. + * 2. Prevents iOS text size adjust after orientation change, without disabling + * user zoom. + */ + +html { + font-family: sans-serif; /* 1 */ + -webkit-text-size-adjust: 100%; /* 2 */ + -ms-text-size-adjust: 100%; /* 2 */ +} + +/* + * Removes default margin. + */ + +body { + margin: 0; +} + +/* ========================================================================== + Links + ========================================================================== */ + +/* + * Addresses `outline` inconsistency between Chrome and other browsers. + */ + +a:focus { + outline: thin dotted; +} + +/* + * Improves readability when focused and also mouse hovered in all browsers. + */ + +a:active, +a:hover { + outline: 0; +} + +/* ========================================================================== + Typography + ========================================================================== */ + +/* + * Addresses `h1` font sizes within `section` and `article` in Firefox 4+, + * Safari 5, and Chrome. + */ + +h1 { + font-size: 2em; +} + +/* + * Addresses styling not present in IE 8/9, Safari 5, and Chrome. + */ + +abbr[title] { + border-bottom: 1px dotted; +} + +/* + * Addresses style set to `bolder` in Firefox 4+, Safari 5, and Chrome. + */ + +b, +strong { + font-weight: bold; +} + +/* + * Addresses styling not present in Safari 5 and Chrome. + */ + +dfn { + font-style: italic; +} + +/* + * Addresses styling not present in IE 8/9. + */ + +mark { + background: #ff0; + color: #000; +} + + +/* + * Corrects font family set oddly in Safari 5 and Chrome. + */ + +code, +kbd, +pre, +samp { + font-family: monospace, serif; + font-size: 1em; +} + +/* + * Improves readability of pre-formatted text in all browsers. + */ + +pre { + white-space: pre; + white-space: pre-wrap; + word-wrap: break-word; +} + +/* + * Sets consistent quote types. + */ + +q { + quotes: "\201C" "\201D" "\2018" "\2019"; +} + +/* + * Addresses inconsistent and variable font size in all browsers. + */ + +small { + font-size: 80%; +} + +/* + * Prevents `sub` and `sup` affecting `line-height` in all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +/* ========================================================================== + Embedded content + ========================================================================== */ + +/* + * Removes border when inside `a` element in IE 8/9. + */ + +img { + border: 0; +} + +/* + * Corrects overflow displayed oddly in IE 9. + */ + +svg:not(:root) { + overflow: hidden; +} + +/* ========================================================================== + Figures + ========================================================================== */ + +/* + * Addresses margin not present in IE 8/9 and Safari 5. + */ + +figure { + margin: 0; +} + +/* ========================================================================== + Forms + ========================================================================== */ + +/* + * Define consistent border, margin, and padding. + */ + +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} + +/* + * 1. Corrects color not being inherited in IE 8/9. + * 2. Remove padding so people aren't caught out if they zero out fieldsets. + */ + +legend { + border: 0; /* 1 */ + padding: 0; /* 2 */ +} + +/* + * 1. Corrects font family not being inherited in all browsers. + * 2. Corrects font size not being inherited in all browsers. + * 3. Addresses margins set differently in Firefox 4+, Safari 5, and Chrome + */ + +button, +input, +select, +textarea { + font-family: inherit; /* 1 */ + font-size: 100%; /* 2 */ + margin: 0; /* 3 */ +} + +/* + * Addresses Firefox 4+ setting `line-height` on `input` using `!important` in + * the UA stylesheet. + */ + +button, +input { + line-height: normal; +} + +/* + * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` + * and `video` controls. + * 2. Corrects inability to style clickable `input` types in iOS. + * 3. Improves usability and consistency of cursor style between image-type + * `input` and others. + */ + +button, +html input[type="button"], /* 1 */ +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; /* 2 */ + cursor: pointer; /* 3 */ +} + +/* + * Re-set default cursor for disabled elements. + */ + +button[disabled], +input[disabled] { + cursor: default; +} + +/* + * 1. Addresses box sizing set to `content-box` in IE 8/9. + * 2. Removes excess padding in IE 8/9. + */ + +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} + +/* + * 1. Addresses `appearance` set to `searchfield` in Safari 5 and Chrome. + * 2. Addresses `box-sizing` set to `border-box` in Safari 5 and Chrome + * (include `-moz` to future-proof). + */ + +input[type="search"] { + -webkit-appearance: textfield; /* 1 */ + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; /* 2 */ + box-sizing: content-box; +} + +/* + * Removes inner padding and search cancel button in Safari 5 and Chrome + * on OS X. + */ + +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/* + * Removes inner padding and border in Firefox 4+. + */ + +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} + +/* + * 1. Removes default vertical scrollbar in IE 8/9. + * 2. Improves readability and alignment in all browsers. + */ + +textarea { + overflow: auto; /* 1 */ + vertical-align: top; /* 2 */ +} + +/* ========================================================================== + Tables + ========================================================================== */ + +/* + * Remove most spacing between table cells. + */ + +table { + border-collapse: collapse; + border-spacing: 0; +} \ No newline at end of file diff --git a/docs/index.html b/docs/index.html index 9520683..8183c56 100644 --- a/docs/index.html +++ b/docs/index.html @@ -50,92 +50,107 @@

    -

    SyslogPro

    A pure Javascript Syslog module with support for RFC3164, RFC5424, IBM LEEF +

    SyslogPro

    Build Status +Coverage Status +

    +

    Site | +Docs | +Wiki | +Code of Conduct

    +

    A pure Javascript Syslog module with support for RFC3164, RFC5424, IBM LEEF (Log Event Extended Format), and HP CEF (Common Event Format) formatted -messages. SyslogPro has transport options of UDP, TCP, and TLS. TLS includes -support for Server and Client certificate authrization. For unformatedm and +messages. SyslogPro has transport options for UDP, TCP, and TLS. TLS includes +support for Server and Client certificate authorization. For unformatted and RFC messages there is support for Basic and Extended ANSI coloring. RFC5424 -Strucutred Data is also encluded in the module. All 28 standard CEF Extentions -are included in the defualt CEF class. All 45 standard LEEF Atrabutes are -included in the defualt LEEF class. It is the goal of this project is for every -relase to offer full code covrage unit testing and documentation. Please see -the full documation for usage and options.

    -

    Installation

    npm install SyslogPro

    -

    Usage

    const SyslogPro = require('syslogpro');
    -
    -let syslog = new SyslogPro.Syslog({
    -  target: 'localhost',
    -  protocol: 'udp',
    -  format: 'rfc5424'
    -});
    -
    -syslog.rfc5424.info('My Message');
    -
    -// Optionaly you can create each class or class options to pass to SyslogPro
    -// to create formated messages or use directly
    -
    -let rfc3164 = new SyslogPro.RFC3164({
    -  applacationName: 'MyApp',
    -  color: true,
    -  extendedColor: true,
    -  server: {
    -    target: 'myServer.fqdn'
    -  }
    -});
    -
    -rfc3164.info('My Message');
    -
    -let rfc5424 = new SyslogPro.RFC5424({
    -  applacationName: 'MyApp',
    -  timestamp: true,
    -  encludeStructuredData: true
    -  color: true,
    -  extendedColor: true,
    -  server: {
    -    target: 'myServer.fqdn'
    -  }
    -});
    -
    -rfc5424.info('My Message');
    -
    -let leef = new SyslogPro.LEEF({
    -  vendor: 'acme',
    -  product: 'doohickey1000',
    -  version: 'alpha',
    -  eventId: 'hack',
    -  attrabutes: {
    -    cat: 'CC Databreach'
    -  },
    -  server: {
    -    target: 'myServer.fqdn'
    -  }
    -})
    -    .send()
    -        .then((result) => {})
    -        .catch((error) => {
    -          console.log(error);
    -        });
    -
    -let cef = new SyslogPro.CEF({
    -  deviceVendor: 'acme',
    -  deviceProduct: 'doohickey1000',
    -  deviceVersion: 'alpha',
    -  deviceEventClassId: 'hack',
    -  name: 'My Reporting Service',
    -  severity: 'High',
    -  extensions: {
    -    rawEvent: 'CC Databreach'
    -  },
    -  server: {
    -    target: 'myServer.fqdn'
    -  }
    -})
    -    .send()
    -        .then((result) => {})
    -        .catch((error) => {
    -          console.log(error);
    -        });

    Tests

    npm test

    -

    Contributing

    Please try to stay close to the Google JS Style Guid, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code.

    +Structured Data is also included in the module. All 28 standard CEF Extensions +are included in the default CEF class. All 45 standard LEEF Attributes are +included in the default LEEF class. It is the goal of this project is for +every release to offer full code coverage unit testing and documentation.

    +

    Please see the full JSDoc for usage and options: +https://cyamato.github.io/SyslogPro/.

    +

    News

    +

    Installation

      npm install --save SyslogPro

    Usage

      const SyslogPro = require('syslogpro');
    +  let syslog = new SyslogPro.Syslog({
    +    target: 'localhost',
    +    protocol: 'udp',
    +    format: 'rfc5424'
    +  });
    +  syslog.rfc5424.info('My Message');

    Optionaly you can create each class or class options to pass to SyslogPro + to create formated messages or use directly

    +

    RFC3164

    +
      let rfc3164 = new SyslogPro.RFC3164({
    +    applacationName: 'MyApp',
    +    color: true,
    +    extendedColor: true,
    +    server: {
    +      target: 'myServer.fqdn'
    +    }
    +  });
    +  rfc3164.info('My Message');

    RFC5424

    +
      let rfc5424 = new SyslogPro.RFC5424({
    +    applacationName: 'MyApp',
    +    timestamp: true,
    +    encludeStructuredData: true
    +    color: true,
    +    extendedColor: true,
    +    server: {
    +      target: 'myServer.fqdn'
    +    }
    +  });
    +  rfc5424.info('My Message');

    LEEF (Log Event Extended Format)

    +
      let leef = new SyslogPro.LEEF({
    +    vendor: 'acme',
    +    product: 'doohickey1000',
    +    version: 'alpha',
    +    eventId: 'hack',
    +    attrabutes: {
    +      cat: 'CC Databreach'
    +    },
    +    server: {
    +      target: 'myServer.fqdn'
    +    }
    +  })
    +      .send()
    +          .then((result) => {})
    +          .catch((error) => {
    +            console.log(error);
    +          });

    CEF (Common Event Format)

    +
      let cef = new SyslogPro.CEF({
    +    deviceVendor: 'acme',
    +    deviceProduct: 'doohickey1000',
    +    deviceVersion: 'alpha',
    +    deviceEventClassId: 'hack',
    +    name: 'My Reporting Service',
    +    severity: 'High',
    +    extensions: {
    +      rawEvent: 'CC Databreach'
    +    },
    +    server: {
    +      target: 'myServer.fqdn'
    +    }
    +  })
    +      .send()
    +          .then((result) => {})
    +          .catch((error) => {
    +            console.log(error);
    +          });

    API

    For more details see:

    + +

    Test

      npm test

    Contributing

    Please try to maintain the existing coding style. Add unit tests for any new or +changed functionality. Lint and test your code.

    +
    @@ -150,7 +165,7 @@ let cef = new SyslogPro.CEF({
    - Documentation generated by JSDoc 3.5.5 on Mon Sep 24 2018 06:41:35 GMT+0000 (Coordinated Universal Time) using the docdash theme. + Documentation generated by JSDoc 3.5.5 on Tue Sep 25 2018 18:22:00 GMT+0000 (Coordinated Universal Time) using the docdash theme.
    diff --git a/docs/index.js.html b/docs/index.js.html index 629bd2d..a363064 100644 --- a/docs/index.js.html +++ b/docs/index.js.html @@ -44,11 +44,17 @@
    /** Copyright (c) 2018 Craig Yamato */
     
     /**
    - * @fileoverview The SyslogPro class for sending syslog messages
    + * @fileoverview The SyslogPro module for sending syslog messages
    + * Most APIs will return a promise. These APIs can be used using 
    + * `then(...)/catch(...)`
    + *
    + * Syslog formating classes can be used as input into a Syslog class to be used 
    + * simultatniusly to the same Syslog server.  The Syslog Class with a configured
    + * Syslog server target can also be used as the input into each of the formating 
    + * classes so that they may run independtly.
      * @author Craig Yamato <craig@kentik.com>
      * @copyright (c) 2018 - Craig Yamato
    - * @version 0.0.0
    - * @since 0.0.0
    + * @version 0.1.0
      * @exports Syslog
      * @exports LEEF
      * @exports CEF
    @@ -133,15 +139,16 @@ function rgbToAnsi (hex, extendedColor) {
      * A class to work with syslog messages using UDP, TCP, or TLS transport.  
      * There is suport for Syslog message formating RFC-3164, RFC-5424 including 
      * Structured Data, IBM LEEF (Log Event Extended Format), and HP CEF (Common
    - * Event Format). The meesaging is fully configurabule and Ansi foreground 
    - * colors can be added.  Both ANSI 8 and ANSI 256 color are fully suported.
    + * Event Format).
    + * Syslog formating classes can be used as input into a Syslog class to be used 
    + * simultatniusly to the same Syslog server. * 
      * @requires moment
      * @version 0.0.0
      * @since 0.0.0
      */
     class Syslog {
       /**
    -   * Construct a new Syslog object with user options 
    +   * Construct a new Syslog transport object with user options 
        * @public
        * @version 0.0.0
        * @since 0.0.0
    @@ -486,7 +493,18 @@ class Syslog {
     }
      
     /**
    - * A class to work with RFC3164 formated syslog messages.
    + * A class to work with RFC3164 formated syslog messages. The meesaging is fully configurabule and Ansi foreground 
    + * colors can be added.  Both ANSI 8 and ANSI 256 color are fully suported.
    + * Most APIs will return a promise. These APIs can be used using 
    + * `then(...)/catch(...)`
    + * 
    + * A Syslog class with a configured
    + * Syslog server target can also be used as the input into the formating 
    + * classes so that it may run independtly.
    + * 
    + * The RFC3164 Syslog logging format is ment to be used as a stream of log data 
    + * from a service or applacation. This class is designed to be used in this
    + * fashion where new messages are writen to the class as needed.
      * @requires moment
      * @version 0.0.0
      * @since 0.0.0
    @@ -1034,7 +1052,18 @@ class RFC3164 {
     }
     
     /**
    - * A class to work with RFC5424 formated syslog messages.
    + * A class to work with RFC5424 formated syslog messages. The meesaging is fully configurabule and Ansi foreground 
    + * colors can be added.  Both ANSI 8 and ANSI 256 color are fully suported.
    + * Most APIs will return a promise. These APIs can be used using 
    + * `then(...)/catch(...)`
    + * 
    + * A Syslog class with a configured
    + * Syslog server target can also be used as the input into the formating 
    + * classes so that it may run independtly.
    + * 
    + * The RFC5424 Syslog logging format is ment to be used as a stream of log data 
    + * from a service or applacation. This class is designed to be used in this
    + * fashion where new messages are writen to the class as needed.
      * @requires moment
      * @version 0.0.0
      * @since 0.0.0
    @@ -1704,14 +1733,21 @@ class RFC5424 {
      * of system messages are designed to work with security systems.  Messages can
      * be saved to file (Saving to file if not part of this module but a LEEF 
      * formated mesage produced by this module can be saved externaly to it) or 
    - * sent via Syslog.
    + * sent via Syslog. 
    + * Most APIs will return a promise. These APIs can be used using 
    + * `then(...)/catch(...)`
    + * 
    + * A Syslog class with a configured Syslog server target can also be used as 
    + * the input into the formating classes so that it may run independtly. The 
    + * LEEF format is designed to send event data to a SIEM system and should not 
    + * be as a logging stream. This class is ment to be used once per message.
      * @requires moment
      * @version 0.0.0
      * @since 0.0.0
      */
     class LEEF {
       /**
    -   * Construct a new LEEF object with user options 
    +   * Construct a new LEEF formating object with user options
        * @public
        * @param {object} [options] - Options object
        * @param {string} [options.vendor='unknown'] - The vendor of the system that
    @@ -1862,13 +1898,20 @@ class LEEF {
      * be saved to file (Saving to file if not part of this module but a CEF 
      * formated mesage produced by this module can be saved externaly to it) or 
      * sent via Syslog.
    + * Most APIs will return a promise. These APIs can be used using 
    + * `then(...)/catch(...)`
    + * 
    + * A Syslog class with a configured Syslog server target can also be used as 
    + * the input into the formating classes so that it may run independtly. The CEF 
    + * format is designed to send event data to a SIEM system and should not be as 
    + * a logging stream. This class is ment to be used once per message.
      * @requires moment
      * @version 0.0.0
      * @since 0.0.0
      */
     class CEF {
       /**
    -   * Construct a new CEF object with user options 
    +   * Construct a new CEF formating object with user options 
        * @public
        * @param {object} [options] - Options object
        * @param {string} [options.deviceVendor='unknown'] - The vendor of the system 
    @@ -2373,7 +2416,7 @@ module.exports = {
     
    - Documentation generated by JSDoc 3.5.5 on Mon Sep 24 2018 06:41:35 GMT+0000 (Coordinated Universal Time) using the docdash theme. + Documentation generated by JSDoc 3.5.5 on Tue Sep 25 2018 18:22:00 GMT+0000 (Coordinated Universal Time) using the docdash theme.
    diff --git a/docs/module-SyslogPro-CEF.html b/docs/module-SyslogPro-CEF.html index 2ed9944..b0465d5 100644 --- a/docs/module-SyslogPro-CEF.html +++ b/docs/module-SyslogPro-CEF.html @@ -53,7 +53,14 @@ of system messages are designed to work with security systems. Messages can be saved to file (Saving to file if not part of this module but a CEF formated mesage produced by this module can be saved externaly to it) or -sent via Syslog. +sent via Syslog. +Most APIs will return a promise. These APIs can be used using +`then(...)/catch(...)` + +A Syslog class with a configured Syslog server target can also be used as +the input into the formating classes so that it may run independtly. The CEF +format is designed to send event data to a SIEM system and should not be as +a logging stream. This class is ment to be used once per message. @@ -80,7 +87,7 @@ sent via Syslog.
    Source:
    @@ -126,7 +133,7 @@ sent via Syslog.
    - Construct a new CEF object with user options + Construct a new CEF formating object with user options
    @@ -603,7 +610,7 @@ sent via Syslog.
    Source:
    @@ -662,7 +669,7 @@ sent via Syslog.
    Source:
    @@ -731,7 +738,7 @@ sent via Syslog.
    Source:
    @@ -800,7 +807,7 @@ sent via Syslog.
    Source:
    @@ -869,7 +876,7 @@ sent via Syslog.
    Source:
    @@ -938,7 +945,7 @@ sent via Syslog.
    Source:
    @@ -1007,7 +1014,7 @@ sent via Syslog.
    Source:
    @@ -1076,7 +1083,7 @@ sent via Syslog.
    Source:
    @@ -1135,7 +1142,7 @@ sent via Syslog.
    Source:
    @@ -1214,7 +1221,7 @@ sent via Syslog.
    Source:
    @@ -1320,7 +1327,7 @@ sent via Syslog.
    Source:
    @@ -1470,7 +1477,7 @@ sent via Syslog.
    Source:
    @@ -1608,7 +1615,7 @@ sent via Syslog.
    - Documentation generated by JSDoc 3.5.5 on Mon Sep 24 2018 06:41:35 GMT+0000 (Coordinated Universal Time) using the docdash theme. + Documentation generated by JSDoc 3.5.5 on Tue Sep 25 2018 18:22:00 GMT+0000 (Coordinated Universal Time) using the docdash theme.
    diff --git a/docs/module-SyslogPro-LEEF.html b/docs/module-SyslogPro-LEEF.html index de36096..6fae4e5 100644 --- a/docs/module-SyslogPro-LEEF.html +++ b/docs/module-SyslogPro-LEEF.html @@ -53,7 +53,14 @@ of system messages are designed to work with security systems. Messages can be saved to file (Saving to file if not part of this module but a LEEF formated mesage produced by this module can be saved externaly to it) or -sent via Syslog. +sent via Syslog. +Most APIs will return a promise. These APIs can be used using +`then(...)/catch(...)` + +A Syslog class with a configured Syslog server target can also be used as +the input into the formating classes so that it may run independtly. The +LEEF format is designed to send event data to a SIEM system and should not +be as a logging stream. This class is ment to be used once per message. @@ -80,7 +87,7 @@ sent via Syslog.
    Source:
    @@ -126,7 +133,7 @@ sent via Syslog.
    - Construct a new LEEF object with user options + Construct a new LEEF formating object with user options
    @@ -564,7 +571,7 @@ sent via Syslog.
    Source:
    @@ -633,7 +640,7 @@ sent via Syslog.
    Source:
    @@ -692,7 +699,7 @@ sent via Syslog.
    Source:
    @@ -761,7 +768,7 @@ sent via Syslog.
    Source:
    @@ -830,7 +837,7 @@ sent via Syslog.
    Source:
    @@ -889,7 +896,7 @@ sent via Syslog.
    Source:
    @@ -958,7 +965,7 @@ sent via Syslog.
    Source:
    @@ -1027,7 +1034,7 @@ sent via Syslog.
    Source:
    @@ -1106,7 +1113,7 @@ sent via Syslog.
    Source:
    @@ -1212,7 +1219,7 @@ sent via Syslog.
    Source:
    @@ -1365,7 +1372,7 @@ sent via Syslog.
    - Documentation generated by JSDoc 3.5.5 on Mon Sep 24 2018 06:41:35 GMT+0000 (Coordinated Universal Time) using the docdash theme. + Documentation generated by JSDoc 3.5.5 on Tue Sep 25 2018 18:22:00 GMT+0000 (Coordinated Universal Time) using the docdash theme.
    diff --git a/docs/module-SyslogPro-RFC3164.html b/docs/module-SyslogPro-RFC3164.html index dda9c08..2c7a9d0 100644 --- a/docs/module-SyslogPro-RFC3164.html +++ b/docs/module-SyslogPro-RFC3164.html @@ -49,7 +49,18 @@ RFC3164 -
    A class to work with RFC3164 formated syslog messages.
    +
    A class to work with RFC3164 formated syslog messages. The meesaging is fully configurabule and Ansi foreground +colors can be added. Both ANSI 8 and ANSI 256 color are fully suported. +Most APIs will return a promise. These APIs can be used using +`then(...)/catch(...)` + +A Syslog class with a configured +Syslog server target can also be used as the input into the formating +classes so that it may run independtly. + +The RFC3164 Syslog logging format is ment to be used as a stream of log data +from a service or applacation. This class is designed to be used in this +fashion where new messages are writen to the class as needed.
    @@ -76,7 +87,7 @@
    Source:
    @@ -865,7 +876,7 @@
    Source:
    @@ -924,7 +935,7 @@
    Source:
    @@ -993,7 +1004,7 @@
    Source:
    @@ -1052,7 +1063,7 @@
    Source:
    @@ -1111,7 +1122,7 @@
    Source:
    @@ -1170,7 +1181,7 @@
    Source:
    @@ -1229,7 +1240,7 @@
    Source:
    @@ -1288,7 +1299,7 @@
    Source:
    @@ -1357,7 +1368,7 @@
    Source:
    @@ -1416,7 +1427,7 @@
    Source:
    @@ -1475,7 +1486,7 @@
    Source:
    @@ -1534,7 +1545,7 @@
    Source:
    @@ -1603,7 +1614,7 @@
    Source:
    @@ -1787,7 +1798,7 @@
    Source:
    @@ -2123,7 +2134,7 @@
    Source:
    @@ -2307,7 +2318,7 @@
    Source:
    @@ -2491,7 +2502,7 @@
    Source:
    @@ -2675,7 +2686,7 @@
    Source:
    @@ -2859,7 +2870,7 @@
    Source:
    @@ -3043,7 +3054,7 @@
    Source:
    @@ -3227,7 +3238,7 @@
    Source:
    @@ -3411,7 +3422,7 @@
    Source:
    @@ -3595,7 +3606,7 @@
    Source:
    @@ -3779,7 +3790,7 @@
    Source:
    @@ -3963,7 +3974,7 @@
    Source:
    @@ -4147,7 +4158,7 @@
    Source:
    @@ -4331,7 +4342,7 @@
    Source:
    @@ -4675,7 +4686,7 @@
    Source:
    @@ -5096,7 +5107,7 @@
    Source:
    @@ -5280,7 +5291,7 @@
    Source:
    @@ -5467,7 +5478,7 @@
    - Documentation generated by JSDoc 3.5.5 on Mon Sep 24 2018 06:41:35 GMT+0000 (Coordinated Universal Time) using the docdash theme. + Documentation generated by JSDoc 3.5.5 on Tue Sep 25 2018 18:22:00 GMT+0000 (Coordinated Universal Time) using the docdash theme.
    diff --git a/docs/module-SyslogPro-RFC5424.html b/docs/module-SyslogPro-RFC5424.html index f4a7017..d348606 100644 --- a/docs/module-SyslogPro-RFC5424.html +++ b/docs/module-SyslogPro-RFC5424.html @@ -49,7 +49,18 @@ RFC5424 -
    A class to work with RFC5424 formated syslog messages.
    +
    A class to work with RFC5424 formated syslog messages. The meesaging is fully configurabule and Ansi foreground +colors can be added. Both ANSI 8 and ANSI 256 color are fully suported. +Most APIs will return a promise. These APIs can be used using +`then(...)/catch(...)` + +A Syslog class with a configured +Syslog server target can also be used as the input into the formating +classes so that it may run independtly. + +The RFC5424 Syslog logging format is ment to be used as a stream of log data +from a service or applacation. This class is designed to be used in this +fashion where new messages are writen to the class as needed.
    @@ -76,7 +87,7 @@
    Source:
    @@ -1062,7 +1073,7 @@
    Source:
    @@ -1121,7 +1132,7 @@
    Source:
    @@ -1190,7 +1201,7 @@
    Source:
    @@ -1249,7 +1260,7 @@
    Source:
    @@ -1308,7 +1319,7 @@
    Source:
    @@ -1367,7 +1378,7 @@
    Source:
    @@ -1426,7 +1437,7 @@
    Source:
    @@ -1495,7 +1506,7 @@
    Source:
    @@ -1554,7 +1565,7 @@
    Source:
    @@ -1623,7 +1634,7 @@
    Source:
    @@ -1682,7 +1693,7 @@
    Source:
    @@ -1741,7 +1752,7 @@
    Source:
    @@ -1800,7 +1811,7 @@
    Source:
    @@ -1869,7 +1880,7 @@
    Source:
    @@ -1938,7 +1949,7 @@
    Source:
    @@ -2007,7 +2018,7 @@
    Source:
    @@ -2076,7 +2087,7 @@
    Source:
    @@ -2145,7 +2156,7 @@
    Source:
    @@ -2214,7 +2225,7 @@
    Source:
    @@ -2398,7 +2409,7 @@
    Source:
    @@ -2855,7 +2866,7 @@
    Source:
    @@ -3039,7 +3050,7 @@
    Source:
    @@ -3223,7 +3234,7 @@
    Source:
    @@ -3407,7 +3418,7 @@
    Source:
    @@ -3591,7 +3602,7 @@
    Source:
    @@ -3775,7 +3786,7 @@
    Source:
    @@ -3959,7 +3970,7 @@
    Source:
    @@ -4143,7 +4154,7 @@
    Source:
    @@ -4327,7 +4338,7 @@
    Source:
    @@ -4511,7 +4522,7 @@
    Source:
    @@ -4695,7 +4706,7 @@
    Source:
    @@ -4879,7 +4890,7 @@
    Source:
    @@ -5063,7 +5074,7 @@
    Source:
    @@ -5256,7 +5267,7 @@
    Source:
    @@ -5677,7 +5688,7 @@
    Source:
    @@ -5861,7 +5872,7 @@
    Source:
    @@ -6048,7 +6059,7 @@
    - Documentation generated by JSDoc 3.5.5 on Mon Sep 24 2018 06:41:35 GMT+0000 (Coordinated Universal Time) using the docdash theme. + Documentation generated by JSDoc 3.5.5 on Tue Sep 25 2018 18:22:00 GMT+0000 (Coordinated Universal Time) using the docdash theme.
    diff --git a/docs/module-SyslogPro-Syslog.html b/docs/module-SyslogPro-Syslog.html index 39932e5..612b5d6 100644 --- a/docs/module-SyslogPro-Syslog.html +++ b/docs/module-SyslogPro-Syslog.html @@ -52,8 +52,9 @@
    A class to work with syslog messages using UDP, TCP, or TLS transport. There is suport for Syslog message formating RFC-3164, RFC-5424 including Structured Data, IBM LEEF (Log Event Extended Format), and HP CEF (Common -Event Format). The meesaging is fully configurabule and Ansi foreground -colors can be added. Both ANSI 8 and ANSI 256 color are fully suported.
    +Event Format). +Syslog formating classes can be used as input into a Syslog class to be used +simultatniusly to the same Syslog server. * @@ -80,7 +81,7 @@ colors can be added. Both ANSI 8 and ANSI 256 color are fully suported.
    Source:
    @@ -126,7 +127,7 @@ colors can be added. Both ANSI 8 and ANSI 256 color are fully suported.
    - Construct a new Syslog object with user options + Construct a new Syslog transport object with user options
    @@ -755,7 +756,7 @@ colors can be added. Both ANSI 8 and ANSI 256 color are fully suported.
    Source:
    @@ -824,7 +825,7 @@ colors can be added. Both ANSI 8 and ANSI 256 color are fully suported.
    Source:
    @@ -893,7 +894,7 @@ colors can be added. Both ANSI 8 and ANSI 256 color are fully suported.
    Source:
    @@ -962,7 +963,7 @@ colors can be added. Both ANSI 8 and ANSI 256 color are fully suported.
    Source:
    @@ -1031,7 +1032,7 @@ colors can be added. Both ANSI 8 and ANSI 256 color are fully suported.
    Source:
    @@ -1100,7 +1101,7 @@ colors can be added. Both ANSI 8 and ANSI 256 color are fully suported.
    Source:
    @@ -1169,7 +1170,7 @@ colors can be added. Both ANSI 8 and ANSI 256 color are fully suported.
    Source:
    @@ -1238,7 +1239,7 @@ colors can be added. Both ANSI 8 and ANSI 256 color are fully suported.
    Source:
    @@ -1307,7 +1308,7 @@ colors can be added. Both ANSI 8 and ANSI 256 color are fully suported.
    Source:
    @@ -1376,7 +1377,7 @@ colors can be added. Both ANSI 8 and ANSI 256 color are fully suported.
    Source:
    @@ -1445,7 +1446,7 @@ colors can be added. Both ANSI 8 and ANSI 256 color are fully suported.
    Source:
    @@ -1514,7 +1515,7 @@ colors can be added. Both ANSI 8 and ANSI 256 color are fully suported.
    Source:
    @@ -1583,7 +1584,7 @@ colors can be added. Both ANSI 8 and ANSI 256 color are fully suported.
    Source:
    @@ -1652,7 +1653,7 @@ colors can be added. Both ANSI 8 and ANSI 256 color are fully suported.
    Source:
    @@ -1847,7 +1848,7 @@ input as a file location straing and add it to an array of certificates
    Source:
    @@ -2059,7 +2060,7 @@ selected transport.
    Source:
    @@ -2270,7 +2271,7 @@ selected transport.
    Source:
    @@ -2481,7 +2482,7 @@ selected transport.
    Source:
    @@ -2668,7 +2669,7 @@ selected transport.
    - Documentation generated by JSDoc 3.5.5 on Mon Sep 24 2018 06:41:36 GMT+0000 (Coordinated Universal Time) using the docdash theme. + Documentation generated by JSDoc 3.5.5 on Tue Sep 25 2018 18:22:00 GMT+0000 (Coordinated Universal Time) using the docdash theme.
    diff --git a/docs/module-SyslogPro.html b/docs/module-SyslogPro.html index ba55b56..64004a3 100644 --- a/docs/module-SyslogPro.html +++ b/docs/module-SyslogPro.html @@ -54,7 +54,14 @@
    -
    The SyslogPro class for sending syslog messages
    +
    The SyslogPro module for sending syslog messages +Most APIs will return a promise. These APIs can be used using +`then(...)/catch(...)` + +Syslog formating classes can be used as input into a Syslog class to be used +simultatniusly to the same Syslog server. The Syslog Class with a configured +Syslog server target can also be used as the input into each of the formating +classes so that they may run independtly.
    @@ -74,13 +81,10 @@
    Version:
    -
    • 0.0.0
    +
    • 0.1.0
    -
    Since:
    -
    • 0.0.0
    - @@ -203,7 +207,7 @@
    Source:
    @@ -391,7 +395,7 @@
    - Documentation generated by JSDoc 3.5.5 on Mon Sep 24 2018 06:41:35 GMT+0000 (Coordinated Universal Time) using the docdash theme. + Documentation generated by JSDoc 3.5.5 on Tue Sep 25 2018 18:22:00 GMT+0000 (Coordinated Universal Time) using the docdash theme.
    diff --git a/index.js b/index.js index 786914a..874be00 100644 --- a/index.js +++ b/index.js @@ -1,11 +1,17 @@ /** Copyright (c) 2018 Craig Yamato */ /** - * @fileoverview The SyslogPro class for sending syslog messages + * @fileoverview The SyslogPro module for sending syslog messages + * Most APIs will return a promise. These APIs can be used using + * `then(...)/catch(...)` + * + * Syslog formating classes can be used as input into a Syslog class to be used + * simultatniusly to the same Syslog server. The Syslog Class with a configured + * Syslog server target can also be used as the input into each of the formating + * classes so that they may run independtly. * @author Craig Yamato * @copyright (c) 2018 - Craig Yamato - * @version 0.0.0 - * @since 0.0.0 + * @version 0.1.0 * @exports Syslog * @exports LEEF * @exports CEF @@ -90,15 +96,16 @@ function rgbToAnsi (hex, extendedColor) { * A class to work with syslog messages using UDP, TCP, or TLS transport. * There is suport for Syslog message formating RFC-3164, RFC-5424 including * Structured Data, IBM LEEF (Log Event Extended Format), and HP CEF (Common - * Event Format). The meesaging is fully configurabule and Ansi foreground - * colors can be added. Both ANSI 8 and ANSI 256 color are fully suported. + * Event Format). + * Syslog formating classes can be used as input into a Syslog class to be used + * simultatniusly to the same Syslog server. * * @requires moment * @version 0.0.0 * @since 0.0.0 */ class Syslog { /** - * Construct a new Syslog object with user options + * Construct a new Syslog transport object with user options * @public * @version 0.0.0 * @since 0.0.0 @@ -443,7 +450,18 @@ class Syslog { } /** - * A class to work with RFC3164 formated syslog messages. + * A class to work with RFC3164 formated syslog messages. The meesaging is fully configurabule and Ansi foreground + * colors can be added. Both ANSI 8 and ANSI 256 color are fully suported. + * Most APIs will return a promise. These APIs can be used using + * `then(...)/catch(...)` + * + * A Syslog class with a configured + * Syslog server target can also be used as the input into the formating + * classes so that it may run independtly. + * + * The RFC3164 Syslog logging format is ment to be used as a stream of log data + * from a service or applacation. This class is designed to be used in this + * fashion where new messages are writen to the class as needed. * @requires moment * @version 0.0.0 * @since 0.0.0 @@ -991,7 +1009,18 @@ class RFC3164 { } /** - * A class to work with RFC5424 formated syslog messages. + * A class to work with RFC5424 formated syslog messages. The meesaging is fully configurabule and Ansi foreground + * colors can be added. Both ANSI 8 and ANSI 256 color are fully suported. + * Most APIs will return a promise. These APIs can be used using + * `then(...)/catch(...)` + * + * A Syslog class with a configured + * Syslog server target can also be used as the input into the formating + * classes so that it may run independtly. + * + * The RFC5424 Syslog logging format is ment to be used as a stream of log data + * from a service or applacation. This class is designed to be used in this + * fashion where new messages are writen to the class as needed. * @requires moment * @version 0.0.0 * @since 0.0.0 @@ -1661,14 +1690,21 @@ class RFC5424 { * of system messages are designed to work with security systems. Messages can * be saved to file (Saving to file if not part of this module but a LEEF * formated mesage produced by this module can be saved externaly to it) or - * sent via Syslog. + * sent via Syslog. + * Most APIs will return a promise. These APIs can be used using + * `then(...)/catch(...)` + * + * A Syslog class with a configured Syslog server target can also be used as + * the input into the formating classes so that it may run independtly. The + * LEEF format is designed to send event data to a SIEM system and should not + * be as a logging stream. This class is ment to be used once per message. * @requires moment * @version 0.0.0 * @since 0.0.0 */ class LEEF { /** - * Construct a new LEEF object with user options + * Construct a new LEEF formating object with user options * @public * @param {object} [options] - Options object * @param {string} [options.vendor='unknown'] - The vendor of the system that @@ -1819,13 +1855,20 @@ class LEEF { * be saved to file (Saving to file if not part of this module but a CEF * formated mesage produced by this module can be saved externaly to it) or * sent via Syslog. + * Most APIs will return a promise. These APIs can be used using + * `then(...)/catch(...)` + * + * A Syslog class with a configured Syslog server target can also be used as + * the input into the formating classes so that it may run independtly. The CEF + * format is designed to send event data to a SIEM system and should not be as + * a logging stream. This class is ment to be used once per message. * @requires moment * @version 0.0.0 * @since 0.0.0 */ class CEF { /** - * Construct a new CEF object with user options + * Construct a new CEF formating object with user options * @public * @param {object} [options] - Options object * @param {string} [options.deviceVendor='unknown'] - The vendor of the system diff --git a/jsdoc.json b/jsdoc.json new file mode 100644 index 0000000..833c458 --- /dev/null +++ b/jsdoc.json @@ -0,0 +1,25 @@ +{ + "sourceType": "module", + "tags": { + "allowUnknownTags": true, + "dictionaries": ["jsdoc","closure"] + }, + "source": { + "includePattern": ".+\\.js(doc|x)?$", + "excludePattern": "(^|\\/|\\\\)_" + }, + "plugins": [], + "templates": { + "cleverLinks": false, + "monospaceLinks": false, + "default": { + "outputSourceFiles": true + } + }, + "opts": { + "destination": "./docs", + "private": true, + "readme": "./README.md", + "template": "./node_modules/docdash" + } +} \ No newline at end of file diff --git a/jsdoc2md/api.hbs b/jsdoc2md/api.hbs new file mode 100644 index 0000000..12ab71d --- /dev/null +++ b/jsdoc2md/api.hbs @@ -0,0 +1,22 @@ +API +========================== + +- back to [README.md](../README.md) + +API convention +== + +{{>main}} + +*docs autogenerated via [jsdoc2md] +(https://github.com/jsdoc2md/jsdoc-to-markdown)* + +## Test +```shell + npm test +``` + +## Contributing + +Please try to maintain the existing coding style. Add unit tests for any new or +changed functionality. Lint and test your code. diff --git a/package-lock.json b/package-lock.json index 8feaad4..11dde16 100644 --- a/package-lock.json +++ b/package-lock.json @@ -80,6 +80,15 @@ "json-schema-traverse": "^0.3.0" } }, + "ansi-escape-sequences": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/ansi-escape-sequences/-/ansi-escape-sequences-4.0.0.tgz", + "integrity": "sha512-v+0wW9Wezwsyb0uF4aBVCjmSqit3Ru7PZFziGF0o2KwTvN2zWfTi3BRLq9EkJFdg3eBbyERXGTntVpBxH1J68Q==", + "dev": true, + "requires": { + "array-back": "^2.0.0" + } + }, "ansi-escapes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", @@ -405,6 +414,16 @@ "sprintf-js": "~1.0.2" } }, + "argv-tools": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/argv-tools/-/argv-tools-0.1.1.tgz", + "integrity": "sha512-Cc0dBvx4dvrjjKpyDA6w8RlNAw8Su30NvZbWl/Tv9ZALEVlLVkWQiHMi84Q0xNfpVuSaiQbYkdmWK8g1PLGhKw==", + "dev": true, + "requires": { + "array-back": "^2.0.0", + "find-replace": "^2.0.1" + } + }, "arr-diff": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", @@ -426,6 +445,15 @@ "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", "dev": true }, + "array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "requires": { + "typical": "^2.6.1" + } + }, "array-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", @@ -907,6 +935,17 @@ } } }, + "cache-point": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cache-point/-/cache-point-0.4.1.tgz", + "integrity": "sha512-4TgWfe9SF+bUy5cCql8gWHqKNrviufNwSYxLjf2utB0pY4+bdcuFwMmY1hDB+67Gz/L1vmhFNhePAjJTFBtV+Q==", + "dev": true, + "requires": { + "array-back": "^2.0.0", + "fs-then-native": "^2.0.0", + "mkdirp2": "^1.0.3" + } + }, "callsites": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", @@ -1012,6 +1051,16 @@ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true }, + "collect-all": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/collect-all/-/collect-all-1.0.3.tgz", + "integrity": "sha512-0y0rBgoX8IzIjBAUnO73SEtSb4Mhk3IoceWJq5zZSxb9mWORhWH8xLYo4EDSOE1jRBk1LhmfjqWFFt10h/+MEA==", + "dev": true, + "requires": { + "stream-connect": "^1.0.2", + "stream-via": "^1.0.4" + } + }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", @@ -1046,12 +1095,56 @@ "delayed-stream": "~1.0.0" } }, + "command-line-args": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.0.2.tgz", + "integrity": "sha512-/qPcbL8zpqg53x4rAaqMFlRV4opN3pbla7I7k9x8kyOBMQoGT6WltjN6sXZuxOXw6DgdK7Ad+ijYS5gjcr7vlA==", + "dev": true, + "requires": { + "argv-tools": "^0.1.1", + "array-back": "^2.0.0", + "find-replace": "^2.0.1", + "lodash.camelcase": "^4.3.0", + "typical": "^2.6.1" + } + }, + "command-line-tool": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/command-line-tool/-/command-line-tool-0.8.0.tgz", + "integrity": "sha512-Xw18HVx/QzQV3Sc5k1vy3kgtOeGmsKIqwtFFoyjI4bbcpSgnw2CWVULvtakyw4s6fhyAdI6soQQhXc2OzJy62g==", + "dev": true, + "requires": { + "ansi-escape-sequences": "^4.0.0", + "array-back": "^2.0.0", + "command-line-args": "^5.0.0", + "command-line-usage": "^4.1.0", + "typical": "^2.6.1" + } + }, + "command-line-usage": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-4.1.0.tgz", + "integrity": "sha512-MxS8Ad995KpdAC0Jopo/ovGIroV/m0KHwzKfXxKag6FHOkGsH8/lv5yjgablcRxCJJC0oJeUMuO/gmaq+Wq46g==", + "dev": true, + "requires": { + "ansi-escape-sequences": "^4.0.0", + "array-back": "^2.0.0", + "table-layout": "^0.4.2", + "typical": "^2.6.1" + } + }, "commander": { "version": "2.18.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.18.0.tgz", "integrity": "sha512-6CYPa+JP2ftfRU2qkDK+UTVeQYosOg/2GbcjIcKPHfinyOLPVGXu/ovN86RP49Re5ndJK1N0kuiidFFuepc4ZQ==", "dev": true }, + "common-sequence": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/common-sequence/-/common-sequence-1.0.2.tgz", + "integrity": "sha1-MOB/P49vf5s97oVPILLTnu4Ibeg=", + "dev": true + }, "component-emitter": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", @@ -1064,6 +1157,23 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, + "config-master": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/config-master/-/config-master-3.1.0.tgz", + "integrity": "sha1-ZnZjWQUFooO/JqSE1oSJ10xUhdo=", + "dev": true, + "requires": { + "walk-back": "^2.0.1" + }, + "dependencies": { + "walk-back": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-2.0.1.tgz", + "integrity": "sha1-VU4qnYdPrEeoywBr9EwvDEmYoKQ=", + "dev": true + } + } + }, "convert-source-map": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", @@ -1193,6 +1303,12 @@ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "dev": true }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true + }, "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", @@ -1297,6 +1413,34 @@ "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true }, + "dmd": { + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/dmd/-/dmd-3.0.12.tgz", + "integrity": "sha512-79w644JdsB2TthYpVl2bDurX7i9Abaegg2E7X46Ajc135aASTMXxrHzJ9mOa5X5nbmnXwlBYiF68K+1baX+BzQ==", + "dev": true, + "requires": { + "array-back": "^2.0.0", + "cache-point": "^0.4.1", + "common-sequence": "^1.0.2", + "file-set": "^2.0.0", + "handlebars": "^4.0.11", + "marked": "^0.3.16", + "object-get": "^2.1.0", + "reduce-flatten": "^1.0.1", + "reduce-unique": "^1.0.0", + "reduce-without": "^1.0.1", + "test-value": "^3.0.0", + "walk-back": "^3.0.0" + }, + "dependencies": { + "marked": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.19.tgz", + "integrity": "sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg==", + "dev": true + } + } + }, "docco": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/docco/-/docco-0.8.0.tgz", @@ -1552,6 +1696,16 @@ "bser": "^2.0.0" } }, + "file-set": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/file-set/-/file-set-2.0.1.tgz", + "integrity": "sha512-XgOUUpgR6FbbfYcniLw0qm1Am7PnNYIAkd+eXxRt42LiYhjaso0WiuQ+VmrNdtwotyM+cLCfZ56AZrySP3QnKA==", + "dev": true, + "requires": { + "array-back": "^2.0.0", + "glob": "^7.1.3" + } + }, "filename-regex": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", @@ -1581,6 +1735,16 @@ "repeat-string": "^1.5.2" } }, + "find-replace": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-2.0.1.tgz", + "integrity": "sha512-LzDo3Fpa30FLIBsh6DCDnMN1KW2g4QKkqKmejlImgWY67dDFPX/x9Kh/op/GK522DchQXEvDi/wD48HKW49XOQ==", + "dev": true, + "requires": { + "array-back": "^2.0.0", + "test-value": "^3.0.0" + } + }, "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", @@ -1653,6 +1817,12 @@ "universalify": "^0.1.0" } }, + "fs-then-native": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fs-then-native/-/fs-then-native-2.0.0.tgz", + "integrity": "sha1-GaEk2U2QwiyOBF8ujdbr6jbUjGc=", + "dev": true + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -1720,7 +1890,8 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", @@ -1730,7 +1901,8 @@ "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -1847,7 +2019,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -1859,6 +2032,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -1984,7 +2158,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -1996,6 +2171,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -2117,6 +2293,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -3337,6 +3514,52 @@ } } }, + "jsdoc-api": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/jsdoc-api/-/jsdoc-api-4.0.3.tgz", + "integrity": "sha512-dfYq9JgB+XahY0XfSEw93PmXmocjwYcvJ5aMuQUJ/OdDRGWamf2SSOk3W06Bsj8qdjp/UdefzqpP/mpwsvHuvA==", + "dev": true, + "requires": { + "array-back": "^2.0.0", + "cache-point": "^0.4.1", + "collect-all": "^1.0.3", + "file-set": "^2.0.0", + "fs-then-native": "^2.0.0", + "jsdoc": "~3.5.5", + "object-to-spawn-args": "^1.1.1", + "temp-path": "^1.0.0", + "walk-back": "^3.0.0" + } + }, + "jsdoc-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/jsdoc-parse/-/jsdoc-parse-3.0.1.tgz", + "integrity": "sha512-btZLp4wYl90vcAfgk4hoGQbO17iBVrhh3LJRMKZNtZgniO3F8H2CjxXld0owBIB1XxN+j3bAcWZnZKMnSj3iMA==", + "dev": true, + "requires": { + "array-back": "^2.0.0", + "lodash.omit": "^4.5.0", + "lodash.pick": "^4.4.0", + "reduce-extract": "^1.0.0", + "sort-array": "^2.0.0", + "test-value": "^3.0.0" + } + }, + "jsdoc-to-markdown": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsdoc-to-markdown/-/jsdoc-to-markdown-4.0.1.tgz", + "integrity": "sha512-LHJRoLoLyDdxNcColgkLoB/rFG5iRP+PNJjMILI0x+95IdEAtyjSt0wJ6ZlKxRpkhBYtQXTQQ119hMqPIUZzTQ==", + "dev": true, + "requires": { + "array-back": "^2.0.0", + "command-line-tool": "^0.8.0", + "config-master": "^3.1.0", + "dmd": "^3.0.10", + "jsdoc-api": "^4.0.1", + "jsdoc-parse": "^3.0.1", + "walk-back": "^3.0.0" + } + }, "jsdom": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz", @@ -3512,6 +3735,30 @@ "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", "dev": true }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", + "dev": true + }, + "lodash.omit": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", + "integrity": "sha1-brGa5aHuHdnfC5aeZs4Lf6MLXmA=", + "dev": true + }, + "lodash.padend": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz", + "integrity": "sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4=", + "dev": true + }, + "lodash.pick": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", + "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=", + "dev": true + }, "lodash.sortby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", @@ -3690,6 +3937,12 @@ "minimist": "0.0.8" } }, + "mkdirp2": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp2/-/mkdirp2-1.0.4.tgz", + "integrity": "sha512-Q2PKB4ZR4UPtjLl76JfzlgSCUZhSV1AXQgAZa1qt5RiaALFjP/CDrGvFBrOz7Ck6McPcwMAxTsJvWOUjOU8XMw==", + "dev": true + }, "moment": { "version": "2.22.2", "resolved": "https://registry.npmjs.org/moment/-/moment-2.22.2.tgz", @@ -3847,12 +4100,24 @@ } } }, + "object-get": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/object-get/-/object-get-2.1.0.tgz", + "integrity": "sha1-ciu9tgA576R8rTxtws5RqFwCxa4=", + "dev": true + }, "object-keys": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==", "dev": true }, + "object-to-spawn-args": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-to-spawn-args/-/object-to-spawn-args-1.1.1.tgz", + "integrity": "sha1-d9qIJ/Bz0BHJ4bFz+JV4FHAkZ4U=", + "dev": true + }, "object-visit": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", @@ -4284,6 +4549,78 @@ "util.promisify": "^1.0.0" } }, + "reduce-extract": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/reduce-extract/-/reduce-extract-1.0.0.tgz", + "integrity": "sha1-Z/I4W+2mUGG19fQxJmLosIDKFSU=", + "dev": true, + "requires": { + "test-value": "^1.0.1" + }, + "dependencies": { + "array-back": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", + "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", + "dev": true, + "requires": { + "typical": "^2.6.0" + } + }, + "test-value": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/test-value/-/test-value-1.1.0.tgz", + "integrity": "sha1-oJE29y7AQ9J8iTcHwrFZv6196T8=", + "dev": true, + "requires": { + "array-back": "^1.0.2", + "typical": "^2.4.2" + } + } + } + }, + "reduce-flatten": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-1.0.1.tgz", + "integrity": "sha1-JYx479FT3fk8tWEjf2EYTzaW4yc=", + "dev": true + }, + "reduce-unique": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/reduce-unique/-/reduce-unique-1.0.0.tgz", + "integrity": "sha1-flhrz4ek4ytter2Cd/rWzeyfSAM=", + "dev": true + }, + "reduce-without": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/reduce-without/-/reduce-without-1.0.1.tgz", + "integrity": "sha1-aK0OrRGFXJo31OglbBW7+Hly/Iw=", + "dev": true, + "requires": { + "test-value": "^2.0.0" + }, + "dependencies": { + "array-back": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", + "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", + "dev": true, + "requires": { + "typical": "^2.6.0" + } + }, + "test-value": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/test-value/-/test-value-2.1.0.tgz", + "integrity": "sha1-Edpv9nDzRxpztiXKTz/c97t0gpE=", + "dev": true, + "requires": { + "array-back": "^1.0.3", + "typical": "^2.6.0" + } + } + } + }, "regenerator-runtime": { "version": "0.11.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", @@ -4969,6 +5306,28 @@ "kind-of": "^3.2.0" } }, + "sort-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sort-array/-/sort-array-2.0.0.tgz", + "integrity": "sha1-OKnG2if9fRR7QuYFVPKBGHtN9HI=", + "dev": true, + "requires": { + "array-back": "^1.0.4", + "object-get": "^2.1.0", + "typical": "^2.6.0" + }, + "dependencies": { + "array-back": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", + "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", + "dev": true, + "requires": { + "typical": "^2.6.0" + } + } + } + }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -5100,6 +5459,32 @@ "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", "dev": true }, + "stream-connect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-connect/-/stream-connect-1.0.2.tgz", + "integrity": "sha1-GLyB8u2zW4tdmoAJIAqYUxRCipc=", + "dev": true, + "requires": { + "array-back": "^1.0.2" + }, + "dependencies": { + "array-back": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", + "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", + "dev": true, + "requires": { + "typical": "^2.6.0" + } + } + } + }, + "stream-via": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/stream-via/-/stream-via-1.0.4.tgz", + "integrity": "sha512-DBp0lSvX5G9KGRDTkR/R+a29H+Wk2xItOF+MpZLLNDWbEV9tGPnqLPxHEYjmiz8xGtJHRIqmI+hCjmNzqoA4nQ==", + "dev": true + }, "string-length": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz", @@ -5182,12 +5567,31 @@ "integrity": "sha1-rifbOPZgp64uHDt9G8KQgZuFGeY=", "dev": true }, + "table-layout": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-0.4.4.tgz", + "integrity": "sha512-uNaR3SRMJwfdp9OUr36eyEi6LLsbcTqTO/hfTsNviKsNeyMBPICJCC7QXRF3+07bAP6FRwA8rczJPBqXDc0CkQ==", + "dev": true, + "requires": { + "array-back": "^2.0.0", + "deep-extend": "~0.6.0", + "lodash.padend": "^4.6.1", + "typical": "^2.6.1", + "wordwrapjs": "^3.0.0" + } + }, "taffydb": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=", "dev": true }, + "temp-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/temp-path/-/temp-path-1.0.0.tgz", + "integrity": "sha1-JLFUOXOrRCiW2a02fdnL2/r+kYs=", + "dev": true + }, "test-exclude": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-4.2.3.tgz", @@ -5201,6 +5605,16 @@ "require-main-filename": "^1.0.1" } }, + "test-value": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/test-value/-/test-value-3.0.0.tgz", + "integrity": "sha512-sVACdAWcZkSU9x7AOmJo5TqE+GyNJknHaHsMrR6ZnhjVlVN9Yx6FjHrsKZ3BjIpPCT68zYesPWkakrNupwfOTQ==", + "dev": true, + "requires": { + "array-back": "^2.0.0", + "typical": "^2.6.1" + } + }, "throat": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz", @@ -5319,6 +5733,12 @@ "prelude-ls": "~1.1.2" } }, + "typical": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", + "integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0=", + "dev": true + }, "uglify-js": { "version": "3.4.9", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz", @@ -5520,6 +5940,12 @@ "browser-process-hrtime": "^0.1.2" } }, + "walk-back": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-3.0.0.tgz", + "integrity": "sha1-I1h4ejXakQMtrV6S+AsSNw2HlcU=", + "dev": true + }, "walker": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz", @@ -5600,6 +6026,16 @@ "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", "dev": true }, + "wordwrapjs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-3.0.0.tgz", + "integrity": "sha512-mO8XtqyPvykVCsrwj5MlOVWvSnCdT+C+QVbm6blradR7JExAhbkZ7hZ9A+9NUtwzSqrlUo9a67ws0EiILrvRpw==", + "dev": true, + "requires": { + "reduce-flatten": "^1.0.1", + "typical": "^2.6.1" + } + }, "wrap-ansi": { "version": "2.1.0", "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", diff --git a/package.json b/package.json index f3a7184..ca3f4cb 100644 --- a/package.json +++ b/package.json @@ -36,8 +36,8 @@ } ], "homepage": "https://cyamato.github.io/SyslogPro/", - "bugs": { - "url" : "https://github.com/cyamato/SyslogPro/issues" + "bugs": { + "url": "https://github.com/cyamato/SyslogPro/issues" }, "license": "MIT", "repository": { @@ -48,7 +48,7 @@ "doc": "./docs", "example": "./example", "test": "./test" - } + }, "main": "index.js", "engines": { "node": ">=10.0.0" @@ -61,11 +61,15 @@ "docco": "^0.8.0", "docdash": "^1.0.0", "jest": "^23.5.0", - "jsdoc": "^3.5.5" + "jsdoc": "^3.5.5", + "jsdoc-to-markdown": "^4.0.1" }, "scripts": { "test": "jest --colors --expand --logHeapUsage --runInBand && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js", - "doc": "jsdoc *.js --destination ./docs --private --readme ./readme.md --template ./node_modules/docdash" + "docs": "jsdoc *.js -c ./jsdoc.json; jsdoc2md --template ./jsdoc2md/api.hbs --files *.js > ./docs/api.md; docco --output ./docs/docco --layout plain-markdown *.js && mv ./docs/docco/index.html ./docs/docco/README.md; docco --output ./docs/docco *.js", + "jsdoc": "jsdoc *.js -c ./jsdoc.json", + "readme": "jsdoc2md --template ./jsdoc2md/api.hbs --files *.js > ./docs/api.md", + "docco": "docco --output ./docs/docco --layout plain-markdown *.js && mv ./docs/docco/index.html ./docs/docco/README.md; docco --output ./docs/docco *.js" }, "jest": { "collectCoverage": true,