From 0fdb74a9a261a9da49f58959cf231902a401d0ed Mon Sep 17 00:00:00 2001 From: Julian Rother Date: Wed, 21 May 2025 16:26:00 +0200 Subject: [PATCH] Initial commit --- defaults/main.yml | 8 ++++ files/opnsense-dhcp-exporter | 36 ++++++++++++++++ .../prometheus-opnsense-dhcp-exporter.service | 33 +++++++++++++++ files/prometheus-opnsense-exporter.service | 33 +++++++++++++++ handlers/main.yml | 13 ++++++ tasks/main.yml | 42 +++++++++++++++++++ templates/prometheus-opnsense-exporter.j2 | 3 ++ 7 files changed, 168 insertions(+) create mode 100644 defaults/main.yml create mode 100755 files/opnsense-dhcp-exporter create mode 100644 files/prometheus-opnsense-dhcp-exporter.service create mode 100644 files/prometheus-opnsense-exporter.service create mode 100644 handlers/main.yml create mode 100644 tasks/main.yml create mode 100644 templates/prometheus-opnsense-exporter.j2 diff --git a/defaults/main.yml b/defaults/main.yml new file mode 100644 index 0000000..da1aae8 --- /dev/null +++ b/defaults/main.yml @@ -0,0 +1,8 @@ +prometheus_opnsense_exporter_version: 0.0.8 +prometheus_opnsense_exporter_config: + OPNSENSE_EXPORTER_ARGS: "--web.listen-address=127.0.0.1:9097 --exporter.instance-label=opnsense --opnsense.insecure" + OPNSENSE_DHCP_EXPORTER_PORT: "9098" + #OPNSENSE_EXPORTER_OPS_API: "..." + OPNSENSE_EXPORTER_OPS_PROTOCOL: "https" + #OPNSENSE_EXPORTER_OPS_API_KEY: "..." + #OPNSENSE_EXPORTER_OPS_API_SECRET: "..." diff --git a/files/opnsense-dhcp-exporter b/files/opnsense-dhcp-exporter new file mode 100755 index 0000000..67ab29f --- /dev/null +++ b/files/opnsense-dhcp-exporter @@ -0,0 +1,36 @@ +#!/usr/bin/python3 +import time +import urllib3 +import requests +import json +import os +from prometheus_client import start_http_server, PROCESS_COLLECTOR, PLATFORM_COLLECTOR, GC_COLLECTOR +from prometheus_client.core import GaugeMetricFamily, CounterMetricFamily, REGISTRY +from prometheus_client.registry import Collector + +urllib3.disable_warnings() + +class CustomCollector(Collector): + def collect(self): + api_host = os.environ['OPNSENSE_EXPORTER_OPS_API'] + api_key = os.environ['OPNSENSE_EXPORTER_OPS_API_KEY'] + api_secret = os.environ['OPNSENSE_EXPORTER_OPS_API_SECRET'] + result = requests.get(f'https://{api_host}/api/dhcpv4/leases/searchLease', verify=False, auth=(api_key, api_secret)) + leases = {} + for lease in result.json()['rows']: + if lease['state'] == 'active' and lease['type'] == 'dynamic': + leases.setdefault(lease['if_descr'], set()).add(lease['mac']) + opnsense_dhcpv4_active_leases_count = GaugeMetricFamily('opnsense_dhcpv4_active_leases_count', 'Number of active DHCPv4 leases per interface', labels=['interface']) + for if_descr, macs in leases.items(): + opnsense_dhcpv4_active_leases_count.add_metric([if_descr], len(macs)) + yield opnsense_dhcpv4_active_leases_count + +REGISTRY.unregister(PROCESS_COLLECTOR) +REGISTRY.unregister(PLATFORM_COLLECTOR) +REGISTRY.unregister(GC_COLLECTOR) +REGISTRY.register(CustomCollector()) + +if __name__ == '__main__': + start_http_server(addr='127.0.0.1', port=int(os.environ['OPNSENSE_DHCP_EXPORTER_PORT'])) + while True: + time.sleep(100) diff --git a/files/prometheus-opnsense-dhcp-exporter.service b/files/prometheus-opnsense-dhcp-exporter.service new file mode 100644 index 0000000..1500bba --- /dev/null +++ b/files/prometheus-opnsense-dhcp-exporter.service @@ -0,0 +1,33 @@ +[Unit] +Description=Prometheus exporter for OPNsense DHCPv4 metrics +Requires=network-online.target +After=network-online.target + +[Service] +DynamicUser=yes +User=opnsense-exporter +Restart=on-failure +EnvironmentFile=-/etc/default/prometheus-opnsense-exporter +ExecStart=/usr/local/sbin/opnsense-dhcp-exporter + +LockPersonality=yes +MemoryDenyWriteExecute=yes +NoNewPrivileges=true +PrivateDevices=yes +PrivateTmp=disconnected +PrivateUsers=yes +ProcSubset=pid +ProtectClock=yes +ProtectControlGroups=strict +ProtectHome=yes +ProtectHostname=yes +ProtectKernelLogs=yes +ProtectKernelModules=yes +ProtectKernelTunables=yes +ProtectProc=invisible +ProtectSystem=strict +RestrictNamespaces=yes +RestrictRealtime=yes + +[Install] +WantedBy=multi-user.target diff --git a/files/prometheus-opnsense-exporter.service b/files/prometheus-opnsense-exporter.service new file mode 100644 index 0000000..637e98d --- /dev/null +++ b/files/prometheus-opnsense-exporter.service @@ -0,0 +1,33 @@ +[Unit] +Description=Prometheus exporter for OPNsense metrics +Requires=network-online.target +After=network-online.target + +[Service] +DynamicUser=yes +User=opnsense-exporter +Restart=on-failure +EnvironmentFile=-/etc/default/prometheus-opnsense-exporter +ExecStart=/usr/local/sbin/opnsense-exporter $OPNSENSE_EXPORTER_ARGS + +LockPersonality=yes +MemoryDenyWriteExecute=yes +NoNewPrivileges=true +PrivateDevices=yes +PrivateTmp=disconnected +PrivateUsers=yes +ProcSubset=pid +ProtectClock=yes +ProtectControlGroups=strict +ProtectHome=yes +ProtectHostname=yes +ProtectKernelLogs=yes +ProtectKernelModules=yes +ProtectKernelTunables=yes +ProtectProc=invisible +ProtectSystem=strict +RestrictNamespaces=yes +RestrictRealtime=yes + +[Install] +WantedBy=multi-user.target diff --git a/handlers/main.yml b/handlers/main.yml new file mode 100644 index 0000000..3619b66 --- /dev/null +++ b/handlers/main.yml @@ -0,0 +1,13 @@ +- name: Restart prometheus-opnsense-exporter + ansible.builtin.systemd_service: + name: prometheus-opnsense-exporter + daemon_reload: true + state: restarted + enabled: yes + +- name: Restart prometheus-opnsense-dhcp-exporter + ansible.builtin.systemd_service: + name: prometheus-opnsense-dhcp-exporter + daemon_reload: true + state: restarted + enabled: yes diff --git a/tasks/main.yml b/tasks/main.yml new file mode 100644 index 0000000..7638ecf --- /dev/null +++ b/tasks/main.yml @@ -0,0 +1,42 @@ +- name: Update config + ansible.builtin.template: + src: prometheus-opnsense-exporter.j2 + dest: /etc/default/prometheus-opnsense-exporter + mode: "0640" + notify: + - Restart prometheus-opnsense-exporter + - Restart prometheus-opnsense-dhcp-exporter + +- name: Download opnsense-exporter release tarball + ansible.builtin.get_url: + url: "https://github.com/AthennaMind/opnsense-exporter/releases/download/v{{ prometheus_opnsense_exporter_version }}/opnsense-exporter_Linux_x86_64.tar.gz" + dest: "/var/tmp/opnsense-exporter-{{ prometheus_opnsense_exporter_version }}.tar.gz" + mode: "0644" + +- name: Extract binary from opnsense-exporter release tarball + ansible.builtin.unarchive: + remote_src: true + src: "/var/tmp/opnsense-exporter-{{ prometheus_opnsense_exporter_version }}.tar.gz" + dest: "/usr/local/sbin/" + include: "opnsense-exporter" + mode: "0755" + notify: Restart prometheus-opnsense-exporter + +- name: Create opnsense-exporter systemd unit + ansible.builtin.copy: + src: prometheus-opnsense-exporter.service + dest: /etc/systemd/system/prometheus-opnsense-exporter.service + notify: Restart prometheus-opnsense-exporter + +- name: Copy opnsense-dhcp-exporter script + ansible.builtin.copy: + src: opnsense-dhcp-exporter + dest: /usr/local/sbin/opnsense-dhcp-exporter + mode: "0755" + notify: Restart prometheus-opnsense-dhcp-exporter + +- name: Create opnsense-dhcp-exporter systemd unit + ansible.builtin.copy: + src: prometheus-opnsense-dhcp-exporter.service + dest: /etc/systemd/system/prometheus-opnsense-dhcp-exporter.service + notify: Restart prometheus-opnsense-dhcp-exporter diff --git a/templates/prometheus-opnsense-exporter.j2 b/templates/prometheus-opnsense-exporter.j2 new file mode 100644 index 0000000..82e043c --- /dev/null +++ b/templates/prometheus-opnsense-exporter.j2 @@ -0,0 +1,3 @@ +{% for key, value in prometheus_opnsense_exporter_config.items() %} +{{ key }}="{{ value }}" +{% endfor %}