def ModuleInitialization(): # Initialize module ifc_spec = trap.parseParams(sys.argv, module_info) trap.init(module_info, ifc_spec) trap.registerDefaultSignalHandler() # This is needed to allow module termination using s SIGINT or SIGTERM signal # this module accepts all UniRec fieds -> set required format: trap.set_required_fmt(0, trap.TRAP_FMT_UNIREC, "")
action="store_false", dest="verbose", default=True, help="don't print status messages to stdout") # usage of OptionParser can be found in its help module_info = trap.CreateModuleInfo( "PythonExample", # Module name "An example TRAP module written in Python", # Description 1, # Number of input interfaces 1, # Number of output interfaces parser # use previously defined OptionParser ) # Initialize module ifc_spec = trap.parseParams(sys.argv, module_info) trap.init(module_info, ifc_spec) trap.registerDefaultSignalHandler( ) # This is needed to allow module termination using s SIGINT or SIGTERM signal # Parse remaining command-line arguments (options, args) = parser.parse_args() # this module accepts all UniRec fieds -> set required format: trap.set_required_fmt(0, trap.TRAP_FMT_UNIREC, "") # Specifier of UniRec records will be received during libtrap negotiation UR_Flow = None
def Run(module_name, module_desc, req_type, req_format, conv_func, arg_parser = None): """ TODO doc """ # *** Parse command-line arguments *** if arg_parser is None: arg_parser = argparse.ArgumentParser() arg_parser.formatter_class = argparse.RawDescriptionHelpFormatter # Set description arg_parser.description = str.format(desc_template, name=module_name, type={trap.TRAP_FMT_RAW:'raw', trap.TRAP_FMT_UNIREC:'UniRec', trap.TRAP_FMT_JSON:'JSON'}.get(req_type,'???'), fmt=req_format, original_desc = module_desc+"\n\n " if module_desc else "", ) # Add arguments defining outputs # TRAP output arg_parser.add_argument('--trap', action='store_true', help='Enable output via TRAP interface (JSON type with format id "IDEA"). Parameters are set using "-i" option as usual.') # File output arg_parser.add_argument('--file', metavar="FILE", type=str, help='Enable output to file (each IDEA message printed to new line in JSON format). Set to "-" to use standard output.') arg_parser.add_argument('--file-indent', metavar="N", type=int, help='Pretty-format JSON in output file using N spaces for indentation.') arg_parser.add_argument('--file-append', action='store_true', help='Append to file instead of overwrite.') # MongoDB output arg_parser.add_argument('--mongodb', metavar="DBNAME", help='Enable output to MongoDB. Connect to database named DBNAME.') arg_parser.add_argument('--mongodb-coll', metavar="COLL", default='alerts', help='Put IDEA messages into collection named COLL (default: "alerts").') arg_parser.add_argument('--mongodb-host', metavar="HOSTNAME", default='localhost', help='Connect to MongoDB running on HOSTNAME (default: "localhost").') arg_parser.add_argument('--mongodb-port', metavar="PORT", type=int, default=27017, help='Connect to MongoDB running on port number PORT (default: 27017).') # Warden3 output arg_parser.add_argument('--warden', metavar="CONFIG_FILE", help='Send IDEA messages to Warden server. Load configuration of Warden client from CONFIG_FILE.') # Other options arg_parser.add_argument('-n', '--name', metavar='NODE_NAME', help='Name of the node, filled into "Node.Name" element of the IDEA message. Required if Warden output is used, recommended otherwise.') arg_parser.add_argument('--test', action='store_true', help='Add "Test" to "Category" before sending a message to output(s).') arg_parser.add_argument('-v', '--verbose', action='store_true', help="Enable verbose mode (may be used by some modules, common part donesn't print anything") # TRAP parameters trap_args = arg_parser.add_argument_group('Common TRAP parameters') trap_args.add_argument('-i', metavar="IFC_SPEC", required=True, help='TODO (ideally this section should be added by TRAP') # Parse arguments args = arg_parser.parse_args() # Check if at least one output is enabled if not (args.file or args.trap or args.mongodb or args.warden): sys.stderr.write(module_name+": Error: At least one output must be selected\n") exit(1) # Check if node name is set if Warden output is enabled if args.name is None: if args.warden: sys.stderr.write(module_name+": Error: Node name must be specified if Warden output is used (set param --name).\n") exit(1) else: sys.stderr.write(module_name+": Warning: Node name is not specified.\n") # *** Initialize TRAP *** module_info = trap.CreateModuleInfo( module_name, # Module name "", # Description 1, # Number of input interfaces 1 if args.trap else 0, # Number of output interfaces None # optionParser ) ifc_spec = trap.parseParams(['-i', args.i], module_info) trap.init(module_info, ifc_spec) trap.registerDefaultSignalHandler() # Set required input format trap.set_required_fmt(0, req_type, req_format) # If TRAP output is enabled, set output format (JSON, format id "IDEA") if args.trap: trap.set_data_fmt(0, trap.TRAP_FMT_JSON, "IDEA") # *** Create output handles/clients/etc *** filehandle = None mongoclient = None mongocoll = None wardenclient = None if args.file: if args.file == '-': filehandle = sys.stdout else: filehandle = open(args.file, "a" if args.file_append else "w") if args.mongodb: import pymongo mongoclient = pymongo.MongoClient(args.mongodb_host, args.mongodb_port) mongocoll = mongoclient[args.mongodb][args.mongodb_coll] if args.warden: import warden_client wardenclient = warden_client.Client(**warden_client.read_cfg(args.warden)) # *** Main loop *** URInputTmplt = None if req_type == trap.TRAP_FMT_UNIREC and req_format != "": URInputTmplt = unirec.CreateTemplate("URInputTmplt", req_format) # TRAP expects us to have predefined template for required set of fields while not trap.stop: # *** Read data from input interface *** try: data = trap.recv(0) except trap.EFMTMismatch: sys.stderr.write(module_name+": Error: input data format mismatch\n")#Required: "+str((req_type,req_format))+"\nReceived: "+str(trap.get_data_fmt(trap.IFC_INPUT, 0))+"\n") break except trap.EFMTChanged as e: # TODO: This should be handled by trap.recv transparently # Get negotiated input data format (fmttype, fmtspec) = trap.get_data_fmt(trap.IFC_INPUT, 0) # If data type is UniRec, create UniRec template #print "Creating template", fmtspec if fmttype == trap.TRAP_FMT_UNIREC: URInputTmplt = unirec.CreateTemplate("URInputTmplt", fmtspec) else: URInputTmplt = None data = e.data except trap.ETerminated: break # Check for "end-of-stream" record if len(data) <= 1: # If we have output, send "end-of-stream" record and exit if args.trap: trap.send(0, "0") break # Assert that if UniRec input is required, input template is set assert(req_type != trap.TRAP_FMT_UNIREC or URInputTmplt is not None) # Convert raw input data to UniRec object (if UniRec input is expected) if req_type == trap.TRAP_FMT_UNIREC: rec = URInputTmplt(data) elif req_type == trap.TRAP_FMT_JSON: rec = json.loads(data) else: # TRAP_FMT_RAW rec = data # *** Convert input record to IDEA *** # Pass the input record to conversion function to create IDEA message idea = conv_func(rec, args) if idea is None: continue # Record can't be converted - skip it (notice should be printed by the conv function) if args.name is not None: idea['Node'][0]['Name'] = args.name if args.test: idea['Category'].append('Test') # *** Send IDEA to outputs *** # File output if filehandle: filehandle.write(json.dumps(idea, indent=args.file_indent)+'\n') # TRAP output if args.trap: try: trap.send(0, json.dumps(idea)) except trap.ETerminated: # don't exit immediately, first finish sending to other outputs trap.stop = 1 # MongoDB output if mongocoll: # Convert timestamps from string to Date format idea['DetectTime'] = datetime.strptime(idea['DetectTime'], "%Y-%m-%dT%H:%M:%SZ") for i in [ 'CreateTime', 'EventTime', 'CeaseTime' ]: if idea.has_key(i): idea[i] = datetime.strptime(idea[i], "%Y-%m-%dT%H:%M:%SZ") try: mongocoll.insert(idea) except pymongo.errors.AutoReconnect: sys.stderr.write(module_name+": Error: MongoDB connection failure.\n") trap.stop = 1 # Warden output if wardenclient: wardenclient.sendEvents([idea]) # *** Cleanup *** if filehandle and filehandle != sys.stdout: filehandle.close() if mongoclient: mongoclient.close() if wardenclient: wardenclient.close() trap.finalize()
parser.add_option("-q", "--quiet", action="store_false", dest="verbose", default=True, help="don't print status messages to stdout") # usage of OptionParser can be found in its help module_info = trap.CreateModuleInfo( "PythonExample", # Module name "An example TRAP module written in Python", # Description 1, # Number of input interfaces 1, # Number of output interfaces parser # use previously defined OptionParser ) # Initialize module ifc_spec = trap.parseParams(sys.argv, module_info) trap.init(module_info, ifc_spec) trap.registerDefaultSignalHandler() # This is needed to allow module termination using s SIGINT or SIGTERM signal # Parse remaining command-line arguments (options, args) = parser.parse_args() # this module accepts all UniRec fieds -> set required format: trap.set_required_fmt(0, trap.TRAP_FMT_UNIREC, "") # Specifier of UniRec records will be received during libtrap negotiation UR_Flow = None # Main loop (trap.stop is set to True when SIGINT or SIGTERM is received)
def Run(module_name, module_desc, req_type, req_format, conv_func, arg_parser=None): """ TODO doc """ # *** Parse command-line arguments *** if arg_parser is None: arg_parser = argparse.ArgumentParser() arg_parser.formatter_class = argparse.RawDescriptionHelpFormatter # Set description arg_parser.description = str.format( desc_template, name=module_name, type={ trap.TRAP_FMT_RAW: 'raw', trap.TRAP_FMT_UNIREC: 'UniRec', trap.TRAP_FMT_JSON: 'JSON' }.get(req_type, '???'), fmt=req_format, original_desc=module_desc + "\n\n " if module_desc else "", ) # Add arguments defining outputs # TRAP output arg_parser.add_argument( '--trap', action='store_true', help= 'Enable output via TRAP interface (JSON type with format id "IDEA"). Parameters are set using "-i" option as usual.' ) # File output arg_parser.add_argument( '--file', metavar="FILE", type=str, help= 'Enable output to file (each IDEA message printed to new line in JSON format). Set to "-" to use standard output.' ) arg_parser.add_argument( '--file-indent', metavar="N", type=int, help='Pretty-format JSON in output file using N spaces for indentation.' ) arg_parser.add_argument('--file-append', action='store_true', help='Append to file instead of overwrite.') # MongoDB output arg_parser.add_argument( '--mongodb', metavar="DBNAME", help='Enable output to MongoDB. Connect to database named DBNAME.') arg_parser.add_argument( '--mongodb-coll', metavar="COLL", default='alerts', help='Put IDEA messages into collection named COLL (default: "alerts").' ) arg_parser.add_argument( '--mongodb-host', metavar="HOSTNAME", default='localhost', help='Connect to MongoDB running on HOSTNAME (default: "localhost").') arg_parser.add_argument( '--mongodb-port', metavar="PORT", type=int, default=27017, help='Connect to MongoDB running on port number PORT (default: 27017).' ) # Warden3 output arg_parser.add_argument( '--warden', metavar="CONFIG_FILE", help= 'Send IDEA messages to Warden server. Load configuration of Warden client from CONFIG_FILE.' ) # Other options arg_parser.add_argument( '-n', '--name', metavar='NODE_NAME', help= 'Name of the node, filled into "Node.Name" element of the IDEA message. Required if Warden output is used, recommended otherwise.' ) arg_parser.add_argument( '--test', action='store_true', help='Add "Test" to "Category" before sending a message to output(s).') arg_parser.add_argument( '-v', '--verbose', action='store_true', help= "Enable verbose mode (may be used by some modules, common part donesn't print anything" ) # TRAP parameters trap_args = arg_parser.add_argument_group('Common TRAP parameters') trap_args.add_argument( '-i', metavar="IFC_SPEC", required=True, help='TODO (ideally this section should be added by TRAP') # Parse arguments args = arg_parser.parse_args() # Check if at least one output is enabled if not (args.file or args.trap or args.mongodb or args.warden): sys.stderr.write(module_name + ": Error: At least one output must be selected\n") exit(1) # Check if node name is set if Warden output is enabled if args.name is None: if args.warden: sys.stderr.write( module_name + ": Error: Node name must be specified if Warden output is used (set param --name).\n" ) exit(1) else: sys.stderr.write(module_name + ": Warning: Node name is not specified.\n") # *** Initialize TRAP *** module_info = trap.CreateModuleInfo( module_name, # Module name "", # Description 1, # Number of input interfaces 1 if args.trap else 0, # Number of output interfaces None # optionParser ) ifc_spec = trap.parseParams(['-i', args.i], module_info) trap.init(module_info, ifc_spec) trap.registerDefaultSignalHandler() # Set required input format trap.set_required_fmt(0, req_type, req_format) # If TRAP output is enabled, set output format (JSON, format id "IDEA") if args.trap: trap.set_data_fmt(0, trap.TRAP_FMT_JSON, "IDEA") # *** Create output handles/clients/etc *** filehandle = None mongoclient = None mongocoll = None wardenclient = None if args.file: if args.file == '-': filehandle = sys.stdout else: filehandle = open(args.file, "a" if args.file_append else "w") if args.mongodb: import pymongo mongoclient = pymongo.MongoClient(args.mongodb_host, args.mongodb_port) mongocoll = mongoclient[args.mongodb][args.mongodb_coll] if args.warden: import warden_client wardenclient = warden_client.Client( **warden_client.read_cfg(args.warden)) # *** Main loop *** URInputTmplt = None if req_type == trap.TRAP_FMT_UNIREC and req_format != "": URInputTmplt = unirec.CreateTemplate( "URInputTmplt", req_format ) # TRAP expects us to have predefined template for required set of fields while not trap.stop: # *** Read data from input interface *** try: data = trap.recv(0) except trap.EFMTMismatch: sys.stderr.write( module_name + ": Error: input data format mismatch\n" ) #Required: "+str((req_type,req_format))+"\nReceived: "+str(trap.get_data_fmt(trap.IFC_INPUT, 0))+"\n") break except trap.EFMTChanged as e: # TODO: This should be handled by trap.recv transparently # Get negotiated input data format (fmttype, fmtspec) = trap.get_data_fmt(trap.IFC_INPUT, 0) # If data type is UniRec, create UniRec template #print "Creating template", fmtspec if fmttype == trap.TRAP_FMT_UNIREC: URInputTmplt = unirec.CreateTemplate("URInputTmplt", fmtspec) else: URInputTmplt = None data = e.data except trap.ETerminated: break # Check for "end-of-stream" record if len(data) <= 1: # If we have output, send "end-of-stream" record and exit if args.trap: trap.send(0, "0") break # Assert that if UniRec input is required, input template is set assert (req_type != trap.TRAP_FMT_UNIREC or URInputTmplt is not None) # Convert raw input data to UniRec object (if UniRec input is expected) if req_type == trap.TRAP_FMT_UNIREC: rec = URInputTmplt(data) elif req_type == trap.TRAP_FMT_JSON: rec = json.loads(data) else: # TRAP_FMT_RAW rec = data # *** Convert input record to IDEA *** # Pass the input record to conversion function to create IDEA message idea = conv_func(rec, args) if idea is None: continue # Record can't be converted - skip it (notice should be printed by the conv function) if args.name is not None: idea['Node'][0]['Name'] = args.name if args.test: idea['Category'].append('Test') # *** Send IDEA to outputs *** # File output if filehandle: filehandle.write(json.dumps(idea, indent=args.file_indent) + '\n') # TRAP output if args.trap: try: trap.send(0, json.dumps(idea)) except trap.ETerminated: # don't exit immediately, first finish sending to other outputs trap.stop = 1 # MongoDB output if mongocoll: # Convert timestamps from string to Date format idea['DetectTime'] = datetime.strptime(idea['DetectTime'], "%Y-%m-%dT%H:%M:%SZ") for i in ['CreateTime', 'EventTime', 'CeaseTime']: if idea.has_key(i): idea[i] = datetime.strptime(idea[i], "%Y-%m-%dT%H:%M:%SZ") try: mongocoll.insert(idea) except pymongo.errors.AutoReconnect: sys.stderr.write(module_name + ": Error: MongoDB connection failure.\n") trap.stop = 1 # Warden output if wardenclient: wardenclient.sendEvents([idea]) # *** Cleanup *** if filehandle and filehandle != sys.stdout: filehandle.close() if mongoclient: mongoclient.close() if wardenclient: wardenclient.close() trap.finalize()