Uninett / nav

Network Administration Visualized
GNU General Public License v3.0
181 stars 38 forks source link

Implement SNMPv3 contexts as alternative to community indexing for retrieval of logical BRIDGE-MIB instances on Cisco switches #2811

Open lunkwill42 opened 7 months ago

lunkwill42 commented 4 months ago

NAV currently uses ENTITY-MIB::entLogicalTable entries (if it can) to discover alternate logical views of the BRIDGE-MIB (SNMPv2-SMI::mib-2.17).

For matching entries, it fetches an alternative community from ENTITY-MIB::entLogicalCommunity:

entLogicalCommunity OBJECT-TYPE
  -- FROM   ENTITY-MIB
  SYNTAX    OCTET STRING (0..255)
  MAX-ACCESS    read-only
  STATUS    deprecated
  DESCRIPTION   "An SNMPv1 or SNMPv2C community-string, which can be used to
            access detailed management information for this logical
            entity.  The agent should allow read access with this
            community string (to an appropriate subset of all managed
            objects) and may also return a community string based on the
            privileges of the request used to read this object.  Note
            that an agent may return a community string with read-only
            privileges, even if this object is accessed with a
            read-write community string.  However, the agent must take

            care not to return a community string that allows more
            privileges than the community string used to access this
            object.

            A compliant SNMP agent may wish to conserve naming scopes by
            representing multiple logical entities in a single 'default'
            naming scope.  This is possible when the logical entities,
            represented by the same value of entLogicalCommunity, have
            no object instances in common.  For example, 'bridge1' and
            'repeater1' may be part of the main naming scope, but at
            least one additional community string is needed to represent
            'bridge2' and 'repeater2'.

            Logical entities 'bridge1' and 'repeater1' would be
            represented by sysOREntries associated with the 'default'
            naming scope.

            For agents not accessible via SNMPv1 or SNMPv2C, the value
            of this object is the empty string.  This object may also
            contain an empty string if a community string has not yet
            been assigned by the agent, or if no community string with
            suitable access rights can be returned for a particular SNMP
            request.

            Note that this object is deprecated.  Agents which implement
            SNMPv3 access should use the entLogicalContextEngineID and
            entLogicalContextName objects to identify the context
            associated with each logical entity.  SNMPv3 agents may
            return a zero-length string for this object, or may continue
            to return a community string (e.g., tri-lingual agent
            support)."
::= { iso(1) org(3) dod(6) internet(1) mgmt(2) mib-2(1) entityMIB(47) entityMIBObjects(1) entityLogical(2) entLogicalTable(1) entLogicalEntry(1) 4 }

For SNMPv3, it should rather look at ENTITY-MIB::entLogicalContextName (and, potentially, heed ENTITY-MIB::entLogicalContextEngineID):

entLogicalContextName OBJECT-TYPE
  -- FROM   ENTITY-MIB
  -- TEXTUAL CONVENTION SnmpAdminString
  SYNTAX    OCTET STRING (0..255)
  DISPLAY-HINT  "255t"
  MAX-ACCESS    read-only
  STATUS    current
  DESCRIPTION   "The contextName that can be used to send an SNMP message
            concerning information held by this logical entity, to the
            address specified by the associated
            'entLogicalTAddress/entLogicalTDomain' pair.

            This object, together with the associated
            entLogicalContextEngineID object, defines the context
            associated with a particular logical entity, and allows

            access to SNMP engines identified by a contextEngineId and
            contextName pair.

            If no value has been configured by the agent, a zero-length
            string is returned, or the agent may choose not to
            instantiate this object at all."
::= { iso(1) org(3) dod(6) internet(1) mgmt(2) mib-2(1) entityMIB(47) entityMIBObjects(1) entityLogical(2) entLogicalTable(1) entLogicalEntry(1) 8 }
lunkwill42 commented 4 months ago

Two mibretriever implementations implement retrieve_alternate_bridge_mibs: entity_mib and cisco_vtp_mib. The former fetched from ENTITY-MIB, the latter synthesizes entries from inspecting the proprietary CISCO-VTP-MIB.

These are both used from this function (responses from ENTITY-MIB being preferred): https://github.com/Uninett/nav/blob/276e9f47fdfea81ccaf462a5141249e2528a639e/python/nav/ipdevpoll/utils.py#L146

The signature of the return values of these functions must likely be changed to include optional SNMPv3 contexts and engine IDs.

lunkwill42 commented 4 months ago

The results of these functions are used by this class to implement collection across multiple logical instances of a MIB:

https://github.com/Uninett/nav/blob/a21c6b2b2910b1aaf035387f8a96711045a4b67a/python/nav/mibs/mibretriever.py#L580-L610

The instance list is still a plain list of tuples of (description, community), and if we are to extend these tuples, they should probably be more formalized as a NamedTuple and annotated properly in modern Python.