Pour faire suite au très bon post de Kamel sur les REST APIs, disponible ici, je souhaitais faire un petit focus sur les APIs disponibles sur ArubaOS-Switch.
Depuis la disponibilité de la version 16.xx d’AOS-Switch, de nombreuses API sont disponibles, notamment au travers d’URI spécifiques, comme par exemple pour la gestion de VLANs, la récupération d’informations systèmes, etc…
Cependant, depuis la publication de la dernière release d’AOS-Switch (16.04), , qui est publique depuis fin juillet, d’importantes fonctionnalités liées aux API ont été mises en place, et notamment :
- Le support des API dans des environnements stackés ou virtualisés avec VSF, démocratisant ainsi l'usage de ces interfaces de programmation à tous les types d'environnements.
- La disponibilité d’AnyCLI, permettant d’envoyer n’importe quelle commande CLI via un requête API.
- La disponibilité de Batch_CLI, permettant d’envoyer jusqu’à 300 lignes de commandes au travers d’une seule requête API, ce qui peut être extrêmement pratique dans le cadre d’une gestion de templates, de déploiement de nouveau service, ou d’automatisation de manière générale.
Ce post est donc là pour présenter les étapes de configuration des switchs compatibles, mais également des exemples d’API sur AOS-Switch, que ce soit au travers de POSTMAN ou de Python, qui est un des languages les plus utilisés, notamment dans l'automatisation réseau.
Généralités sur les API dans ArubaOS-Switch
Comme décrit précédemment, les équipements ArubaOS-Switch supportent les API depuis la parution des premières releases 16.xx.
Elles sont parties intégrantes de l’un des piliers stratégiques d’Aruba, qui consiste à rendre nos solutions extrêmement ouvertes, interopérables dans un contexte SI globale, et programmables.

L’utilisation des API dans les environnements filaires permet donc :
- De pouvoir réduire drastiquement les temps d’exploitation, en simplifiant et automatisant les tâches au maximum, que ce soit pour la visualisation d'informations, pour configurer un élément, tels un VLAN, une IP, une route, voire pour gérer un change de configuration ou déployer un service fonctionnel complet.
- De réduire très fortement les erreurs de configuration.
- D'avoir des configurations homogènes sur l'ensemble des équipements, puisque ce sont les mêmes lignes de commandes qui seront tout le temps utilisées.
Les API utilisées sur les équipements ArubaOS-Switch sont basées sur l’architecture RESTful, utilisant JSON comme format d’échange.

L'utilisation de ces API peut être effectuées directement via des solutions tierces qui possèdent un client API, ou via l'utilisation de scripts/interfaces développés pour des besoins propres, comme par exemple avec Python, YAML, Golang ou PHP.
Au sein des équipements ArubaOS-Switch, plusieurs versions peuvent être utilisées, en commençant par la version 1, jusqu’à la dernière qui est la version 3. Chaque version supporte les fonctionnalités/URI des versions précédentes, plus certaines améliorations.
Vous pouvez choisir la version que vous souhaitez utiliser en modifiant la version dans l’URI :
- Utilisation de la version 1 : http(s)://IP/rest/v1/
- Utilisation de la version 2 : http(s)://IP/rest/v2/
- Utilisation de la version 3 : http(s)://IP/rest/v3/
De très nombreuses ressources, et donc actions, sont disponibles au travers des API sur ArubaOS-Switch. En effet, il est par exemple possible de :
- Récupérer un grand nombre d’informations systèmes, comme le status, la CPU, la mémoire, le storage, la liste des transceivers, voire même de redémarrer l’équipement
- Visualiser, créer, modifier, supprimer des VLAN, les adressages IP ou les routes
- Visualiser, créer ou modifier les aspects authentification, incluant les Radius
- Visualiser, créer, modifier, supprimer les aspects ACL ou QoS
- Visualiser, créer ou modifier les configurations DHCP Relay, DNS, SNMP, LACP, PoE ou Mirroring
- Visualiser, créer ou modifier les configurations IP SLA
- Utiliser des services comme Ping ou Traceroute
- Récupérer des logs de debug ou Syslog.
- Visualiser, créer, modifier, supprimer des services Aruba, comme ArubaVPN ou Smart Rate.
- Faire des transferts de fichiers, par exemple pour mettre à jour un équipement ou lui changer sa startup configuration
Quelques éléments importants sont à prendre en considération sur la gestion des API sur ArubaOS-Switch :
- Par défaut, les requêtes de type GET sont ouvertes, sans authentification. Il est nécessaire d’avoir un compte de type "operator" pour verrouiller l’accès à ces requêtes.
- Par défaut, les requêtes de type POST, DELETE ou PUT sont quant à elles fermées. Une authentification, et donc l’obtention d’un cookie de session, est obligatoire. Un compte de type "Manager" est nécessaire.
- Les switchs ArubaOS-Switch ne possèdent pas d’API client. Il n’est donc pas possible d’initier des requêtes à partir des switchs.
- Il existe un nombre limité de sessions simultanées (Maximum 5). Il est donc (fortement) conseillé de fermer les sessions lorsque vos requêtes sont terminées, afin de ne pas laisser de sessions en idle.
Configuration des switchs ArubaOS compatibles.
Tout d’abord, il est important de mentionner que seuls les équipements suivants supportent l’intégralité des fonctions présentées ici :
- 5400R
- 3810
- 3800
- 2920
- 2930F/M
- 2540
- 2530
Afin de pouvoir utiliser les API, 3 étapes sont requises :
Activation de l’interface REST
Afin d'activer l'interface REST, une seule ligne de commande suffit :
2930F-Demo(config)# rest-interface
Il est à noter qu’il est possible de personnaliser l’Idle Time-Out des sessions ouvertes, avec la commande suivante :
2930F-Demo(config)# rest-interface session-idle-timeout
Activation du Web Management
Les requêtes REST étant basées sur des requêtes HTTP et/ou HTTPS, il est donc nécessaire d’activer le Web Management sur les équipements cibles.
Cette opération est réalisée de la manière suivante :
2930F-Demo(config)# aaa authentication web login local
2930F-Demo(config)# aaa authentication web enable local
Pourquoi seulement "local" ? Parce qu’à ce jour, seuls des utilisateurs locaux peuvent être utilisés pour s’authentifier auprès du moteur REST. Une authentification RADIUS ou TACACS n’est pour l’instant pas supportée.
Si HTTPS est un pré-requis dans le cadre de la mise en place d’un management Web, alors il est nécessaire d’activer ssl.
La ligne de commande ci-dessus implique qu'un certificat est déjà présent sur l'équipement, que ce soit importé ou self-signed.
2930F-Demo(config)# web-management ssl
Rappel, pour désactiver l'interface HTTP uniquement :
2930F-Demo(config)# no web-management plaintext
Une fois que tout ceci est réalisé, vous pouvez vérifier la bonne configuration au travers de la commande "show rest-interface", comme dans l’exemple ci-dessous :
2930F-Demo# show rest-interface
REST Interface - Server Configuration
REST Interface : Enabled
REST Operational Status : Up
REST Session Idle Timeout : 7200 seconds
HTTP Access : Enabled
HTTPS Access : Enabled
SSL Port : 443
Sécurisation des accès
Comme décrit précédemment, par défaut, les requêtes GET peuvent être réalisées sans authentification.
Pour des raisons évidentes de sécurité, il est nécessaire d’activer une authentification, même sur les simples requêtes GET. Pour cela, un utilisateur de type "Operator" sera utilisé pour sécuriser ces requêtes.
L’utilisateur de type "Manager" sera quant à lui utilisé pour sécuriser les requêtes de type POST, DELETE ou PUT.
Si des utilisateurs locaux doivent être créés, dans ce cas il faut utiliser les commandes suivantes :
2930F-Demo(config)# password manager user-name <user> plaintext <password>
2930F-Demo(config)# password operator user-name <user> plaintext <password>
Dans l'exemple, ci-dessous le mot de passe est tapé en "plaintext" (Mais n'apparaît pas dans la configuration de l'équipement).
Il est possible de les insérer en SHA-1 ou SHA-256, mais il faudra auparavant les convertir de Plaintext vers SHA-1 ou SHA-256 via un convertisseur externe.
Attention : Un utilisateur de type "Manager" ne peut pas à lui tout seul sécuriser l’ensemble des requêtes (GET/POST/DELETE/PUT). Pour les requêtes GET, un utilisateur de type "Operator" doit avoir été créé.
Cependant, une fois que l'accès aux requêtes GET a été sécurisée par la création d'un utilisateur de type "Operator", un "Manager" a accès à tout.
Environnement de test
L’environnement suivant a été utilisé pour les exemples décrits ci-dessous :
- Switch : Aruba 2930F, en standalone ou en VSF. Les équipements sont en 16.04.0008.
- IDE : PyCharm Community Edition 2017
- Python : Version 3.6, avec les packages "requests", "json" et "base64". La version 2.x est également fonctionnelle. Certains ajustements de code doivent être réalisés sur les exemples suivants afin de les porter en Python 2.x.
- POSTMAN : Installé comme application dans Google Chrome.

Chaque script Python commence par les éléments suivants :
import requests
import base64
import json
Gestion des sessions REST sur ArubaOS-Switch
Comme vous avez pu le voir dans les exemples ci-dessus, il est avant tout nécessaire d’ouvrir une session avant de pouvoir réaliser n'importe quelle requête, notamment ce qui demande des droits en écriture, comme les POSTS, DELETE ou PUT. Dès lors qu’une session est ouverte, un cookie est délivré et devra être utilisé dans les requêtes suivantes. C’est ce qui permettra d’authentifier la requête.
Afin d’obtenir un cookie de session (ou "SessionID"), une première requête de type POST doit être adressée à une URI spécifique : "/rest/v3/login-sessions", avec le nom d’utilisateur et le mot de passe de l'utilisateur dans le corps de la requête.
Voici un exemple avec POSTMAN :
La réponse à cette requête contient bien une valeur "cookie", et le Status Code retourné est de valeur 201, correspondant à "Created".
C’est cette valeur "Cookie" qui doit par la suite être utilisée dans l’entête de toutes vos requêtes.
Voici un exemple de récupération du cookie de session en Python :
# L'URI est inscrit dans une variable
url_login = "http://IP/rest/v3/login-sessions"
# On crée un dictionnaire dans lequel on positionne les valeurs souhaitées
payload_login = {
"userName" : "votre_user",
"password" : "votre_password"
}
# On utilise le package "requests" pour lancer la requête - Le dictionnaire est converti en JSON et positionné dans le corps de la requête
get_cookie = requests.post(url_login, data=json.dumps(payload_login))
# On récupère la valeur de la clé "cookie", une fois la réponse décodée.
cookie = get_cookie.json()['cookie']
# On positionne le cookie dans un nouveau dictionnaire qui sera notre futur entête
headers = {"Cookie" : cookie}
Attention : La casse dans les clés des dictionnaires est très importante. Bien utiliser la valeur "userName".
Afin de supprimer une session en cours, il suffit de faire un DELETE sur cette même URI, avec le cookie présent dans l’entête.
En Python :
delete_session = requests.delete(url_login,headers=header)
Le code 204 doit vous être retourné si la requête s’est bien passée.
Requête sur une URI spécifique
Requête GET
Dans cette exemple, nous allons simplement faire un GET simple afin de récupérer et visualiser la liste des VLAN présents sur l’équipement cible
Pour se faire, et comme indiqué précédemment, il suffit de 2 éléments pour faire cette requête :
- Le cookie de session, intégré dans l’entête de notre requête
- L’URI spécifique, qui nous renverra les valeurs attendues.
Voici un exemple avec POSTMAN :

Voici le même exemple, avec Python (hors phase d’authentification) :
# l'URI est positionnée dans une variable
url_vlans = "https://IP/rest/v3/vlans"
# On lance la requête, avec le header créé
get_vlans = requests.get(url_vlans, headers=header, verify=False)
# On boucle pour récupérer l'ensemble des valeurs de la clé "vlan_id"
for vlan in get_vlans.json()['vlan_element']:
print(vlan['vlan_id'])
Et le résultat associé :
Lorsque la requête est un succès, le Status Code de la réponse doit être de type 200 – "OK"
Requête POST
Dans cette exemple, nous allons simplement faire un POST afin de créer un nouveau VLAN sur l’équipement cible, ainsi que le nom associé.
Pour se faire, il suffit de 3 éléments pour faire cette requête :
- Le cookie de session, intégré dans l’entête de notre requête
- L’URI spécifique, auprès de laquelle on va créer les valeurs, et qui nous renverra le contenu qui a été créé.
- Le contenu du corps de la requête, au format JSON, qui contient les valeurs à créer.
Voici un exemple avec POSTMAN :

Voici le même exemple, avec Python (hors phase d’authentification) :
# L'URI est positionné dans une variable
url_vlan = "http://IP/rest/v3/vlans"
# On crée un nouveau dictionnaire avec les valeurs à envoyer au switch pour la création du nouveau VLAN
payload_vlan = {
"vlan_id" : 1001,
"name": "DemoAPIAH"
}
# On lance la requête, avec le dictionnaire convertit en JSON, et le header de session
config_vlan = requests.post(url_vlan, data=json.dumps(payload_vlan), headers=header)
Et le résultat associé :
Lorsque la requête est un succès, le Status Code de la réponse doit être de type 201 – "Created"
Nouveauté 16.04 : API via AnyCLI et Batch_CLI
Nota : Les fonctions AnyCLI et Batch_CLI ne sont accessibles qu’au travers de la version 3 des API.
Il est donc nécessaire d’utiliser "/rest/v3/" dans les URI.
AnyCLI
Comme évoqué dans l’introduction de ce post, la version 16.04 apporte des nouveautés très intéressantes sur la gestion des API, et notamment la fonction AnyCLI.
AnyCLI permet de pouvoir envoyer n’importe quelle commande CLI via une simple requête API.

Ceci permet donc, par exemple, de pouvoir très facilement envoyer des lignes de commandes CLI vers de très nombreux équipements, en un seul clic, et sans prendre la main manuellement sur les équipements.
C’est donc un énorme gain de temps, que ce soit en termes de temps d’exécution, car on peut imaginer que la liste des équipements est déjà inscrite dans un fichier qui sera lu par le script, mais également de réduction des erreurs.
Cela permet également de pouvoir récupérer ou créer des éléments qui ne sont pas disponibles dans les URI prédéterminées.
Mode de fonctionnement
AnyCLI utilise une URI spécifique afin de recevoir les commandes : http(s)://IP/rest/v3/cli
Le switch reçoit la commande dans le corps de la requête, traite la commande, et renvoie le résultat dans la réponse.
La réponse est encodée en base64. Il faut donc décoder de base-64 en utf-8, afin d’afficher un résultat propre.

Le JSON doit comporter la clé "cmd", dont la valeur sera la ligne de commande que vous souhaitez utiliser :
{ "cmd" : "<votre_commande>" }
Le résultat de la commande est récupérable dans la clé :
{ "result_base64_encoded" : "<le_resultat_en_base64" }
Exemple
Voici un exemple directement avec Python :
# L'URI est positionnée dans une variable
url_cli = "http://IP/rest/v3/cli"
# On crée le dictionnaire avec la clé "cmd" et la valeur de la commande convertit en châine
data = {
"cmd": "show rest"
}
# On lance la requête avec le dictionnaire convertit en JSON et l'entête de session
post_cmd = requests.post(url_cli, data= json.dumps(data), headers=header)
# On récupère le résultat de la requête, qui est décodé de base64, puis décodé en utf-8
result_decode = base64.b64decode(post_cmd.json()['result_base64_encoded']).decode('utf-8')
Et voici le résultat, pour un "show rest", avec les différentes valeurs reçus et décodées :

Lorsque la requête est un succès, le Status Code de la réponse doit être de type 200 – "OK".
Comme évoqué précédemment, la commande CLI est envoyée et interprétée telle quelle par l’équipement. Il est donc évidemment possible également de passer des commandes "raccourcies", de manière identique à une prise en main via CLI classique :

Idem avec les erreurs de syntaxe :

Quasiment toutes les commandes CLI supportées par les équipements, que ce soit en visualisation, au travers de la commande "show", ou en configuration, par exemple pour créer un VLAN ou passer une commande d’activation d’une fonctionnalité particulières, sont disponibles.
Lors du passage d'une commande de configuration, il n'y aura pas de retour spécifique. La clé "result_base64_encoded" est retournée vide.
Le Status Code 200 est également renvoyée dans le cas où la requête s'est bien passée.
Seules quelques commandes, qui peuvent demander des validations utilisateurs (comme ("crypto key xxx"), réalisent des interactions dynamiques dans le terminal (comme "repeat") ne peuvent pas être passées.
La gestion du stacking ou de VSF n'est également pas possible.
Batch_CLI
Concernant Batch_CLI, cette nouvelle fonctionnalité, également introduite en 16.04, permet quant à elle d’envoyer jusqu’à 300 lignes de commandes en une seule requête.
Cela permet donc de pouvoir déployer un service complet, sur plusieurs équipements si besoin, au travers d’un seul clic, réduisant ainsi de manière drastique les temps de déploiements mais également les risques d'erreurs.
Il devient ainsi très facile de gérer un changement de configuration sur un port par exemple, ou de gérer de manière globale la mobilité des utilisateurs.
Mode de fonctionnement
Le mode de fonctionnement est assez similaire à celui d’AnyCLI.
La différence principale est que les commandes doivent être encodées en base64 avant envoi au switch.
Au même titre qu’AnyCLI, Batch_CLI utilise une URI spécifique afin de recevoir les commandes : http(s)://IP/rest/v3/cli_batch
Le switch reçoit la commande dans le corps de la requête, traite la commande, et renvoie le statut global au format JSON ("status" : "CBS_INITIATED")
La réponse est quant à elle renvoyée en clair.

Le JSON doit comporter la clé "cli_batch_base64_encoded", dont la valeur sera l'ensemble des lignes de commandes que vous souhaitez utiliser :
{ "cli_batch_base64_encoded" : <votre_template_en_base64> }
Exemple
Voici un exemple directement avec Python, qui permet de configurer totalement la partie OpenFlow pour un équipement donné :
# L'URI est positionnée dans une variable
url_cli = "http://IP/rest/v3/cli_batch"
# Les lignes de commandes sont positionnées dans une variable. Toutes les commandes sont séparées par un "
" pour indiquer un passage à la ligne, et donc une nouvelle commande.
commands = "openflow
controller-id 1 ip 10.10.10.201 controller-interface vlan 100
instance \"test\"
member vlan 800
version 1.3 only
limit software-rate 700
connection-interruption-mode fail-standalone
enable
exit
enable
exit"
# La variable est encodée en base64, après un passage en UTF-8.
encoded_data = base64.b64encode(commands.encode(‘utf-8’))
# On crée un dictionnaire qui contient la clé "cli_batch_base64_encoded". La valeur est décodée en UTF-8, pour éviter d'envoyer du binaire.
REST_JSON_DATA = {
"cli_batch_base64_encoded": encoded_data.decode(‘utf-8’)
}
# On lance la requête, avec le dictionnaire convertit en JSON dans le corps, et l'entête de session
post_cli = requests.post(url_cli, data=json.dumps(REST_JSON_DATA), headers=header)
Voici un extrait de la configuration de l’équipement avant déroulement du script de déploiement du service OpenFlow :
aaa port-access authenticator active
aaa port-access mac-based 1-2
vlan 1
name "DEFAULT_VLAN"
no untagged 6,10
On exécute maintenant le script de déploiement du service :

Et voici le même extrait de configuration après l’exécution du script :
aaa port-access authenticator active
aaa port-access mac-based 1-2
openflow
controller-id 1 ip 10.10.10.201 controller-interface vlan 100
instance "test"
member vlan 800
version 1.3 only
limit software-rate 700
connection-interruption-mode fail-standalone
exit
enable
exit
vlan 1
name "DEFAULT_VLAN"
no untagged 6,1
Lorsque la requête est un succès, le Status Code de la réponse doit être de type 202 – "Accepted"
Debugging
Des commandes de debug sont bien entendu disponibles, permettant de pouvoir troubleshooter plus facilement les éventuels problèmes lors de vos requêtes.
Pour se faire, 2 commandes sont nécessaires :
# Activation du debug pour REST
2930F-Demo# debug rest
# Affichage du debug en temps réel sur la console utilisée
2930F-Demo# debug destination session
En voici un exemple, qui reprend l’enchaînement suivant :
Création d'une session
Création d’un vlan au travers d’une requête POST sur l’URI spécifique

Suppression de la session en cours

Vous avez donc une visibilité en temps réel sur vos requêtes, et les éventuelles erreurs, comme dans l’exemple ci-dessous :

Et ensuite ?
Une fois que tout cela est expliqué, il serait bon d’avoir la liste des URI disponibles, afin de savoir quelles actions vous pouvez utiliser au travers de vos requêtes. Selon les équipements/logiciels, des interfaces graphiques, comme Swagger UI ou Spring REST Docs, sont disponibles afin de pouvoir avoir la liste des ressources disponibles au travers d’URI. Ce n’est malheureusement pas le cas sur les équipements ArubaOS-Switch.
Vous pouvez cependant retrouver l’ensemble de ces informations via le téléchargement d’une archive comprenant un descriptif de toutes les ressources disponibles.
Afin d’obtenir ce document, il faut se rendre sur la page de téléchargement de firmware de l’équipement souhaité, et dans la catégorie "Other", vous trouverez le fichier "REST API and JSON Schema" :

Un "ArubaOS-Switch REST API Guide" est également disponible. Il est récupérable sur le site du support HPE. Il suffit de se rendre dans la section "Manuals" de vos équipements, puis "User Guide".
Des videos sont également réalisées par Joe Neville, sur la mise en place d'un environement de developpement, et l'utilisation de scripts Python GET et POST sur nos équipements.
Elles sont disponibles sur la chaîne Youtube "ABC Networking"
Et tout ceci n'est qu'un aperçu des évolutions à venir et du potentiel de nos équipements sur des notions de programmabilité, mais également et surtout d'ArubaOS-CX, qui sera extrêmement orienté sur les API, Python et l'automatisation.
Et maintenant, Let's code :-)