---
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**.
---