Description
pysnmp est une librairie en Python, multiplateforme pour SNMP , capable d’agir en tant qu’agent, gestionnaire, proxy, sur les trois versions du protocole SNMP, de “discuter” sur les protocoles réseaux IPv(4|6).
Le propos est de (dé) montrer l’utilisation de pysnmp avec l’authentification forte de la v3 de SNMP.
Documentation
- La documentation officielle de la librairie : http://snmplabs.com/pysnmp/
Installation
- OpenBSD 6.6
- Version : 4.4.6
Sous OpenBSD, Installez
le paquet py3-snmp
Malheureusement, cette version ne semble pas (pleinement ?) fonctionnelle.
Donc, installons-le par le biais de l’outil pip : 
# python3.7 -m pip install --upgrade --user pysnmp
Travailler avec les MIB OpenBSD
L’équipe OpenBSD a créé ses propres MIB - ce sont des arborescences de données, que l’on peut aussi appeler “base de données arborescente” -
pysnmp nativement n’est pas capable de les interroger. Mais heureusement, on peut lui “donner à manger”.
Avec pysnmp est fourni un outil nommé mibdump.py - depuis la v4.3 ;
avant il fallait utiliser build-pysnmp-mib.py -, et lui indiquer le
chemin des MIB d’OpenBSD.
Ces MIB sont fournis dans le répertoire /usr/share/snmp/mibs/.
$ for file in /usr/share/snmp/mibs/*; do mibdump.py $file; done
Source MIB repositories: /usr/share/snmp/mibs, file:///usr/share/snmp/mibs, http://mibs.snmplabs.com/asn1/@mib@
Borrow missing/failed MIBs from: http://mibs.snmplabs.com/pysnmp/notexts/@mib@
Existing/compiled MIB locations: pysnmp.smi.mibs, pysnmp_mibs
Compiled MIBs destination directory: /home/zou/.pysnmp/mibs
MIBs excluded from code generation: INET-ADDRESS-MIB, PYSNMP-USM-MIB, RFC-1212, RFC-1215, RFC1065-SMI, RFC1155-SMI, RFC1158-MIB, RFC1213-MIB, SNMP-FRAMEWORK-MIB, SNMP-TARGET-MIB, SNMPv2-CONF, SNMPv2-SMI, SNMPv2-TC, SNMPv2-TM, TRANSPORT-ADDRESS-MIB
MIBs to compile: OPENBSD-BASE-MIB
Destination format: pysnmp
Parser grammar cache directory: not used
Also compile all relevant MIBs: yes
Rebuild MIBs regardless of age: no
Dry run mode: no
Create/update MIBs: yes
Byte-compile Python modules: yes (optimization level no)
Ignore compilation errors: no
Generate OID->MIB index: no
Generate texts in MIBs: no
Keep original texts layout: no
Try various file names while searching for MIB module: yes
Created/updated MIBs: OPENBSD-BASE-MIB
Pre-compiled MIBs borrowed:
Up to date MIBs: OPENBSD-BASE-MIB, SNMPv2-CONF, SNMPv2-SMI, SNMPv2-TC
Missing source MIBs:
Ignored MIBs:
Failed MIBs:
(…)
je n’ai volontairement recopié que la sortie écran du premier fichier
Les lignes à vérifier sont :
- MIBs to compilequi nous montre quel fichier est compilé
- Created/updated MIBsqui nous restitue le nom du nouveau fichier compilé
- Ignored MIBset- Failed MIBsqui peut informer des informations MIB défectueuses ou ignorées
Une fois le traitement terminé, les nouveaux fichiers compilés ont été
créés dans : ~/.pysnmp/mibs/
Mais avant de (sa?)voir comment utiliser les fichiers MIB nouvellement
créés, voyons comment utiliser pysnmp dans le contexte de SNMPv3. 
Je m’attarderais très particulièrement sur la manière de l’utiliser avec
l’authentification forte.
Coding
Appelons l’outil :
from pprint import PrettyPrinter
from pysnmp.hlapi import *
from pysnmp.smi.view import MibViewController
pp = PrettyPrinter(indent=4)
Puis paramétrons les variables nécessaires pour l’authentification forte, à savoir :
host = "localhost"
user = "uenc"
authkey = "zx4pyrfyeu5x5c3kxqirhtsxksbmawju"
privkey = "XHVBzYUpP8dKns75BaSwq6t7SUgF6oMz"
j’ai repris celles de l’exemple, dans l’article sur l’outil natif à OpenBSD, snmp , ni plus ni moins.
SNMP Engine, MIB View Controller
Une des premières choses à déclarer est le Contrôleur de Vue MIB, qui nécessite la création d’un moteur SNMP :
# create SNMP Engine and MIB view Controller
se = SnmpEngine()
mvc = se.getUserContext('mibViewController')
if not mvc:
   mvc = MibViewController(se.getMibBuilder())
Et, maintenant, nous allons voir comment appeler les MIB d’OpenBSD !
OID + MIB
# get Object Identity and Type
oi = ObjectIdentity('iso.org.dod.internet.private.enterprises.openBSD.memMIBObjects')
oi.addMibSource('~/.pysnmp/mibs/')
oi.loadMibs('OPENBSD-BASE-MIB')
oi.loadMibs('OPENBSD-CARP-MIB')
oi.loadMibs('OPENBSD-MEM-MIB')
oi.loadMibs('OPENBSD-PF-MIB')
oi.loadMibs('OPENBSD-RELAYD-MIB')
oi.loadMibs('OPENBSD-SENSORS-MIB')
oi.loadMibs('OPENBSD-SNMPD-CONF')
oi.resolveWithMib(mvc)
- ObjectIdenttity(): en premier, nous construisons un objet identifiant, selon un OID précis que nous recherchons - ici le nombre d’interfaces vues par la MIB PF d’OpenBSD
- addMibSource(): référence le chemin où ont été créé les fichiers MIB précédemment
- loadMibs(): pour appeler chacun des fichiers MIB créés précédemment- pour info, selon l’OID recherché, il n’est pas forcément nécessaire de toutes les charger -
 
- resolvedWithMib(): nous permet d’appliquer le Contrôleur de Vue MIB sur l’objet
Continuons avec la gestion des données utilisateurs nécessaires à l’identification :
USM User Data
uud = UsmUserData(user, authKey=authkey, privKey=privkey,
            authProtocol=usmHMAC384SHA512AuthProtocol,
            privProtocol=usmAesCfb128Protocol)
Pour information, les différentes valeurs du protocole de chiffrement d’authentification sont :
- usmNoAuthProtocolpour aucun protocol
- usmHMACMD5AuthProtocolpour le chiffrement- MD5
- usmHMACSHAAuthProtocolpour- SHA
- usmHMAC128SHA224AuthProtocolpour- SHA-224
- usmHMAC192SHA256AuthProtocolpour- SHA-256
- usmHMAC256SHA384AuthProtocolpour- SHA-384
- usmHMAC384SHA512AuthProtocolpour- SHA-512
Concernant le chiffrement du protocole de confidentialité, ces valeurs sont :
- usmNoPrivProtocolsi aucun
- usmDESPrivProtocolpour- DES
- usmAesCfb128Protocolpour- AES
(Pour information, il en existe d’autres, mais ce sont surtout des “drafts”, du moins pour l’instant !)
Générateur
Nous avons besoin de construire le générateur de la commande get :
gc = getCmd(se, uud, UdpTransportTarget((host, 161)), ContextData(),
    ObjectType(oi))
Retourner le résultat
# return results
errorIndication, errorStatus, errorIndex, varBinds = next(gc)
# Display informations
if errorIndication:
    print(str(errorIndication))
elif errorStatus:
    print('%s at %s' % (str(errorStatus.prettyPrint()),
        errorIndex and varBinds[int(errorIndex) - 1][0] or '?'))
else:
    for varBind in varBinds:
        oid = varBind[0]
        value = varBind[1]
        print(oid)
        print(value)
ne pas s’inquiéter du temps que mets la requête à s’afficher ; cela est dû au chiffrement des informations
L’exécution nous retourne ceci :
1.3.6.1.4.1.30155.5
Fin
Pour finir, nous venons de voir que discuter avec l’outil pysnmp sur SNMPv3 avec authentification forte EST possible.
Le plus délicat est de récupérer les informations dans les MIB. Trés vite,
vous allez avoir à buter sur des erreurs incompréhensibles, et difficiles
à résoudre. 
Et, ça, ça le don de m’énerver ! (enfin presque…)
Remerciements
- J’ai beaucoup appris grâce à cet article, trouvé sur le site Makina Corpus.