--- categories: ['OpenBSD','Système','Réseau'] date: 2019-11-27T22:50:53+01:00 description: "pysnmp : outil Python pour SNMP ; utilisation sous OpenBSD, principalement v3 avec authentification forte" draft: false tags: ['OpenBSD','Python','Python3','SNMP'] title: "Pysnmp: outil Python pour SNMP (authPriv v3)" translationKey: 'openbsd-pysnmp' --- ## Description **pysnmp** est une librairie en Python, multiplateforme pour {{< abbr SNMP "Simple Network Management Protocol" >}}, 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, {{< inside2 l="sys/openbsd/pkg" t="Installez" a="installer" >}} 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 {{< abbr MIB "Management Information Base" >}} - *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/`. ```sh $ 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` et `Failed 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 : ```python3 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 : ```python3 host = "localhost" user = "uenc" authkey = "zx4pyrfyeu5x5c3kxqirhtsxksbmawju" privkey = "XHVBzYUpP8dKns75BaSwq6t7SUgF6oMz" ``` *j'ai repris celles de l'exemple, dans l'article sur l'outil natif à OpenBSD, {{< inside2 t="snmp" l="sys:openbsd:snmp" a="authentification-forte" >}}, 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** : ```python3 # 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 ```python3 # 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 ```python3 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 protocol * `usmHMACMD5AuthProtocol` pour le chiffrement `MD5` * `usmHMACSHAAuthProtocol` pour `SHA` * `usmHMAC128SHA224AuthProtocol` pour `SHA-224` * `usmHMAC192SHA256AuthProtocol` pour `SHA-256` * `usmHMAC256SHA384AuthProtocol` pour `SHA-384` * `usmHMAC384SHA512AuthProtocol` pour `SHA-512` Concernant le chiffrement du protocole de confidentialité, ces valeurs sont : * `usmNoPrivProtocol` si aucun * `usmDESPrivProtocol` pour `DES` * `usmAesCfb128Protocol` pour `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` : ```python3 gc = getCmd(se, uud, UdpTransportTarget((host, 161)), ContextData(), ObjectType(oi)) ``` ### Retourner le résultat ```python3 # 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 : ```python3 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](https://makina-corpus.com/blog/metier/2016/initiation-a-snmp-avec-python-pysnmp-partie2), trouvé sur le site **Makina Corpus**. ---