def init_snmp_engine(self): # each SNMP-based application has an engine self._snmpEngine = engine.SnmpEngine() # config.addTransport(self._snmpEngine, udp.domainName, udp.UdpSocketTransport().openClientMode()) config.addSocketTransport(self._snmpEngine, udp.domainName, udp.UdpTransport().openServerMode(('', self.port))) # SecurityName <-> CommunityName mapping. # config.addV1System(self._snmpEngine, 'my-area', 'public') # Allow read MIB access for this user / securityModels at VACM # config.addVacmUser(self._snmpEngine, 2, 'my-area', 'noAuthNoPriv', (1, 3, 6)) # ===== SNMP v2c ===== # SecurityName <-> CommunityName mapping config.addV1System(self._snmpEngine, "public-v1-sec", "public") config.addVacmUser(self._snmpEngine, 2, 'public-v1-sec', 'noAuthNoPriv', (1, 3, 6)) # ===== SNMP v3 support ===== config.addV3User(self._snmpEngine, 'user1', config.usmHMACMD5AuthProtocol, 'authkey1') config.addVacmUser(self._snmpEngine, 3, 'user1', 'authNoPriv', (1, 3, 6)) # each app has one or more contexts self._snmpContext = context.SnmpContext(self._snmpEngine)
def cfgNtfOrg(self, authData, transportTarget, notifyType, tagList): addrName, paramsName = self.cfgCmdGen( authData, transportTarget, tagList ) k = paramsName, tagList, notifyType if self.__knownNotifyNames.has_key(k): notifyName, _ = self.__knownNotifyNames[k] else: notifyName = 'n%s' % cmdgen.nextID() config.addNotificationTarget( self.snmpEngine, notifyName, paramsName, tagList, notifyType ) self.__knownNotifyNames[k] = notifyName, paramsName if not self.__knownAuths.has_key(authData): subTree = (1,3,6) config.addTrapUser( self.snmpEngine, authData.securityModel, authData.securityName, authData.securityLevel, subTree ) self.__knownAuths[authData] = subTree if self.snmpContext is None: self.snmpContext = context.SnmpContext(self.snmpEngine) config.addContext( self.snmpEngine, '' # this is leaky ) return notifyName
def cfgNtfOrg(self, authData, transportTarget, notifyType): addrName, paramsName = self.cfgCmdGen(authData, transportTarget) tagList = transportTarget.tagList.split() if not tagList: tagList = [''] for tag in tagList: k = paramsName, tag, notifyType if k in self.__knownNotifyNames: notifyName, _ = self.__knownNotifyNames[k] else: notifyName = 'n%s' % nextID() config.addNotificationTarget(self.snmpEngine, notifyName, paramsName, tag, notifyType) self.__knownNotifyNames[k] = notifyName, paramsName k = (authData.securityModel, authData.securityName, authData.securityLevel) if k not in self.__knownAuths: subTree = (1, 3, 6) config.addTrapUser(self.snmpEngine, authData.securityModel, authData.securityName, authData.securityLevel, subTree) self.__knownAuths[k] = subTree if self.snmpContext is None: self.snmpContext = context.SnmpContext(self.snmpEngine) config.addContext( self.snmpEngine, '' # this is leaky ) return notifyName
def run(self) -> None: self.snmpEngine = engine.SnmpEngine() config.addSocketTransport( self.snmpEngine, udp.domainName, udp.UdpTransport().openServerMode(('127.0.0.1', 1161)) ) config.addV1System(self.snmpEngine, 'my-area', 'public', contextName='my-context') config.addVacmUser(self.snmpEngine, 2, 'my-area', 'noAuthNoPriv', (1, 3, 6), (1, 3, 6)) snmpContext = context.SnmpContext(self.snmpEngine) class SimpleController(instrum.AbstractMibInstrumController): def readVars(self, varBinds, acInfo=(None, None)): return [(ov[0], v2c.Integer(random.uniform(120, 140))) for ov in varBinds] snmpContext.registerContextName( v2c.OctetString('my-context'), # Context Name SimpleController() # Management Instrumentation ) cmdrsp.GetCommandResponder(self.snmpEngine, snmpContext) # cmdrsp.SetCommandResponder(self.snmpEngine, snmpContext) self.snmpEngine.transportDispatcher.jobStarted(1) try: self.snmpEngine.transportDispatcher.runDispatcher() except: self.snmpEngine.transportDispatcher.closeDispatcher() raise
def __init__(self, mibObjects): """ mibObjects - a list of MibObject tuples that this agent will serve """ #each SNMP-based application has an engine self._snmpEngine = engine.SnmpEngine() #open a UDP socket on port 161 to listen for snmp requests config.addSocketTransport(self._snmpEngine, udp.domainName, udp.UdpTransport().openServerMode(('', 161))) #Here we configure two distinct Community Strings to control read and write #operations. public --> Read only, private --> Read/Write config.addV1System(self._snmpEngine, "agent", "public") config.addV1System(self._snmpEngine, 'my-write-area', 'private') #let anyone accessing 'public' read anything in the subtree below, #which is the enterprises subtree that we defined our MIB to be in config.addVacmUser(self._snmpEngine, 2, "agent", "noAuthNoPriv", readSubTree=(1,3,6,1,4,1)) #let anyone accessing 'private' read and write anything in the subtree below, #which is the enterprises subtree that we defined our MIB to be in config.addVacmUser(self._snmpEngine, 2, 'my-write-area', 'noAuthNoPriv', readSubTree=(1, 3, 6, 1, 4, 1), writeSubTree=(1, 3, 6, 1, 4, 1)) #Create Agent context self._snmpContext = context.SnmpContext(self._snmpEngine) #the builder is used to load mibs. tell it to look in the #current directory for our new MIB. We'll also use it to #export our symbols later mibBuilder = self._snmpContext.getMibInstrum().getMibBuilder() mibSources = mibBuilder.getMibSources() + (builder.DirMibSource('.'),) mibBuilder.setMibSources(*mibSources) MibScalarInstance, = mibBuilder.importSymbols('SNMPv2-SMI', 'MibScalarInstance') #export our custom mib for mibObject in mibObjects: nextVar, = mibBuilder.importSymbols(mibObject.mibName, mibObject.objectType) instance = createVariable(MibScalarInstance, mibObject.valueFunc, mibObject.valueSetFunc, nextVar.name, (0,), nextVar.syntax) #need to export as <var name>Instance instanceDict = {str(nextVar.name)+"Instance":instance} mibBuilder.exportSymbols(mibObject.mibName, **instanceDict) # tell pysnmp to respond to get, set, getnext, and getbulk cmdrsp.GetCommandResponder(self._snmpEngine, self._snmpContext) cmdrsp.SetCommandResponder(self._snmpEngine,self._snmpContext) cmdrsp.NextCommandResponder(self._snmpEngine, self._snmpContext) cmdrsp.BulkCommandResponder(self._snmpEngine, self._snmpContext)
def __init__(self, host, port, log_queue): self.log_queue = log_queue # Create SNMP engine self.snmpEngine = engine.SnmpEngine() # Transport setup udp_sock = gevent.socket.socket(gevent.socket.AF_INET, gevent.socket.SOCK_DGRAM) udp_sock.setsockopt(gevent.socket.SOL_SOCKET, gevent.socket.SO_BROADCAST, 1) udp_sock.bind((host, port)) # UDP over IPv4 self.addSocketTransport( self.snmpEngine, udp.domainName, udp_sock ) #SNMPv1 config.addV1System(self.snmpEngine, 'public-read', 'public') # SNMPv3/USM setup # user: usr-md5-des, auth: MD5, priv DES config.addV3User( self.snmpEngine, 'usr-md5-des', config.usmHMACMD5AuthProtocol, 'authkey1', config.usmDESPrivProtocol, 'privkey1' ) # user: usr-sha-none, auth: SHA, priv NONE config.addV3User( self.snmpEngine, 'usr-sha-none', config.usmHMACSHAAuthProtocol, 'authkey1' ) # user: usr-sha-aes128, auth: SHA, priv AES/128 config.addV3User( self.snmpEngine, 'usr-sha-aes128', config.usmHMACSHAAuthProtocol, 'authkey1', config.usmAesCfb128Protocol, 'privkey1' ) # Allow full MIB access for each user at VACM config.addVacmUser(self.snmpEngine, 1, 'public-read', 'noAuthNoPriv', (1, 3, 6, 1, 2, 1)) config.addVacmUser(self.snmpEngine, 3, 'usr-md5-des', 'authPriv', (1, 3, 6, 1, 2, 1), (1, 3, 6, 1, 2, 1)) config.addVacmUser(self.snmpEngine, 3, 'usr-sha-none', 'authNoPriv', (1, 3, 6, 1, 2, 1), (1, 3, 6, 1, 2, 1)) config.addVacmUser(self.snmpEngine, 3, 'usr-sha-aes128', 'authPriv', (1, 3, 6, 1, 2, 1), (1, 3, 6, 1, 2, 1)) # Get default SNMP context this SNMP engine serves snmpContext = context.SnmpContext(self.snmpEngine) # Register SNMP Applications at the SNMP engine for particular SNMP context cmdrsp.GetCommandResponder(self.snmpEngine, snmpContext) cmdrsp.SetCommandResponder(self.snmpEngine, snmpContext) cmdrsp.NextCommandResponder(self.snmpEngine, snmpContext) cmdrsp.BulkCommandResponder(self.snmpEngine, snmpContext)
def __init__(self, host, port, users, naming_scheme): """ host = public ip to listen on port = port to listen on (usually 161) users = list of ('username', 'password', 'privatekey', 'authPriv') #authentication method for snmp v3 if users is None, authentication will be snmp v1 public community string, read only """ self.naming_scheme = naming_scheme self.run = True self.users = users # Create SNMP engine self.snmpEngine = engine.SnmpEngine() # Get default SNMP context this SNMP engine serves self.snmpContext = context.SnmpContext(self.snmpEngine) # MIB builder self.mibBuilder = self.snmpContext.getMibInstrum().getMibBuilder() self.MibScalar, self.MibScalarInstance = self.mibBuilder.importSymbols( 'SNMPv2-SMI', 'MibScalar', 'MibScalarInstance') # Transport setup # UDP over IPv4 try: config.addSocketTransport( self.snmpEngine, udp.domainName, udp.UdpTransport().openServerMode((host, port))) print('Serving on port %s' % port) except error.CarrierError as carrier_error: if "[Errno 98]" in carrier_error.message: raise RuntimeError('Port %s is in use' % port) # SNMPv3/USM setup # user: usr-md5-des, auth: MD5, priv DES if users: for user in users: self._add_v3_md5_des_user(user) # Allow full MIB access for each user at VACM else: # SNMPv1 public community string setup config.addV1System(self.snmpEngine, 'my-read-area', 'public') self._add_user_permission( "1.3.6.1.2.1" ) #full walk permission, without this snmpwalk returns None # Overwrite default strings with custom name sysDescr, = self.snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols( 'SNMPv2-MIB', 'sysDescr') sysDescr = self.MibScalarInstance( sysDescr.name, (0, ), sysDescr.syntax.clone( "PySNMP engine - OVS 1.2.0 SNMP Agent")) # Get from config? self.snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.exportSymbols( 'SNMPv2-MIB', sysDescr) self._add_user_permission(self.naming_scheme.replace('.%s', ''))
def __init__(self, host, port, rcommunity): self.snmpEngine = engine.SnmpEngine() config.addSocketTransport(self.snmpEngine, udp.domainName, udp.UdpTransport().openServerMode((host, port))) config.addV1System(self.snmpEngine, 'my-area', rcommunity) config.addVacmUser(self.snmpEngine, 2, 'my-area', 'noAuthNoPriv', (1, 3, 6)) self.snmpContext = context.SnmpContext(self.snmpEngine) self.mibBuilder = self.snmpContext.getMibInstrum().getMibBuilder() self.MibScalar, self.MibScalarInstance = self.mibBuilder.importSymbols('SNMPv2-SMI', 'MibScalar', 'MibScalarInstance') cmdrsp.GetCommandResponder(self.snmpEngine, self.snmpContext) cmdrsp.NextCommandResponder(self.snmpEngine, self.snmpContext) cmdrsp.BulkCommandResponder(self.snmpEngine, self.snmpContext)
def __init__(self, mibObjects): """ mibObjects - a list of MibObject tuples that this agent will serve """ #each SNMP-based application has an engine self._snmpEngine = engine.SnmpEngine() #open a UDP socket to listen for snmp requests config.addSocketTransport(self._snmpEngine, udp.domainName, udp.UdpTransport().openServerMode(('', 161))) #add a v2 user with the community string public config.addV1System(self._snmpEngine, "agent", "public") #let anyone accessing 'public' read anything in the subtree below, #which is the enterprises subtree that we defined our MIB to be in config.addVacmUser(self._snmpEngine, 2, "agent", "noAuthNoPriv", readSubTree=(1, 3, 6, 1, 4, 1)) #each app has one or more contexts self._snmpContext = context.SnmpContext(self._snmpEngine) #the builder is used to load mibs. tell it to look in the #current directory for our new MIB. We'll also use it to #export our symbols later mibBuilder = self._snmpContext.getMibInstrum().getMibBuilder() mibSources = mibBuilder.getMibSources() + (builder.DirMibSource('.'), ) mibBuilder.setMibSources(*mibSources) mibBuilder.loadModules('HOST-RESOURCES-MIB') #our variables will subclass this since we only have scalar types #can't load this type directly, need to import it MibScalarInstance, = mibBuilder.importSymbols('SNMPv2-SMI', 'MibScalarInstance') #export our custom mib for mibObject in mibObjects: nextVar, = mibBuilder.importSymbols(mibObject.mibName, mibObject.objectType) instance = createVariable(MibScalarInstance, mibObject.valueFunc, nextVar.name, (0, ), nextVar.syntax) #need to export as <var name>Instance instanceDict = {str(nextVar.name) + "Instance": instance} mibBuilder.exportSymbols(mibObject.mibName, **instanceDict) # tell pysnmp to respotd to get, getnext, and getbulk cmdrsp.GetCommandResponder(self._snmpEngine, self._snmpContext) cmdrsp.NextCommandResponder(self._snmpEngine, self._snmpContext) cmdrsp.BulkCommandResponder(self._snmpEngine, self._snmpContext)
def __init__(self, snmpEngine=None, snmpContext=None): if snmpEngine is None: self.snmpEngine = snmpEngine = SnmpEngine() else: self.snmpEngine = snmpEngine if snmpContext is None: self.snmpContext = context.SnmpContext(self.snmpEngine) config.addContext( self.snmpEngine, '' # this is leaky ) else: self.snmpContext = snmpContext self.mibViewController = self.vbProcessor.getMibViewController(self.snmpEngine)
def __init__(self, snmpEngine=None, snmpContext=None): cmdgen.AsynCommandGenerator.__init__(self, snmpEngine) self.__asyncNtfOrg = AsyncNotificationOriginator() # grab/create MibViewController from/for the real AsyncCommandGen cache = self.__asyncNtfOrg._getCmdCache(self.snmpEngine) self.mibViewController = cache['mibViewController'] if snmpContext is None: self.snmpContext = context.SnmpContext(self.snmpEngine) config.addContext( self.snmpEngine, '' # this is leaky ) else: self.snmpContext = snmpContext
def __init__(self, host, port, mibObjects): self._snmpEngine = engine.SnmpEngine() config.addSocketTransport( self._snmpEngine, udp.domainName, udp.UdpTransport().openServerMode((host, port))) config.addV1System(self._snmpEngine, "agent", "publick") # password config.addV1System(self._snmpEngine, 'my-write-area', 'private') config.addVacmUser(self._snmpEngine, 2, "agent", "noAuthNoPriv", readSubTree=(1, 3, 6, 1, 4, 1)) config.addVacmUser(self._snmpEngine, 2, 'my-write-area', 'noAuthNoPriv', readSubTree=(1, 3, 6, 1, 4, 1), writeSubTree=(1, 3, 6, 1, 4, 1)) self._snmpContext = context.SnmpContext(self._snmpEngine) mibBuilder = self._snmpContext.getMibInstrum().getMibBuilder() mibSources = mibBuilder.getMibSources() + (builder.DirMibSource('.'), ) mibBuilder.setMibSources(*mibSources) MibScalarInstance, = mibBuilder.importSymbols('SNMPv2-SMI', 'MibScalarInstance') for mibObject in mibObjects: nextVar, = mibBuilder.importSymbols(mibObject.mibName, mibObject.objectType) instance = createVariable(MibScalarInstance, mibObject.valueFunc, mibObject.valueSetFunc, nextVar.name, (0, ), nextVar.syntax) instanceDict = {str(nextVar.name) + "Instance": instance} mibBuilder.exportSymbols(mibObject.mibName, **instanceDict) cmdrsp.GetCommandResponder(self._snmpEngine, self._snmpContext) cmdrsp.SetCommandResponder(self._snmpEngine, self._snmpContext) cmdrsp.NextCommandResponder(self._snmpEngine, self._snmpContext) cmdrsp.BulkCommandResponder(self._snmpEngine, self._snmpContext)
def setMibController(snmpEngine, controller): """Register SNMP MIB instrumentation controller with SNMP engine. Args: snmpEngine (object): pysnmp `SnmpEngine` class instance controller (object): SNMP MIB instrumentation controller compliant to pysnmp MIB instrumentation API. Returns: object: pysnmp `SnmpContext` object representing SNMP context for which SNMP MIB instrumentation controller is registered. """ snmpContextName = v2c.OctetString('') # https://github.com/openstack/virtualpdu/blob/master/virtualpdu/pdu/pysnmp_handler.py snmpContext = context.SnmpContext(snmpEngine) snmpContext.unregisterContextName(snmpContextName) snmpContext.registerContextName(snmpContextName, controller) return snmpContext
def __init__(self, mibObjects): # Each SNMP-based application has an engine self._snmpEngine = engine.SnmpEngine() # Open a UDP socket to listen for snmp requests (requset sudo command) config.addSocketTransport(self._snmpEngine, udp.domainName, udp.UdpTransport().openServerMode(('', 161))) config.addV1System(self._snmpEngine, 'agent', 'public') # add a v2 user with the community string public config.addVacmUser(self._snmpEngine, 2, 'agent', 'noAuthNoPriv', readSubTree=(1, 3, 6, 1, 4, 1), writeSubTree=(1, 3, 6, 1, 4, 1)) # each app has one or more contexts self._snmpContext = context.SnmpContext(self._snmpEngine) # the builder is used to load mibs. tell it to look in the # current directory for our new MIB. We'll also use it to # export our symbols later mibBuilder = self._snmpContext.getMibInstrum().getMibBuilder() mibSources = mibBuilder.getMibSources() + (builder.DirMibSource('.'), ) mibBuilder.setMibSources(*mibSources) # our variables will subclass this since we only have scalar types # can't load this type directly, need to import it (MibTable, MibTableRow, MibTableColumn, MibScalarInstance) = mibBuilder.importSymbols('SNMPv2-SMI', 'MibTable', 'MibTableRow', 'MibTableColumn', 'MibScalarInstance') # import and maintain Table maintaintable = maintainTableThread(0, mibObjects, mibBuilder, MibScalarInstance) maintaintable.start() # tell pysnmp to respotd to get, getnext, and getbulk cmdrsp.GetCommandResponder(self._snmpEngine, self._snmpContext) cmdrsp.SetCommandResponder(self._snmpEngine, self._snmpContext) cmdrsp.NextCommandResponder(self._snmpEngine, self._snmpContext) cmdrsp.BulkCommandResponder(self._snmpEngine, self._snmpContext)
def run(self): snmpEngine = engine.SnmpEngine() config.addSocketTransport( snmpEngine, udp.domainName, udp.UdpTransport().openServerMode(('127.0.0.1', self.__listening_port)) ) config.addV1System( snmpEngine, 'my-area', 'public', contextName='my-context') config.addVacmUser(snmpEngine=snmpEngine, securityModel=2, securityName='my-area', securityLevel='noAuthNoPriv', readSubTree=SNMPAgentResponder.OID_PREFIX, writeSubTree=(), notifySubTree=()) snmpContext = context.SnmpContext(snmpEngine) snmpContext.registerContextName( v2c.OctetString('my-context'), # Context Name self.__responder # Management Instrumentation ) cmdrsp.GetCommandResponder(snmpEngine, snmpContext) snmpEngine.transportDispatcher.jobStarted(1) self.__barrier.wait() # TODO with statement here! try: snmpEngine.transportDispatcher.runDispatcher() except: snmpEngine.transportDispatcher.closeDispatcher() raise
def __init__(self, objects): self._snmpEngine = engine.SnmpEngine() config.addSocketTransport( self._snmpEngine, udp.domainName, udp.UdpTransport().openServerMode((_addr, _port))) config.addV3User(self._snmpEngine, _account, config.usmHMACMD5AuthProtocol, _auth_key, config.usmDESPrivProtocol, _priv_key) config.addVacmUser(self._snmpEngine, 3, _account, "authPriv", (1, 3, 6, 1, 4, 1), (1, 3, 6, 1, 4, 1)) self._snmpContext = context.SnmpContext(self._snmpEngine) #builder create mibBuilder = self._snmpContext.getMibInstrum().getMibBuilder() mibSources = mibBuilder.getMibSources() + ( builder.DirMibSource('.'), ) + (builder.DirMibSource(filepath), ) mibBuilder.setMibSources(*mibSources) MibScalarInstance, = mibBuilder.importSymbols('SNMPv2-SMI', 'MibScalarInstance') for mibObject in objects: nextVar, = mibBuilder.importSymbols(mibObject.mibName, mibObject.objectType) instance = createVariable(MibScalarInstance, mibObject.valueGetFunc, nextVar.name, (0, ), nextVar.syntax) #need to export as <var name>Instance instanceDict = {str(nextVar.name) + "Instance": instance} mibBuilder.exportSymbols(mibObject.mibName, **instanceDict) cmdrsp.GetCommandResponder(self._snmpEngine, self._snmpContext) cmdrsp.SetCommandResponder(self._snmpEngine, self._snmpContext) cmdrsp.NextCommandResponder(self._snmpEngine, self._snmpContext) cmdrsp.BulkCommandResponder(self._snmpEngine, self._snmpContext)
def __init__(self, array_config, access_config, engine_id=None, transport_dispatcher=None): self.array_config = array_config self.access_config = access_config self.port = (int(array_config.agent_port) if array_config.agent_port else 161) self.ip = (array_config.agent_ip if array_config.agent_ip else '0.0.0.0') self.engine_id = engine_id self.transport_dispatcher = (dispatch.AsyncoreDispatcher() if transport_dispatcher is None else transport_dispatcher) self.engine = engine.SnmpEngine() self.context = context.SnmpContext(self.engine) self.setup_transport() self.setup_access() self.engine.unity_client = self.connect_backend_device() self.engine.parent = self self.create_managed_objects() self.register_cmd_responders() self.enable_observer()
# UDP over IPv4 config.addTransport(snmpEngine, udp.domainName, udp.UdpTransport().openServerMode(('127.0.0.1', 161))) # SNMPv3/USM setup # user: usr-md5-none, auth: MD5, priv NONE config.addV3User(snmpEngine, 'usr-md5-none', config.usmHMACMD5AuthProtocol, 'authkey1') # Allow full MIB access for each user at VACM config.addVacmUser(snmpEngine, 3, 'usr-md5-none', 'authNoPriv', (1, 3, 6, 1, 2, 1), (1, 3, 6, 1, 2, 1)) # Create an SNMP context with ContextEngineId = 8000000001020304 snmpContext = context.SnmpContext( snmpEngine, contextEngineId=v2c.OctetString(hexValue='8000000001020304')) # Create an [empty] set of Managed Objects (MibBuilder), pass it to # Management Instrumentation Controller and register at SNMP Context # under ContextName 'my-context' snmpContext.registerContextName( v2c.OctetString('my-context'), # Context Name instrum.MibInstrumController(builder.MibBuilder()) # Managed Objects ) # Register SNMP Applications at the SNMP engine for particular SNMP context cmdrsp.GetCommandResponder(snmpEngine, snmpContext) cmdrsp.SetCommandResponder(snmpEngine, snmpContext) cmdrsp.NextCommandResponder(snmpEngine, snmpContext) cmdrsp.BulkCommandResponder(snmpEngine, snmpContext)
# UDP over IPv4 config.addTransport(snmpEngine, udp.domainName, udp.UdpTransport().openServerMode(('127.0.0.1', 161))) # SNMPv3/USM setup # user: usr-md5-none, auth: MD5, priv NONE config.addV3User(snmpEngine, 'usr-md5-none', config.usmHMACMD5AuthProtocol, 'authkey1') # Allow full MIB access for each user at VACM config.addVacmUser(snmpEngine, 3, 'usr-md5-none', 'authNoPriv', (1, 3, 6, 1, 2, 1), (1, 3, 6, 1, 2, 1)) # Create an SNMP context with default ContextEngineId (same as SNMP engine ID) snmpContext = context.SnmpContext(snmpEngine) # Create multiple independent trees of MIB managed objects (empty so far) mibTreeA = instrum.MibInstrumController(builder.MibBuilder()) mibTreeB = instrum.MibInstrumController(builder.MibBuilder()) # Register MIB trees at distinct SNMP Context names snmpContext.registerContextName(v2c.OctetString('context-a'), mibTreeA) snmpContext.registerContextName(v2c.OctetString('context-b'), mibTreeB) # Register SNMP Applications at the SNMP engine for particular SNMP context cmdrsp.GetCommandResponder(snmpEngine, snmpContext) cmdrsp.SetCommandResponder(snmpEngine, snmpContext) cmdrsp.NextCommandResponder(snmpEngine, snmpContext) cmdrsp.BulkCommandResponder(snmpEngine, snmpContext)
def __init__(self, mibObjects): self._snmpEngine = engine.SnmpEngine() # open a UDP socket to listen for snmp requests config.addSocketTransport( self._snmpEngine, udp.domainName, udp.UdpTransport().openServerMode(('', 7757))) # add a v2 user with the community string public config.addV1System(self._snmpEngine, "agent", "public") # let anyone accessing 'public' read anything in the subtree below, # which is the enterprises subtree that we defined our MIB to be in config.addVacmUser(self._snmpEngine, 2, "agent", "noAuthNoPriv", readSubTree=(1, 3, 6, 1, 4, 1)) # each app has one or more contexts self._snmpContext = context.SnmpContext(self._snmpEngine) # the builder is used to load mibs. tell it to look in the # current directory for our new MIB. We'll also use it to # export our symbols later mibBuilder = self._snmpContext.getMibInstrum().getMibBuilder() mibSources = mibBuilder.getMibSources() + (builder.DirMibSource('.'), ) mibBuilder.setMibSources(*mibSources) # our variables will subclass this since we only have scalar types # can't load this type directly, need to import it MibScalarInstance, = mibBuilder.importSymbols('SNMPv2-SMI', 'MibTable') mib = Mib() (nodeEntry, profileEntry, nodeIdxColumn, profileIdxColumn, dcdColumn, profileNameColumn) = mibBuilder.importSymbols('AKSION-CONTROL-MIB', 'nodeEntry', 'profileEntry', 'nodeIdx', 'profileIdx', 'dcd', 'profileName') rowInstanceId = nodeEntry.getInstIdFromIndices(1) mibInstrumentation = self._snmpContext.getMibInstrum() mibInstrumentation.writeVars( ((dcdColumn.name + rowInstanceId, 'xx1'), )) rowProfileInstanceId = profileEntry.getInstIdFromIndices(1) mibInstrumentation = self._snmpContext.getMibInstrum() mibInstrumentation.writeVars( ((profileNameColumn.name + rowInstanceId + rowProfileInstanceId, 'ProfileNode1'), )) # rowInstanceId = nodeEntry.getInstIdFromIndices(2) mibInstrumentation = self._snmpContext.getMibInstrum() mibInstrumentation.writeVars( ((dcdColumn.name + rowInstanceId, 'xx 2'), )) rowProfileInstanceId = profileEntry.getInstIdFromIndices(2) mibInstrumentation = self._snmpContext.getMibInstrum() mibInstrumentation.writeVars( ((profileNameColumn.name + rowInstanceId + rowProfileInstanceId, 'ProfileNode2'), )) # tell pysnmp to respotd to get, getnext, and getbulk cmdrsp.GetCommandResponder(self._snmpEngine, self._snmpContext) cmdrsp.NextCommandResponder(self._snmpEngine, self._snmpContext) cmdrsp.BulkCommandResponder(self._snmpEngine, self._snmpContext)
def _setup(self, q): """Setup a new agent in a separate process. The port the agent is listening too will be returned using the provided queue. """ port = random.randrange(22000, 22989) snmpEngine = engine.SnmpEngine() if self.ipv6: config.addSocketTransport( snmpEngine, udp6.domainName, udp6.Udp6Transport().openServerMode(('::1', port))) else: config.addSocketTransport( snmpEngine, udp.domainName, udp.UdpTransport().openServerMode(('127.0.0.1', port))) # Community is public and MIB is writable config.addV1System(snmpEngine, 'read-write', 'public') config.addVacmUser(snmpEngine, 1, 'read-write', 'noAuthNoPriv', (1, 3, 6), (1, 3, 6)) config.addVacmUser(snmpEngine, 2, 'read-write', 'noAuthNoPriv', (1, 3, 6), (1, 3, 6)) config.addV3User(snmpEngine, 'read-write', config.usmHMACMD5AuthProtocol, 'authpass', config.usmAesCfb128Protocol, 'privpass') config.addVacmUser(snmpEngine, 3, 'read-write', 'authPriv', (1, 3, 6), (1, 3, 6)) # Build MIB def stringToOid(string): return [ord(x) for x in string] def flatten(*args): result = [] for el in args: if isinstance(el, (list, tuple)): for sub in el: result.append(sub) else: result.append(el) return tuple(result) snmpContext = context.SnmpContext(snmpEngine) mibBuilder = snmpContext.getMibInstrum().getMibBuilder() (MibTable, MibTableRow, MibTableColumn, MibScalar, MibScalarInstance) = mibBuilder.importSymbols( 'SNMPv2-SMI', 'MibTable', 'MibTableRow', 'MibTableColumn', 'MibScalar', 'MibScalarInstance') mibBuilder.exportSymbols( '__MY_SNMPv2_MIB', # SNMPv2-MIB::sysDescr MibScalar((1, 3, 6, 1, 2, 1, 1, 1), v2c.OctetString()), MibScalarInstance((1, 3, 6, 1, 2, 1, 1, 1), (0, ), v2c.OctetString("Snimpy Test Agent"))) mibBuilder.exportSymbols( '__MY_IF_MIB', # IF-MIB::ifNumber MibScalar((1, 3, 6, 1, 2, 1, 2, 1), v2c.Integer()), MibScalarInstance((1, 3, 6, 1, 2, 1, 2, 1), (0, ), v2c.Integer(3)), # IF-MIB::ifTable MibTable((1, 3, 6, 1, 2, 1, 2, 2)), MibTableRow((1, 3, 6, 1, 2, 1, 2, 2, 1)).setIndexNames( (0, '__MY_IF_MIB', 'ifIndex')), # IF-MIB::ifIndex MibScalarInstance((1, 3, 6, 1, 2, 1, 2, 2, 1, 1), (1, ), v2c.Integer(1)), MibScalarInstance((1, 3, 6, 1, 2, 1, 2, 2, 1, 1), (2, ), v2c.Integer(2)), MibScalarInstance((1, 3, 6, 1, 2, 1, 2, 2, 1, 1), (3, ), v2c.Integer(3)), # IF-MIB::ifDescr MibTableColumn((1, 3, 6, 1, 2, 1, 2, 2, 1, 2), v2c.OctetString()), MibScalarInstance((1, 3, 6, 1, 2, 1, 2, 2, 1, 2), (1, ), v2c.OctetString("lo")), MibScalarInstance((1, 3, 6, 1, 2, 1, 2, 2, 1, 2), (2, ), v2c.OctetString("eth0")), MibScalarInstance((1, 3, 6, 1, 2, 1, 2, 2, 1, 2), (3, ), v2c.OctetString("eth1")), # IF-MIB::ifType MibTableColumn((1, 3, 6, 1, 2, 1, 2, 2, 1, 3), v2c.Integer()), MibScalarInstance((1, 3, 6, 1, 2, 1, 2, 2, 1, 3), (1, ), v2c.Integer(24)), MibScalarInstance((1, 3, 6, 1, 2, 1, 2, 2, 1, 3), (2, ), v2c.Integer(6)), MibScalarInstance((1, 3, 6, 1, 2, 1, 2, 2, 1, 3), (3, ), v2c.Integer(6)), # IF-MIB::ifIndex ifIndex=MibTableColumn((1, 3, 6, 1, 2, 1, 2, 2, 1, 1), v2c.Integer())) mibBuilder.exportSymbols( '__MY_SNIMPY-MIB', # SNIMPY-MIB::snimpyIpAddress MibScalar((1, 3, 6, 1, 2, 1, 45121, 1, 1), v2c.OctetString()).setMaxAccess("readwrite"), MibScalarInstance((1, 3, 6, 1, 2, 1, 45121, 1, 1), (0, ), v2c.OctetString("AAAA")), # SNIMPY-MIB::snimpyString MibScalar((1, 3, 6, 1, 2, 1, 45121, 1, 2), v2c.OctetString()).setMaxAccess("readwrite"), MibScalarInstance((1, 3, 6, 1, 2, 1, 45121, 1, 2), (0, ), v2c.OctetString("bye")), # SNIMPY-MIB::snimpyInteger MibScalar((1, 3, 6, 1, 2, 1, 45121, 1, 3), v2c.Integer()).setMaxAccess("readwrite"), MibScalarInstance((1, 3, 6, 1, 2, 1, 45121, 1, 3), (0, ), v2c.Integer(19)), # SNIMPY-MIB::snimpyEnum MibScalar((1, 3, 6, 1, 2, 1, 45121, 1, 4), v2c.Integer()).setMaxAccess("readwrite"), MibScalarInstance((1, 3, 6, 1, 2, 1, 45121, 1, 4), (0, ), v2c.Integer(2)), # SNIMPY-MIB::snimpyObjectId MibScalar((1, 3, 6, 1, 2, 1, 45121, 1, 5), v2c.ObjectIdentifier()).setMaxAccess("readwrite"), MibScalarInstance((1, 3, 6, 1, 2, 1, 45121, 1, 5), (0, ), v2c.ObjectIdentifier((1, 3, 6, 4454, 0, 0))), # SNIMPY-MIB::snimpyBoolean MibScalar((1, 3, 6, 1, 2, 1, 45121, 1, 6), v2c.Integer()).setMaxAccess("readwrite"), MibScalarInstance((1, 3, 6, 1, 2, 1, 45121, 1, 6), (0, ), v2c.Integer(1)), # SNIMPY-MIB::snimpyCounter MibScalar((1, 3, 6, 1, 2, 1, 45121, 1, 7), v2c.Counter32()).setMaxAccess("readwrite"), MibScalarInstance((1, 3, 6, 1, 2, 1, 45121, 1, 7), (0, ), v2c.Counter32(47)), # SNIMPY-MIB::snimpyGauge MibScalar((1, 3, 6, 1, 2, 1, 45121, 1, 8), v2c.Gauge32()).setMaxAccess("readwrite"), MibScalarInstance((1, 3, 6, 1, 2, 1, 45121, 1, 8), (0, ), v2c.Gauge32(18)), # SNIMPY-MIB::snimpyTimeticks MibScalar((1, 3, 6, 1, 2, 1, 45121, 1, 9), v2c.TimeTicks()).setMaxAccess("readwrite"), MibScalarInstance((1, 3, 6, 1, 2, 1, 45121, 1, 9), (0, ), v2c.TimeTicks(12111100)), # SNIMPY-MIB::snimpyCounter64 MibScalar((1, 3, 6, 1, 2, 1, 45121, 1, 10), v2c.Counter64()).setMaxAccess("readwrite"), MibScalarInstance((1, 3, 6, 1, 2, 1, 45121, 1, 10), (0, ), v2c.Counter64(2**48 + 3)), # SNIMPY-MIB::snimpyBits MibScalar((1, 3, 6, 1, 2, 1, 45121, 1, 11), v2c.OctetString()).setMaxAccess("readwrite"), MibScalarInstance((1, 3, 6, 1, 2, 1, 45121, 1, 11), (0, ), v2c.OctetString(b"\xa0")), # SNIMPY-MIB::snimpyMacAddress MibScalar((1, 3, 6, 1, 2, 1, 45121, 1, 15), v2c.OctetString()).setMaxAccess("readwrite"), MibScalarInstance((1, 3, 6, 1, 2, 1, 45121, 1, 15), (0, ), v2c.OctetString(b"\x11\x12\x13\x14\x15\x16")), # SNIMPY-MIB::snimpyMacAddressInvalid MibScalar((1, 3, 6, 1, 2, 1, 45121, 1, 16), v2c.OctetString()).setMaxAccess("readwrite"), MibScalarInstance((1, 3, 6, 1, 2, 1, 45121, 1, 16), (0, ), v2c.OctetString(b"\xf1\x12\x13\x14\x15\x16")), # SNIMPY-MIB::snimpyIndexTable MibTable((1, 3, 6, 1, 2, 1, 45121, 2, 3)), MibTableRow((1, 3, 6, 1, 2, 1, 45121, 2, 3, 1)).setIndexNames( (0, "__MY_SNIMPY-MIB", "snimpyIndexVarLen"), (0, "__MY_SNIMPY-MIB", "snimpyIndexOidVarLen"), (0, "__MY_SNIMPY-MIB", "snimpyIndexFixedLen"), (1, "__MY_SNIMPY-MIB", "snimpyIndexImplied")), # SNIMPY-MIB::snimpyIndexInt MibScalarInstance((1, 3, 6, 1, 2, 1, 45121, 2, 3, 1, 6), flatten(4, stringToOid('row1'), 3, 1, 2, 3, stringToOid('alpha5'), stringToOid('end of row1')), v2c.Integer(4571)), MibScalarInstance((1, 3, 6, 1, 2, 1, 45121, 2, 3, 1, 6), flatten(4, stringToOid('row2'), 4, 1, 0, 2, 3, stringToOid('beta32'), stringToOid('end of row2')), v2c.Integer(78741)), MibScalarInstance((1, 3, 6, 1, 2, 1, 45121, 2, 3, 1, 6), flatten(4, stringToOid('row3'), 4, 120, 1, 2, 3, stringToOid('gamma7'), stringToOid('end of row3')), v2c.Integer(4110)), # SNIMPY-MIB::snimpyInvalidTable MibTable((1, 3, 6, 1, 2, 1, 45121, 2, 5)), MibTableRow((1, 3, 6, 1, 2, 1, 45121, 2, 5, 1)).setIndexNames( (0, "__MY_SNIMPY-MIB", "snimpyInvalidIndex")), # SNIMPY-MIB::snimpyInvalidDescr MibScalarInstance((1, 3, 6, 1, 2, 1, 45121, 2, 5, 1, 2), (1, ), v2c.OctetString(b"Hello")), MibScalarInstance((1, 3, 6, 1, 2, 1, 45121, 2, 5, 1, 2), (2, ), v2c.OctetString(b"\xf1\x12\x13\x14\x15\x16")), # Indexes snimpyIndexVarLen=MibTableColumn( (1, 3, 6, 1, 2, 1, 45121, 2, 3, 1, 1), v2c.OctetString()).setMaxAccess("noaccess"), snimpyIndexIntIndex=MibTableColumn( (1, 3, 6, 1, 2, 1, 45121, 2, 3, 1, 2), v2c.Integer()).setMaxAccess("noaccess"), snimpyIndexOidVarLen=MibTableColumn( (1, 3, 6, 1, 2, 1, 45121, 2, 3, 1, 3), v2c.ObjectIdentifier()).setMaxAccess("noaccess"), snimpyIndexFixedLen=MibTableColumn( (1, 3, 6, 1, 2, 1, 45121, 2, 3, 1, 4), v2c.OctetString().setFixedLength(6)).setMaxAccess("noaccess"), snimpyIndexImplied=MibTableColumn( (1, 3, 6, 1, 2, 1, 45121, 2, 3, 1, 5), v2c.OctetString()).setMaxAccess("noaccess"), snimpyIndexInt=MibTableColumn( (1, 3, 6, 1, 2, 1, 45121, 2, 3, 1, 6), v2c.Integer()).setMaxAccess("readwrite"), snimpyInvalidIndex=MibTableColumn( (1, 3, 6, 1, 2, 1, 45121, 2, 5, 1, 1), v2c.Integer()).setMaxAccess("noaccess"), snimpyInvalidDescr=MibTableColumn( (1, 3, 6, 1, 2, 1, 45121, 2, 5, 1, 2), v2c.OctetString()).setMaxAccess("readwrite")) # Start agent cmdrsp.GetCommandResponder(snmpEngine, snmpContext) cmdrsp.SetCommandResponder(snmpEngine, snmpContext) cmdrsp.NextCommandResponder(snmpEngine, snmpContext) cmdrsp.BulkCommandResponder(snmpEngine, snmpContext) q.put(port) snmpEngine.transportDispatcher.jobStarted(1) snmpEngine.transportDispatcher.runDispatcher()
def __init__(self, host, port, mibpaths): self.oid_mapping = {} self.databus_mediator = DatabusMediator(self.oid_mapping) # mapping between OID and databus keys # Create SNMP engine self.snmpEngine = engine.SnmpEngine() # path to custom mibs mibBuilder = self.snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder mibSources = mibBuilder.getMibSources() for mibpath in mibpaths: mibSources += (builder.DirMibSource(mibpath), ) mibBuilder.setMibSources(*mibSources) # Transport setup udp_sock = gevent.socket.socket(gevent.socket.AF_INET, gevent.socket.SOCK_DGRAM) udp_sock.setsockopt(gevent.socket.SOL_SOCKET, gevent.socket.SO_BROADCAST, 1) udp_sock.bind((host, port)) self.server_port = udp_sock.getsockname()[1] # UDP over IPv4 self.addSocketTransport(self.snmpEngine, udp.domainName, udp_sock) # SNMPv1 config.addV1System(self.snmpEngine, 'public-read', 'public') # SNMPv3/USM setup # user: usr-md5-des, auth: MD5, priv DES config.addV3User(self.snmpEngine, 'usr-md5-des', config.usmHMACMD5AuthProtocol, 'authkey1', config.usmDESPrivProtocol, 'privkey1') # user: usr-sha-none, auth: SHA, priv NONE config.addV3User(self.snmpEngine, 'usr-sha-none', config.usmHMACSHAAuthProtocol, 'authkey1') # user: usr-sha-aes128, auth: SHA, priv AES/128 config.addV3User(self.snmpEngine, 'usr-sha-aes128', config.usmHMACSHAAuthProtocol, 'authkey1', config.usmAesCfb128Protocol, 'privkey1') # Allow full MIB access for each user at VACM config.addVacmUser(self.snmpEngine, 1, 'public-read', 'noAuthNoPriv', readSubTree=(1, 3, 6, 1, 2, 1), writeSubTree=(1, 3, 6, 1, 2, 1)) config.addVacmUser(self.snmpEngine, 3, 'usr-md5-des', 'authPriv', readSubTree=(1, 3, 6, 1, 2, 1), writeSubTree=(1, 3, 6, 1, 2, 1)) config.addVacmUser(self.snmpEngine, 3, 'usr-sha-none', 'authNoPriv', readSubTree=(1, 3, 6, 1, 2, 1), writeSubTree=(1, 3, 6, 1, 2, 1)) config.addVacmUser(self.snmpEngine, 3, 'usr-sha-aes128', 'authPriv', readSubTree=(1, 3, 6, 1, 2, 1), writeSubTree=(1, 3, 6, 1, 2, 1)) # Get default SNMP context this SNMP engine serves snmpContext = context.SnmpContext(self.snmpEngine) # Register SNMP Applications at the SNMP engine for particular SNMP context self.resp_app_get = conpot_cmdrsp.c_GetCommandResponder( self.snmpEngine, snmpContext, self.databus_mediator) self.resp_app_set = conpot_cmdrsp.c_SetCommandResponder( self.snmpEngine, snmpContext, self.databus_mediator) self.resp_app_next = conpot_cmdrsp.c_NextCommandResponder( self.snmpEngine, snmpContext, self.databus_mediator) self.resp_app_bulk = conpot_cmdrsp.c_BulkCommandResponder( self.snmpEngine, snmpContext, self.databus_mediator)
def start(self): if self._engine is None: # Create SNMP engine with autogenernated engineID and pre-bound # to socket transport dispatcher self._engine = engine.SnmpEngine() # Setup UDP over IPv4 transport endpoint try: iface = ('0.0.0.0', self.port) self._logger.info("[pid: %d] Starting SNMP server on %s:%d", os.getpid(), iface[0], iface[1]) config.addSocketTransport( self._engine, udp.domainName, udp.UdpSocketTransport().openServerMode(iface) ) except CarrierError: self._logger.error('Can\'t run SNMP agent on port %d: Address already in use', self.port) raise mibBuilder = self._engine.msgAndPduDsp.mibInstrumController.mibBuilder MibSources = mibBuilder.getMibPath() sources = ['/mibs','/mibs/instances'] for source in sources: MibSources += ((os.path.realpath(os.path.dirname(__file__) + source), )) apply(mibBuilder.setMibPath, MibSources) try: mibBuilder.loadModules(*self._modules) except SmiError: self._logger.warn('Can\'t load modules') raise config.addV1System(self._engine, self._security_name, self._community_name) # VACM setup config.addContext(self._engine, '') config.addRwUser(self._engine, 1, self._security_name, 'noAuthNoPriv', (1,3,6)) # v1 config.addRwUser(self._engine, 2, self._security_name, 'noAuthNoPriv', (1,3,6)) # v2c # SNMP context snmpContext = context.SnmpContext(self._engine) # Apps registration cmdrsp.GetCommandResponder(self._engine, snmpContext) cmdrsp.SetCommandResponder(self._engine, snmpContext) cmdrsp.NextCommandResponder(self._engine, snmpContext) cmdrsp.BulkCommandResponder(self._engine, snmpContext) # Start server self._logger.debug('Starting transport dispatcher') self._engine.transportDispatcher.jobStarted(1) try: self._logger.debug('Run transport dispatcher') self._engine.transportDispatcher.runDispatcher() except select.error, e: if e.args[0] == 9: # 'Bad file descriptor' # Throws when dispatcher closed from another thread pass else: raise
def __init__(self): #each SNMP-based application has an engine self._snmpEngine = engine.SnmpEngine() # Reading configuration self._read_conf() self._serialtcp = SerialHTTPProcess( self._CONF['LOG_DIR'] if 'LOG_DIR' in self._CONF else '') #open a UDP socket to listen for snmp requests port = int(self._CONF['PORT'] ) if 'PORT' in self._CONF and self._CONF['PORT'] else 161 config.addSocketTransport( self._snmpEngine, udp.domainName, udp.UdpTransport().openServerMode(('0.0.0.0', port))) #add a v2 user with the community string public config.addV1System( self._snmpEngine, "read-area", self._CONF['PUBLIC'] if 'PUBLIC' in self._CONF and self._CONF['PUBLIC'] else "public") config.addV1System( self._snmpEngine, 'write-area', self._CONF['PRIVATE'] if 'PRIVATE' in self._CONF and self._CONF['PRIVATE'] else 'private') #let anyone accessing 'public' read anything in the subtree below, #which is the enterprises subtree that we defined our MIB to be in config.addVacmUser(self._snmpEngine, 1, "read-area", "noAuthNoPriv", readSubTree=(1, 3, 6, 1, 2)) #config.addVacmUser(self._snmpEngine, 1, "read-area", "noAuthNoPriv", # readSubTree=(1, 3, 6, 1, 2, 1, 19, 2, 1)) config.addVacmUser(self._snmpEngine, 1, "read-area", "noAuthNoPriv", readSubTree=(1, 3, 6, 1, 4, 1, 332, 11)) config.addVacmUser(self._snmpEngine, 2, "read-area", "noAuthNoPriv", readSubTree=(1, 3, 6, 1, 2, 1, 10, 33)) config.addVacmUser(self._snmpEngine, 2, "read-area", "noAuthNoPriv", readSubTree=(1, 3, 6, 1, 2, 1, 19, 2, 1)) config.addVacmUser(self._snmpEngine, 2, "read-area", "noAuthNoPriv", readSubTree=(1, 3, 6, 1, 4, 1, 332, 11)) # Write Subtree log('before enable write-area') if self._CONF and 'ALLOW' in self._CONF and self._CONF['ALLOW'].lower( ) in 'true': log('Adding Write community with write-area') config.addVacmUser(self._snmpEngine, 1, 'write-area', 'noAuthNoPriv', readSubTree=(1, 3, 6, 1, 2, 1, 10, 33), writeSubTree=(1, 3, 6, 1, 2, 1, 10, 33)) config.addVacmUser(self._snmpEngine, 2, 'write-area', 'noAuthNoPriv', readSubTree=(1, 3, 6, 1, 2, 1, 10, 33), writeSubTree=(1, 3, 6, 1, 2, 1, 10, 33)) config.addVacmUser(self._snmpEngine, 1, 'write-area', 'noAuthNoPriv', readSubTree=(1, 3, 6, 1, 2, 1, 19, 2, 1), writeSubTree=(1, 3, 6, 1, 2, 1, 19, 2, 1)) config.addVacmUser(self._snmpEngine, 2, 'write-area', 'noAuthNoPriv', readSubTree=(1, 3, 6, 1, 2, 1, 19, 2, 1), writeSubTree=(1, 3, 6, 1, 2, 1, 19, 2, 1)) #each app has one or more contexts self._snmpContext = context.SnmpContext(self._snmpEngine) #the builder is used to load mibs. tell it to look in the #MIBS directory for our new MIB. We'll also use it to #export our symbols later mibBuilder = self._snmpContext.getMibInstrum().getMibBuilder() pub = path.join(getcwd(), 'PYSNMP_MIBS') priv = path.join(getcwd(), 'MIBSPY') mibSources = mibBuilder.getMibSources() + ( builder.DirMibSource(pub), ) + (builder.DirMibSource(priv), ) mibBuilder.setMibSources(*mibSources) #export our custom mib self._exportprivMIBS(mibBuilder) self._exportpubMIBS(mibBuilder) # tell pysnmp to respotd to get, getnext, set and getbulk cmdrsp.GetCommandResponder(self._snmpEngine, self._snmpContext) cmdrsp.NextCommandResponder(self._snmpEngine, self._snmpContext) cmdrsp.SetCommandResponder(self._snmpEngine, self._snmpContext) cmdrsp.BulkCommandResponder(self._snmpEngine, self._snmpContext)
except error.PySnmpError: self.handleResponsePdu( snmpEngine, stateReference, 'error', None, cbCtx ) # SNMP response relay # noinspection PyUnusedLocal def handleResponsePdu(self, snmpEngine, sendRequestHandle, errorIndication, PDU, cbCtx): stateReference, reqPDU = cbCtx if errorIndication: PDU = v2c.apiPDU.getResponse(reqPDU) PDU.setErrorStatus(PDU, 5) self.sendPdu(snmpEngine, stateReference, PDU) self.releaseStateInformation(stateReference) CommandResponder(snmpEngine, context.SnmpContext(snmpEngine)) snmpEngine.transportDispatcher.jobStarted(1) # this job would never finish # Run I/O dispatcher which would receive queries and send responses try: snmpEngine.transportDispatcher.runDispatcher() finally: snmpEngine.transportDispatcher.closeDispatcher()
# * in behalf of contextEngineId 0x8000000004030201, contextName '' # * over IPv4/UDP # * with TRAP ID 'warmStart' specified as a string OID # # Sending SNMPv3 Notification in behalf of non-default ContextEngineId # requires having a collection of Managed Objects registered under # the ContextEngineId being used. # from pysnmp.entity import engine from pysnmp.entity.rfc3413 import context from pysnmp.entity.rfc3413.oneliner import ntforg from pysnmp.proto import rfc1902 snmpEngine = engine.SnmpEngine() snmpContext = context.SnmpContext( snmpEngine,contextEngineId=rfc1902.OctetString(hexValue='8000000004030201') ) ntfOrg = ntforg.NotificationOriginator(snmpEngine, snmpContext) errorIndication, errorStatus, errorIndex, varBinds = ntfOrg.sendNotification( ntforg.UsmUserData('usr-md5-none', 'authkey1'), ntforg.UdpTransportTarget(('localhost', 162)), 'inform', '1.3.6.1.6.3.1.1.5.2' ) if errorIndication: print('Notification not sent: %s' % errorIndication) elif errorStatus: print('Notification Receiver returned error: %s @%s' %
def engine(self): """ Setup SNMP engine and context """ log = 'SNMP agent engine initialization sequence begun. ' +\ 'This may take a minute or two.' logger.info(log) print(log) MPQ_ACT.put_nowait([datetime.now().isoformat(' '), 'INFO', log]) # Create SNMP engine with auto generated engineID and pre-bound # to socket transport dispatcher self.eng_snmp = engine.SnmpEngine() # Transport setup # UDP over IPv4 at 0.0.0.0:8900 config.addTransport( self.eng_snmp, udp.domainName, udp.UdpTransport().openServerMode(iface=('', 8900))) # UDP over IPv6 at [::]:8900 config.addTransport( self.eng_snmp, udp6.domainName, udp6.Udp6Transport().openServerMode(iface=('::', 8900))) # SNMPv2c setup # SecurityName <-> CommunityName mapping. config.addV1System(snmpEngine=self.eng_snmp, communityIndex='agent', communityName='janusess') # Allow full MIB access for this user / securityModels at VACM # MIB 1.3.6.1.4.1.9934 refers to Janus Research Group # MIB 1.3.6.1.4.1.9934.0 refers to JanusESS Project config.addVacmUser(snmpEngine=self.eng_snmp, securityModel=2, securityName='agent', securityLevel='noAuthNoPriv', readSubTree=(1, 3, 6, 1, 4, 1, 9934, 0)) # Get default SNMP context this SNMP engine serves self.ctx_snmp = context.SnmpContext(snmpEngine=self.eng_snmp) # Create custom Managed Object Instance self.mib_builder = self.ctx_snmp.getMibInstrum().getMibBuilder() mib_sources = self.mib_builder.getMibSources() + \ ( builder.DirMibSource('/opt/Janus/ESS/python3/server/snmp/mibs'), ) self.mib_builder.setMibSources(*mib_sources) # JANUS-MIB defines and locates all Janus Research Group projects # JANUSESS-MIB defines all JanusESS project entries self.mib_builder.loadModules('JANUS-MIB', 'JANUSESS-MIB') self.config_base() self.config_lane() self.config_module() self.config_sensor() # Register SNMP Applications at the SNMP engine for particular SNMP context cmdrsp.GetCommandResponder(self.eng_snmp, self.ctx_snmp) cmdrsp.NextCommandResponder(self.eng_snmp, self.ctx_snmp) cmdrsp.BulkCommandResponder(self.eng_snmp, self.ctx_snmp) dispatcher = threading.Thread(target=self.dispatcher, args=()) dispatcher.start() MPQ_STAT.put_nowait(['snmp_agent', dispatcher.ident]) log = 'SNMP agent engine sequence concluded.' logger.info(log) MPQ_ACT.put_nowait([datetime.now().isoformat(' '), 'INFO', log]) MPQ_STAT.put_nowait(['base', ['snmp_agent', STAT_LVL['op']]]) log = 'SNMP agent listener started.' logger.info(log) print(log) MPQ_ACT.put_nowait([datetime.now().isoformat(' '), 'INFO', log]) # Poll SNMP agent queues for values to update variables while True: if not MPQ_SNMPA_STOP.empty(): MPQ_SNMPA_STOP.get() self.eng_snmp.transportDispatcher.closeDispatcher() break if not MPQ_SNMPA2.empty(): mpq_record = MPQ_SNMPA2.get() self.base(mpq_record=mpq_record) if not MPQ_SNMPA3.empty(): mpq_record = MPQ_SNMPA3.get() self.lane(mpq_record=mpq_record) if not MPQ_SNMPA4.empty(): mpq_record = MPQ_SNMPA4.get() self.module(mpq_record=mpq_record) if not MPQ_SNMPA5.empty(): mpq_record = MPQ_SNMPA5.get() self.sensor(mpq_record=mpq_record) time.sleep(0.1) MPQ_STAT.put_nowait(['snmp_agent', False]) log = 'SNMP agent dispatcher stopped.' logger.info(log) MPQ_ACT.put_nowait([datetime.now().isoformat(' '), 'INFO', log]) log = 'SNMP agent listener stopped.' logger.info(log) print(log) MPQ_ACT.put_nowait([datetime.now().isoformat(' '), 'INFO', log]) MPQ_STAT.put_nowait(['base', ['snmp_agent', STAT_LVL['not_cfg']]])
def main(): class CommandResponder(cmdrsp.CommandResponderBase): pduTypes = (rfc1905.SetRequestPDU.tagSet, rfc1905.GetRequestPDU.tagSet, rfc1905.GetNextRequestPDU.tagSet, rfc1905.GetBulkRequestPDU.tagSet) def handleMgmtOperation(self, snmpEngine, stateReference, contextName, pdu, acInfo): trunkReq = gCurrentRequestContext.copy() trunkReq['snmp-pdu'] = pdu pluginIdList = trunkReq['plugins-list'] logCtx = LogString(trunkReq) reqCtx = {} for pluginNum, pluginId in enumerate(pluginIdList): st, pdu = pluginManager.processCommandRequest( pluginId, snmpEngine, pdu, trunkReq, reqCtx) if st == status.BREAK: log.debug('plugin %s inhibits other plugins' % pluginId, ctx=logCtx) pluginIdList = pluginIdList[:pluginNum] break elif st == status.DROP: log.debug( 'received SNMP message, plugin %s muted request' % pluginId, ctx=logCtx) self.releaseStateInformation(stateReference) return elif st == status.RESPOND: log.debug( 'received SNMP message, plugin %s forced immediate response' % pluginId, ctx=logCtx) try: self.sendPdu(snmpEngine, stateReference, pdu) except PySnmpError: log.error('failure sending SNMP response', ctx=logCtx) else: self.releaseStateInformation(stateReference) return # pass query to trunk trunkIdList = trunkReq['trunk-id-list'] if trunkIdList is None: log.error('no route configured', ctx=logCtx) self.releaseStateInformation(stateReference) return for trunkId in trunkIdList: cbCtx = pluginIdList, trunkId, trunkReq, snmpEngine, stateReference, reqCtx try: msgId = trunkingManager.sendReq(trunkId, trunkReq, self.trunkCbFun, cbCtx) except SnmpfwdError: log.error( 'received SNMP message, message not sent to trunk "%s"' % sys.exc_info()[1], ctx=logCtx) return log.debug( 'received SNMP message, forwarded as trunk message #%s' % msgId, ctx=logCtx) def trunkCbFun(self, msgId, trunkRsp, cbCtx): pluginIdList, trunkId, trunkReq, snmpEngine, stateReference, reqCtx = cbCtx for key in tuple(trunkRsp): if key != 'callflow-id': trunkRsp['client-' + key] = trunkRsp[key] del trunkRsp[key] trunkRsp['callflow-id'] = trunkReq['callflow-id'] logCtx = LogString(trunkRsp) if trunkRsp['client-error-indication']: log.info( 'received trunk message #%s, remote end reported error-indication "%s", NOT responding' % (msgId, trunkRsp['client-error-indication']), ctx=logCtx) elif 'client-snmp-pdu' not in trunkRsp: log.info( 'received trunk message #%s, remote end does not send SNMP PDU, NOT responding' % msgId, ctx=logCtx) else: pdu = trunkRsp['client-snmp-pdu'] for pluginId in pluginIdList: st, pdu = pluginManager.processCommandResponse( pluginId, snmpEngine, pdu, trunkReq, reqCtx) if st == status.BREAK: log.debug('plugin %s inhibits other plugins' % pluginId, ctx=logCtx) break elif st == status.DROP: log.debug('plugin %s muted response' % pluginId, ctx=logCtx) self.releaseStateInformation(stateReference) return try: self.sendPdu(snmpEngine, stateReference, pdu) except PySnmpError: log.error('failure sending SNMP response', ctx=logCtx) else: log.debug( 'received trunk message #%s, forwarded as SNMP message' % msgId, ctx=logCtx) self.releaseStateInformation(stateReference) # # SNMPv3 NotificationReceiver implementation # class NotificationReceiver(ntfrcv.NotificationReceiver): pduTypes = (rfc1157.TrapPDU.tagSet, rfc1905.SNMPv2TrapPDU.tagSet) def processPdu(self, snmpEngine, messageProcessingModel, securityModel, securityName, securityLevel, contextEngineId, contextName, pduVersion, pdu, maxSizeResponseScopedPDU, stateReference): trunkReq = gCurrentRequestContext.copy() if messageProcessingModel == 0: pdu = rfc2576.v1ToV2(pdu) # TODO: why this is not automatic? v2c.apiTrapPDU.setDefaults(pdu) trunkReq['snmp-pdu'] = pdu pluginIdList = trunkReq['plugins-list'] logCtx = LogString(trunkReq) reqCtx = {} for pluginNum, pluginId in enumerate(pluginIdList): st, pdu = pluginManager.processNotificationRequest( pluginId, snmpEngine, pdu, trunkReq, reqCtx) if st == status.BREAK: log.debug('plugin %s inhibits other plugins' % pluginId, ctx=logCtx) pluginIdList = pluginIdList[:pluginNum] break elif st == status.DROP: log.debug('plugin %s muted request' % pluginId, ctx=logCtx) return elif st == status.RESPOND: log.debug('plugin %s NOT forced immediate response' % pluginId, ctx=logCtx) # TODO: implement immediate response for confirmed-class PDU return # pass query to trunk trunkIdList = trunkReq['trunk-id-list'] if trunkIdList is None: log.error('no route configured', ctx=logCtx) return for trunkId in trunkIdList: # TODO: pass messageProcessingModel to respond cbCtx = pluginIdList, trunkId, trunkReq, snmpEngine, stateReference, reqCtx try: msgId = trunkingManager.sendReq(trunkId, trunkReq, self.trunkCbFun, cbCtx) except SnmpfwdError: log.error( 'received SNMP message, message not sent to trunk "%s" %s' % (trunkId, sys.exc_info()[1]), ctx=logCtx) return log.debug( 'received SNMP message, forwarded as trunk message #%s' % msgId, ctx=logCtx) def trunkCbFun(self, msgId, trunkRsp, cbCtx): pluginIdList, trunkId, trunkReq, snmpEngine, stateReference, reqCtx = cbCtx for key in tuple(trunkRsp): if key != 'callflow-id': trunkRsp['client-' + key] = trunkRsp[key] del trunkRsp[key] trunkRsp['callflow-id'] = trunkReq['callflow-id'] logCtx = LazyLogString(trunkReq, trunkRsp) if trunkRsp['client-error-indication']: log.info( 'received trunk message #%s, remote end reported error-indication "%s", NOT responding' % (msgId, trunkRsp['client-error-indication']), ctx=logCtx) else: if 'client-snmp-pdu' not in trunkRsp: log.debug( 'received trunk message #%s -- unconfirmed SNMP message' % msgId, ctx=logCtx) return pdu = trunkRsp['client-snmp-pdu'] for pluginId in pluginIdList: st, pdu = pluginManager.processNotificationResponse( pluginId, snmpEngine, pdu, trunkReq, reqCtx) if st == status.BREAK: log.debug('plugin %s inhibits other plugins' % pluginId, ctx=logCtx) break elif st == status.DROP: log.debug( 'received trunk message #%s, plugin %s muted response' % (msgId, pluginId), ctx=logCtx) return log.debug( 'received trunk message #%s, forwarded as SNMP message' % msgId, ctx=logCtx) # TODO: implement response part # # Agent-side API complies with SMIv2 # if messageProcessingModel == 0: # PDU = rfc2576.v2ToV1(PDU, origPdu) # # statusInformation = {} # # # 3.4.3 # try: # snmpEngine.msgAndPduDsp.returnResponsePdu( # snmpEngine, messageProcessingModel, securityModel, # securityName, securityLevel, contextEngineId, # contextName, pduVersion, rspPDU, maxSizeResponseScopedPDU, # stateReference, statusInformation) # # except error.StatusInformation: # log.error('processPdu: stateReference %s, statusInformation %s' % (stateReference, sys.exc_info()[1])) class LogString(LazyLogString): GROUPINGS = [ ['callflow-id'], [ 'snmp-engine-id', 'snmp-transport-domain', 'snmp-bind-address', 'snmp-bind-port', 'snmp-security-model', 'snmp-security-level', 'snmp-security-name', 'snmp-credentials-id' ], ['snmp-context-engine-id', 'snmp-context-name', 'snmp-context-id'], ['snmp-pdu', 'snmp-content-id'], ['snmp-peer-address', 'snmp-peer-port', 'snmp-peer-id'], ['trunk-id'], ['client-snmp-pdu'], ] FORMATTERS = { 'client-snmp-pdu': LazyLogString.prettyVarBinds, 'snmp-pdu': LazyLogString.prettyVarBinds, } def securityAuditObserver(snmpEngine, execpoint, variables, cbCtx): securityModel = variables.get('securityModel', 0) logMsg = 'SNMPv%s auth failure' % securityModel logMsg += ' at %s:%s' % variables['transportAddress'].getLocalAddress() logMsg += ' from %s:%s' % variables['transportAddress'] statusInformation = variables.get('statusInformation', {}) if securityModel in (1, 2): logMsg += ' using snmp-community-name "%s"' % statusInformation.get( 'communityName', '?') elif securityModel == 3: logMsg += ' using snmp-usm-user "%s"' % statusInformation.get( 'msgUserName', '?') try: logMsg += ': %s' % statusInformation['errorIndication'] except KeyError: pass log.error(logMsg) def requestObserver(snmpEngine, execpoint, variables, cbCtx): trunkReq = { 'callflow-id': '%10.10x' % random.randint(0, 0xffffffffff), 'snmp-engine-id': snmpEngine.snmpEngineID, 'snmp-transport-domain': variables['transportDomain'], 'snmp-peer-address': variables['transportAddress'][0], 'snmp-peer-port': variables['transportAddress'][1], 'snmp-bind-address': variables['transportAddress'].getLocalAddress()[0], 'snmp-bind-port': variables['transportAddress'].getLocalAddress()[1], 'snmp-security-model': variables['securityModel'], 'snmp-security-level': variables['securityLevel'], 'snmp-security-name': variables['securityName'], 'snmp-context-engine-id': variables['contextEngineId'], 'snmp-context-name': variables['contextName'], } trunkReq['snmp-credentials-id'] = macro.expandMacro( credIdMap.get( (str(snmpEngine.snmpEngineID), variables['transportDomain'], variables['securityModel'], variables['securityLevel'], str(variables['securityName']))), trunkReq) k = '#'.join([ str(x) for x in (variables['contextEngineId'], variables['contextName']) ]) for x, y in contextIdList: if y.match(k): trunkReq['snmp-context-id'] = macro.expandMacro(x, trunkReq) break else: trunkReq['snmp-context-id'] = None addr = '%s:%s#%s:%s' % ( variables['transportAddress'][0], variables['transportAddress'][1], variables['transportAddress'].getLocalAddress()[0], variables['transportAddress'].getLocalAddress()[1]) for pat, peerId in peerIdMap.get(str(variables['transportDomain']), ()): if pat.match(addr): trunkReq['snmp-peer-id'] = macro.expandMacro(peerId, trunkReq) break else: trunkReq['snmp-peer-id'] = None pdu = variables['pdu'] if pdu.tagSet == v1.TrapPDU.tagSet: pdu = rfc2576.v1ToV2(pdu) v2c.apiTrapPDU.setDefaults(pdu) k = '#'.join([ snmpPduTypesMap.get(variables['pdu'].tagSet, '?'), '|'.join([str(x[0]) for x in v2c.apiTrapPDU.getVarBinds(pdu)]) ]) for x, y in contentIdList: if y.match(k): trunkReq['snmp-content-id'] = macro.expandMacro(x, trunkReq) break else: trunkReq['snmp-content-id'] = None trunkReq['plugins-list'] = pluginIdMap.get( (trunkReq['snmp-credentials-id'], trunkReq['snmp-context-id'], trunkReq['snmp-peer-id'], trunkReq['snmp-content-id']), []) trunkReq['trunk-id-list'] = trunkIdMap.get( (trunkReq['snmp-credentials-id'], trunkReq['snmp-context-id'], trunkReq['snmp-peer-id'], trunkReq['snmp-content-id'])) cbCtx.clear() cbCtx.update(trunkReq) # # main script starts here # helpMessage = """\ Usage: %s [--help] [--version ] [--debug-snmp=<%s>] [--debug-asn1=<%s>] [--daemonize] [--process-user=<uname>] [--process-group=<gname>] [--pid-file=<file>] [--logging-method=<%s[:args>]>] [--log-level=<%s>] [--config-file=<file>]""" % (sys.argv[0], '|'.join([ x for x in pysnmp_debug.flagMap.keys() if x != 'mibview' ]), '|'.join([x for x in pyasn1_debug.flagMap.keys()]), '|'.join( log.methodsMap.keys()), '|'.join(log.levelsMap)) try: opts, params = getopt.getopt(sys.argv[1:], 'hv', [ 'help', 'version', 'debug=', 'debug-snmp=', 'debug-asn1=', 'daemonize', 'process-user='******'process-group=', 'pid-file=', 'logging-method=', 'log-level=', 'config-file=' ]) except Exception: sys.stderr.write('ERROR: %s\r\n%s\r\n' % (sys.exc_info()[1], helpMessage)) return if params: sys.stderr.write('ERROR: extra arguments supplied %s\r\n%s\r\n' % (params, helpMessage)) return pidFile = '' cfgFile = CONFIG_FILE foregroundFlag = True procUser = procGroup = None loggingMethod = ['stderr'] loggingLevel = None for opt in opts: if opt[0] == '-h' or opt[0] == '--help': sys.stderr.write("""\ Synopsis: SNMP Proxy Forwarder: server part. Receives SNMP requests at one or many built-in SNMP Agents and routes them to encrypted trunks established with Forwarder's Manager part(s) running elsewhere. Can implement complex routing logic through analyzing parts of SNMP messages and matching them against proxying rules. Documentation: http://snmpfwd.sourceforge.io/ %s """ % helpMessage) return if opt[0] == '-v' or opt[0] == '--version': import snmpfwd import pysnmp import pyasn1 sys.stderr.write("""\ SNMP Proxy Forwarder version %s, written by Ilya Etingof <*****@*****.**> Using foundation libraries: pysnmp %s, pyasn1 %s. Python interpreter: %s Software documentation and support at https://github.com/etingof/snmpfwd %s """ % (snmpfwd.__version__, hasattr(pysnmp, '__version__') and pysnmp.__version__ or 'unknown', hasattr(pyasn1, '__version__') and pyasn1.__version__ or 'unknown', sys.version, helpMessage)) return elif opt[0] == '--debug-snmp': pysnmp_debug.setLogger( pysnmp_debug.Debug(*opt[1].split(','), **dict(loggerName=PROGRAM_NAME + '.pysnmp'))) elif opt[0] == '--debug-asn1': pyasn1_debug.setLogger( pyasn1_debug.Debug(*opt[1].split(','), **dict(loggerName=PROGRAM_NAME + '.pyasn1'))) elif opt[0] == '--daemonize': foregroundFlag = False elif opt[0] == '--process-user': procUser = opt[1] elif opt[0] == '--process-group': procGroup = opt[1] elif opt[0] == '--pid-file': pidFile = opt[1] elif opt[0] == '--logging-method': loggingMethod = opt[1].split(':') elif opt[0] == '--log-level': loggingLevel = opt[1] elif opt[0] == '--config-file': cfgFile = opt[1] try: log.setLogger(PROGRAM_NAME, *loggingMethod, **dict(force=True)) if loggingLevel: log.setLevel(loggingLevel) except SnmpfwdError: sys.stderr.write('%s\r\n%s\r\n' % (sys.exc_info()[1], helpMessage)) return try: cfgTree = cparser.Config().load(cfgFile) except SnmpfwdError: log.error('configuration parsing error: %s' % sys.exc_info()[1]) return if cfgTree.getAttrValue('program-name', '', default=None) != PROGRAM_NAME: log.error('config file %s does not match program name %s' % (cfgFile, PROGRAM_NAME)) return if cfgTree.getAttrValue('config-version', '', default=None) != CONFIG_VERSION: log.error( 'config file %s version is not compatible with program version %s' % (cfgFile, CONFIG_VERSION)) return random.seed() gCurrentRequestContext = {} credIdMap = {} peerIdMap = {} contextIdList = [] contentIdList = [] pluginIdMap = {} trunkIdMap = {} engineIdMap = {} transportDispatcher = AsynsockDispatcher() transportDispatcher.registerRoutingCbFun(lambda td, t, d: td) transportDispatcher.setSocketMap() # use global asyncore socket map # # Initialize plugin modules # pluginManager = PluginManager(macro.expandMacros( cfgTree.getAttrValue('plugin-modules-path-list', '', default=[], vector=True), {'config-dir': os.path.dirname(cfgFile)}), progId=PROGRAM_NAME, apiVer=PLUGIN_API_VERSION) for pluginCfgPath in cfgTree.getPathsToAttr('plugin-id'): pluginId = cfgTree.getAttrValue('plugin-id', *pluginCfgPath) pluginMod = cfgTree.getAttrValue('plugin-module', *pluginCfgPath) pluginOptions = macro.expandMacros( cfgTree.getAttrValue('plugin-options', *pluginCfgPath, **dict(default=[], vector=True)), {'config-dir': os.path.dirname(cfgFile)}) log.info( 'configuring plugin ID %s (at %s) from module %s with options %s...' % (pluginId, '.'.join(pluginCfgPath), pluginMod, ', '.join(pluginOptions) or '<none>')) try: pluginManager.loadPlugin(pluginId, pluginMod, pluginOptions) except SnmpfwdError: log.error('plugin %s not loaded: %s' % (pluginId, sys.exc_info()[1])) return for configEntryPath in cfgTree.getPathsToAttr('snmp-credentials-id'): credId = cfgTree.getAttrValue('snmp-credentials-id', *configEntryPath) configKey = [] log.info('configuring snmp-credentials %s (at %s)...' % (credId, '.'.join(configEntryPath))) engineId = cfgTree.getAttrValue('snmp-engine-id', *configEntryPath) if engineId in engineIdMap: snmpEngine, snmpContext, snmpEngineMap = engineIdMap[engineId] log.info('using engine-id %s' % snmpEngine.snmpEngineID.prettyPrint()) else: snmpEngine = engine.SnmpEngine(snmpEngineID=engineId) snmpContext = context.SnmpContext(snmpEngine) snmpEngineMap = {'transportDomain': {}, 'securityName': {}} snmpEngine.observer.registerObserver( securityAuditObserver, 'rfc2576.prepareDataElements:sm-failure', 'rfc3412.prepareDataElements:sm-failure', cbCtx=gCurrentRequestContext) snmpEngine.observer.registerObserver( requestObserver, 'rfc3412.receiveMessage:request', cbCtx=gCurrentRequestContext) CommandResponder(snmpEngine, snmpContext) NotificationReceiver(snmpEngine, None) engineIdMap[engineId] = snmpEngine, snmpContext, snmpEngineMap log.info('new engine-id %s' % snmpEngine.snmpEngineID.prettyPrint()) configKey.append(str(snmpEngine.snmpEngineID)) transportDomain = cfgTree.getAttrValue('snmp-transport-domain', *configEntryPath) transportDomain = rfc1902.ObjectName(transportDomain) if transportDomain in snmpEngineMap['transportDomain']: h, p, transportDomain = snmpEngineMap['transportDomain'][ transportDomain] log.info('using transport endpoint %s:%s, transport ID %s' % (h, p, transportDomain)) else: if transportDomain[:len(udp.domainName)] == udp.domainName: transport = udp.UdpTransport() elif transportDomain[:len(udp6.domainName)] == udp6.domainName: transport = udp6.Udp6Transport() else: log.error('unknown transport domain %s' % (transportDomain, )) return h, p = cfgTree.getAttrValue('snmp-bind-address', *configEntryPath).split(':', 1) snmpEngine.registerTransportDispatcher(transportDispatcher, transportDomain) transportOptions = cfgTree.getAttrValue( 'snmp-transport-options', *configEntryPath, **dict(default=[], vector=True)) t = transport.openServerMode((h, int(p))) if 'transparent-proxy' in transportOptions: t.enablePktInfo() t.enableTransparent() elif 'virtual-interface' in transportOptions: t.enablePktInfo() config.addSocketTransport(snmpEngine, transportDomain, t) snmpEngineMap['transportDomain'][ transportDomain] = h, p, transportDomain log.info( 'new transport endpoint %s:%s, options %s, transport ID %s' % (h, p, transportOptions and '/'.join(transportOptions) or '<none>', transportDomain)) configKey.append(transportDomain) securityModel = cfgTree.getAttrValue('snmp-security-model', *configEntryPath) securityModel = rfc1902.Integer(securityModel) securityLevel = cfgTree.getAttrValue('snmp-security-level', *configEntryPath) securityLevel = rfc1902.Integer(securityLevel) securityName = cfgTree.getAttrValue('snmp-security-name', *configEntryPath) if securityModel in (1, 2): if securityName in snmpEngineMap['securityName']: if snmpEngineMap['securityName'][ securityModel] == securityModel: log.info('using security-name %s' % securityName) else: raise SnmpfwdError( 'snmp-security-name %s already in use at snmp-security-model %s' % (securityName, securityModel)) else: communityName = cfgTree.getAttrValue('snmp-community-name', *configEntryPath) config.addV1System(snmpEngine, securityName, communityName, securityName=securityName) log.info( 'new community-name %s, security-model %s, security-name %s, security-level %s' % (communityName, securityModel, securityName, securityLevel)) snmpEngineMap['securityName'][securityName] = securityModel configKey.append(securityModel) configKey.append(securityLevel) configKey.append(securityName) elif securityModel == 3: if securityName in snmpEngineMap['securityName']: log.info('using USM security-name: %s' % securityName) else: usmUser = cfgTree.getAttrValue('snmp-usm-user', *configEntryPath) log.info( 'new USM user %s, security-model %s, security-level %s, security-name %s' % (usmUser, securityModel, securityLevel, securityName)) if securityLevel in (2, 3): usmAuthProto = cfgTree.getAttrValue( 'snmp-usm-auth-protocol', *configEntryPath, **dict(default=config.usmHMACMD5AuthProtocol)) usmAuthProto = rfc1902.ObjectName(usmAuthProto) usmAuthKey = cfgTree.getAttrValue('snmp-usm-auth-key', *configEntryPath) log.info( 'new USM authentication key: %s, authentication protocol: %s' % (usmAuthKey, usmAuthProto)) if securityLevel == 3: usmPrivProto = cfgTree.getAttrValue( 'snmp-usm-priv-protocol', *configEntryPath, **dict(default=config.usmDESPrivProtocol)) usmPrivProto = rfc1902.ObjectName(usmPrivProto) usmPrivKey = cfgTree.getAttrValue( 'snmp-usm-priv-key', *configEntryPath, **dict(default=None)) log.info( 'new USM encryption key: %s, encryption protocol: %s' % (usmPrivKey, usmPrivProto)) config.addV3User(snmpEngine, usmUser, usmAuthProto, usmAuthKey, usmPrivProto, usmPrivKey) else: config.addV3User(snmpEngine, usmUser, usmAuthProto, usmAuthKey) else: config.addV3User(snmpEngine, usmUser) snmpEngineMap['securityName'][securityName] = securityModel configKey.append(securityModel) configKey.append(securityLevel) configKey.append(securityName) else: raise SnmpfwdError('unknown snmp-security-model: %s' % securityModel) configKey = tuple(configKey) if configKey in credIdMap: log.error( 'ambiguous configuration for key snmp-credentials-id=%s at %s' % (credId, '.'.join(configEntryPath))) return credIdMap[configKey] = credId duplicates = {} for peerCfgPath in cfgTree.getPathsToAttr('snmp-peer-id'): peerId = cfgTree.getAttrValue('snmp-peer-id', *peerCfgPath) if peerId in duplicates: log.error( 'duplicate snmp-peer-id=%s at %s and %s' % (peerId, '.'.join(peerCfgPath), '.'.join(duplicates[peerId]))) return duplicates[peerId] = peerCfgPath log.info('configuring peer ID %s (at %s)...' % (peerId, '.'.join(peerCfgPath))) transportDomain = cfgTree.getAttrValue('snmp-transport-domain', *peerCfgPath) if transportDomain not in peerIdMap: peerIdMap[transportDomain] = [] for peerAddress in cfgTree.getAttrValue( 'snmp-peer-address-pattern-list', *peerCfgPath, **dict(vector=True)): for bindAddress in cfgTree.getAttrValue( 'snmp-bind-address-pattern-list', *peerCfgPath, **dict(vector=True)): peerIdMap[transportDomain].append( (re.compile(peerAddress + '#' + bindAddress), peerId)) duplicates = {} for contextCfgPath in cfgTree.getPathsToAttr('snmp-context-id'): contextId = cfgTree.getAttrValue('snmp-context-id', *contextCfgPath) if contextId in duplicates: log.error('duplicate snmp-context-id=%s at %s and %s' % (contextId, '.'.join(contextCfgPath), '.'.join( duplicates[contextId]))) return duplicates[contextId] = contextCfgPath k = '#'.join((cfgTree.getAttrValue('snmp-context-engine-id-pattern', *contextCfgPath), cfgTree.getAttrValue('snmp-context-name-pattern', *contextCfgPath))) log.info('configuring context ID %s (at %s), composite key: %s' % (contextId, '.'.join(contextCfgPath), k)) contextIdList.append((contextId, re.compile(k))) duplicates = {} for contentCfgPath in cfgTree.getPathsToAttr('snmp-content-id'): contentId = cfgTree.getAttrValue('snmp-content-id', *contentCfgPath) if contentId in duplicates: log.error('duplicate snmp-content-id=%s at %s and %s' % (contentId, '.'.join(contentCfgPath), '.'.join( duplicates[contentId]))) return duplicates[contentId] = contentCfgPath for x in cfgTree.getAttrValue('snmp-pdu-oid-prefix-pattern-list', *contentCfgPath, **dict(vector=True)): k = '#'.join([ cfgTree.getAttrValue('snmp-pdu-type-pattern', *contentCfgPath), x ]) log.info('configuring content ID %s (at %s), composite key: %s' % (contentId, '.'.join(contentCfgPath), k)) contentIdList.append((contentId, re.compile(k))) del duplicates for pluginCfgPath in cfgTree.getPathsToAttr('using-plugin-id-list'): pluginIdList = cfgTree.getAttrValue('using-plugin-id-list', *pluginCfgPath, **dict(vector=True)) log.info('configuring plugin ID(s) %s (at %s)...' % (','.join(pluginIdList), '.'.join(pluginCfgPath))) for credId in cfgTree.getAttrValue('matching-snmp-credentials-id-list', *pluginCfgPath, **dict(vector=True)): for peerId in cfgTree.getAttrValue('matching-snmp-peer-id-list', *pluginCfgPath, **dict(vector=True)): for contextId in cfgTree.getAttrValue( 'matching-snmp-context-id-list', *pluginCfgPath, **dict(vector=True)): for contentId in cfgTree.getAttrValue( 'matching-snmp-content-id-list', *pluginCfgPath, **dict(vector=True)): k = credId, contextId, peerId, contentId if k in pluginIdMap: log.error( 'duplicate snmp-credentials-id %s, snmp-context-id %s, snmp-peer-id %s, snmp-content-id %s at plugin-id(s) %s' % (credId, contextId, peerId, contentId, ','.join(pluginIdList))) return else: log.info( 'configuring plugin(s) %s (at %s), composite key: %s' % (','.join(pluginIdList), '.'.join(pluginCfgPath), '/'.join(k))) for pluginId in pluginIdList: if not pluginManager.hasPlugin(pluginId): log.error( 'undefined plugin ID %s referenced at %s' % (pluginId, '.'.join(pluginCfgPath))) return pluginIdMap[k] = pluginIdList for routeCfgPath in cfgTree.getPathsToAttr('using-trunk-id-list'): trunkIdList = cfgTree.getAttrValue('using-trunk-id-list', *routeCfgPath, **dict(vector=True)) log.info('configuring destination trunk ID(s) %s (at %s)...' % (','.join(trunkIdList), '.'.join(routeCfgPath))) for credId in cfgTree.getAttrValue('matching-snmp-credentials-id-list', *routeCfgPath, **dict(vector=True)): for peerId in cfgTree.getAttrValue('matching-snmp-peer-id-list', *routeCfgPath, **dict(vector=True)): for contextId in cfgTree.getAttrValue( 'matching-snmp-context-id-list', *routeCfgPath, **dict(vector=True)): for contentId in cfgTree.getAttrValue( 'matching-snmp-content-id-list', *routeCfgPath, **dict(vector=True)): k = credId, contextId, peerId, contentId if k in trunkIdMap: log.error( 'duplicate snmp-credentials-id %s, snmp-context-id %s, snmp-peer-id %s, snmp-content-id %s at trunk-id(s) %s' % (credId, contextId, peerId, contentId, ','.join(trunkIdList))) return else: trunkIdMap[k] = trunkIdList log.info( 'configuring trunk routing to %s (at %s), composite key: %s' % (','.join(trunkIdList), '.'.join(routeCfgPath), '/'.join(k))) def dataCbFun(trunkId, msgId, msg): log.debug('message ID %s received from trunk %s' % (msgId, trunkId)) trunkingManager = TrunkingManager(dataCbFun) def getTrunkAddr(a, port=0): f = lambda h, p=port: (h, int(p)) try: return f(*a.split(':')) except Exception: raise SnmpfwdError('improper IPv4 endpoint %s' % a) for trunkCfgPath in cfgTree.getPathsToAttr('trunk-id'): trunkId = cfgTree.getAttrValue('trunk-id', *trunkCfgPath) secret = cfgTree.getAttrValue('trunk-crypto-key', *trunkCfgPath, **dict(default='')) secret = secret and (secret * ((16 // len(secret)) + 1))[:16] log.info('configuring trunk ID %s (at %s)...' % (trunkId, '.'.join(trunkCfgPath))) connectionMode = cfgTree.getAttrValue('trunk-connection-mode', *trunkCfgPath) if connectionMode == 'client': trunkingManager.addClient( trunkId, getTrunkAddr( cfgTree.getAttrValue('trunk-bind-address', *trunkCfgPath)), getTrunkAddr( cfgTree.getAttrValue('trunk-peer-address', *trunkCfgPath), 30201), cfgTree.getAttrValue('trunk-ping-period', *trunkCfgPath, default=0, expect=int), secret) log.info( 'new trunking client from %s to %s' % (cfgTree.getAttrValue('trunk-bind-address', *trunkCfgPath), cfgTree.getAttrValue('trunk-peer-address', *trunkCfgPath))) if connectionMode == 'server': trunkingManager.addServer( getTrunkAddr( cfgTree.getAttrValue('trunk-bind-address', *trunkCfgPath), 30201), cfgTree.getAttrValue('trunk-ping-period', *trunkCfgPath, default=0, expect=int), secret) log.info( 'new trunking server at %s' % (cfgTree.getAttrValue('trunk-bind-address', *trunkCfgPath))) transportDispatcher.registerTimerCbFun(trunkingManager.setupTrunks, random.randrange(1, 5)) transportDispatcher.registerTimerCbFun(trunkingManager.monitorTrunks, random.randrange(1, 5)) try: daemon.dropPrivileges(procUser, procGroup) except Exception: log.error('can not drop privileges: %s' % sys.exc_info()[1]) return if not foregroundFlag: try: daemon.daemonize(pidFile) except Exception: log.error('can not daemonize process: %s' % sys.exc_info()[1]) return # Run mainloop log.info('starting I/O engine...') transportDispatcher.jobStarted(1) # server job would never finish # Python 2.4 does not support the "finally" clause while True: try: transportDispatcher.runDispatcher() except (PySnmpError, SnmpfwdError, socket.error): log.error(str(sys.exc_info()[1])) continue except Exception: transportDispatcher.closeDispatcher() raise
def __init__(self, mibPath, temperatureValue, snmpRelays, criticalStatus=True): from types import ListType, TupleType, StringTypes from re import compile, search from socket import gethostbyname extractPaths = compile(r'[,:]') checkIP = compile(r'(\d{1,3}\.){3}\d{1,3}') # Create SNMP engine instance self.snmpEngine = engine.SnmpEngine() if not temperatureValue: raise ValueError, 'A temperature must be provided' self.temperature = temperatureValue #print "============>mibPath type: %s" %type(mibPath) if type(mibPath) in StringTypes: mibPathTuple = tuple(extractPaths.split(mibPath)) elif type(mibPath) in (ListType, TupleType): mibPathTuple = tuple(mibPath) else: mibPathTuple = ('/usr/local/share/snmp/python/', ) mibBuilder = self.snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder #print mibPathTuple mibSources = mibBuilder.getMibPath() + mibPathTuple mibBuilder.setMibPath(*mibSources) mibBuilder.loadModules('USC-IGFAE-MIB') if type(snmpRelays) in StringTypes: snmpRelays = snmpRelays.split(',') elif not type(snmpRelays) in (ListType, TupleType): raise TypeError, 'The list of SNMP relays must be a string or a list or tuple of strings' (temperatureCritical, temperatureOK, self.roomTemp) = mibBuilder.importSymbols('USC-IGFAE-MIB', 'temperatureCritical', 'temperatureOK', 'roomTemp') # SecurityName <-> CommunityName mapping config.addV1System(self.snmpEngine, 'Arduino', 'ups') # Specify security settings per SecurityName (SNMPv2c -> 1) config.addTargetParams(self.snmpEngine, 'creds', 'Arduino', 'noAuthNoPriv', 0) # Setup transport endpoint and bind it with security settings yielding # a target name config.addSocketTransport(self.snmpEngine, udp.domainName, udp.UdpSocketTransport().openClientMode()) index = 0 for machine in snmpRelays: index = index + 1 if not checkIP.match(machine): try: machine = gethostbyname(machine) except: continue #print "==============>SNMP relay IP: %s" % machine config.addTargetAddr(self.snmpEngine, 'NMS%s' % index, udp.domainName, (machine, 162), 'creds', tagList='managers') # Specify what kind of notification should be sent (TRAP or INFORM), # to what targets (chosen by tag) and what filter should apply to # the set of targets (selected by tag) config.addNotificationTarget(self.snmpEngine, 'sendShutdownTrap', 'my-filter', 'managers', 'trap') # Allow NOTIFY access to Agent's MIB by this SNMP model (2), securityLevel # and SecurityName config.addContext(self.snmpEngine, '') config.addVacmUser(self.snmpEngine, 1, 'Arduino', 'noAuthNoPriv', (), (), (1, 3, 6)) # *** SNMP engine configuration is complete by this line *** # Create default SNMP context where contextEngineId == SnmpEngineId snmpContext = context.SnmpContext(self.snmpEngine) if criticalStatus: self.trap = temperatureCritical else: self.trap = temperatureOK # Create Notification Originator App instance. ntforg.NotificationOriginator.__init__(self, snmpContext)
def sendTrap(self, version, enterprise, varList, community=False, destPort=False): if destPort: trapPort = destPort else: trapPort = TRAP_PORT if community: comm = community else: comm = DEFAULT_COMM snmpEngine = engine.SnmpEngine() # v1/2 setup config.addV1System(snmpEngine, TEST_AGENT, comm) # v3 setup config.addV3User(snmpEngine, TEST_USER, config.usmHMACMD5AuthProtocol, 'authKey1', config.usmDESPrivProtocol, 'privKey1') # Transport params config.addTargetParams(snmpEngine, PARAM, TEST_USER, AUTHPRIV) #config.addTargetParams(snmpEngine, 'myParams', 'test-agent', 'noAuthNoPriv', 0) # Transport addresses config.addTargetAddr(snmpEngine, NMS, config.snmpUDPDomain, (self.dataCollector, trapPort), PARAM, tagList='myManagementStations') # Notification targets config.addNotificationTarget( # snmpEngine, 'myNotifyName', 'myParams', 'myManagementStations', 'trap' snmpEngine, 'myNotifyName', PARAM, 'myManagementStations', 'inform') # Setup transport endpoint config.addSocketTransport(snmpEngine, udp.domainName, udp.UdpSocketTransport().openClientMode()) # Agent-side VACM setup config.addContext(snmpEngine, '') config.addTrapUser(snmpEngine, 1, 'test-agent', 'noAuthNoPriv', (1, 3, 6)) # v1 config.addTrapUser(snmpEngine, 2, 'test-agent', 'noAuthNoPriv', (1, 3, 6)) # v2c config.addTrapUser(snmpEngine, 3, 'test-user', 'authPriv', (1, 3, 6)) # v3 # SNMP context snmpContext = context.SnmpContext(snmpEngine) def cbFun(sendRequestHandle, errorIndication, cbCtx): if errorIndication: print errorIndication ntforg.NotificationOriginator(snmpContext).sendNotification( snmpEngine, 'myNotifyName', ('SNMPv2-MIB', 'coldStart'), (((1, 3, 6, 1, 2, 1, 1, 5), v2c.OctetString('Example Notificator')), ), cbFun) snmpEngine.transportDispatcher.runDispatcher()