SNMP Trapd LAM v2 and Indirect Traps
An indirect trap is an SNMP trap payload sent to Moogsoft Onprem encapsulated in another transport, for example, as a REST, Kafka, Syslog, etc. payload. This may occur where SNMP traps are received by an underlying system such as ServiceNow, Splunk, Elastic or similar system, or transported via a common event bus.
The TrapdLamV2 allows indirect traps to be processed by any LAMbot using the existing include
files. Traps can be processed directly (via the trapd_lam
) and indirectly at the same time, and without any modifications needed to the include
file.
Indirect processing is achieved by converting the indirect payload (for example OID key:value pairs) into a format suitable for the include
files.
Prerequisites
TrapdLamV2 bundle installed.
A suitable payload:
Varbind key:value pairs
Trap meta-data
Version, source, trap identification (enterprise, specific, generic, snmpTrapOID or similar)
The MIBs to support the indirect traps
The trap processing will still need the appropriate MIBs to process an indirect trap.
Suitable payloads
To process an indirect trap, the LAMbot needs to convert the incoming payload into "proto-trap" - a set of OID key:value pairs, and suitable trap meta data (version, source, etc.) to allow the trap processing to normalize, route, and process the data via the correct include file as if it were being received directly via the trapd_lam
.
The simplest payload is an OID key:value pair.
For example:
{ ".1.3.6.1.4.1.116.5.11.4.2.1" : 1 ".1.3.6.1.4.1.116.5.11.4.2.2" : "A value for eventTrapNickname", ".1.3.6.1.4.1.116.5.11.4.2.3" : "A value for eventTrapREFCODE" , ".1.3.6.1.4.1.116.5.11.4.2.4" : "1.3.6.1.4.1.116.5.11.4.1.1.6.1.2", ".1.3.6.1.4.1.116.5.11.4.2.5" : "A value for eventTrapDate" , ".1.3.6.1.4.1.116.5.11.4.2.6" : "A value for eventTrapTime" , ".1.3.6.1.4.1.116.5.11.4.2.7" : "A value for eventTrapDescription" }
But partial or full translation also accepted:
{ "SNMPv2-SMI::enterprises.116.5.11.4.2.1" : 1 "SNMPv2-SMI::enterprises.116.5.11.4.2.2" : "A value for eventTrapNickname", "SNMPv2-SMI::enterprises.116.5.11.4.2.3" : "A value for eventTrapREFCODE" , "SNMPv2-SMI::enterprises.116.5.11.4.2.4" : "1.3.6.1.4.1.116.5.11.4.1.1.6.1.2", "SNMPv2-SMI::enterprises.116.5.11.4.2.5" : "A value for eventTrapDate" , "SNMPv2-SMI::enterprises.116.5.11.4.2.6" : "A value for eventTrapTime" , "SNMPv2-SMI::enterprises.116.5.11.4.2.7" : "A value for eventTrapDescription" }
Note
If it is possible to control the source format, aim to get as close to the raw “OID : value” pairs as possible. Full translation can lead to issues over duplicate object names. For example, a fully translated name of “ifIndex” with no MIB module qualifier could come from multiple mibs.
Required payload components
Any indirect trap must be able to supply the following required data to be processed:
A source - generally the agent address is the most authoritative
A generic trap number 0-6
A specific trap number
An enterprise OID (or name that can be translated)
An optional set of varbinds
A source - either explicitly defined or as the
snmpTrapAddress
varbind (as from a forwarded trap)An snmpTrapOID - the unique OID (or name that can be translated)
An optional set of varbinds.
Example SNMP V1 REST Payload
{ "agent_address" : "10.0.0.1", "trap_address" : "127.0.0.1", "version" : "1", "enterprise" : ".1.3.6.1.4.1.116.3.11.4.1.1", "generic_code" : 6, "specific_code" : 1, "trap_oid" : ".0.0", "varbinds" [ { "oid" : ".1.3.6.1.4.1.116.5.11.4.2.1", "type" : "integer" , "value" : 1 }, { "oid" : ".1.3.6.1.4.1.116.5.11.4.2.2", "type" : "string" , "value" : "A value for eventTrapNickname" }, { "oid" : ".1.3.6.1.4.1.116.5.11.4.2.3", "type" : "string" , "value" : "A value for eventTrapREFCODE" }, { "oid" : ".1.3.6.1.4.1.116.5.11.4.2.4", "type" : "oid" , "value" : "1.3.6.1.4.1.116.5.11.4.1.1.6.1.2""}, { "oid" : ".1.3.6.1.4.1.116.5.11.4.2.5", "type" : "string" , "value" : "A value for eventTrapDate" }, { "oid" : ".1.3.6.1.4.1.116.5.11.4.2.6", "type" : "string" , "value" : "A value for eventTrapTime" }, { "oid" : ".1.3.6.1.4.1.116.5.11.4.2.7", "type" : "string" , "value" : "A value for eventTrapDescription" } ] }
Example SNMP v2c REST Payload
{ "trap_address" : "10.0.0.1", "version" : "2c", "trap_oid" : ".1.3.6.1.4.1.17163.2.1.1.6", "varbinds" : [ { "oid" : ".1.3.6.1.6.3.1.1.4.1.0", "type" : "oid" , "value" : ".1.3.6.1.4.1.17163.2.1.1.6" }, { "oid" : ".1.3.6.1.4.1.17163.2.1.2.21", "type" : "string" , "value" : "A value for auditUsername" }, { "oid" : ".1.3.6.1.4.1.17163.2.1.2.33", "type" : "integer" , "value" : 1 }, { "oid" : ".1.3.6.1.4.1.17163.2.1.2.29", "type" : "string" , "value" : "A value for auditRESTNamespace" }, { "oid" : ".1.3.6.1.4.1.17163.2.1.2.34", "type" : "string" , "value" : "A value for auditIdentifier" }, { "oid" : ".1.3.6.1.4.1.17163.2.1.2.17", "type" : "string" , "value" : "A value for auditTimestamp" }, { "oid" : ".1.3.6.1.4.1.17163.2.1.2.27", "type" : "integer" , "value" : 1 }, { "oid" : ".1.3.6.1.4.1.17163.2.1.2.18", "type" : "string" , "value" : "A value for auditAction" }, { "oid" : ".1.3.6.1.4.1.17163.2.1.2.28", "type" : "string" , "value" : "A value for auditRESTLink" }, { "oid" : ".1.3.6.1.4.1.17163.2.1.2.22", "type" : "string" , "value" : "A value for auditIPAddr" }, { "oid" : ".1.3.6.1.4.1.17163.2.1.2.19", "type" : "string" , "value" : "A value for auditEventType" }, { "oid" : ".1.3.6.1.4.1.17163.2.1.2.30", "type" : "string" , "value" : "A value for auditRESTVersion" }, { "oid" : ".1.3.6.1.4.1.17163.2.1.2.31", "type" : "string" , "value" : "A value for auditRESTResource" }, { "oid" : ".1.3.6.1.4.1.17163.2.1.2.26", "type" : "string" , "value" : "A value for auditModule" }, { "oid" : ".1.3.6.1.4.1.17163.2.1.2.32", "type" : "string" , "value" : "A value for auditDetails" }, { "oid" : ".1.3.6.1.4.1.17163.2.1.2.20", "type" : "integer" , "value" : 1 }, { "oid" : ".1.3.6.1.4.1.17163.2.1.2.23", "type" : "string" , "value" : "A value for auditUserAgent" }, { "oid" : ".1.3.6.1.4.1.17163.2.1.2.24", "type" : "integer" , "value" : 1 }, { "oid" : ".1.3.6.1.4.1.17163.2.1.2.25", "type" : "string" , "value" : "A value for auditSID" } ] }
Creating a LAMbot to process Indirect Traps
Important
The MoogTrapdLamV2.js has example code for processing both v1 and v2c indirect traps.
In this example we are going to use the basic REST LAM and a custom LAMbot to process a basic OID key:value payload. The v1 and v2c payloads will contain the OID:key value pairs and also the v1 or v2c specific metadata. In this case, the varbinds are presented as a list and include the data type. The payload you have will be different, and you will need to adjust the code as needed to adapt to your unique payload structure.
Step 1
Ensure that the appropriate MIBs are included in a precompiledMib file generated from the mibparser
.
mibparser -i $MOOGSOFT_HOME/etc/mibs -o $MOOGSOFT_HOME/etc/precompiledMibs.EXAMPLE.json
Step 2
Create a new lam config file using the rest_lam.conf
as a template.
cp $MOOGSOFT_HOME/config/rest_lam.conf $MOOGSOFT_HO?ME/config/rest_trap.conf
Step 3
Edit the rest_trap.conf
file, add the required port number, credentials and other information, and modify the “mapping” and “filter” sections to remove all mapping apart from severity and agent_time
:
mapping : { catchAll: "overflow", rules: [ { name: "signature", rule: "" }, { name: "source_id", rule: "" }, { name: "external_id", rule: "" }, { name: "manager", rule: "" }, { name: "source", rule: "" }, { name: "class", rule: "" }, { name: "agent", rule: "" }, { name: "agent_location", rule: "" }, { name: "type", rule: "" }, { name: "severity", rule: "1", conversion: "stringToInt" }, { name: "description", rule: "" }, { name: "agent_time", rule: "$moog_now" } ] }, filter: { presend: "RestTrap.js" }
Important
Notice the filter section contains a custom LAMbot (RestTrap.js
) and not the standard MoogTrapdLamV2.js
.
Ensure that accept_all_json
is set to true
if the Moogsoft event format is not being followed.
Step 4
In the agent section, disable LAMbot optimization:
agent: { #--------------------------------------------- # The agent name that will appear as # $LamInstanceName in the mapping rules below #--------------------------------------------- name : "REST_TRAP", lambot_optimization : -1 #,capture_log: "$MOOGSOFT_HOME/log/data-capture/rest_lam.log" },
Step 5
Create a blank $MOOGSOFT_HOME/bots/lambots/RestTrap.js
and add the following lines:
Load and initialize the required LAMbot, trap utility, and associated modules for processing the indirect trap
// ---------------------------------------------------------------------------------------- // Initialise // ---------------------------------------------------------------------------------------- // Load standard modules var logger = LamBot.loadModule("Logger"); var constants = LamBot.loadModule("Constants"); var mibDb = LamBot.loadModule("MibDb"); var utilities = LamBot.loadModule("Utilities"); // ---------------------------------------------------------------------------------------- // Load the utility modules // ---------------------------------------------------------------------------------------- LamBot.loadModule("BotUtility.js"); LamBot.loadModule("SyslogUtil.js"); LamBot.loadModule("SyslogEvents.js"); LamBot.loadModule("RegExpUtil.js"); LamBot.loadModule("TrapUtility.js"); // ---------------------------------------------------------------------------------------- // Initialise utiity modules and pass to the TrapUtility module. // ---------------------------------------------------------------------------------------- var botUtil = new BotUtility(); var syslogUtil = new SyslogUtil(botUtil); var regExpUtil = new RegExpUtil(botUtil); var regExpLib = regExpUtil.buildRegExpLib(); var botModules = { "constants" : constants, "botUtil" : botUtil, "mibDb" : mibDb, "syslogUtil" : syslogUtil, "regExpLib" : regExpLib, "utilities" : utilities };
Initialize the trapUtility
and mibDB
// ---------------------------------------------------------------------------------------- // Instaniate the trapUtility. // Load the precompiled mibs // ---------------------------------------------------------------------------------------- var trapUtil = new TrapUtility(botModules); mibDb.loadMibDb("/usr/share/moogsoft/etc/precompiledMibs.EXAMPLE.json");
Line 9 above is loading the precompiled MIB file created in step 1, above.
Define the onLoad()
function
function onLoad() { // ------------------------------------------------------------------------------------ // Intitialise the trapUtility passing the include file // if no include file is specified, the default trapModules/master.includes will be // used. // // trapUtil.init("trapModules/master.custom.includes"); // // Log the loaded modules and the routing keys: // (only shown at debug level) // // trapUtil.logLoadedModules(); // trapUtil.logTrapRoutes(); // ------------------------------------------------------------------------------------ // trapUtil.init("trapModules/master.none.includes"); trapUtil.init("trapModules/master.includes"); // ------------------------------------------------------------------------------------ // Enable trap debug (trap payload will be added to final event). // Note: this can lead to large event sizes. // ------------------------------------------------------------------------------------ trapUtil.setTrapDebug(true); trapUtil.logLoadedModules(); trapUtil.logTrapRoutes(); // ------------------------------------------------------------------------------------ return true; }
This code is executed when the LAM first loads. This initializes the trap utility (trapUtil
), passing the master.includes
files that will be used to define the list of include files to include for processing.
The three trapUtil
functions (setTrapDebug
, logLoadedModules
, logTrapRoutes
) are useful for development and debug, but do not need to be included for production processing.
Declare the presend
function
LamBot.filterFunction("presend");
Define the presend()
function
function presend(event) { // ---------------------------------------------------- // Build the trap, and add varbinds. // ---------------------------------------------------- var overflow = botUtil.getOverflow(event); if ( !overflow ) { logger.warning("Failed to retrieve overflow, dropping event"); return false; }
All of the indirect trap payload will be held in “overflow” as there was no mapping defined in the rest_trap.conf
configuration.
Check for required attributes in the payload
This code will be different for each indirect source - adjust your code as needed. Our example payload has a “version” key which we will use to switch between v1 and v2c processing paths.
var version = overflow.version.toString(); var trap = null; if ( version === "1" ) { // V1 processing ... } else if ( /^(2(c)?|3)$/.test(version) ) { // V2c | 3 processing ... } else { logger.warning("Unrecognised SNMP version: " + overflow.version + ", dropping event."); return false; }
v1 processing
In our v1 example payload, the trap structure is:
{ "agent_address" : "<ip>", "trap_address" : "<ip>", "version" : "1", "enterprise" : "<oid>", "generic_code" : n, "specific_code" : n, "trap_oid" : "<oid>", "varbinds" [ ... ] }
We’ll add code to our v1 block to check for the required items - using the botUtil.checkConfig()
utility passing the overflow and a list of required items.
if ( version === "1" ) { // Check our v1 payload has the minimum required items to proceed. var requiredV1items = [ "agent_address", "enterprise", "generic_code", "specific_code" ]; if ( !botUtil.checkConfig(overflow,requiredV1items) ) { logger.warning("Failed to find SNMP v1 trap required items in overflow, dropping event."); return false; }
Note
Subsequent code for V1 will be within this code block - see the Full LAMbot for a full structure.
Add code to create a V1 "trap" and populate the values from overflow
// Create a v1 "trap" and populate the required fields // for a v1 trap // - version // - enterprise // - source // - generic // - specific // - varbinds trap = new trapUtil.Trap(); trap.setSnmpVersion(1); trap.setEnterprise(overflow.enterprise) trap.setSpecificCode(overflow.specific_code); trap.setGenericCode(overflow.generic_code); trap.setSource(overflow.agent_address);
Note
See the Trap functions for a full list of available functions
version
- setting to v1enterprise
- set to the “enterprise” value.specific
- set to the “specific_code” valuegeneric
- set to the “generic_code” valuesource
- In this case we are setting the source to theagent_address
- which for a v1 trap would be considered the authoritative source (overridingtrap_source
).
v2c | v3 processing
In our v2 payload the structure is:
{ "trap_address" : "<ip>", "version" : "2c", "trap_oid" : "<oid>", "varbinds" : [ ... ] }
We’ll add code to the v2c/3 block to check for the required items, create a v2c trap, and populate the required fields:
... else if ( /^(2(c)?|3)$/.test(version) ) { // Create a v2 "trap" and populate the required fields // for a v2c / 3 trap. // - version // - source - either explicitly or via addition of the snmpTrapAddress OID // as a varbind (1.3.6.1.6.3.18.1.3.0) var requiredV2items = [ "trap_address", "trap_oid" ]; if ( !botUtil.checkConfig(overflow,requiredV2items) ) { logger.warning("Failed to find SNMP v2c trap required items in overflow, dropping event."); return false; } trap = new trapUtil.Trap(); trap.setSnmpVersion(2); trap.setSnmpTrapOID(overflow.trap_oid); trap.setSource(overflow.trap_address); }
We now have a “trap” object with the correct characteristics for a v1 or v2c trap - we now want to add varbinds to this. Both the v1 and v2c incoming payloads have a list of varbind objects - and we will iterate through these adding these to the trap object.
At the end of the initial processing block add a loop to iterate over the varbinds and add these to the trap:
// Populate varbinds - we are expecting a list of objects with a 'oid' and 'value' key. if ( botUtil.isPopulatedList(overflow.varbinds) ) { overflow.varbinds.forEach(function(varbind) { if ( typeof varbind.oid !== 'undefined' && typeof varbind.value !== 'undefined' ) { trap.addVarbind(varbind.oid,varbind.value); } }); }
Notes on adding varbinds:
Varbinds values do not need to be coerced to the correct data type (the eventual trap processing will do this in the include file if needed)
Full OIDs do not need to be translated - the
addVarbind()
function will do the translation.
Validate, process and dispatch the event
At this stage we have a fully formed “trap” containing both meta data and varbind data. This then needs to be processed via the appropriate include file.
// ---------------------------------------------------- // Validate the trap contains enough data to proceed. // ---------------------------------------------------- var validated = trap.validate(); if ( !validated ) { logger.warning("Trap failed validation - generating ingeston alert"); botUtil.printObj(trap,"failed to validate"); botUtil.generateIngestEvent(event,"Trap failed to validate"); return true; } // ---------------------------------------------------- // Process the trap, prepare and despatch // ---------------------------------------------------- var trapEvent = trap.processTrap(); var eventOk = trapUtil.prepareEvent(event,trapEvent); if ( !eventOk ) { logger.warning("Trap failed validation - generating ingeston alert"); botUtil.printObj(trapEvent,"failed to validate"); botUtil.generateIngestEvent(event,"Trap failed to validate"); return true; } // ------------------------------------------------------------------------------------ // Check for a stream in the trapEvent and despatch. // ------------------------------------------------------------------------------------ if ( trapEvent.streamName ) { return( { passed: true, stream: trapEvent.streamName } ); } else { return(true); }
The TrapUtility
provides functions to validate the “proto-trap” that has been created, process this via the appropriate include file and convert the resulting data into the originally received event:
validate()
- ensure that the “trap” has enough data to continue processing.This validation will perform the following actions:
Validate the required meta-data for a v1 or v2c/3 trap.
If the source of the trap is an IP address - attempt to DNS resolve this (as the
trapd_lam
would do). This resolution uses the built in LAM DNS resolution utility and caches the results, so does not introduce any significant overhead.
processTrap()
- pass the “trap” to the processing layer, find the correct include file and run the appropriate function within it.prepareEvent()
- take the output of the include processing, and copy these details into the original event.
If any of these steps fail, an ingestion error event will be produced - this details the source data and any reason for failure. Ingestion events are created as unique alerts in Moogsoft Onprem, allowing an operator or administrator to easily see where the indirect trap processing has failed allowing remedial action to be taken.
Full LAMbot
Payloads used:
V1:
{ "agent_address" : "10.0.0.1", "trap_address" : "127.0.0.1", "version" : "1", "enterprise" : ".1.3.6.1.4.1.116.3.11.4.1.1", "generic_code" : 6, "specific_code" : 1, "trap_oid" : ".0.0", "varbinds" : [ { "oid" : ".1.3.6.1.4.1.116.5.11.4.2.1", "type" : "integer" , "value" : 1 }, { "oid" : ".1.3.6.1.4.1.116.5.11.4.2.2", "type" : "string" , "value" : "A value for eventTrapNickname" }, { "oid" : ".1.3.6.1.4.1.116.5.11.4.2.3", "type" : "string" , "value" : "A value for eventTrapREFCODE" }, { "oid" : ".1.3.6.1.4.1.116.5.11.4.2.4", "type" : "oid" , "value" : ".0.0"}, { "oid" : ".1.3.6.1.4.1.116.5.11.4.2.5", "type" : "string" , "value" : "A value for eventTrapDate" }, { "oid" : ".1.3.6.1.4.1.116.5.11.4.2.6", "type" : "string" , "value" : "A value for eventTrapTime" }, { "oid" : ".1.3.6.1.4.1.116.5.11.4.2.7", "type" : "string" , "value" : "A value for eventTrapDescription" } ] }
V2:
{ "agent_address" : "10.0.0.1", "trap_address" : "10.0.0.1", "version" : "2c", "enterprise" : "0.0", "generic_code" : 0, "specific_code" : 0, "trap_oid" : ".1.3.6.1.4.1.17163.2.1.1.6", "varbinds" : [ { "oid" : ".1.3.6.1.6.3.1.1.4.1.0", "type" : "oid" , "value" : ".1.3.6.1.4.1.17163.2.1.1.6" }, { "oid" : ".1.3.6.1.4.1.17163.2.1.2.21", "type" : "string" , "value" : "A value for auditUsername" }, { "oid" : ".1.3.6.1.4.1.17163.2.1.2.33", "type" : "integer" , "value" : 1 }, { "oid" : ".1.3.6.1.4.1.17163.2.1.2.29", "type" : "string" , "value" : "A value for auditRESTNamespace" }, { "oid" : ".1.3.6.1.4.1.17163.2.1.2.34", "type" : "string" , "value" : "A value for auditIdentifier" }, { "oid" : ".1.3.6.1.4.1.17163.2.1.2.17", "type" : "string" , "value" : "A value for auditTimestamp" }, { "oid" : ".1.3.6.1.4.1.17163.2.1.2.27", "type" : "integer" , "value" : 1 }, { "oid" : ".1.3.6.1.4.1.17163.2.1.2.18", "type" : "string" , "value" : "A value for auditAction" }, { "oid" : ".1.3.6.1.4.1.17163.2.1.2.28", "type" : "string" , "value" : "A value for auditRESTLink" }, { "oid" : ".1.3.6.1.4.1.17163.2.1.2.22", "type" : "string" , "value" : "A value for auditIPAddr" }, { "oid" : ".1.3.6.1.4.1.17163.2.1.2.19", "type" : "string" , "value" : "A value for auditEventType" }, { "oid" : ".1.3.6.1.4.1.17163.2.1.2.30", "type" : "string" , "value" : "A value for auditRESTVersion" }, { "oid" : ".1.3.6.1.4.1.17163.2.1.2.31", "type" : "string" , "value" : "A value for auditRESTResource" }, { "oid" : ".1.3.6.1.4.1.17163.2.1.2.26", "type" : "string" , "value" : "A value for auditModule" }, { "oid" : ".1.3.6.1.4.1.17163.2.1.2.32", "type" : "string" , "value" : "A value for auditDetails" }, { "oid" : ".1.3.6.1.4.1.17163.2.1.2.20", "type" : "integer" , "value" : 1 }, { "oid" : ".1.3.6.1.4.1.17163.2.1.2.23", "type" : "string" , "value" : "A value for auditUserAgent" }, { "oid" : ".1.3.6.1.4.1.17163.2.1.2.24", "type" : "integer" , "value" : 1 }, { "oid" : ".1.3.6.1.4.1.17163.2.1.2.25", "type" : "string" , "value" : "A value for auditSID" } ] }
LAMbot:
/******************************************************************************* * Copyright (c) Moogsoft Inc 2021 * * * *-----------------------------------------------------------------------------* * * * All information contained herein is and remains the property of Moogsoft * * Inc. The intellectual and technical concepts contained herein may be * * covered by U.S. and Foreign Patents or patents in process, are protected by * * trade secret law, and cannot be disseminated beyond authorized users. * * * * This source code is confidential and protected by copyright law. Any person * * who believes that they are viewing it without permission is asked to notify * * Moogsoft Inc.'s legal department at legal@moogsoft.com. Dissemination of * * this information in any form or by any means is strictly forbidden unless * * prior written permission is obtained from Moogsoft Inc. This source code * * may be modified for purposes of configuration or integration into Moogsoft * * Inc.'s authorized customer's computer systems in accordance with the terms * * of the customer's license. * * * * If you are uncertain about the means in which you may modify this source * * code, contact your Moogsoft Inc. customer representative or Moogsoft Inc.'s * * legal department at legal@moogsoft.com. * * * *******************************************************************************/ // ---------------------------------------------------------------------------------------- // Initialise // ---------------------------------------------------------------------------------------- // Load standard modules var logger = LamBot.loadModule("Logger"); var constants = LamBot.loadModule("Constants"); var mibDb = LamBot.loadModule("MibDb"); var utilities = LamBot.loadModule("Utilities"); // ---------------------------------------------------------------------------------------- // Load the utility modules // ---------------------------------------------------------------------------------------- LamBot.loadModule("BotUtility.js"); LamBot.loadModule("SyslogUtil.js"); LamBot.loadModule("SyslogEvents.js"); LamBot.loadModule("RegExpUtil.js"); LamBot.loadModule("TrapUtility.js"); // ---------------------------------------------------------------------------------------- // Initialise utiity modules and pass to the TrapUtility module. // ---------------------------------------------------------------------------------------- var botUtil = new BotUtility(); var syslogUtil = new SyslogUtil(botUtil); var regExpUtil = new RegExpUtil(botUtil); var regExpLib = regExpUtil.buildRegExpLib(); var botModules = { "constants" : constants, "botUtil" : botUtil, "mibDb" : mibDb, "syslogUtil" : syslogUtil, "regExpLib" : regExpLib, "utilities" : utilities }; // ---------------------------------------------------------------------------------------- // Instaniate the trapUtility. // Load the precompiled mibs // ---------------------------------------------------------------------------------------- var trapUtil = new TrapUtility(botModules); mibDb.loadMibDb("/usr/share/moogsoft/etc/precompiledMibs.EXAMPLE.json"); // ---------------------------------------------------------------------------------------- function onLoad() { // ------------------------------------------------------------------------------------ // Intitialise the trapUtility passing the include file // if no include file is specified, the default trapModules/master.includes will be // used. // // trapUtil.init("trapModules/master.custom.includes"); // // Log the loaded modules and the routing keys: // (only shown at debug level) // // trapUtil.logLoadedModules(); // trapUtil.logTrapRoutes(); // ------------------------------------------------------------------------------------ // trapUtil.init("trapModules/master.none.includes"); trapUtil.init("trapModules/master.includes"); // ------------------------------------------------------------------------------------ // Enable trap debug (trap payload will be added to final event). // Note: this can lead to large event sizes. // ------------------------------------------------------------------------------------ // // trapUtil.setTrapDebug(true); trapUtil.logLoadedModules(); // ------------------------------------------------------------------------------------ return true; } // // Tell the LamBot that we filter using the presend function // LamBot.filterFunction("presend"); function presend(event) { // ---------------------------------------------------- // Build the trap, and add varbinds. // ---------------------------------------------------- var overflow = botUtil.getOverflow(event); if ( !overflow ) { logger.warning("Failed to retrieve overflow, dropping event."); return false; } // Check to see if we have a version. if ( !overflow.version ) { logger.warning("Failed to find SNMP trap version in overflow, dropping event."); return false; } var version = overflow.version.toString(); var trap = null; if ( version === "1" ) { // Check our v1 payload has the minimum required items to proceed. var requiredV1items = [ "agent_address", "enterprise", "generic_code", "specific_code" ]; if ( !botUtil.checkConfig(overflow,requiredV1items) ) { logger.warning("Failed to find SNMP v1 trap required items in overflow, dropping event."); return false; } // Create a v1 "trap" and populate the required fields // for a v1 trap // - version // - enterprise // - source // - generic // - specific // - varbinds trap = new trapUtil.Trap(); trap.setSnmpVersion(1); trap.setEnterprise(overflow.enterprise); trap.setSpecificCode(overflow.specific_code); trap.setGenericCode(overflow.generic_code); trap.setSource(overflow.agent_address); } else if ( /^(2(c)?|3)$/.test(version) ) { // Create a v2 "trap" and populate the required fields // for a v2c / 3 trap. // - version // - source - either explicitly or via addition of the snmpTrapAddress OID // as a varbind (1.3.6.1.6.3.18.1.3.0) var requiredV2items = [ "trap_address", "trap_oid" ]; if ( !botUtil.checkConfig(overflow,requiredV2items) ) { logger.warning("Failed to find SNMP v2c trap required items in overflow, dropping event."); return false; } trap = new trapUtil.Trap(); trap.setSnmpVersion(2); trap.setSnmpTrapOID(overflow.trap_oid); trap.setSource(overflow.trap_address); } else { logger.warning("Unrecognised SNMP version: " + overflow.version + ", dropping event."); return false; } // ---------------------------------------------------- // Populate varbinds - we are expecting a list of objects with a 'oid' and 'value' key. // ---------------------------------------------------- if ( botUtil.isPopulatedList(overflow.varbinds) ) { overflow.varbinds.forEach(function(varbind) { if ( typeof varbind.oid !== 'undefined' && typeof varbind.value !== 'undefined' ) { trap.addVarbind(varbind.oid,varbind.value); } }); } // ---------------------------------------------------- // Validate the trap contains enough data to proceed. // ---------------------------------------------------- var validated = trap.validate(); if ( !validated ) { logger.warning("Trap failed validation - generating ingeston alert"); botUtil.printObj(trap,"failed to validate"); botUtil.generateIngestEvent(event,"Trap failed to validate"); return true; } // ---------------------------------------------------- // Process the trap, prepare and despatch // ---------------------------------------------------- var trapEvent = trap.processTrap(); var eventOk = trapUtil.prepareEvent(event,trapEvent); if ( !eventOk ) { logger.warning("Trap failed validation - generating ingeston alert"); botUtil.printObj(trapEvent,"failed to validate"); botUtil.generateIngestEvent(event,"Trap failed to validate"); return true; } // ------------------------------------------------------------------------------------ // Check for a stream in the trapEvent and despatch. // ------------------------------------------------------------------------------------ if ( trapEvent.streamName ) { return( { passed: true, stream: trapEvent.streamName } ); } else { return(true); } }