Forum Français

 View Only
Expand all | Collapse all

How-to : REST API sur ArubaOS-Switch

This thread has been viewed 20 times
  • 1.  How-to : REST API sur ArubaOS-Switch

    Posted Aug 18, 2017 07:39 AM

    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.

     

    Aruba API.PNG

      

    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.

     

    rest base.png

    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.

     environnement.png

     

    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 :CREATE SESSIONS POSTMAN.PNG

     

    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 :

    1. Le cookie de session, intégré dans l’entête de notre requête
    2. L’URI spécifique, qui nous renverra les valeurs attendues. 

    Voici un exemple avec POSTMAN :

    GET POSTMAN with auth.PNG

     

     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é :get vlan python.PNG

    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 :

    1. Le cookie de session, intégré dans l’entête de notre requête
    2. L’URI spécifique, auprès de laquelle on va créer les valeurs, et qui nous renverra le contenu qui a été créé.
    3. Le contenu du corps de la requête, au format JSON, qui contient les valeurs à créer.

    Voici un exemple avec POSTMAN :

     

    POST VLAN POSTMAN - 2.PNG

     

    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é :post vlan python.PNG

    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.

     anycli.png

     

    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.

     schema anycli.png

    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 : 

     

    show rest python.PNG

     

    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 :

    show rest shortcut.PNG

     

    Idem avec les erreurs de syntaxe :

      

    show rest failure.PNG

     

    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.

     schema batch_cli.png

    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 :

     

    batch_cli_script.PNG

     

      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 sessiondebug open session.pngCréation d’un vlan au travers d’une requête POST sur l’URI spécifique
    debug post.png

    Suppression de la session en cours
    debug close session.png

     

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

    debug failure.png

     

    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" :
    hpe_support.png

     

    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 :-)



  • 2.  RE: How-to : REST API sur ArubaOS-Switch

    Posted Aug 22, 2017 03:58 AM

    Top ! Merci Arnaud !



  • 3.  RE: How-to : REST API sur ArubaOS-Switch

    Posted Aug 22, 2017 04:01 AM

    Merci Arnaud !

     

    a quand un Workshop sur le sujet ? ;-)



  • 4.  RE: How-to : REST API sur ArubaOS-Switch

    Posted Aug 22, 2017 05:46 AM

    Roadmap :-)