Faites fonctionner ACL de Cisco IOS-XE avec RESTCONF (version Python)

introduction

Il s'agit d'un mémo lors de la définition de l'ACL de Cisco IOS-XE à l'aide de RESTCONF parmi les protocoles de transport (NETCONF, RESTCONF, gRPC) utilisés dans la programmabilité pilotée par modèle. Il existe Postman, Python, Ansible, etc. comme outils d'opération, mais cette fois j'ai utilisé Python et effectué CRUD (créer, obtenir, mettre à jour, supprimer) sur l'ACL étendue nommée.

1. Présentation de RESTCONF

RESTCONF est un protocole basé sur HTTP (S) qui fournit une interface RESTFul. Outre XML, le format JSON est également pris en charge en tant que format de données (NETCONF est basé sur SSH et uniquement au format XML).

Fonctionnement CRUD RESTCONF / NETCONF

RESTCONF NETCONF
GET <get>, <get-config>
POST <edit-config> (operation="create")
PUT <edit-config> (operation="create/replace")
PATCH <edit-config> (operation="merge")
DELETE <edit-config> (operation="delete")

À l'origine, IOS prend également en charge l'API REST, mais alors que l'API REST est une implémentation spécifique au fournisseur, RESTCONF est un protocole standardisé dans la RFC8040 et est une entité distincte.

Un aperçu de la programmabilité basée sur les modèles, y compris RESTCONF, est résumé dans les sessions suivantes des DevNet Learning Labs. Introduction de la programmabilité basée sur les modèles

2. Environnement préparé

[Cet article](https://qiita.com/tech_kitara/items/4c201a83f1f9286d002b#2-%E7%94%A8%E6%84%8F%E3%81%97%E3%81%9F%E7%92 Comme pour% B0% E5% A2% 83), nous avons utilisé l'environnement Cisco dCloud. Le périphérique cible utilisé était "CSR1000v avec IOS XE 16.08" et la version Python du client était "3.6.8".

3. Créer une ACL

Tout d'abord, ajoutez une ligne du nom ACL TEST à partir de l'état où il n'y a pas de paramètre ACL.

3-1. Code Python

Une demande est faite à URL https: // [adresse IP]: [numéro de port] / restconf / data / Cisco-IOS-XE-native: native / ip / access-list en utilisant la méthode PUT. Les données dans Body sont définies au format JSON. Au fait, il n'a pas pu être créé par la méthode POST.

create_acl.py


#!/usr/bin/python
import requests
import json

# disable warnings from SSL/TLS certificates
requests.packages.urllib3.disable_warnings()

# credentials for CSR1000v
HOST = '[adresse IP]'
PORT = 443  #Dépend de l'environnement
USER = '[Nom d'utilisateur]'
PASS = '[mot de passe]'


def main():
    # url string to issue request
    url = "https://{h}:{p}/restconf/data/Cisco-IOS-XE-native:native/ip/access-list".format(h=HOST, p=PORT)

    # RESTCONF media types for REST API headers
    headers = {'Content-Type': 'application/yang-data+json',
               'Accept': 'application/yang-data+json'}

    # RESTCONF doby for new ACL
    body_data = {
                    "Cisco-IOS-XE-native:access-list": {
                        "Cisco-IOS-XE-acl:extended": [
                            {
                                "name": "TEST",
                                "access-list-seq-rule": [
                                    {
                                        "sequence": "30",
                                        "ace-rule": {
                                            "action": "permit",
                                            "protocol": "ip",
                                            "ipv4-address": "192.168.4.0",
                                            "mask": "0.0.0.255",
                                            "dest-ipv4-address": "192.168.100.0",
                                            "dest-mask": "0.0.0.255"
                                            }
                                        }
                                    ]
                                }
                            ]
                        }
                    }

    # this statement performs a PUT on the specified url
    response = requests.put(url, auth=(USER, PASS),
                            headers=headers, data=json.dumps(body_data), verify=False)

    # print the json that is returned
    print(response)

if __name__ == '__main__':
    main()

3-2. Résultat de l'exécution

Le code d'état 204 (aucun contenu) est renvoyé.

$ python create_acl.py
<Response [204]>

En regardant la configuration, l'ACL a été créée comme prévu.

csr1#sh run | begin TEST
ip access-list extended TEST
 permit ip 192.168.4.0 0.0.0.255 192.168.100.0 0.0.0.255

4. Obtenez ACL

Ensuite, essayez d'obtenir les informations de l'ACL créée avec RESTCONF.

4-1. Code Python (1) Obtenir les paramètres IP

À l'exception de la fonction main (), c'est la même chose qu'en 3., ce qui suit est un extrait. Tout d'abord, pour URL https: // [adresse IP]: [numéro de port] / restconf / data / Cisco-IOS-XE-native: native / ip, obtenez les informations de configuration relatives à l'IP avec la méthode GET. Je l'ai essayé.

get_ip_info.py


def main():
    # url string to issue request
    url = "https://{h}:{p}/restconf/data/Cisco-IOS-XE-native:native/ip".format(h=HOST, p=PORT)

    # RESTCONF media types for REST API headers
    headers = {'Content-Type': 'application/yang-data+json',
               'Accept': 'application/yang-data+json'}

    # this statement performs a GET on the specified url
    response = requests.get(url, auth=(USER, PASS),
                            headers=headers, verify=False)

    # print the json that is returned
    print(response.text)

4-2. Résultat de l'exécution (1) Acquisition des paramètres IP

Au milieu de "access-list": {"Cisco-IOS-XE-acl: extended": [~]} , j'ai pu confirmer les paramètres. D'ailleurs, avant de paramétrer ACL, il n'a pas été créé avec cette clé " access-list ". Par conséquent, lors de la création 3., même si vous METTEZ soudainement "" Cisco-IOS-XE-acl: extended ": [~] dans la hiérarchie inférieure, une erreur s'est produite.

$ python get_ip_info.py
{
  "Cisco-IOS-XE-native:ip": {
    "domain": {
      "name": "demo.dcloud.cisco.com"
    },
    "forward-protocol": {
      "protocol": "nd"
    },
    "route": {
      "ip-route-interface-forwarding-list": [
        {
          "prefix": "0.0.0.0",
          "mask": "0.0.0.0",
          "fwd-list": [
            {
              "fwd": "GigabitEthernet1",
              "interface-next-hop": [
                {
                  "ip-address": "198.18.128.1"
                }
              ]
            }
          ]
        }
      ]
    },
    "ssh": {
      "rsa": {
        "keypair-name": "ssh-key"
      },
      "version": 2
    },
    "access-list": {
      "Cisco-IOS-XE-acl:extended": [
        {
          "name": "TEST",
          "access-list-seq-rule": [
            {
              "sequence": "30",
              "ace-rule": {
                "action": "permit",
                "protocol": "ip",
                "ipv4-address": "192.168.4.0",
                "mask": "0.0.0.255",
                "dest-ipv4-address": "192.168.100.0",
                "dest-mask": "0.0.0.255"
              }
            }
          ]
        }
      ]
    },
    "Cisco-IOS-XE-http:http": {
      "authentication": {
        "local": [null]
      },
      "server": true,
      "secure-server": true
    }
  }
}

4-3. Code Python (2) Obtenir les paramètres ACL étendus

Il s'agit d'une URL de hiérarchie plus profonde https: // [adresse IP]: [numéro de port] / restconf / data / Cisco-IOS-XE-native: native / ip / access-list / extended, ACL étendue uniquement Est un exemple pour obtenir une précision.

get_acl.py


def main():
    # url string to issue request
    url = "https://{h}:{p}/restconf/data/Cisco-IOS-XE-native:native/ip/access-list/extended".format(h=HOST, p=PORT)

    # RESTCONF media types for REST API headers
    headers = {'Content-Type': 'application/yang-data+json',
               'Accept': 'application/yang-data+json'}

    # this statement performs a GET on the specified url
    response = requests.get(url, auth=(USER, PASS),
                            headers=headers, verify=False)

    # print the json that is returned
    print(response.text)

4-4. Résultat de l'exécution (2) Acquisition des paramètres ACL étendus

$ python get_acl.py
{
  "Cisco-IOS-XE-acl:extended": [
    {
      "name": "TEST",
      "access-list-seq-rule": [
        {
          "sequence": "30",
          "ace-rule": {
            "action": "permit",
            "protocol": "ip",
            "ipv4-address": "192.168.4.0",
            "mask": "0.0.0.255",
            "dest-ipv4-address": "192.168.100.0",
            "dest-mask": "0.0.0.255"
          }
        }
      ]
    }
  ]
}

5. Fusion d'ACL

Voici un exemple d'ajout d'une entrée (ACE) et d'ajout d'une autre ACL à une ACL existante.

5-1. Code Python (1) Ajouter une entrée

Essayez d'ajouter une entrée à la deuxième ligne du nom ACL existant TEST. Cette fois, "50" est spécifié pour le numéro de séquence "30". En passant, si vous ne spécifiez pas le numéro de séquence, vous ne pouvez pas le définir en raison d'une erreur. En utilisant PATCH, qui est une méthode de fusion, les paramètres existants sont laissés tels quels et le contenu du corps est ajouté.

merge_ace.py


def main():
    # url string to issue request
    url = "https://{h}:{p}/restconf/data/Cisco-IOS-XE-native:native/ip/access-list".format(h=HOST, p=PORT)

    # RESTCONF media types for REST API headers
    headers = {'Content-Type': 'application/yang-data+json',
               'Accept': 'application/yang-data+json'}

    # RESTCONF doby for new ACL
    body_data = {
                    "Cisco-IOS-XE-native:access-list": {
                        "Cisco-IOS-XE-acl:extended": [
                            {
                                "name": "TEST",
                                "access-list-seq-rule": [
                                    {
                                        "sequence": "50",
                                        "ace-rule": {
                                            "action": "permit",
                                            "protocol": "ip",
                                            "ipv4-address": "192.168.5.0",
                                            "mask": "0.0.0.255",
                                            "dest-ipv4-address": "192.168.100.0",
                                            "dest-mask": "0.0.0.255"
                                            }
                                        }
                                    ]
                                }
                            ]
                        }
                    }

    # this statement performs a PUT on the specified url
    response = requests.patch(url, auth=(USER, PASS),
                            headers=headers, data=json.dumps(body_data), verify=False)

    # print the json that is returned
    print(response)

5-2. Résultat de l'exécution (1) Ajout d'une entrée

Le code d'état 204 (aucun contenu) est renvoyé.

$ python merge_ace.py
<Response [204]>

En regardant Config, il a été ajouté à la deuxième ligne comme prévu.

csr1#sh run | begin TEST
ip access-list extended TEST
 permit ip 192.168.4.0 0.0.0.255 192.168.100.0 0.0.0.255
 permit ip 192.168.5.0 0.0.0.255 192.168.100.0 0.0.0.255

5-3. Code Python (2) Ajouter une autre ACL

Ajoutons maintenant une autre ligne de nom ACL TEST2.

merge_another_acl.py


def main():
    # url string to issue request
    url = "https://{h}:{p}/restconf/data/Cisco-IOS-XE-native:native/ip/access-list".format(h=HOST, p=PORT)

    # RESTCONF media types for REST API headers
    headers = {'Content-Type': 'application/yang-data+json',
               'Accept': 'application/yang-data+json'}

    # RESTCONF doby for new ACL
    body_data = {
                    "Cisco-IOS-XE-native:access-list": {
                        "Cisco-IOS-XE-acl:extended": [
                            {
                                "name": "TEST2",
                                "access-list-seq-rule": [
                                    {
                                        "sequence": "70",
                                        "ace-rule": {
                                            "action": "permit",
                                            "protocol": "ip",
                                            "ipv4-address": "192.168.7.0",
                                            "mask": "0.0.0.255",
                                            "dest-ipv4-address": "192.168.100.0",
                                            "dest-mask": "0.0.0.255"
                                            }
                                        }
                                    ]
                                }
                            ]
                        }
                    }

    # this statement performs a PUT on the specified url
    response = requests.patch(url, auth=(USER, PASS),
                            headers=headers, data=json.dumps(body_data), verify=False)

    # print the json that is returned
    print(response)

5-4. Résultat de l'exécution (2) Ajouter une autre ACL

$ python merge_another_acl.py
<Response [204]>

Vous pouvez voir que le nom ACL TEST2 a été ajouté.

csr1#sh run | begin TEST
ip access-list extended TEST
 permit ip 192.168.4.0 0.0.0.255 192.168.100.0 0.0.0.255
 permit ip 192.168.5.0 0.0.0.255 192.168.100.0 0.0.0.255
ip access-list extended TEST2
 permit ip 192.168.7.0 0.0.0.255 192.168.100.0 0.0.0.255

6. Remplacement de l'ACL

Cette fois, c'est un exemple d'écrasement d'une ACL existante et de création d'un autre nom d'ACL TEST3. Je pense que c'est un cas où le travail normal d'ACL n'est fondamentalement pas effectué (un accident majeur se produira s'il est fait par inadvertance). Cependant, à part les paramètres ACL, il peut être défini comme un type déclaratif basé sur la feuille de paramètres, tel que "Le paramètre de ... devrait être XX", je pense donc qu'il y a un avantage à le définir sans avoir à supprimer les paramètres existants. Je vais.

6-1. Code Python

La méthode utilise PUT comme lors de la création d'un nouveau.

replace_acl.py


def main():
    # url string to issue request
    url = "https://{h}:{p}/restconf/data/Cisco-IOS-XE-native:native/ip/access-list".format(h=HOST, p=PORT)

    # RESTCONF media types for REST API headers
    headers = {'Content-Type': 'application/yang-data+json',
               'Accept': 'application/yang-data+json'}

    # RESTCONF doby for new ACL
    body_data = {
                    "Cisco-IOS-XE-native:access-list": {
                        "Cisco-IOS-XE-acl:extended": [
                            {
                                "name": "TEST3",
                                "access-list-seq-rule": [
                                    {
                                        "sequence": "90",
                                        "ace-rule": {
                                            "action": "permit",
                                            "protocol": "ip",
                                            "ipv4-address": "192.168.9.0",
                                            "mask": "0.0.0.255",
                                            "dest-ipv4-address": "192.168.100.0",
                                            "dest-mask": "0.0.0.255"
                                            }
                                        }
                                    ]
                                }
                            ]
                        }
                    }

    # this statement performs a PUT on the specified url
    response = requests.put(url, auth=(USER, PASS),
                            headers=headers, data=json.dumps(body_data), verify=False)

    # print the json that is returned
    print(response)

6-2. Résultat de sortie

$ python replace_acl.py
<Response [204]>

Il a été écrasé avec succès.

csr1#sh run | begin TEST
ip access-list extended TEST3
 permit ip 192.168.9.0 0.0.0.255 192.168.100.0 0.0.0.255

En passant, selon la personne qui a écrit l'article suivant, dans le cas de NX-OS, il y a des cas où la méthode PUT ne répond pas aux spécifications de la RFC8040 et est fusionnée comme la méthode PATCH. Exploring IOS-XE and NX-OS based RESTCONF Implementations with YANG and Openconfig

7. Supprimer l'ACL

Enfin, essayez de supprimer l'ACL créée. Exécutez «3. Création d'ACL» et «5. Fusion d'ACL» à l'avance pour écraser «TEST3» et laisser «TEST» et «TEST2» définis.

csr1#sh run | begin TEST
ip access-list extended TEST
 permit ip 192.168.4.0 0.0.0.255 192.168.100.0 0.0.0.255
 permit ip 192.168.5.0 0.0.0.255 192.168.100.0 0.0.0.255
ip access-list extended TEST2
 permit ip 192.168.7.0 0.0.0.255 192.168.100.0 0.0.0.255

7-1. Code Python

Faites une demande à URL https: // [adresse IP]: [numéro de port] / restconf / data / Cisco-IOS-XE-native: native / ip / access-list / extended = TEST2 avec la méthode DELETE Je le ferai. Vous pouvez supprimer TEST2 sur une base par ACL en spécifiant / extended = TEST2 à la fin de l'URL. (Je ne savais pas comment supprimer chaque entrée.)

delete_acl.py


def main():
    # url string to issue request
    url = "https://{h}:{p}/restconf/data/Cisco-IOS-XE-native:native/ip/access-list/extended=TEST2".format(h=HOST, p=PORT)

    # RESTCONF media types for REST API headers
    headers = {'Content-Type': 'application/yang-data+json',
               'Accept': 'application/yang-data+json'}

    # this statement performs a DELETE on the specified url
    response = requests.delete(url, auth=(USER, PASS),
                            headers=headers, verify=False)

    # print the json that is returned
    print(response)

7-2. Résultat de l'exécution

$ python delete_acl.py
<Response [204]>

«TEST2» a été supprimé.

csr1#sh run | begin TEST
ip access-list extended TEST
 permit ip 192.168.4.0 0.0.0.255 192.168.100.0 0.0.0.255
 permit ip 192.168.5.0 0.0.0.255 192.168.100.0 0.0.0.255

finalement

Il n'y avait pas encore beaucoup d'exemples de codes sur Internet, alors je l'ai essayé. Dans l'article précédent, ACL Config a été généré en combinant le matériel d'exigence et le modèle complexe Jinja2, mais avec RESTCONF, il peut être défini en convertissant les informations de paramètre telles que le matériel d'exigence au format JSON, de sorte qu'il est automatisé. Je pense que ça va bien avec. Cette fois, c'était un exemple de Python, mais j'aimerais résumer un exemple en utilisant les modules restconf_get et restconf_config d'Ansible et comment vérifier et créer un modèle (URL) pour chaque élément de réglage.

Recommended Posts

Faites fonctionner ACL de Cisco IOS-XE avec RESTCONF (version Python)
Manipulation des fichiers EAGLE .brd avec Python
Cisco Catalyst IOS-Python et Bash sur XE
Surveillance des appareils effectuée par Python On-box de IOS-XE
Premier YDK à essayer avec Cisco IOS-XE
FizzBuzz en Python3
Grattage avec Python
Statistiques avec python
Grattage avec Python
Twilio avec Python
Intégrer avec Python
Jouez avec 2016-Python
AES256 avec python
Testé avec Python
python commence par ()
avec syntaxe (Python)
Bingo avec python
Zundokokiyoshi avec python
Excel avec Python
Micro-ordinateur avec Python
Cast avec python
Communication série avec Python
Django 1.11 a démarré avec Python3.6
Jugement des nombres premiers avec Python
Python avec eclipse + PyDev.
Communication de socket avec Python
Analyse de données avec python 2
Grattage en Python (préparation)
Essayez de gratter avec Python.
Apprendre Python avec ChemTHEATER 03
"Orienté objet" appris avec python
Exécutez Python avec VBA
Manipuler yaml avec python
Résolvez AtCoder 167 avec python
Communication série avec python
[Python] Utiliser JSON avec Python
Apprendre Python avec ChemTHEATER 05-1
Apprenez Python avec ChemTHEATER
Exécutez prepDE.py avec python3
1.1 Premiers pas avec Python
Collecter des tweets avec Python
Binarisation avec OpenCV / Python
3. 3. Programmation IA avec Python
Méthode Kernel avec Python
Non bloquant avec Python + uWSGI
Grattage avec Python + PhantomJS
Publier des tweets avec python
Conduisez WebDriver avec python
Utiliser mecab avec Python 3
[Python] Redirection avec CGIHTTPServer
Analyse vocale par python
Pensez à yaml avec python
Premiers pas avec Python
Utiliser DynamoDB avec Python
Getter Zundko avec python
Gérez Excel avec python
Loi d'Ohm avec Python
Jugement des nombres premiers avec python
Exécutez Blender avec python
Résoudre des maths avec Python
Python à partir de Windows 7