As demonstrated in an episode of Cisco DevNet Snack Minute on YouTube!
This is a demonstration of using Python to receive and process webhook data generated by NetBox. Initial use cases:
- Interfaces:
- Add / change / remove interface description
- Change interface MTU
- Change interface state (shutdown / no shutdown)
- IPAM:
- Add / change / remove IPv4 or IPv6 addresses on interfaces
- Python 3.8 or higher (this code was developed using Python 3.9)
- Physical or virtual Cisco IOS XE device with RESTCONF enabled
- Code tested against a Cisco Catalyst 8000V Edge (virtual) device running IOS XE 17.06.03a
- Running NetBox instance provisioned with an administrative API token
- Use the
git clone
command to create a local repository containing the source code:
$ git clone https://github.com/CiscoLearning/netbox-webhook-automation.git Cloning into 'netbox-webhook-automation'...
- Once the repository has been cloned to the local machine, create a new Python virtual environment using the desired Python interpreter. In this example, Python 3.9 will be used:
$ python3.9 -m venv venv $ source venv/bin/activate (venv) $
- After the virtual environment has been activated, it's recommended to update the
pip
,setuptools
, andwheel
packages to the latest version. Use thepip install --upgrade
command with the list of packages to upgrade:
(venv) $ pip install --upgrade pip setuptools wheel Requirement already satisfied: pip in ./venv/lib/python3.9/site-packages (21.1.1) Collecting pip Using cached pip-22.2.2-py3-none-any.whl (2.0 MB) Requirement already satisfied: setuptools in ./venv/lib/python3.9/site-packages (56.0.0) Collecting setuptools Using cached setuptools-65.3.0-py3-none-any.whl (1.2 MB) Collecting wheel Using cached wheel-0.37.1-py2.py3-none-any.whl (35 kB) Installing collected packages: wheel, setuptools, pip Attempting uninstall: setuptools Found existing installation: setuptools 56.0.0 Uninstalling setuptools-56.0.0: Successfully uninstalled setuptools-56.0.0 Attempting uninstall: pip Found existing installation: pip 21.1.1 Uninstalling pip-21.1.1: Successfully uninstalled pip-21.1.1 Successfully installed pip-22.2.2 setuptools-65.3.0 wheel-0.37.1
- Now install the prerequisite packages for this application using the
pip install
command. Add the-r
option to instructpip
that requirements will be loaded from a file, and supply the path to this application'srequirements.txt
file:
(venv) $ pip install -r netbox-webhook-automation/requirements.txt Collecting Flask~=2.2.2 Using cached Flask-2.2.2-py3-none-any.whl (101 kB) Collecting pynetbox~=6.6.2 Using cached pynetbox-6.6.2-py3-none-any.whl (32 kB) ... (output truncated) ... Successfully installed Flask-2.2.2 Jinja2-3.1.2 MarkupSafe-2.1.1 Werkzeug-2.2.2 certifi-2022.9.14 charset-normalizer-2.1.1 click-8.1.3 idna-3.4 importlib-metadata-4.12.0 itsdangerous-2.1.2 pynetbox-6.6.2 requests-2.28.1 requests-toolbelt-0.9.1 six-1.16.0 urllib3-1.26.12 zipp-3.8.1
- Change to the
netbox-webhook-automation/webhook_listener
directory:
(venv) $ cd netbox-webhook-automation/webhook_listener
- Copy the
credentials.py.dist
file tocredentials.py
:
(venv) $ cp credentials.py.dist credentials.py
- Use your editor of choice to open the
credentials.py
file. Change the NetBox URL and API token to match your environment, and define credentials for the destination virtual device(s). Note: as this application is for demonstration purposes, only a single credential will be used. The user associated with this credential must have privilege level 15 on the remote device(s).
NETBOX_URL = "https://netbox"
NETBOX_TOKEN = "0123456789abcdef0123456789abcdef01234567"
DEVICE_USERNAME = "developer"
DEVICE_PASSWORD = "1234QWer"
- The default port for the Flask webhook listener is
19703
. If you wish to change this, open themain.py
file in your editor and modify theapp.run
parameters in the main section:
if __name__ == "__main__": app.debug = True app.run(host="0.0.0.0", port=19703)
- Launch the
main.py
file usingpython
. The flask app will start and some output will be displayed:
(venv) $ python main.py * Serving Flask app 'main' * Debug mode: on WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. * Running on all addresses (0.0.0.0) * Running on http://127.0.0.1:19703 * Running on http://192.168.1.2:19703 Press CTRL+C to quit * Restarting with stat * Debugger is active! * Debugger PIN: 123-456-789
- In the NetBox interface left menu bar, click Other and then Webhooks to enter the webhook configuration context:
-
On the Webhooks configuration page, click + Add in the top right corner to create a new webhook.
-
Complete the following fields to add a new webhook:
- Name: Provide a useful name such as interface-webhook
- Content types: DCIM > interface
- Enabled: checked to enable the webhook.
- Events: Creations, Updates, and Deletions
- URL: Enter the IP or hostname of the system running the webhook listener, the port, and the default path for the interface listener which is
/api/update-interface
. An example URL would be http://192.168.1.2:19703/api/update-interface - HTTP method: POST
- HTTP content type: application/json
- Additional headers: None (leave empty)
- Body template: None (leave empty)
- Secret: None (leave empty)
- Conditions: null (do not change the default)
- SSL verification: irrelevant (the application is not configured to use TLS)
- CA File path: None (leave empty)
-
When completed, your configuration should appear similar to the following:
-
Return to the Webhook configuration screen (Other -> Webhooks)
-
Click + Add to create another webhook
-
Add a description name and follow the same steps as for the interface webhook, but note the following important differences:
- Content types: IPAM > IP address
- URL: IP/Port of the receiver but the path is /api/update-address
-
When complete, your webhook configuration for the IP address should appear as follows:
When you create, update, or delete an IP address or an interface in NetBox, a webhook should be created and your Flask application should display some output. It might not do anything at first, which is OK!
To ensure that something useful happens, verify that you have a device configured in NetBox to represent your virtual / test device and that there is a Primary IPv4 address associated with the device. Verify that there is at least one interface associated with this device that is not marked as "management only."
If successful, you should see output similar to the following when updating an interface:
Configuring interface 'GigabitEthernet3' on device 'access-rtr01'...
Enabling interface.
Target URL: https://198.18.1.157/restconf/data/Cisco-IOS-XE-native:native/interface/GigabitEthernet=3/shutdown
Interface GigabitEthernet3 is already enabled!
Response: 404 (Not Found)
Setting interface description to 'Baconrific!!'
URL: https://198.18.1.157/restconf/data/Cisco-IOS-XE-native:native/interface/GigabitEthernet=3/description
Payload:
{'description': 'Baconrific!!'}
Response: 201 (Created)
Setting interface MTU to '1500'
URL: https://198.18.1.157/restconf/data/Cisco-IOS-XE-native:native/interface/GigabitEthernet=3/mtu
Payload:
{'mtu': 1500}
Response: 201 (Created)
198.18.1.146 - - [19/Sep/2022 14:42:16] "POST /api/update-interface HTTP/1.1" 204 -
And output similar to the following when updating an IP address. In this example, an address is being changed from interface GigabitEthernet3 on access-rtr01 to GigabitEthernet3 on access-rtr02:
Updating IP address...
Removing address 192.168.222.222/24 from interface 'GigabitEthernet3' on device 'access-rtr01'...
Response: 204 (No Content)
Assigning address 192.168.222.222/24 to interface 'GigabitEthernet3' on device 'access-rtr02'...
Sending payload:
{'primary': {'address': '192.168.222.222', 'mask': '255.255.255.0'}}
To URL:
https://198.18.1.158/restconf/data/Cisco-IOS-XE-native:native/interface/GigabitEthernet=3/ip/address/primary
Response: 204 (No Content)
198.18.1.146 - - [19/Sep/2022 15:05:29] "POST /api/update-address HTTP/1.1" 204 -
Now that you've seen how to automate network device configuration with NetBox webhooks, keep learning and experimenting!
See if you can add more functionality or create your own webhook listeners for other events - perhaps for VRF definitions or subinterfaces. Your imagination is the only limit!
- NetBox-Community GitHub repository contains the source for NetBox as well as project information
- NetBox documentation site contains everything NetBox-related - from downloading to advanced configuration.
- Python Flask documentation - Flask is used as the API listener in this project. The documentation site includes quickstart guides, reference material, and code examples.
- pynetbox - Python API client library for NetBox has many examples of using pynetbox to interact with NetBox using Python.
- Cisco YANG Suite - Browse YANG models interactively! If you're getting started with YANG models, this tool is very useful.
Original development by Palmer Sample, September 2022. Distributed under the MIT license.
Please send questions, comments, or suggestions to [email protected]