feat: Add Be and tbd skill, also added Roadmap file

This commit is contained in:
2026-05-10 16:32:12 -04:00
parent 3500ade13f
commit 0bb8885802
29587 changed files with 10611695 additions and 0 deletions

19
Skills/@be/node_modules/@myndzi/glossy/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,19 @@
Copyright (c) 2010, Squeeks.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

129
Skills/@be/node_modules/@myndzi/glossy/README.md generated vendored Normal file
View File

@@ -0,0 +1,129 @@
glossy
===========
glossy aims to be a very generic yet powerful library for both producing and
also parsing raw syslog messages. The library aims to be capable of adhearing to
RFC 3164, RFC 5424 and RFC 5848 and by itself does no network interactions, it's
up to you to use this library as a syslog producer, a consumer, relay or
something else entirely. In addition, glossy has no dependencies and can be
bootstrapped to operate in browser or other non-node.js environments.
Parsing
-------
var syslogParser = require('@myndzi/glossy').Parse; // or wherever your glossy libs are
parsedMessage = syslogParser.parse(message);
parsedMessage will return an object containing as many parsed values as
possible, as well as the original message. The date value will be a Date object.
Structured data will return as an object. Alternatively, you can give it a
callback as your second argument:
syslogParser.parse(message, function(parsedMessage){
console.log(parsedMessage);
});
Producing
-------
Unless you stipulate for BSD/RFC 3164 style messages, it will default to
generating all messages as newer, RFC 5424 format. This might break consumers or
relays not expecting it.
var syslogProducer = require('@myndzi/glossy').Produce; // or wherever glossy lives
var msg = syslogProducer.produce({
facility: 'local4', // these can either be a valid integer,
severity: 'error', // or a relevant string
host: 'localhost',
appName: 'sudo',
pid: '123',
date: new Date(Date()),
message: 'Nice, Neat, New, Oh Wow'
});
Again, you can specify a callback for the second argument.
var msg = syslogProducer.produce({
facility: 'ntp',
severity: 'info',
host: 'localhost',
date: new Date(Date()),
message: 'Lunch Time!'
}, function(syslogMsg){
console.log(syslogMsg);
});
In addition, you can also predefined most of the values when you create the
object, to save having to repeat yourself:
var syslogProducer = new require('@myndzi/glossy').Produce({
type: 'BSD',
facility: 'ftp',
pid: 42,
host: '::1'
});
For RFC5424 messages, you can also include structured data. Keys should comply
with the definition in [Section 7, RFC5424](http://tools.ietf.org/html/rfc5424#section-7)
regarding names - keep them unique and your own custom keys should have at least
an @ sign.
var msg = syslogProducer.produce({
facility: 'local4',
severity: 'error',
host: 'localhost',
appName: 'starman',
pid: '123',
date: new Date(Date()),
message: 'ACHTUNG!',
structuredData: {
'plack@host': {
status: 'broken',
hasTried: 'not really'
}
}
});
Finally, we expose all the severities as functions themselves:
var infoMsg = glossy.info({
message: 'Info Message',
});
Function names facilitating this are named debug, info, notice, warn, crit,
alert and emergency.
Parsing Example
-------
Handle incoming syslog messages coming in on UDP port 514:
var syslogParser = require('@myndzi/glossy').Parse; // or wherever your glossy libs are
var dgram = require("dgram");
var server = dgram.createSocket("udp4");
server.on("message", function(rawMessage) {
syslogParser.parse(rawMessage.toString('utf8', 0), function(parsedMessage){
console.log(parsedMessage.host + ' - ' + parsedMessage.message);
});
});
server.on("listening", function() {
var address = server.address();
console.log("Server now listening at " +
address.address + ":" + address.port);
});
server.bind(514); // Remember ports < 1024 need suid
Author
-------
Squeeks - privacymyass@gmail.com
License
-------
This is free software licensed under the MIT License - see the LICENSE file that
should be included with this package.

12
Skills/@be/node_modules/@myndzi/glossy/index.js generated vendored Normal file
View File

@@ -0,0 +1,12 @@
/*
* Imports
*/
var producer = require('./lib/glossy/produce.js');
var parser = require('./lib/glossy/parse.js');
/*
* Exports
*/
exports.Produce = producer;
exports.Parse = parser;

View File

@@ -0,0 +1,520 @@
/*
* Glossy Parser - Parse incoming syslog messages
*
* Copyright Squeeks <privacymyass@gmail.com>.
* This is free software licensed under the MIT License -
* see the LICENSE file that should be included with this package.
*/
/*
* These values replace the integers in message that define the facility.
*/
var FacilityIndex = [
'kern', // kernel messages
'user', // user-level messages
'mail', // mail system
'daemon', // system daemons
'auth', // security/authorization messages
'syslog', // messages generated internally by syslogd
'lpr', // line printer subsystem
'news', // network news subsystem
'uucp', // UUCP subsystem
'clock', // clock daemon
'sec', // security/authorization messages
'ftp', // FTP daemon
'ntp', // NTP subsystem
'audit', // log audit
'alert', // log alert
'clock', // clock daemon (note 2)
'local0', // local use 0 (local0)
'local1', // local use 1 (local1)
'local2', // local use 2 (local2)
'local3', // local use 3 (local3)
'local4', // local use 4 (local4)
'local5', // local use 5 (local5)
'local6', // local use 6 (local6)
'local7' // local use 7 (local7)
];
// Note 1 - Various operating systems have been found to utilize
// Facilities 4, 10, 13 and 14 for security/authorization,
// audit, and alert messages which seem to be similar.
// Note 2 - Various operating systems have been found to utilize
// both Facilities 9 and 15 for clock (cron/at) messages.
/*
* These values replace the integers in message that define the severity.
*/
var SeverityIndex = [
'emerg', // Emergency: system is unusable
'alert', // Alert: action must be taken immediately
'crit', // Critical: critical conditions
'err', // Error: error conditions
'warn', // Warning: warning conditions
'notice', // Notice: normal but significant condition
'info', // Informational: informational messages
'debug' // Debug: debug-level messages
];
/*
* Defines the range matching BSD style months to integers.
*/
var BSDDateIndex = {
'Jan': 0,
'Feb': 1,
'Mar': 2,
'Apr': 3,
'May': 4,
'Jun': 5,
'Jul': 6,
'Aug': 7,
'Sep': 8,
'Oct': 9,
'Nov': 10,
'Dec': 11
};
// These values match the hasing algorithm values as defined in RFC 5848
var signedBlockValues = {
// Section 4.2.1
hashAlgorithm: [
null,
'SHA1',
'SHA256'
],
// Section 5.2.1
keyBlobType: {
'C': 'PKIX Certificate',
'P': 'OpenPGP KeyID',
'K': 'Public Key',
'N': 'No key information',
'U': 'Unknown'
}
};
var GlossyParser = function() {};
/*
* Parse the raw message received.
*
* @param {String/Buffer} rawMessage Raw message received from socket
* @param {Function} callback Callback to run after parse is complete
* @return {Object} map containing all successfully parsed data.
*/
GlossyParser.prototype.parse = function(rawMessage, callback) {
// Are you node.js? Is this a Buffer?
if(typeof Buffer == 'function' && Buffer.isBuffer(rawMessage)) {
rawMessage = rawMessage.toString('utf8', 0);
} else if(typeof rawMessage != 'string') {
return rawMessage;
}
// Always return the original message
var parsedMessage = {
originalMessage: rawMessage
};
var segments = rawMessage.split(' ');
if(segments.length < 2) return parsedMessage;
var priKeys = this.decodePri(segments[0]);
if(priKeys) {
for (var key in priKeys) parsedMessage[key] = priKeys[key];
}
var timeStamp;
//TODO Could our detection between 3164/5424 be improved?
if(segments[0].match(/^(<\d+>\d)$/)) {
segments.shift(); // Shift the prival off
timeStamp = segments.shift();
parsedMessage.type = 'RFC5424';
parsedMessage.time = this.parseTimeStamp(timeStamp);
parsedMessage.host = this.decideValue(segments.shift());
parsedMessage.appName = this.decideValue(segments.shift());
parsedMessage.pid = this.decideValue(segments.shift());
parsedMessage.msgID = this.decideValue(segments.shift());
if(segments[0] !== '-') {
var spliceMarker = 0;
for (i = segments.length -1; i > -1; i--) {
if(segments[i].substr(-1) === ']'){
spliceMarker = i;
spliceMarker++;
break;
}
}
if(spliceMarker !== 0) {
var sd = segments.splice(0, spliceMarker).join(' ');
parsedMessage.structuredData = this.parseStructure(sd);
if(parsedMessage.structuredData.ssign) {
parsedMessage.structuredData.signedBlock =
this.parseSignedBlock(parsedMessage.structuredData);
} else if(parsedMessage.structuredData['ssign-cert']) {
parsedMessage.structuredData.signedBlock =
this.parseSignedCertificate(parsedMessage.structuredData);
}
}
} else {
segments.shift(); // Shift the SD marker off
}
parsedMessage.message = segments.join(' ');
} else if (segments[0].match(/^(<\d+>\d+:)$/)) {
parsedMessage.type = 'RFC3164';
timeStamp = segments.splice(0,1).join(' ').replace(/^(<\d+>)/,'');
parsedMessage.time = this.parseBsdTime(timeStamp);
parsedMessage.message = segments.join(' ');
} else if(segments[0].match(/^(<\d+>\w+)/)) {
parsedMessage.type = 'RFC3164';
if (segments[1] === '') segments.splice(1,1);
timeStamp = segments.splice(0,3).join(' ').replace(/^(<\d+>)/,'');
parsedMessage.time = this.parseBsdTime(timeStamp);
parsedMessage.host = segments.shift();
parsedMessage.message = segments.join(' ');
}
if(callback) {
callback(parsedMessage);
} else {
return parsedMessage;
}
};
/*
* RFC5424 messages are supposed to specify '-' as the null value
* @param {String} a section from an RFC5424 message
* @return {Boolean/String} null if string is entirely '-', or the original value
*/
GlossyParser.prototype.decideValue = function(value) {
return value === '-' ? null : value;
};
/*
* Parses the PRI value from the start of message
*
* @param {String} message Supplied raw primary value and version
* @return {Object} Returns object containing Facility, Severity and Version
* if correctly parsed, empty values on failure.
*/
GlossyParser.prototype.decodePri = function(message) {
if(typeof message != 'string') return;
var privalMatch = message.match(/^<(\d+)>/);
if(!privalMatch) return false;
var returnVal = {
prival: parseInt(privalMatch[1], 10)
};
if(privalMatch[2]) returnVal.versio = parseInt(privalMatch[2], 10);
if(returnVal.prival && returnVal.prival >= 0 && returnVal.prival <= 191) {
returnVal.facilityID = parseInt(returnVal.prival / 8, 10);
returnVal.severityID = returnVal.prival - (returnVal.facilityID * 8);
if(returnVal.facilityID < 24 && returnVal.severityID < 8) {
returnVal.facility = FacilityIndex[returnVal.facilityID];
returnVal.severity = SeverityIndex[returnVal.severityID];
}
} else if(returnVal.prival >= 191) {
return false;
}
return returnVal;
};
/*
* Attempts to parse a given timestamp
* @param {String} timeStamp Supplied timestamp, should only be the timestamp,
* not the entire message
* @return {Object} Date object on success
*/
GlossyParser.prototype.parseTimeStamp = function(timeStamp) {
if(typeof timeStamp != 'string') return;
var parsedTime;
parsedTime = this.parse8601(timeStamp);
if(parsedTime) return parsedTime;
parsedTime = this.parseRfc3339(timeStamp);
if(parsedTime) return parsedTime;
parsedTime = this.parseBsdTime(timeStamp);
if(parsedTime) return parsedTime;
return parsedTime;
};
/*
* Parse RFC3339 style timestamps
* @param {String} timeStamp
* @return {Date/false} Timestamp, if parsed correctly
* @see http://blog.toppingdesign.com/2009/08/13/fast-rfc-3339-date-processing-in-javascript/
*/
GlossyParser.prototype.parseRfc3339 = function(timeStamp){
  var utcOffset, offsetSplitChar, offsetString,
    offsetMultiplier = 1,
    dateTime = timeStamp.split("T");
if(dateTime.length < 2) return false;
    var date = dateTime[0].split("-"),
    time = dateTime[1].split(":"),
    offsetField = time[time.length - 1];
    offsetFieldIdentifier = offsetField.charAt(offsetField.length - 1);
    if (offsetFieldIdentifier === "Z") {
    utcOffset = 0;
        time[time.length - 1] = offsetField.substr(0, offsetField.length - 2);
    } else {
    if (offsetField[offsetField.length - 1].indexOf("+") != -1) {
            offsetSplitChar = "+";
            offsetMultiplier = 1;
        } else {
            offsetSplitChar = "-";
            offsetMultiplier = -1;
        }
        offsetString = offsetField.split(offsetSplitChar);
if(offsetString.length < 2) return false;
        time[(time.length - 1)] = offsetString[0];
        offsetString = offsetString[1].split(":");
        utcOffset = (offsetString[0] * 60) + offsetString[1];
        utcOffset = utcOffset * 60 * 1000;
    }
               
    var parsedTime = new Date(Date.UTC(date[0], date[1] - 1, date[2], time[0], time[1], time[2]) + (utcOffset * offsetMultiplier ));
    return parsedTime;
};
/*
* Parse "BSD style" timestamps, as defined in RFC3164
* @param {String} timeStamp
* @return {Date/false} Timestamp, if parsed correctly
*/
GlossyParser.prototype.parseBsdTime = function(timeStamp) {
var parsedTime;
var d = timeStamp.match(/(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s+(\d{1,2})\s+(\d{2}):(\d{2}):(\d{2})/);
if(d) {
// Years are absent from the specification, use this year
currDate = new Date();
parsedTime = new Date(
currDate.getUTCFullYear(),
BSDDateIndex[ d[1] ],
d[2],
d[3],
d[4],
d[5]);
}
return parsedTime;
};
/*
* Parse ISO 8601 timestamps
* @param {String} timeStamp
* @return {Object/false} Timestamp, if successfully parsed
*/
GlossyParser.prototype.parse8601 = function(timeStamp) {
var parsedTime = new Date(Date.parse(timeStamp));
if(parsedTime.toString() === 'Invalid Date') return; //FIXME not the best
return parsedTime;
};
/*
* Parse the structured data out of RFC5424 messages
* @param {String} msg The STRUCTURED-DATA section
* @return {Object} sdStructure parsed structure
*/
GlossyParser.prototype.parseStructure = function(msg) {
var sdStructure = { };
var state = 0,
ignore = false,
sdId = '',
sdParam = '',
sdValue = '';
/*
* Build the structure using a horrible FSM.
* The states we cycle are as following:
* 0 1 2 34 20
* [sdID sdParam="sdValue"]
*/
for(var i = 0; i < msg.length; i++) {
var c = msg[i];
switch(state) {
case 0: // SD-ELEMENT
state = (c === '[') ? 1 : 0;
break;
case 1: // SD-ID
if(c != ' ') {
sdId += c;
} else {
sdStructure[sdId] = {};
state = 2;
}
break;
case 2: // SD-PARAM
if(c === '=') {
sdStructure[sdId][sdParam] = '';
state = 3;
} else if(c === ']') {
sdId = '';
state = 0;
} else if(c != ' '){
sdParam += c;
}
break;
case 3: // SD-PARAM/SD-VALUE
state = c === '"' ? 4 : null; // FIXME Handle rubbish better
break;
case 4: // SD-VALUE
if(c === '\\' && !ignore) {
ignore = true;
} else if(c === '"' && !ignore) {
sdStructure[sdId][sdParam] = sdValue;
sdParam = '', sdValue = '';
state = 2;
} else {
sdValue += c;
ignore = false;
}
break;
default:
break;
}
}
return sdStructure;
};
/*
* Make sense of signed block messages
* @param {Object} block the parsed structured data containing signed data
* @return {Object} validatedBlock translated and named values, binary
* elements will be Buffer objects, if available
*/
GlossyParser.prototype.parseSignedBlock = function(block) {
if(typeof block != 'object') return false;
var signedBlock = { };
var validatedBlock = { };
// Figure out where in the object the keys live...
if(block.structuredData && block.structuredData.ssign) {
signedBlock = block.structuredData.ssign;
} else if(block.ssign) {
signedBlock = block.ssign;
} else if(block.VER) {
signedBlock = block;
} else {
return false;
}
var versionMatch = signedBlock.VER.match(/^(\d{2})(\d|\w)(\d)$/);
if(versionMatch !== null) {
validatedBlock.version = versionMatch[1];
validatedBlock.hashAlgorithm = parseInt(versionMatch[2], 10);
validatedBlock.hashAlgoString = signedBlockValues.hashAlgorithm[validatedBlock.hashAlgorithm];
validatedBlock.sigScheme = parseInt(versionMatch[3], 10);
}
validatedBlock.rebootSessionID = parseInt(signedBlock.RSID, 10);
validatedBlock.signatureGroup = parseInt(signedBlock.SG, 10);
validatedBlock.signaturePriority = parseInt(signedBlock.SPRI, 10);
validatedBlock.globalBlockCount = parseInt(signedBlock.GBC, 10);
validatedBlock.firstMsgNumber = parseInt(signedBlock.FMN, 10);
validatedBlock.msgCount = parseInt(signedBlock.CNT, 10);
validatedBlock.hashBlock = signedBlock.HB.split(/\s/);
// Check to see if we're in node or have a Buffer type
if(typeof Buffer == 'function') {
for(var hash in validatedBlock.hashBlock) {
validatedBlock.hashBlock[hash] = new Buffer(
validatedBlock.hashBlock[hash], encoding='base64');
}
validatedBlock.thisSignature = new Buffer(
signedBlock.SIGN, encoding='base64');
} else {
validatedBlock.thisSignature = signedBlock.SIGN;
}
return validatedBlock;
};
/*
* Make sense of signed certificate messages
* @param {Object} block the parsed structured data containing signed data
* @return {Object} validatedBlock translated and named values, binary
* elements will be Buffer objects, if available
*/
GlossyParser.prototype.parseSignedCertificate = function(block) {
if(typeof block != 'object') return false;
var signedBlock = { };
var validatedBlock = { };
// Figure out where in the object the keys live...
if(block.structuredData && block.structuredData['ssign-cert']) {
signedBlock = block.structuredData['ssign-cert'];
} else if(block['ssign-cert']) {
signedBlock = block['ssign-cert'];
} else if(block.VER) {
signedBlock = block;
} else {
return false;
}
var versionMatch = signedBlock.VER.match(/^(\d{2})(\d|\w)(\d)$/);
if(versionMatch !== null) {
validatedBlock.version = versionMatch[1];
validatedBlock.hashAlgorithm = parseInt(versionMatch[2], 10);
validatedBlock.hashAlgoString = signedBlockValues.hashAlgorithm[validatedBlock.hashAlgorithm];
validatedBlock.sigScheme = parseInt(versionMatch[3], 10);
}
validatedBlock.rebootSessionID = parseInt(signedBlock.RSID, 10);
validatedBlock.signatureGroup = parseInt(signedBlock.SG, 10);
validatedBlock.signaturePriority = parseInt(signedBlock.SPRI, 10);
validatedBlock.totalPayloadLength = parseInt(signedBlock.TPBL, 10);
validatedBlock.payloadIndex = parseInt(signedBlock.INDEX, 10);
validatedBlock.fragmentLength = parseInt(signedBlock.FLEN, 10);
var payloadFragment = signedBlock.FRAG.split(/\s/);
validatedBlock.payloadTimestamp = this.parseTimeStamp(payloadFragment[0]);
validatedBlock.payloadType = payloadFragment[1];
validatedBlock.payloadName = signedBlockValues.keyBlobType[payloadFragment[1]];
if(typeof Buffer == 'function') {
validatedBlock.keyBlob = new Buffer(
payloadFragment[2], encoding='base64');
validatedBlock.thisSignature = new Buffer(
signedBlock.SIGN, encoding='base64');
} else {
validatedBlock.keyBlob = payloadFragment[2];
validatedBlock.thisSignature = signedBlock.SIGN;
}
return validatedBlock;
};
if(typeof module == 'object') {
module.exports = new GlossyParser();
}

View File

@@ -0,0 +1,428 @@
/*
* Glossy Producer - Generate valid syslog messages
*
* Copyright Squeeks <privacymyass@gmail.com>.
* This is free software licensed under the MIT License -
* see the LICENSE file that should be included with this package.
*/
/*
* These values replace the integers in message that define the facility.
*/
var FacilityIndex = {
'kern': 0, // kernel messages
'user': 1, // user-level messages
'mail': 2, // mail system
'daemon': 3, // system daemons
'auth': 4, // security/authorization messages
'syslog': 5, // messages generated internally by syslogd
'lpr': 6, // line printer subsystem
'news': 7, // network news subsystem
'uucp': 8, // UUCP subsystem
'clock': 9, // clock daemon
'sec': 10, // security/authorization messages
'ftp': 11, // FTP daemon
'ntp': 12, // NTP subsystem
'audit': 13, // log audit
'alert': 14, // log alert
// 'clock': 15, // clock daemon (note 2)
'local0': 16, // local use 0 (local0)
'local1': 17, // local use 1 (local1)
'local2': 18, // local use 2 (local2)
'local3': 19, // local use 3 (local3)
'local4': 20, // local use 4 (local4)
'local5': 21, // local use 5 (local5)
'local6': 22, // local use 6 (local6)
'local7': 23 // local use 7 (local7)
};
// Note 1 - Various operating systems have been found to utilize
// Facilities 4, 10, 13 and 14 for security/authorization,
// audit, and alert messages which seem to be similar.
// Note 2 - Various operating systems have been found to utilize
// both Facilities 9 and 15 for clock (cron/at) messages.
/*
* These values replace the integers in message that define the severity.
*/
var SeverityIndex = {
'emerg': 0, // Emergency: system is unusable
'emergency': 0,
'alert': 1, // Alert: action must be taken immediately
'crit': 2, // Critical: critical conditions
'critical': 2,
'err': 3, // Error: error conditions
'error': 3,
'warn': 4, // Warning: warning conditions
'warning': 4,
'notice': 5, // Notice: normal but significant condition
'info': 6 , // Informational: informational messages
'information': 6,
'informational': 6,
'debug': 7 // Debug: debug-level messages
};
/*
* Defines the range matching BSD style months to integers.
*/
var BSDDateIndex = [
'Jan',
'Feb',
'Mar',
'Apr',
'May',
'Jun',
'Jul',
'Aug',
'Sep',
'Oct',
'Nov',
'Dec'
];
/*
* GlossyProducer class
* @param {Object} provides persistent details of all messages:
* facility: The facility index
* severity: Severity index
* host: Host address, either name or IP
* appName: Application/Process name
* pid: Process ID
* msgID: Message ID (RFC5424 only)
* type: RFC3164/RFC5424 message type
* @return {Object} GlossyProducer object
*/
var GlossyProducer = function(options) {
if(options && typeof options =='object' && options.type) {
this.type = options.type.match(/bsd|3164/i) ? "RFC3164" : "RFC5424";
} else if(options && typeof options == 'string') {
this.type = options.match(/bsd|3164/i) ? "RFC3164" : "RFC5424";
} else {
this.type = "RFC5424";
}
if(options && options.facility && FacilityIndex[options.facility]) {
this.facility = options.facility;
}
if(options && options.pid && parseInt(options.pid, 10)) {
this.pid = options.pid;
}
if(options && options.host) this.host = options.host.replace(/\s+/g, '');
if(options && options.appName) this.appName = options.appName.replace(/\s+/g, '');
if(options && options.msgID) this.msgID = options.msgID.replace(/\s+/g, '');
};
/*
* @param {Object} options object containing details of the message:
* facility: The facility index
* severity: Severity index
* prival: RFC5424 PRIVAL field - will override facility/severity if in valid [0-191] range and both provided
* see ABNF at: (http://tools.ietf.org/html/rfc5424#section-6)
* host: Host address, either name or IP
* appName: Application ID
* pid: Process ID
* date: Timestamp to be applied, uses current GMT by default
* time: Optional Date() argument may be used in lieu of 'date' - allows parse() output to be used for produce args
* msgID: Message ID (RFC5424 only)
* structuredData: Object of structured data (RFC5424 only)
* message: The message to be sent
*
* @param {Function} callback a callback run once the message is built
* @return {String} compiledMessage on completion, false on failure
*/
GlossyProducer.prototype.produce = function(options, callback) {
// TODO: next breaking api change make key output from parse() consistent with produce input options
if(options.time instanceof Date && !options.date) options.date = options.time;
var msgData = [];
if(!options.date) options.date = new Date();
if(!options.facility) options.facility = this.facility;
if(this.type == 'RFC5424') {
if(options.hasOwnProperty('prival') && options.prival >= 0 && options.prival <= 191) {
var prival = '<' + options.prival + '>1';
}
else {
var prival = calculatePrival({
facility: options.facility,
severity: options.severity,
version: 1
});
}
if(prival === false) return false;
msgData.push(prival);
msgData.push(generateDate(options.date));
msgData.push(options.host || this.host || '-');
msgData.push(options.appName || this.appName || '-');
msgData.push(options.pid || this.pid || '-');
msgData.push(options.msgID || this.msgID || '-');
if(options.structuredData) {
msgData.push(generateStructuredData(options.structuredData) || '-');
} else {
msgData.push('-');
}
if(!options.message) options.message = '-';
} else {
options.timestamp = generateBSDDate(options.date);
msgData.push(
calculatePrival({
facility: options.facility,
severity: options.severity
}) + options.timestamp
);
msgData.push(options.host || this.host);
msgData.push();
if(options.appName || this.appName) {
var app = options.appName || this.appName;
var pid = options.pid || this.pid;
if(parseInt(pid, 10)) {
msgData.push(app + '[' + pid + ']:');
} else {
msgData.push(app + ':');
}
}
}
var compiledMessage = msgData.filter(function (messageElement) {
// Filter null/ undefined values
return messageElement;
}).map(function (messageElement) {
// Trim messages to remove successive whitespace
return String(messageElement).trim();
}).join(' ');
compiledMessage += ' ' + options.message || '';
msgData.push(compiledMessage);
if(callback) {
return callback(compiledMessage);
} else {
return compiledMessage;
}
};
/*
* @param {Object} options object containing details of the message with
* the severity as 'debug'
* @param {Function} callback a callback run once the message is built
* @return {String} compiledMessage on completion, false on failure
*/
GlossyProducer.prototype.debug = function(options, callback) {
options.severity = 'debug';
return this.produce(options, callback);
};
/*
* @param {Object} options object containing details of the message with
* the severity as 'info'
* @param {Function} callback a callback run once the message is built
* @return {String} compiledMessage on completion, false on failure
*/
GlossyProducer.prototype.info = function(options, callback) {
options.severity = 'info';
return this.produce(options, callback);
};
/*
* @param {Object} options object containing details of the message with
* the severity as 'notice'
* @param {Function} callback a callback run once the message is built
* @return {String} compiledMessage on completion, false on failure
*/
GlossyProducer.prototype.notice = function(options, callback) {
options.severity = 'notice';
return this.produce(options, callback);
};
/*
* @param {Object} options object containing details of the message with
* the severity as 'warn'
* @param {Function} callback a callback run once the message is built
* @return {String} compiledMessage on completion, false on failure
*/
GlossyProducer.prototype.warn = function(options, callback) {
options.severity = 'warn';
return this.produce(options, callback);
};
/*
* @param {Object} options object containing details of the message with
* the severity as 'crit'
* @param {Function} callback a callback run once the message is built
* @return {String} compiledMessage on completion, false on failure
*/
GlossyProducer.prototype.crit = function(options, callback) {
options.severity = 'crit';
return this.produce(options, callback);
};
/*
* @param {Object} options object containing details of the message with
* the severity as 'alert'
* @param {Function} callback a callback run once the message is built
* @return {String} compiledMessage on completion, false on failure
*/
GlossyProducer.prototype.alert = function(options, callback) {
options.severity = 'alert';
return this.produce(options, callback);
};
/*
* @param {Object} options object containing details of the message with
* the severity as 'emergency'
* @param {Function} callback a callback run once the message is built
* @return {String} compiledMessage on completion, false on failure
*/
GlossyProducer.prototype.emergency = function(options, callback) {
options.severity = 'emergency';
return this.produce(options, callback);
};
/*
* Prepend a zero to a number less than 10
* @param {Number} n
* @return {String}
*
* Where's sprintf when you need it?
*/
function leadZero(n) {
if(typeof n != 'number') return n;
n = n < 10 ? '0' + n : n ;
return n;
}
/*
* Get current date in RFC 3164 format. If no date is supplied, the default
* is the current time in GMT + 0.
* @param {Date} dateObject optional Date object
* @returns {String}
*
* Features code taken from https://github.com/akaspin/ain
*/
function generateBSDDate(dateObject) {
var date = new Date(dateObject);
if (isNaN(date.getTime())) return '-';
var hours = leadZero(dateObject.getHours());
var minutes = leadZero(dateObject.getMinutes());
var seconds = leadZero(dateObject.getSeconds());
var month = dateObject.getMonth();
var day = dateObject.getDate();
if(day < 10) (day = ' ' + day);
return BSDDateIndex[month] + " " + day + " " + hours + ":" + minutes + ":" + seconds;
}
/*
* Generate date in RFC 3339 format. If no date is supplied, the default is
* the current time in GMT + 0.
* @param {Date} dateObject optional Date object
* @returns {String} formatted date
*/
function generateDate(dateObject) {
var date = new Date(dateObject);
if (isNaN(date.getTime())) return '-';
return date.toISOString();
}
/*
* Calculate the PRIVAL for a given facility
* @param {Object} values Contains the three key arguments
* facility {Number}/{String} the Facility Index
* severity {Number}
* version {Number} For RFC 5424 messages, this should be 1
*
* @return {String}
*/
function calculatePrival(values) {
var pri = {};
// Facility
if(typeof values.facility == 'string' && !values.facility.match(/^\d+$/)) {
pri.facility = FacilityIndex[values.facility.toLowerCase()];
} else if( parseInt(values.facility, 10) && parseInt(values.facility, 10) < 24) {
pri.facility = parseInt(values.facility, 10);
}
//Severity
if(typeof values.severity == 'string' && !values.severity.match(/^\d+$/)) {
pri.severity = SeverityIndex[values.severity.toLowerCase()];
} else if( parseInt(values.severity, 10) && parseInt(values.severity, 10) < 8) {
pri.severity = parseInt(values.severity, 10);
}
if(!isNaN(pri.severity) && !isNaN(pri.facility)) {
pri.prival = (pri.facility * 8) + pri.severity;
pri.str = values.version ? '<' + pri.prival + '>' + values.version : '<' + pri.prival + '>';
return pri.str;
} else {
return false;
}
}
/*
* Serialise objects into the structured data segment
* @param {Object} struct The object to serialise
* @return {String} structuredData the serialised data
*/
function generateStructuredData(struct) {
if(typeof struct != 'object') return false;
var structuredData = '';
for(var sdID in struct) {
sdElement = struct[sdID];
structuredData += '[' + sdID;
for(var key in sdElement) {
if (Array.isArray(sdElement[key])) {
for(var i = 0; i < sdElement[key].length; i++) {
sdElement[key][i] = String(sdElement[key][i]).replace(/(\]|\\|")/g, '\\$1');
structuredData += ' ' + key + '="' + sdElement[key][i] + '"';
}
} else {
sdElement[key] = String(sdElement[key]).replace(/(\]|\\|")/g, '\\$1');
structuredData += ' ' + key + '="' + sdElement[key] + '"';
}
}
structuredData += ']';
}
return structuredData;
}
if(typeof module == 'object') {
module.exports = GlossyProducer;
}

43
Skills/@be/node_modules/@myndzi/glossy/package.json generated vendored Normal file
View File

@@ -0,0 +1,43 @@
{
"name" : "@myndzi/glossy",
"version" : "0.1.8",
"description" : "Syslog parser and producer",
"keywords" : ["syslog", "logging"],
"url" : "http://github.com/squeeks/glossy",
"main" : "./index.js",
"author" : "Squeeks <privacymyass@gmail.com>",
"maintainers" : [
{ "name" : "Squeeks", "email" : "privacymyass@gmail.com" }
],
"contributors" : [
{ "name": "artifi", "email": "artifipl@gmail.com" },
{ "name": "Matt Bornski", "email": "matt@bornski.com" },
{ "name": "Fyodor Y", "email": "fygrave@o0o.nu" },
{ "name": "Stan Carney", "email": "stan.carney@rootsh.me" },
{ "name": "Alexander Metzner", "email": "alexander.metzner@thomann.de" },
{ "name": "zaphod1984", "email": "zaphod84@gmx.de" },
{ "name": "Eric Cornelius", "email": "eric.cornelius@mandiant.com" },
{ "name": "horpto", "email": "_singleton__@hackerdom.ru" }
],
"directories" : {
"lib": "./lib",
"test": "./test"
},
"scripts" : {
"test": "node test/runner.js"
},
"repository" : {
"type": "git",
"url": "http://github.com/squeeks/glossy.git"
},
"bugs" : {
"url": "http://github.com/squeeks/glossy/issues"
},
"licenses" : [
{
"type": "MIT",
"url": "http://www.opensource.org/licenses/MIT"
}
],
"engines" : { "node": ">= 0.2.5" }
}

View File

@@ -0,0 +1,7 @@
var syslogParser = require('../lib/glossy/parse.js'),
assert = require('assert');
assert.ok(syslogParser, 'parser loaded');
assert.equal(syslogParser.decideValue(1), "1");
assert.equal(syslogParser.decideValue('-'), null);
assert.equal(syslogParser.decideValue('ー'), 'ー');

View File

@@ -0,0 +1,24 @@
var syslogParser = require('../lib/glossy/parse.js'),
assert = require('assert');
assert.ok(syslogParser, 'parser loaded');
assert.deepEqual(syslogParser.decodePri('<16>'), {
prival: 16,
facilityID: 2,
severityID: 0,
facility: 'mail',
severity: 'emerg'
});
assert.deepEqual(syslogParser.decodePri('<66>1'), {
prival: 66,
facilityID: 8,
severityID: 2,
facility: 'uucp',
severity: 'crit'
});
assert.equal(syslogParser.decodePri('1<16>'), false);
assert.equal(syslogParser.decodePri('<200>'), false);

View File

@@ -0,0 +1,104 @@
var syslogParser = require('../lib/glossy/parse.js'),
syslogGenerator = require('../lib/glossy/produce.js'),
assert = require('assert');
assert.ok(syslogParser, 'parser loaded');
var gen = new syslogGenerator({type: 'bsd'});
var doubleSpaced = "<13>Feb 5 17:32:18 10.0.0.99 Use the BFG!";
syslogParser.parse(doubleSpaced, function(parsedMessage){
var msg = gen.produce(parsedMessage);
assert.equal(doubleSpaced, msg);
var expectedData = {
originalMessage: doubleSpaced,
prival: 13,
facilityID: 1,
severityID: 5,
facility: 'user',
severity: 'notice',
type: 'RFC3164',
host: '10.0.0.99',
message: 'Use the BFG!' };
delete parsedMessage.date;
delete parsedMessage.time;
delete parsedMessage.timestamp;
assert.deepEqual(parsedMessage, expectedData);
});
var withCommand = "<34>Oct 11 22:14:15 mymachine su: 'su root' failed for lonvick on /dev/pts/8";
syslogParser.parse(withCommand, function(parsedMessage){
var expectedData = {
originalMessage: withCommand,
prival: 34,
facilityID: 4,
severityID: 2,
facility: 'auth',
severity: 'crit',
type: 'RFC3164',
host: 'mymachine',
message: "su: 'su root' failed for lonvick on /dev/pts/8" };
var parsedDate = parsedMessage.time;
delete parsedMessage.time;
assert.equal(parsedDate.getUTCMonth(), 9);
assert.equal(parsedDate.getUTCHours(), 20);
assert.deepEqual(parsedMessage, expectedData);
});
var withDifficultTime = "<191>94103: 51w2d: DHCPD: assigned IP address 10.10.1.94 to client 0100.01c4.21d3.b3";
syslogParser.parse(withDifficultTime, function(parsedMessage){
var expectedData = {
originalMessage: withDifficultTime,
prival: 191,
facilityID: 23,
severityID: 7,
facility: 'local7',
severity: 'debug',
type: 'RFC3164',
time: undefined,
message: '51w2d: DHCPD: assigned IP address 10.10.1.94 to client 0100.01c4.21d3.b3'};
assert.deepEqual(parsedMessage, expectedData);
});
var withYear = "<32>Mar 05 2011 22:21:02: %ASA-6-302013: Built inbound TCP connection 401 for outside:123.123.123.123/4413 (123.123.123.123/4413) to net:BOX/25 (BOX/25)";
syslogParser.parse(withYear, function(parsedMessage){
var expectedData = {
originalMessage: withYear,
prival: 32,
facilityID: 4,
severityID: 0,
facility: 'auth',
severity: 'emerg',
type: 'RFC3164',
time: undefined,
host: '22:21:02:',
message: '%ASA-6-302013: Built inbound TCP connection 401 for outside:123.123.123.123/4413 (123.123.123.123/4413) to net:BOX/25 (BOX/25)' };
assert.deepEqual(parsedMessage, expectedData);
});
var withSpaces = "<13>Mar 15 11:22:40 myhost.com 0 11,03/15/12,11:22:38,§ó·s,10.10.10.171,,40C6A91373B6,";
syslogParser.parse(withSpaces, function(parsedMessage){
var expectedData = {
originalMessage: withSpaces,
prival: 13,
facilityID: 1,
severityID: 5,
facility: 'user',
severity: 'notice',
type: 'RFC3164',
host: 'myhost.com',
message: ' 0 11,03/15/12,11:22:38,§ó·s,10.10.10.171,,40C6A91373B6,' };
delete parsedMessage.time;
assert.deepEqual(parsedMessage, expectedData);
});

View File

@@ -0,0 +1,106 @@
var syslogParser = require('../lib/glossy/parse.js'),
assert = require('assert');
assert.ok(syslogParser, 'parser loaded');
var withPrecisionTime = "<165>1 2003-08-24T05:14:15.000003-07:00 192.0.2.1 myproc 8710 - - %% It's time to make the do-nuts.";
syslogParser.parse(withPrecisionTime, function(parsedMessage){
var expectedData = {
originalMessage: withPrecisionTime,
prival: 165,
facilityID: 20,
severityID: 5,
facility: 'local4',
severity: 'notice',
type: 'RFC5424',
host: '192.0.2.1',
appName: 'myproc',
pid: '8710',
msgID: null,
message: "%% It's time to make the do-nuts." };
delete parsedMessage.time;
assert.deepEqual(parsedMessage, expectedData);
});
// FIXME 3 minute offset from UTC?!
var with8601 = "<34>1 2003-10-11T22:14:15.003Z mymachine.example.com su - ID47 - BOM'su root' failed for lonvick on /dev/pts/8";
syslogParser.parse(with8601, function(parsedMessage){
var expectedData = {
originalMessage: with8601,
prival: 34,
facilityID: 4,
severityID: 2,
facility: 'auth',
severity: 'crit',
type: 'RFC5424',
time: new Date('2003-10-11T22:14:15.003Z'),
host: 'mymachine.example.com',
appName: 'su',
pid: null,
msgID: 'ID47',
message: "BOM'su root' failed for lonvick on /dev/pts/8" };
assert.deepEqual(parsedMessage, expectedData);
});
// FIXME 3 minute offset from UTC?!
var withSD = '<165>1 2003-10-11T22:14:15.003Z mymachine.example.com evntslog - ID47 [exampleSDID@32473 iut="3" eventSource="Application" eventID="1011"] BOMAn application event log entry...';
syslogParser.parse(withSD, function(parsedMessage){
var expectedData = {
originalMessage: withSD,
prival: 165,
facilityID: 20,
severityID: 5,
facility: 'local4',
severity: 'notice',
type: 'RFC5424',
time: new Date('2003-10-11T22:14:15.003Z'),
host: 'mymachine.example.com',
appName: 'evntslog',
pid: null,
msgID: 'ID47',
structuredData: {
'exampleSDID@32473': {
iut: '3',
eventSource: 'Application',
eventID: '1011'
}
},
message: 'BOMAn application event log entry...' };
assert.deepEqual(parsedMessage, expectedData);
});
// FIXME 3 minute offset from UTC?!
var withDoubleSD = '<165>1 2003-10-11T22:14:15.003Z mymachine.example.com evntslog - ID47 [exampleSDID@32473 iut="3" eventSource="Application" eventID="1011"][examplePriority@32473 class="high"]';
syslogParser.parse(withDoubleSD, function(parsedMessage){
var expectedStructuredData = {
'exampleSDID@32473': {
iut: '3',
eventSource: 'Application',
eventID: '1011'
},
'examplePriority@32473': {
'class': 'high'
}
};
var expectedData = {
originalMessage: withDoubleSD,
prival: 165,
facilityID: 20,
severityID: 5,
facility: 'local4',
severity: 'notice',
type: 'RFC5424',
time: new Date('2003-10-11T22:14:15.003Z'),
host: 'mymachine.example.com',
appName: 'evntslog',
pid: null,
msgID: 'ID47',
structuredData: expectedStructuredData, //FIXME Both sets should be there
message: '' };
assert.deepEqual(parsedMessage, expectedData);
});

View File

@@ -0,0 +1,40 @@
var syslogParser = require('../lib/glossy/parse.js'),
assert = require('assert');
assert.ok(syslogParser, 'parser loaded');
var fullySigned = '<110>1 2009-05-03T14:00:39.519307+02:00 host.example.org syslogd 2138 - [ssign-cert VER="0111" RSID="1" SG="0" SPRI="0" TPBL="587" INDEX="1" FLEN="587" FRAG="2009-05-03T14:00:39.519005+02:00 K BACsLMZ NCV2NUAwe4RAeAnSQuvv2KS51SnHFAaWJNU2XVDYvW1LjmJgg4vKvQPo3HEOD+2hEkt1zcXADe03u5pmHoWy5FGiyCbglYxJkUJJrQqlTSS6vID9yhsmEnh07w3pOsxmb4qYo0uWQrAAenBweVMlBgV3ZA5IMA8xq8l+i8wCgkWJjCjfLar7s+0X3HVrRroyARv8EAIYoxofh9m N8n821BTTuQnz5hp40d6Z3UudKePu2di5Mx3GFelwnV0Qh5mSs0YkuHJg0mcXyUAoeYry5X6482fUxbm+gOHVmYSDtBmZEB8PTEt8Os8aedWgKEt/E4dT+Hmod4omECLteLXxtScTMgDXyC+bSBMjRRCaeWhHrYYdYBACCWMdTc12hRLJTn8LX99kv1I7qwgieyna8GCJv/rEgC ssS9E1qARM+h19KovIUOhl4VzBw3rK7v8Dlw/CJyYDd5kwSvCwjhO21LiReeS90VPYuZFRC1B82Sub152zOqIcAWsgd4myCCiZbWBsuJ8P0gtarFIpleNacCc6OV3i2Rg==" SIGN="AKAQEUiQptgpd0lKcXbuggGXH/dCdQCgdysrTBLUlbeGAQ4vwrnLOqSL7+c="]';
var fullySignedSD = syslogParser.parseStructure(fullySigned);
assert.deepEqual(fullySignedSD, {
'ssign-cert': {
VER: '0111',
RSID: '1',
SG: '0',
SPRI: '0',
TPBL: '587',
INDEX: '1',
FLEN: '587',
FRAG: '2009-05-03T14:00:39.519005+02:00 K BACsLMZ NCV2NUAwe4RAeAnSQuvv2KS51SnHFAaWJNU2XVDYvW1LjmJgg4vKvQPo3HEOD+2hEkt1zcXADe03u5pmHoWy5FGiyCbglYxJkUJJrQqlTSS6vID9yhsmEnh07w3pOsxmb4qYo0uWQrAAenBweVMlBgV3ZA5IMA8xq8l+i8wCgkWJjCjfLar7s+0X3HVrRroyARv8EAIYoxofh9m N8n821BTTuQnz5hp40d6Z3UudKePu2di5Mx3GFelwnV0Qh5mSs0YkuHJg0mcXyUAoeYry5X6482fUxbm+gOHVmYSDtBmZEB8PTEt8Os8aedWgKEt/E4dT+Hmod4omECLteLXxtScTMgDXyC+bSBMjRRCaeWhHrYYdYBACCWMdTc12hRLJTn8LX99kv1I7qwgieyna8GCJv/rEgC ssS9E1qARM+h19KovIUOhl4VzBw3rK7v8Dlw/CJyYDd5kwSvCwjhO21LiReeS90VPYuZFRC1B82Sub152zOqIcAWsgd4myCCiZbWBsuJ8P0gtarFIpleNacCc6OV3i2Rg==',
SIGN: 'AKAQEUiQptgpd0lKcXbuggGXH/dCdQCgdysrTBLUlbeGAQ4vwrnLOqSL7+c='
}
});
assert.deepEqual(syslogParser.parseSignedCertificate(fullySignedSD['ssign-cert']), {
version: '01',
hashAlgorithm: 1,
hashAlgoString: 'SHA1',
sigScheme: 1,
rebootSessionID: 1,
signatureGroup: 0,
signaturePriority: 0,
totalPayloadLength: 587,
payloadIndex: 1,
fragmentLength: 587,
payloadTimestamp: new Date('2009-05-03T14:00:39.519005+02:00'),
payloadType: 'K',
payloadName: 'Public Key',
keyBlob: new Buffer(fullySignedSD['ssign-cert']['FRAG'].split(/\s/)[2], encoding='base64'),
thisSignature: new Buffer(fullySignedSD['ssign-cert']['SIGN'], encoding='base64')
});

View File

@@ -0,0 +1,14 @@
var syslogParser = require('../lib/glossy/parse.js'),
assert = require('assert');
assert.ok(syslogParser, 'parser loaded');
assert.deepEqual(
syslogParser.parse8601('2011-10-10T14:48:00'),
new Date(Date.parse('2011-10-10T14:48:00'))
);
assert.equal(
syslogParser.parse8601('foo'),
undefined
);

View File

@@ -0,0 +1,9 @@
var syslogParser = require('../lib/glossy/parse.js'),
assert = require('assert');
assert.ok(syslogParser, 'parser loaded');
assert.deepEqual(
syslogParser.parseRfc3339("1985-04-12T23:20:50.52Z"),
new Date(482196050000)
);

180
Skills/@be/node_modules/@myndzi/glossy/test/produce.js generated vendored Normal file
View File

@@ -0,0 +1,180 @@
var assert = require('assert');
var producer = require('../lib/glossy/produce.js');
assert.ok(producer, 'producer loaded');
var syslogProducer = new producer();
assert.ok(syslogProducer, 'new SyslogProducer object created');
assert.equal(syslogProducer.type, 'RFC5424', 'Syslog Producer set correctly');
var BSDProducer = new producer({ type: 'BSD'});
assert.ok(BSDProducer, 'new BSDProducer object created');
assert.equal(BSDProducer.type, 'RFC3164', 'BSD Producer set correctly');
var presetProducer = new producer({
type: 'bsd',
facility: 'ntp',
host: 'localhost',
appName: 'kill'
});
var invalidProducer = new producer({
type: 'invalid',
facility: 'invalid',
});
assert.notEqual(invalidProducer, 'invalid producer is null');
var msg = syslogProducer.produce({
facility: 'local4',
severity: 'error',
host: 'localhost',
appName: 'sudo',
pid: '123',
date: new Date(1234567890000),
message: 'Test Message'
});
assert.equal(msg, "<163>1 2009-02-13T23:31:30.000Z localhost sudo 123 - - Test Message",'Valid message returned');
syslogProducer.produce({
facility: 'audit',
severity: 'error',
host: '127.0.0.1',
appName: 'sudo',
pid: '419',
date: new Date(1234567890000),
message: 'Test Message'
}, function(cbMsg) {
assert.equal(cbMsg, '<107>1 2009-02-13T23:31:30.000Z 127.0.0.1 sudo 419 - - Test Message', 'Valid message in callback returned');
});
BSDProducer.produce({
facility: 'audit',
severity: 'error',
host: '127.0.0.1',
appName: 'sudo',
pid: '419',
date: new Date(1234567890000),
message: 'Test Message'
}, function(cbMsg){
assert.equal(cbMsg, '<107>Feb 14 00:31:30 127.0.0.1 sudo[419]: Test Message');
});
var debugMsg = presetProducer.debug({
facility: 'local2',
message: 'Debug Message',
date: new Date(1234567890000),
pid: 91
});
assert.ok(debugMsg);
assert.equal(debugMsg, '<151>Feb 14 00:31:30 localhost kill[91]: Debug Message');
var infoMsg = presetProducer.info({
facility: 'ntp',
message: 'Info Message',
pid: 42,
date: new Date(1234567890000)
});
assert.ok(infoMsg);
assert.equal(infoMsg, '<102>Feb 14 00:31:30 localhost kill[42]: Info Message');
var noticeMsg = presetProducer.debug({
facility: 'local2',
message: 'Notice Message',
pid: 16,
date: new Date(1234567890000)
});
assert.ok(noticeMsg);
assert.equal(noticeMsg, '<151>Feb 14 00:31:30 localhost kill[16]: Notice Message');
var warnMsg = presetProducer.debug({
facility: 'local4',
message: 'Warning Message',
pid: 91,
date: new Date(1234567890000)
});
assert.ok(warnMsg);
assert.equal(warnMsg, '<167>Feb 14 00:31:30 localhost kill[91]: Warning Message');
var errorMsg = presetProducer.debug({
facility: 'clock',
message: 'Error Message',
pid: 91,
date: new Date(1234567890000)
});
assert.ok(errorMsg);
assert.equal(errorMsg, '<79>Feb 14 00:31:30 localhost kill[91]: Error Message');
var criticalMsg = presetProducer.crit({
facility: 'local0',
message: 'Critical Message',
pid: 91,
date: new Date(1234567890000)
});
assert.ok(criticalMsg);
assert.equal(criticalMsg, '<130>Feb 14 00:31:30 localhost kill[91]: Critical Message');
var alertMsg = presetProducer.alert({
facility: 'clock',
message: 'Alert Message',
pid: 91,
date: new Date(1234567890000)
});
assert.ok(alertMsg);
assert.equal(alertMsg, '<73>Feb 14 00:31:30 localhost kill[91]: Alert Message');
var emergencyMsg = presetProducer.emergency({
facility: 'news',
message: 'Emergency Message',
pid: 91,
date: new Date(1234567890000)
});
assert.ok(emergencyMsg);
assert.equal(emergencyMsg, '<56>Feb 14 00:31:30 localhost kill[91]: Emergency Message');
var structuredMsg = syslogProducer.produce({
facility: 'local4',
severity: 'error',
host: 'mymachine.example.com',
appName: 'evntslog',
msgID: 'ID47',
date: new Date(1234567890000),
structuredData: {
'exampleSDID@32473': {
'iut': "3",
'eventSource': "Application",
'eventID': "1011",
'seqNo': "1"
}
},
message: 'BOMAn application event log entry...'
});
assert.ok(structuredMsg);
assert.equal(structuredMsg, '<163>1 2009-02-13T23:31:30.000Z mymachine.example.com evntslog - ID47 [exampleSDID@32473 iut="3" eventSource="Application" eventID="1011" seqNo="1"] BOMAn application event log entry...');
var structuredWithArray = syslogProducer.produce({
facility: 'local4',
severity: 'error',
host: 'mymachine.example.com',
appName: 'evntslog',
msgID: 'ID47',
date: new Date(1234567890000),
structuredData: {
'origin': {
'ip': ['127.0.1.1', '127.0.0.1']
}
},
message: 'BOMAn application event log entry...'
});
assert.ok(structuredWithArray);
assert.equal(structuredWithArray, '<163>1 2009-02-13T23:31:30.000Z mymachine.example.com evntslog - ID47 [origin ip="127.0.1.1" ip="127.0.0.1"] BOMAn application event log entry...');
var messageWithOneDigitDate = presetProducer.emergency({
facility: 'news',
message: 'Emergency Message',
pid: 91,
date: new Date(1233531090000)
});
assert.ok(messageWithOneDigitDate);
assert.equal(messageWithOneDigitDate, '<56>Feb 2 00:31:30 localhost kill[91]: Emergency Message');

40
Skills/@be/node_modules/@myndzi/glossy/test/runner.js generated vendored Normal file
View File

@@ -0,0 +1,40 @@
// set timezone to CET for tests
process.env.TZ='CET';
var spawn = require('child_process').spawn,
fs = require('fs'),
exitCode = 0,
timeout = 10000;
fs.readdir(__dirname, function (e, files) {
if(e) throw e;
var tests = files.filter(function (f) {return f.substr(-2) === 'js' && f != 'runner.js'});
var next = function () {
if(tests.length === 0) process.exit(exitCode);
var file = tests.shift();
var proc = spawn('node', [ 'test/' + file ]);
var killed = false;
var t = setTimeout(function () {
proc.kill();
exitCode += 1;
console.error(file + ' timeout');
killed = true;
}, timeout)
proc.stdout.pipe(process.stdout);
proc.stderr.pipe(process.stderr);
proc.on('exit', function (code) {
if (code && !killed) console.error(file + ' failed');
exitCode += code || 0;
clearTimeout(t);
next();
})
}
next();
})

View File

@@ -0,0 +1,24 @@
var syslogParser = require('../lib/glossy/parse.js'),
assert = require('assert');
assert.ok(syslogParser, 'parser loaded');
var singleStructure = '[exampleSDID@32473 iut="3" eventSource="Application" eventID="1011"]';
assert.deepEqual(syslogParser.parseStructure(singleStructure), {
'exampleSDID@32473': {
iut: '3',
eventSource: 'Application',
eventID: '1011'
}
});
var doubleStructure = '[exampleSDID@32473 iut="3" eventSource="Application" eventID="1011"][examplePriority@32473 class="high"] ';
assert.deepEqual(syslogParser.parseStructure(doubleStructure), {
'exampleSDID@32473': {
iut: '3',
eventID: '1011',
eventSource: 'Application'
},
'examplePriority@32473': {
'class': 'high'
}
});