Skip to content

Latest commit

 

History

History
217 lines (174 loc) · 10.7 KB

README.md

File metadata and controls

217 lines (174 loc) · 10.7 KB

NetBox Webhook Automation

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

Requirements:

  • 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

Getting started with this application:

Clone the repository and create a Python virtual environment:

  1. 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'...
  1. 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) $
  1. After the virtual environment has been activated, it's recommended to update the pip, setuptools, and wheel packages to the latest version. Use the pip 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
  1. Now install the prerequisite packages for this application using the pip install command. Add the -r option to instruct pip that requirements will be loaded from a file, and supply the path to this application's requirements.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

Configure the application:

  1. Change to the netbox-webhook-automation/webhook_listener directory:
(venv) $ cd netbox-webhook-automation/webhook_listener 
  1. Copy the credentials.py.dist file to credentials.py:
(venv) $ cp credentials.py.dist credentials.py
  1. 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"
  1. The default port for the Flask webhook listener is 19703. If you wish to change this, open the main.py file in your editor and modify the app.run parameters in the main section:
if __name__ == "__main__":
    app.debug = True
    app.run(host="0.0.0.0", port=19703)

Start the webhook listener!

  1. Launch the main.py file using python. 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

Configure NetBox webhooks

Create a webhook for interface updates:

  1. In the NetBox interface left menu bar, click Other and then Webhooks to enter the webhook configuration context:

Webhook configuration link

  1. On the Webhooks configuration page, click + Add in the top right corner to create a new webhook.

  2. 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)
  3. When completed, your configuration should appear similar to the following: Interface webhook configuration example

Create a webhook for IPAM updates:

  1. Return to the Webhook configuration screen (Other -> Webhooks)

  2. Click + Add to create another webhook

  3. 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
  4. When complete, your webhook configuration for the IP address should appear as follows: IPAM webhook configuration example

Test it!

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 -

Have fun and keep coding!

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!

Additional resources:


Original development by Palmer Sample, September 2022. Distributed under the MIT license.

Please send questions, comments, or suggestions to psample@cisco.com