Search code examples
pysnmpsnmptrapd

SNMPTraps: pysnmp and "disableAuthorization"


I have written an SNMP trap receiver but currently I have to hardcode all the SNMPv2 community strings to be able to receive the traps.

How do I emulate the 'disableAuthorization' functionality from snmptrapd in pysnmp?

I have tried to not set the community string: config.addV1System(snmpEngine, 'my-area') but this errors about a missing param. I have also tried an empty string: config.addV1System(snmpEngine, 'my-area', '') but this stops all traps being processed.

What is the best way to allow receiving all traps through pysnmp regardless of the community string they were sent with? I haven't found anything in the pysnmp docs that could help me


Solution

  • I had made progress on setting up an observer for V1/2 (V3 to be added later) that picked up on notifications with an unknown community string and then called addV1System on the fly to dynamically add it in, like so:

    When setting up the transportDispatcher:

      snmpEngine.observer.registerObserver(_handle_unauthenticated_snmptrap,
            "rfc2576.prepareDataElements:sm-failure", "rfc3412.prepareDataElements:sm-failure")
    

    And then:

    def _handle_unauthenticated_snmptrap(snmpEngine, execpoint, variables, cbCtx):
        if variables["securityLevel"] in [ 1, 2 ] and variables["statusInformation"]["errorIndication"] == errind.unknownCommunityName:
            new_comm_string = "%s" % variables["statusInformation"].get("communityName", "")
            config.addV1System(my_snmpEngine, 'my-area', new_comm_string)
            return
        else:
            msg = "%s" % variables["statusInformation"]
            print(f"Trap: { msg }")
    

    However, this will always throw away the first trap received while adding any new community string (and then there is the problem whereby when the daemon is restarted the updated list of community strings is lost).

    In looking to improve this I then found hidden away in the docs this little gem:

    https://pysnmp.readthedocs.io/en/latest/examples/v3arch/asyncore/manager/ntfrcv/advanced-topics.html#serve-snmp-community-names-defined-by-regexp

    This example receives a notification and rewrites the community string into 'public' so all traps will be correctly received.

    In essence, when setting up the transportDispatcher:

        my_snmpEngine.observer.registerObserver(_trap_observer,
            'rfc2576.processIncomingMsg:writable', cbCtx='public')
    

    And then:

    def _trap_observer(snmpEngine, execpoint, variables, community_string):
         variables['communityName'] = variables['communityName'].clone(community_string)