Create firewalld Rules from netbox

The netbox asset management system offers the possiblity to add services to devices and virtual machines. With full automation installed to create virtual machines from netbox it would be cool to also create the firewall rules for new machines from the information stored in netbox.

netbox Service Field

For every device or virtual machine you have a table called Services on the right side. When selecting Assign service a dialog to add a service to that machine opens. It asks you for a name, a protocol (only TCP and UDP possible) and a port.

The field IP addresses allows you to select IP addresses that are defined for this host. And finally the description field gives you the chance to leave a note for later why you added this service to this machine.

Firewalld in ansible

Ansible can use netbox as inventory. This is really cool, since it allows you to automate the deployment of information stored in netbox to the devices.

This also holds the configuration of firewall rules according to the services information from netbox.

In the first tasks of my playbook I request the information about the machine from the netbox API.

- name: Get ID of virtual machine
  uri:
    url: "http://[::1]/api/virtualization/virtual-machines/?name={{ inventory_hostname }}"
    method: GET
    return_content: yes
    headers:
      Accept: application/json
      Authorization: Token {{netbox_token}}
  register: vm
  delegate_to: localhost

The information about the virtual machine with the name matching the {{ inventory_hostname }} contains its ID. With the help of this ID we can retrieve a list of services defined for the virtual server.

- name: List of services if the virtual server
  uri:
    url: "http://[::1]/api/ipam/services/?virtual_machine_id={{ vm.json.results[0].id }}"
    method: GET
    return_content: yes
    headers:
      Accept: application/json
      Authorization: Token {{netbox_token}}
  register: services
  delegate_to: localhost

Finally we call the firewalld module of ansible to set the rules on the target machine to allow access to the services defined in netbox. Please note the loop over the list of services from the last request.

- name: Add rule
  firewalld:
    port: "{{ item.port }}/{{ item.protocol.value }}"
    state: enabled
    permanent: yes
    immediate: yes
  loop: "{{ services.json.results }}"

Final Thoughts

It would be cool also to use the remaining information from netbox like name, IP addresses, or description.

For instance you could use the name field and check if such a name is known to the firewalld as a service. Then you could just allow this service on the target machine and would not have to use the protcol/port definition.

Using the command firewalld --get-services ansible could get a list on known services, check if the name is included in the list. If that is the case, it would use the service, if not, it would use protocol/port information to set up the firewall rule.

With the help of the two other fields, you could compile a rich-rule to define firewall rules more specific.

Anyway the services information from netbox will not be sufficient anyway. The complete ruleset also would include a basic ruleset. This basic ruleset i.e. would allow admin or monitoring access. this basic ruleset could be set during the creation of the host.

Please mail me if you have questions or improvements to ms@sys4.de.

Michael Schwartzkopff, 03 Dec 2020