Giter Club home page Giter Club logo

netbox-kea-dhcp's Introduction

netbox-kea-dhcp

PyPI

Enable use of NetBox as a subnet configuration source for ISC Kea DHCP server.

netbox-kea-dhcp is a one-way sync daemon that exports NetBox prefixes, IP ranges and IP addresses to respectively DHCP subnets, pools and host reservations. It listens for NetBox webhook events, and each time a change occured, it queries NetBox for the full changed data and update Kea throught its API.

The program has two modes of operation:

  • Full sync at program startup: overwrite current DHCP subnets with new ones exported from NetBox.
  • Continuous event-driven sync: listen for NetBox webhook events and update DHCP configuration accordingly.

Key features

  • Automatic sync from Netbox to Kea DHCP with virtualy no delay.
  • Update Kea configuration throught its control agent API: no direct configuration file overwrites, let’s the control agent manage the runtime and permanent configuration.
  • Only use open source Kea API commands (no ISC paid subscription required).
  • Submit new exported configuration to Kea check before applying it to runtime configuration.
  • Query NetBox only for the objects concerned by the event (incremental sync).
  • Get all NetBox data throught the well maintained pynetbox library: unique interface, loose dependency with NetBox internals (only with its API), reduced code to maintain.
  • Customizable NetBox query filters.
  • Customizable mapping between Netbox object attributes and DHCP settings.

Requirements

Python: >= 3.8 (tested on 3.10 but may works down to 3.8).

Netbox: validated on API version 3.4.

ISC Kea DHCP: validated on version 2.2.0.

Install

With pip

netbox-kea-dhcp is available on PyPi and can be installed with pip install netbox-kea-dhcp.

With pipx

A convenient way is to use pipx to install the application in an isolated environnement.

Install pipx (below is for Linux, see pipx homepage for other systems):

python3 -m pip install --user pipx
python3 -m pipx ensurepath

Install netbox-kea-dhcp from PyPi in a isolated environnement:

pipx install netbox-kea-dhcp

Run:

netbox-kea-dhcp --help

Quick start

Sync at startup then listen for netbox events:

netbox-kea-dhcp --netbox-url http://netbox-host \
    --netbox-token 0123456789ABCDEF \
    --kea-url http://kea-api-host --sync-now --listen -v

The default mapping between netbox and Kea is:

  • prefixes are exported to subnets.
  • IP ranges are exported to pools.
  • IP Addresses are exported to reservations. Hardware address is mapped with IP address custom field dhcp_reservation_hw_address if it exists and is non null, otherwise it is mapped with the MAC address of the assigned object.

At least one Netbox webhook needs to be configured for event listening. It has to notify all actions on DHCP-relevant objects:

  • Content types:
    • IPAM: Prefix, IP Range, IP addresse.
    • DCIM: Interface, Device.
    • Virtualization: Interface, Virtual Machine.
  • Events: Creations, Updates, Deletions.
  • HTTP Request:
    • URL: http://{netbox-connector-host}:{port}/event/{free-text}/
    • HTTP Method: POST.

The field free-text is necessary to define several webhooks with same events. The connector only uses it in logs.

More help with netbox-kea-dhcp --help and in the configuration file example under examples/ (or under ~/.local/pipx/venvs/netbox-kea-dhcp/lib/python3.10/site-packages/examples/ if app was installed with pipx).

Recommended Netbox webhooks

Sysadmins should set several webhooks with conditions and restricted body template, in order to filter events and avoid unecessary network and CPU load.

Below is a recommended webhook set-up. It assumes that DHCP hardware addresses are apped with netbox interface MAC addresses. If interfaces are not used (i.e. hardware addresses are only mapped with a custom field defined in netbox IP addresses), webhooks on (vm) interfaces, (virtual) devices are not needed.

Common to all webhooks:

  • HTTP Request:

    • URL: http://{netbox-connector-host}:{port}/event/{optional-free-text}/
    • HTTP Method: POST.
  • Body template:

    { "event": "{{ event }}",
      "model": "{{ model }}",
      "data": { "id": {{ data["id"] }} }
    }

Webhook 1:

  • Content types: IPAM > Prefix, IPAM > IP Range, IPAM > IP Address, DCIM > Device, DCIM > Interface, Virtualization > Virtual Machine, Virtualization > Interface.
  • Events: Updates
  • Conditions: none

Webhook 2:

  • Content types: IPAM > IP Address

  • Events: Creations, Deletions

  • Conditions:

    { "and": [ { "attr": "status.value", "value": "dhcp" } ] }

Webhook 3:

  • Content types: IPAM > IP Range

  • Events: Creations, Deletions

  • Conditions (note: you may have to customize status values to add dhcp):

    { "and": [ { "attr": "status.value", "value": "dhcp"} ] }

Webhook 4:

  • Content types: IPAM > Prefix

  • Events: Creations, Deletions

  • Conditions: none, or a custom field

    { "and": [ { "attr": "custom_fields.dhcp_enabled", "value": true } ] }

It’s also recommended to set a TLS-enabled reverse proxy in front of netbox-kea-dhcp.

Limitations

  • When a change occured, the whole DHCP configuration is gotten from Kea, modified, and sent back. It may put some stress on the DHCP server in case of frequent changes. This is a limitation of Kea open source commands. A better update granularity would require an ISC paid subscription.
  • When Kea URI is of the form file:///path/to/kea-config, config is written to the file in an unsafe manner: if the write fails, the file will be inconsistent. This is because the file feature is intended for tests.

netbox-kea-dhcp's People

Contributors

francoismdj avatar jonkerj avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

netbox-kea-dhcp's Issues

Stuck running script

Netbox 3.7.3
Python: 3.10.2
Kea: 2.2.1

I'm manually running the script and feeding it a basic config. I can see connections being made to both kea and netbox, however it pukes on the first prefix it receives back from netbox. This particular subnet (10.10.0.0/16) is actually empty. I don't have "status" set as dhcp in the config.

2024-02-29 11:32:01,451 [INFO] Start full sync
2024-02-29 11:32:01,451 [INFO] pull running config from DHCP server
2024-02-29 11:32:01,459 [DEBUG] command "config-get" OK (text: None)
2024-02-29 11:32:01,459 [INFO] delete all current subnets
2024-02-29 11:32:01,459 [DEBUG] check configuration
2024-02-29 11:32:01,465 [DEBUG] command "config-test" OK (text: Configuration seems sane. Control-socket, hook-libraries, and D2 configuration were sanity checked, but not applied.)
2024-02-29 11:32:01,465 [DEBUG] commit configuration
2024-02-29 11:32:01,997 [DEBUG] prefix 10.10.0.0/16: generate DHCP config
2024-02-29 11:32:01,997 [INFO] subnets: add 10.10.0.0/16, ID 33997
Traceback (most recent call last):
  File "/usr/local/bin/netbox-kea-dhcp", line 8, in <module>
    sys.exit(run())
  File "/usr/local/lib/python3.10/dist-packages/netboxkea/entry_point.py", line 32, in run
    conn.sync_all()
  File "/usr/local/lib/python3.10/dist-packages/netboxkea/connector.py", line 96, in sync_all
    self._prefix_to_subnet(p, fullsync=True)
  File "/usr/local/lib/python3.10/dist-packages/netboxkea/connector.py", line 179, in _prefix_to_subnet
    for r in self.nb.ip_ranges(parent=pref.prefix):
  File "/usr/local/lib/python3.10/dist-packages/netboxkea/netbox.py", line 31, in ip_ranges
    for r in self.nb.ipam.ip_ranges.filter(
  File "/usr/local/lib/python3.10/dist-packages/pynetbox/core/response.py", line 127, in __next__
    next(self.response), self.endpoint.api, self.endpoint
  File "/usr/local/lib/python3.10/dist-packages/pynetbox/core/query.py", line 280, in get
    req = self._make_call(add_params=add_params)
  File "/usr/local/lib/python3.10/dist-packages/pynetbox/core/query.py", line 247, in _make_call
    raise RequestError(req)
pynetbox.core.query.RequestError: The request failed with code 400 Bad Request: {'status': ['Select a valid choice. dhcp is not one of the available choices.']}

ip-ranges dhcp status is not one of the valid choices

current location of issue: ipaddress_filter={'status': 'dhcp'}
netbox docs explicitly state:

Statuses are hard-coded in NetBox and can be one of the following:

  • Container - A summary of child prefixes
  • Active - Provisioned and in use
  • Reserved - Designated for future use
  • Deprecated - No longer in use

I'd suggest to change this to roles or, is there a plugin that creates extra status fields?

/health/ route doesn't exist in current pypi release

Symptoms
/health/ route returns 404 error when listener is running

Reproduction Steps

  1. Install netbox-kea-dhcp from PyPI
  2. Run netbox-kea-dhcp with --listen flag
  3. Attempt an HTTP GET request to /health/
  4. Recieve a 404 from server

Potential solutions
Re-release pypi package to be in sync with repo

Program crashes when dhcp4 service is offline

During a server reboot, netbox-kea-dhcp crashes with the following trace:

août 22 09:32:08 charade netbox-kea-dhcp[846]: netbox: https://netbox-srv, kea: http://127.0.0.1:8000/
août 22 09:32:08 charade netbox-kea-dhcp[846]: Start full sync
août 22 09:32:08 charade netbox-kea-dhcp[846]: pull running config from DHCP server
août 22 09:32:08 charade netbox-kea-dhcp[846]: Traceback (most recent call last):
août 22 09:32:08 charade netbox-kea-dhcp[846]:   File "/usr/local/bin/netbox-kea-dhcp", line 8, in <module>
août 22 09:32:08 charade netbox-kea-dhcp[846]:     sys.exit(run())
août 22 09:32:08 charade netbox-kea-dhcp[846]:   File "/usr/local/lib/netbox-kea-dhcp/lib/python3.10/site-packages/netboxkea/entry_point.py", line 32, in run
août 22 09:32:08 charade netbox-kea-dhcp[846]:     conn.sync_all()
août 22 09:32:08 charade netbox-kea-dhcp[846]:   File "/usr/local/lib/netbox-kea-dhcp/lib/python3.10/site-packages/netboxkea/connector.py", line 83, in sync_all
août 22 09:32:08 charade netbox-kea-dhcp[846]:     self.kea.pull()
août 22 09:32:08 charade netbox-kea-dhcp[846]:   File "/usr/local/lib/netbox-kea-dhcp/lib/python3.10/site-packages/netboxkea/kea/app.py", line 64, in pull
août 22 09:32:08 charade netbox-kea-dhcp[846]:     self.conf = self.api.get_conf()
août 22 09:32:08 charade netbox-kea-dhcp[846]:   File "/usr/local/lib/netbox-kea-dhcp/lib/python3.10/site-packages/netboxkea/kea/api.py", line 68, in get_conf
août 22 09:32:08 charade netbox-kea-dhcp[846]:     return self._request_kea('config-get')['Dhcp4']
août 22 09:32:08 charade netbox-kea-dhcp[846]:   File "/usr/local/lib/netbox-kea-dhcp/lib/python3.10/site-packages/netboxkea/kea/api.py", line 60, in _request_kea
août 22 09:32:08 charade netbox-kea-dhcp[846]:     raise KeaCmdError(f'command "{command}" returns "{text}"')
août 22 09:32:08 charade netbox-kea-dhcp[846]: netboxkea.kea.exceptions.KeaCmdError: command "config-get" returns "unable to forward command to the dhcp4 service: No such file or directory. The server is likely to be offline"

Expected result: handle errors trowned by Kea API, retry later when dhcp4 service is alive

Feature-Request: Get Information from Parent-Prefix

Hello,

would it be possible to read various DHCP options such as the domain name or the NTP server from the parent prefix? In most cases, the options are the same for all subnets, so that they do not have to be configured individually for each subnet as a Custom_Field in Netbox.

Thanks and Regards,
Daniel

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.