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.
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
[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".
Tout d'abord, ajoutez une ligne du nom ACL TEST
à partir de l'état où il n'y a pas de paramètre ACL.
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()
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
Ensuite, essayez d'obtenir les informations de l'ACL créée avec RESTCONF.
À 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)
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
}
}
}
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)
$ 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"
}
}
]
}
]
}
Voici un exemple d'ajout d'une entrée (ACE) et d'ajout d'une autre ACL à une ACL existante.
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)
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
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)
$ 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
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.
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)
$ 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
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
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)
$ 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
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