Advanced topics¶
Specific SNMP Engine ID¶
Listen and respond to SNMP GET/SET/GETNEXT/GETBULK queries with the following options:
- SNMPv3
- with SNMP EngineID: 8000000004030201
- with USM user ‘usr-md5-des’, auth: MD5, priv DES
- allow access to SNMPv2-MIB objects (1.3.6.1.2.1)
- over IPv4/UDP, listening at 127.0.0.1:161
The following Net-SNMP command will walk this Agent:
from pysnmp.entity import engine, config
from pysnmp.entity.rfc3413 import cmdrsp, context
from pysnmp.carrier.asyncore.dgram import udp
from pysnmp.proto import rfc1902
# Create SNMP engine
snmpEngine = engine.SnmpEngine(rfc1902.OctetString(hexValue='8000000004030201'))
# Transport setup
# UDP over IPv4
config.addTransport(
snmpEngine,
udp.DOMAIN_NAME,
udp.UdpTransport().openServerMode(('127.0.0.1', 161))
)
# SNMPv3/USM setup
# user: usr-md5-des, auth: MD5, priv DES
config.addV3User(
snmpEngine, 'usr-md5-des',
config.USM_AUTH_HMAC96_MD5, 'authkey1',
config.USM_PRIV_CBC56_DES, 'privkey1'
)
# Allow full MIB access for each user at VACM
config.addVacmUser(snmpEngine, 3, 'usr-md5-des', 'authPriv', (1, 3, 6, 1, 2, 1), (1, 3, 6, 1, 2, 1))
# Get default SNMP context this SNMP engine serves
snmpContext = context.SnmpContext(snmpEngine)
# 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)
# Register an imaginary never-ending job to keep I/O dispatcher running forever
snmpEngine.transportDispatcher.jobStarted(1)
# Run I/O dispatcher which would receive queries and send responses
try:
snmpEngine.transportDispatcher.runDispatcher()
finally:
snmpEngine.transportDispatcher.closeDispatcher()
Download
script.
Observe SNMP engine operations¶
Listen and respond to SNMP GET/SET/GETNEXT/GETBULK queries with the following options:
- SNMPv3
- with USM user ‘usr-md5-des’, auth: MD5, priv DES or
- allow access to SNMPv2-MIB objects (1.3.6.1.2.1)
- over IPv4/UDP, listening at 127.0.0.1:161
- registers its own execution observer to snmpEngine
The following Net-SNMP command will walk this Agent:
This script will report some details on request processing as seen by rfc3412.receiveMessage() and rfc3412.returnResponsePdu() abstract interfaces.
from pysnmp.entity import engine, config
from pysnmp.entity.rfc3413 import cmdrsp, context
from pysnmp.carrier.asyncore.dgram import udp
# Create SNMP engine
snmpEngine = engine.SnmpEngine()
# Execution point observer setup
# Register a callback to be invoked at specified execution point of
# SNMP Engine and passed local variables at code point's local scope
# noinspection PyUnusedLocal,PyUnusedLocal
def requestObserver(snmpEngine, execpoint, variables, cbCtx):
print('Execution point: %s' % execpoint)
print('* transportDomain: %s' % '.'.join([str(x) for x in variables['transportDomain']]))
print('* transportAddress: %s (local %s)' % (
'@'.join([str(x) for x in variables['transportAddress']]), '@'.join(
[str(x) for x in variables['transportAddress'].getLocalAddress()])))
print('* securityModel: %s' % variables['securityModel'])
print('* securityName: %s' % variables['securityName'])
print('* securityLevel: %s' % variables['securityLevel'])
print('* contextEngineId: %s' % variables['contextEngineId'].prettyPrint())
print('* contextName: %s' % variables['contextName'].prettyPrint())
print('* PDU: %s' % variables['pdu'].prettyPrint())
snmpEngine.observer.registerObserver(
requestObserver,
'rfc3412.receiveMessage:request',
'rfc3412.returnResponsePdu'
)
# Transport setup
# UDP over IPv4
config.addTransport(
snmpEngine,
udp.DOMAIN_NAME,
udp.UdpTransport().openServerMode(('127.0.0.1', 161))
)
# SNMPv3/USM setup
# user: usr-md5-des, auth: MD5, priv DES
config.addV3User(
snmpEngine, 'usr-md5-des',
config.USM_AUTH_HMAC96_MD5, 'authkey1',
config.USM_PRIV_CBC56_DES, 'privkey1'
)
# Allow full MIB access for each user at VACM
config.addVacmUser(snmpEngine, 3, 'usr-md5-des', 'authPriv',
(1, 3, 6, 1, 2, 1), (1, 3, 6, 1, 2, 1))
# Get default SNMP context this SNMP engine serves
snmpContext = context.SnmpContext(snmpEngine)
# 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)
# Register an imaginary never-ending job to keep I/O dispatcher running forever
snmpEngine.transportDispatcher.jobStarted(1)
# Run I/O dispatcher which would receive queries and send responses
try:
snmpEngine.transportDispatcher.runDispatcher()
finally:
snmpEngine.observer.unregisterObserver()
snmpEngine.transportDispatcher.closeDispatcher()
Download
script.
Multiple SNMP Engines¶
Run multiple SNMP Engines each with a complete Command Responder. Bind each SNMP Engine to a dedicated network transport endpoint:
- IPv4/UDP, listening at 127.0.0.1:161
- IPv4/UDP, listening at 127.0.0.2:161
Each Command Responder will respond to SNMP GET/SET/GETNEXT/GETBULK queries with the following options:
- SNMPv3
- with USM user ‘usr-md5-des’, auth: MD5, priv DES
- allow read access to SNMPv2-MIB objects (1.3.6)
- allow write access to SNMPv2-MIB objects (1.3.6.1.2.1)
The following Net-SNMP commands will walk the first and the second Agent respectively:
Notice differently configured snmpEngineId’s in usmUserEntry columns.
from pysnmp.entity import engine, config
from pysnmp.entity.rfc3413 import cmdrsp, context
from pysnmp.proto import rfc1902
from pysnmp.carrier.asyncore.dispatch import AsyncoreDispatcher
from pysnmp.carrier.asyncore.dgram import udp
# Configuration parameters for each of SNMP Engines
snmpEngineInfo = (
('0102030405060708', udp.DOMAIN_NAME + (0,), ('127.0.0.1', 161)),
('0807060504030201', udp.DOMAIN_NAME + (1,), ('127.0.0.2', 161))
)
# Instantiate the single transport dispatcher object
transportDispatcher = AsyncoreDispatcher()
# Setup a custom data routing function to select snmpEngine by transportDomain
transportDispatcher.registerRoutingCbFun(lambda td, t, d: td)
# Instantiate and configure SNMP Engines
for snmpEngineId, transportDomain, transportAddress in snmpEngineInfo:
# Create SNMP engine with specific engineID
snmpEngine = engine.SnmpEngine(rfc1902.OctetString(hexValue=snmpEngineId))
# Register SNMP Engine object with transport dispatcher. Request incoming
# data from specific transport endpoint to be funneled to this SNMP Engine.
snmpEngine.registerTransportDispatcher(transportDispatcher, transportDomain)
# Transport setup
# UDP over IPv4
config.addTransport(
snmpEngine,
transportDomain,
udp.UdpTransport().openServerMode(transportAddress)
)
# SNMPv3/USM setup
# user: usr-md5-des, auth: MD5, priv DES
config.addV3User(
snmpEngine, 'usr-md5-des',
config.USM_AUTH_HMAC96_MD5, 'authkey1',
config.USM_PRIV_CBC56_DES, 'privkey1'
)
# Allow full MIB access for this user / securityModels at VACM
config.addVacmUser(snmpEngine, 3, 'usr-md5-des', 'authPriv', (1, 3, 6), (1, 3, 6, 1, 2, 1))
# Get default SNMP context this SNMP engine serves
snmpContext = context.SnmpContext(snmpEngine)
# 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)
# Register an imaginary never-ending job to keep I/O dispatcher running forever
transportDispatcher.jobStarted(1)
# Run I/O dispatcher which would receive queries and send responses
try:
transportDispatcher.runDispatcher()
finally:
transportDispatcher.closeDispatcher()
Download
script.
Detailed VACM configuration¶
Serves MIB subtrees under different conditions:
- Respond to SNMPv2c commands
- with SNMP community “public”
- over IPv4/UDP, listening at 127.0.0.1:161
- Serve MIB under non-default contextName abcd
- Allow access to SNMPv2-MIB::system subtree
- Although deny access to SNMPv2-MIB::sysUpTime by a bit mask
- Use partial context name matching (a)
This example demonstrates detailed VACM configuration performed via low-level VACM calls: addContext, addVacmGroup, addVacmAccess and addVacmView. Each function populates one of the tables defined in SNMP-VIEW-BASED-ACM-MIB and used strictly as described in the above mentioned MIB.
The following Net-SNMP’s commands will GET a value at this Agent:
However this command will fail:
This command will not reveal SNMPv2-MIB::sysUpTime.0 among other objects:
from pysnmp.entity import engine, config
from pysnmp.entity.rfc3413 import cmdrsp, context
from pysnmp.carrier.asyncore.dgram import udp
# Create SNMP engine with autogenernated engineID and pre-bound
# to socket transport dispatcher
snmpEngine = engine.SnmpEngine()
# Transport setup
# UDP over IPv4
config.addTransport(
snmpEngine,
udp.domainName,
udp.UdpTransport().openServerMode(('127.0.0.1', 161))
)
# Register default MIB instrumentation controller with a new SNMP context
contextName = 'abcd'
snmpContext = context.SnmpContext(snmpEngine)
snmpContext.registerContextName(
contextName, snmpEngine.msgAndPduDsp.mibInstrumController)
# Add new SNMP community name, map it to a new security name and
# SNMP context
securityName = 'my-area'
communityName = 'public'
config.addV1System(
snmpEngine, securityName, communityName,
contextEngineId=snmpContext.contextEngineId,
contextName=contextName)
# VACM configuration settings
securityModel = 2 # SNMPv2c
securityLevel = 1 # noAuthNoPriv
vacmGroup = 'my-group'
readViewName = 'my-read-view'
# We will match by context name prefix
contextPrefix = contextName[:1]
# Populate SNMP-VIEW-BASED-ACM-MIB::vacmContextTable
config.addContext(snmpEngine, contextName)
# Populate SNMP-VIEW-BASED-ACM-MIB::vacmSecurityToGroupTable
config.addVacmGroup(
snmpEngine, vacmGroup, securityModel, securityName)
# Populate SNMP-VIEW-BASED-ACM-MIB::vacmAccessTable
config.addVacmAccess(
snmpEngine, vacmGroup, contextPrefix, securityModel, securityLevel,
'prefix', readViewName, '', '')
# Populate SNMP-VIEW-BASED-ACM-MIB::vacmViewTreeFamilyTable
# Allow the whole system subtree
config.addVacmView(
snmpEngine, readViewName, 'included', '1.3.6.1.2.1.1.1', '1.1.1.1.1.1.1.0')
# ...but exclude one sub-branch (just one scalar OID)
config.addVacmView(
snmpEngine, readViewName, 'excluded', '1.3.6.1.2.1.1.3', '1.1.1.1.1.1.1.1')
# Register SNMP Applications at the SNMP engine for particular SNMP context
cmdrsp.GetCommandResponder(snmpEngine, snmpContext)
cmdrsp.SetCommandResponder(snmpEngine, snmpContext)
cmdrsp.NextCommandResponder(snmpEngine, snmpContext)
# Register an imaginary never-ending job to keep I/O dispatcher running forever
snmpEngine.transportDispatcher.jobStarted(1)
# Run I/O dispatcher which would receive queries and send responses
try:
snmpEngine.transportDispatcher.runDispatcher()
except Exception:
snmpEngine.transportDispatcher.closeDispatcher()
raise
Download
script.
See also: library reference.