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 compile
qui nous montre quel fichier est compiléCreated/updated MIBs
qui nous restitue le nom du nouveau fichier compiléIgnored MIBs
etFailed MIBs
qui 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’OpenBSDaddMibSource()
: référence le chemin où ont été créé les fichiers MIB précédemmentloadMibs()
: 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 :
usmNoAuthProtocol
pour aucun protocolusmHMACMD5AuthProtocol
pour le chiffrementMD5
usmHMACSHAAuthProtocol
pourSHA
usmHMAC128SHA224AuthProtocol
pourSHA-224
usmHMAC192SHA256AuthProtocol
pourSHA-256
usmHMAC256SHA384AuthProtocol
pourSHA-384
usmHMAC384SHA512AuthProtocol
pourSHA-512
Concernant le chiffrement du protocole de confidentialité, ces valeurs sont :
usmNoPrivProtocol
si aucunusmDESPrivProtocol
pourDES
usmAesCfb128Protocol
pourAES
(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.