Tuto PySNMP
Directory
Sources
Mkina-corpus partie 2
wikipedia
pySnmp
Liens internes
1. Introduction
PySNMP
est une librairie Python qui implémente toutes les versions du protocole SNMP
et ce entièrement en Python (Pas de C).
Ses principles caractéristiques sont:
- Complète, elle implémente l’intégralité du protocole SNMP (v1 à v3)
- Légère, environs 15000 lignes de code
- Assez simple pour les choses simples (phrase de merde)
- Très utilisée
- Très pratique pour écrire des sondes nagios/centreon/autre ou récupérer des informations
SNMP
dans nos programmes Python - Permet d’écrire nos propres agents
- Parfois complexe et manque d’une documentation claire sur certains éléments comme les agents
Installation
Linux/Windows:
pip install pysnmp
Manipuler les données ASN.1
Il nous arriver de manipuler des données au format ASN.1 puisque c’est celui qui est utilisé par le protocole SNMP
.
La librairie PySNMP
s’appuie sur une utre librairie: pyasn1
pour réaliser cela. La conversion des types ASN.1 vers python est presque naturelle:
>>> from pyasn1.type.univ import *
>>> a = Integer(21) * 2
>>> print(a)
42
>>> a = Integer(-1) + Integer(1)
>>> print(a)
0
>>> a = int(Integer(42))
>>> print(a)
42
>>> a = OctetString('Hello') + ', ' + OctetString(hexValue='5079534e4d5021')
>>> print(a, '\n', type(a))
Hello, PySNMP!
<class 'pyasn1.type.univ.OctetString'>
>>>
Commandes de base
PySNMP
propose différentes fonctions de bas niveau pour utiliser le protocole SNMP, mais il est conseillé d’utiliser le module hlapi
signifiant High Level API.
Ce dernier propose des fonctions de haut niveau assez faciles à paramétrer pour exécuter les commandes de base que l’on peut lister de cette manière:
from pysnmp.hlapi import *
l = [ x for x in dir() if 'Cmd' in x]
print(l)
help('pysnmp.hlapi.getCmd')
output:
['bulkCmd', 'getCmd', 'nextCmd', 'setCmd']
Help on function getCmd in pysnmp.hlapi:
pysnmp.hlapi.getCmd = getCmd(snmpEngine, authData, transportTarget, contextData, *varBinds, **options)
Creates a generator to perform one or more SNMP GET queries.
...
Avant d’utiliser ces commandes nous allons apprendre à manipuler les paramètrer dont elles ont besoin:
- Les
OIDs
qu’on souhaite consulter/modifier - Les éléments de connexion
communauté
pour le protocole v2 ou l’utilisateur pour le protocole v3
Les OIDS
Les OIDs
sont les identidiants des informations décrites dans les MIBs
. Un OID
indique le chemin à suivre dans l’arbre de la MIB
pour trouver l’information
1.2.3.0
pourrait se comprendre par:
.
en partant de la place centrle, plusieurs rues sont face à vous1
prenez la première à partir de la guche, vous arrivez sur une nouvelle place.2
plusieurs rues sont de nouveau face vous. Prenez la seconde sur votre gauche. Vous arrivez sur une nouvelle place3
plusieurs rues sont de nouveau face vous. Prenez la troisième sur votre gauche. Vous arrivez sur une nouvelle place0
il y a une plaque sur la place, elle contient votre information. Si vous avez envoyé unGET
vous la lisez, si vous avez envoyé unSET
vous la modifiez
Un OID
est représenté soit par une suite de valeurs numériques, soit par une suite de noms désignant chaque branche parcourue dans la MIB
.
Pour créér un OID
avec PySNMP
il convient d’instancier la classe ObjectIdentity
.
Un OID
peut être défini par:
- une string
- un tuple
- son libellé
Les 4 instances suivantes définissent le même objet
from pysnmp.hlapi import *
o = ObjectIdentity('1.3.6.1.2.1.1.3.0')
o = ObjectIdentity((1,3,6,1,2,1,1,3,0))
o = ObjectIdentity('SNMPv2-MIB', 'sysUpTime', 0)
o = ObjectIdentity('iso.org.dod.internet.mgmt.mib-2.system.sysUpTime.0')
Cela semble simple mais à l’utilisation les soucis commencent:
from pysnmp.hlapi import *
o = ObjectIdentity('1.3.6.1.2.1.1.3.0')
print(o.getLabel())
print(o.getMibNode())
print(o.getMibSymbol())
print(o.getOid())
print(o.prettyPrint())
output:
Traceback (most recent call last):
File "c:\Users\sol.rosca\Cloud\Cours\Programmation\Python-Snmp\00\00.py", line 5, in <module>
print(o.getLabel())
File "C:\Python3\lib\site-packages\pysnmp\smi\rfc1902.py", line 186, in getLabel
raise SmiError('%s object not fully initialized' % self.__class__.__name__)
pysnmp.smi.error.SmiError: ObjectIdentity object not fully initialized
Il faut effectivement rechercher cet OID
dans la MIB
, ce n’est pas automatique car il y a de nombreuses MIBs
. PySNMP
est fourni avec tout un arsenal de Mibs
, néanmoins il faut lui dire où les trouver.
La commande help
de Python montre qu’il existe une méthode resolveWithMib
. Cette méthode prend en paramètre un objet MibViewController
. Ce contrôleur a pour rôle de résoudre la correspondance OID
/MIB
.
La doc de la classe resolveWithMib
est quasiment inexistante. Cette classe prend un objet MibBuilder
en argument lors de sa création. Il faut donc aller voir la classe MibBuilder
…mais une petite recherche dans l’arborescence de PySNMP
montre qu’apparament un MibViewController
s’obtient à partir du monteur SNMP
engin. L’engin est en quelque sorte le coeur de la librairie PySNMP
qui nous permet de dialoguer avec les différents éléments du protocole (messages, hôtes, communautés, OIDs
, MIBs
, etc…)
On peut avoir plusieurs moteurs pour, par exemple travailler avec plusieurs MIBs
. Notre code devient alors:
from pysnmp.hlapi import *
se = SnmpEngine()
mvc = se.getUserContext('mibViewController')
o = ObjectIdentity('1.3.6.1.2.1.1.3.0')
o.resolveWithMib(mvc)
print(o.getLabel())
print(o.getMibNode())
print(o.getMibSymbol())
print(o.getOid())
print(o.prettyPrint())
output:
Traceback (most recent call last):
File "c:\Users\sol.rosca\Cloud\Cours\Programmation\Python-Snmp\00\00.py", line 7, in <module>
o.resolveWithMib(mvc)
File "C:\Python3\lib\site-packages\pysnmp\smi\rfc1902.py", line 356, in resolveWithMib
addMibCompiler(mibViewController.mibBuilder,
AttributeError: 'NoneType' object has no attribute 'mibBuilder'
Toujours pas…
Le mibViewController
n’est pas défini car nous n’avons pas créé de UserContext
. La solution la plus simple revient, finalement, à créer nous-même le MibViewController
:
from pysnmp.hlapi import *
from pysnmp.smi.view import MibViewController
se = SnmpEngine()
mvc = se.getUserContext('mibViewController')
if not mvc:
mvc = MibViewController(se.getMibBuilder())
o = ObjectIdentity('1.3.6.1.2.1.1.3.0')
o.resolveWithMib(mvc)
print(o.getLabel())
print(o.getMibNode())
print(o.getMibSymbol())
print(o.getOid())
print(o.prettyPrint())
output:
('iso', 'org', 'dod', 'internet', 'mgmt', 'mib-2', 'system', 'sysUpTime')
MibScalar((1, 3, 6, 1, 2, 1, 1, 3), TimeTicks())
('SNMPv2-MIB', 'sysUpTime', (ObjectName('0'),))
1.3.6.1.2.1.1.3.0
SNMPv2-MIB::sysUpTime.0
Nous y voila. Le contrôleur de MIB
utilise le MIB
builder oar défaut de PySNMP qui stocke les versions “pythonisées” des MIBS
dans le sous-dossier d’installation de PySNMP
: pysnmp/smi/mibs
. ne pas hésiter à y jetter un oeil .