From f3eec5fcbfbd5db469fb32b7f3d7d74d1c85af9b Mon Sep 17 00:00:00 2001 From: Timotej Lazar Date: Tue, 4 Nov 2025 14:56:40 +0100 Subject: [PATCH 1/3] collector: support custom poll intervals Also simplify config context schema for SNMP since we only use a single instance. --- roles/collector/README.md | 19 ++++++++++--------- roles/collector/tasks/main.yml | 2 +- .../collector/templates/prometheus-job.yml.j2 | 6 +++++- roles/collector/templates/snmp.conf.j2 | 10 +++++----- 4 files changed, 21 insertions(+), 16 deletions(-) diff --git a/roles/collector/README.md b/roles/collector/README.md index 77c4f93..8c89aa5 100644 --- a/roles/collector/README.md +++ b/roles/collector/README.md @@ -1,18 +1,19 @@ Set up metric collection with prometheus and telegraf as the SNMP proxy. -NetBox config context should contain the lists `prometheus_hosts` and `snmp_hosts` with job definitions. Each entry should define `name` and `nb_filter` user to query hosts from NetBox. For example: +Each entry in `prometheus_config` should define `name`, `hosts` and optionally `interval`. As above, `hosts` is used as a query filter. + +For SNMP the properties `snmp_hosts` and optional `snmp_interval` should define respectively the NetBox query filter and poll interval. + +For example: { - "prometheus_hosts": [ + "prometheus_config": [ { "name": "classroom", - "nb_filter": "role=desktop-computer status=active location=classroom" + "hosts": "role=desktop-computer status=active location=classroom", + "interval": 300 } ], - "snmp_hosts": [ - { - "name": "switch", - "nb_filter": "role=switch name__isw=sw- status=active status=staged status=planned" - } - ] + "snmp_hosts": "role=switch name__isw=sw- status=active status=staged status=planned", + "snmp_interval": 300 } diff --git a/roles/collector/tasks/main.yml b/roles/collector/tasks/main.yml index a5176ba..f365f7f 100644 --- a/roles/collector/tasks/main.yml +++ b/roles/collector/tasks/main.yml @@ -28,7 +28,7 @@ template: dest: "/etc/prometheus/conf.d/{{ item.name }}.yml" src: "prometheus-job.yml.j2" - loop: "{{ prometheus_hosts }}" + loop: "{{ prometheus_config }}" loop_control: label: "{{ item.name }}" notify: reload prometheus diff --git a/roles/collector/templates/prometheus-job.yml.j2 b/roles/collector/templates/prometheus-job.yml.j2 index 7e24f05..94e7a11 100644 --- a/roles/collector/templates/prometheus-job.yml.j2 +++ b/roles/collector/templates/prometheus-job.yml.j2 @@ -1,10 +1,14 @@ -{% set devices = query("netbox.netbox.nb_lookup", "devices", api_filter="{{ item.nb_filter }}", raw_data=true) +{% set devices = query("netbox.netbox.nb_lookup", "devices", api_filter="{{ item.hosts }}", raw_data=true) | selectattr("primary_ip") | map(attribute="name") | map("extract", hostvars) -%} scrape_configs: - job_name: "{{ item.name }}" +{% if item.interval is defined %} + scrape_interval: {{ item.interval }}s + scrape_timeout: {{ item.interval // 5 }}s +{% endif %} relabel_configs: - source_labels: [__address__] regex: '([^.]+).*' diff --git a/roles/collector/templates/snmp.conf.j2 b/roles/collector/templates/snmp.conf.j2 index d0de538..ec9aedb 100644 --- a/roles/collector/templates/snmp.conf.j2 +++ b/roles/collector/templates/snmp.conf.j2 @@ -1,13 +1,13 @@ [[inputs.snmp]] - interval = "300s" +{% if snmp_interval is defined %} + interval = "{{ snmp_interval }}s" +{% endif %} agent_host_tag = "source" agents = [ -{% for item in snmp_hosts %} -{% for address in query("netbox.netbox.nb_lookup", "devices", api_filter=item.nb_filter, raw_data=true) +{% for address in query("netbox.netbox.nb_lookup", "devices", api_filter=snmp_hosts, raw_data=true) | selectattr("primary_ip4") | map(attribute="primary_ip4.address") - | ipaddr("address") %} + | ipaddr("int") | sort | ipaddr("address") %} "{{ address }}", -{% endfor %} {% endfor %} ] version = 3 From ff90d3c0a32f260a693257aaaf5141deb05f6294 Mon Sep 17 00:00:00 2001 From: Timotej Lazar Date: Tue, 4 Nov 2025 16:17:33 +0100 Subject: [PATCH 2/3] debian: add wget to base packages --- roles/debian/tasks/main.yml | 3 ++- roles/friwall/README.md | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 roles/friwall/README.md diff --git a/roles/debian/tasks/main.yml b/roles/debian/tasks/main.yml index 19e265d..66b0761 100644 --- a/roles/debian/tasks/main.yml +++ b/roles/debian/tasks/main.yml @@ -39,8 +39,9 @@ - git - ifupdown2 - rsync - - vim - tmux + - vim + - wget # for base Debian the main interfaces file is just an include - name: Remove interface definitions added by installer diff --git a/roles/friwall/README.md b/roles/friwall/README.md new file mode 100644 index 0000000..a6fe6a3 --- /dev/null +++ b/roles/friwall/README.md @@ -0,0 +1 @@ +Install and configure the [FRIwall](https://git.fri.uni-lj.si/rc/friwall) web application for managing firewall nodes. For settings and operation refer to that project. From f52934cd255f9be24c9e6490074006cb9c0600ee Mon Sep 17 00:00:00 2001 From: Timotej Lazar Date: Tue, 4 Nov 2025 16:28:44 +0100 Subject: [PATCH 3/3] =?UTF-8?q?friwall:=20don=E2=80=99t=20template=20setti?= =?UTF-8?q?ngs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let all settings including list of nodes be managed by application. Exception is the list of networks instantiated from NetBox data. --- roles/friwall/tasks/main.yml | 13 +++++++------ roles/friwall/templates/interfaces.j2 | 14 -------------- roles/friwall/templates/nodes.json.j2 | 11 ----------- roles/friwall/templates/settings.json.j2 | 10 ---------- 4 files changed, 7 insertions(+), 41 deletions(-) delete mode 100644 roles/friwall/templates/interfaces.j2 delete mode 100644 roles/friwall/templates/nodes.json.j2 delete mode 100644 roles/friwall/templates/settings.json.j2 diff --git a/roles/friwall/tasks/main.yml b/roles/friwall/tasks/main.yml index 0164136..d0f85ae 100644 --- a/roles/friwall/tasks/main.yml +++ b/roles/friwall/tasks/main.yml @@ -38,17 +38,18 @@ extra_args: --user --break-system-packages --no-warn-script-location notify: restart uwsgi -- name: Configure base settings - template: - dest: "/srv/friwall/{{ item }}" - src: "{{ item }}.j2" +- name: Ensure setting files exist + copy: + dest: "/srv/friwall/{{ item }}.json" + content: | + {} owner: friwall group: friwall mode: 0600 force: no loop: - - nodes.json - - settings.json + - nodes + - settings notify: restart uwsgi - name: Configure list of networks diff --git a/roles/friwall/templates/interfaces.j2 b/roles/friwall/templates/interfaces.j2 deleted file mode 100644 index d738c99..0000000 --- a/roles/friwall/templates/interfaces.j2 +++ /dev/null @@ -1,14 +0,0 @@ -auto lo -iface lo inet loopback - -{% for iface in interfaces %} -auto {{ iface.name }} -iface {{ iface.name }} inet static -{% for address in iface.ip_addresses %} - address {{ address.address }} -{% endfor %} -{% if iface.custom_fields.gateway %} - gateway {{ iface.custom_fields.gateway.address | ipaddr('address') }} -{% endif %} - -{% endfor %} diff --git a/roles/friwall/templates/nodes.json.j2 b/roles/friwall/templates/nodes.json.j2 deleted file mode 100644 index c4ba065..0000000 --- a/roles/friwall/templates/nodes.json.j2 +++ /dev/null @@ -1,11 +0,0 @@ -{% set nodes = query('netbox.netbox.nb_lookup', 'devices', api_filter='role=firewall', raw_data=true) - | selectattr('config_context') | selectattr('config_context', 'contains', 'master') - | selectattr('config_context.master', '==', inventory_hostname) - | map(attribute='name') -%} - -{ -{% for node in nodes %} - "{{ hostvars[node] | device_address | selectattr('family.value', '==', 4) - | map(attribute='address') | ipaddr('address') | first }}": -1{{ '' if loop.last else ',' }} -{% endfor %} -} diff --git a/roles/friwall/templates/settings.json.j2 b/roles/friwall/templates/settings.json.j2 deleted file mode 100644 index 3086ff3..0000000 --- a/roles/friwall/templates/settings.json.j2 +++ /dev/null @@ -1,10 +0,0 @@ -{ - "ldap_host": "{{ domain }}", - "ldap_user": "{{ password.ldap_user }}", - "ldap_pass": "{{ password.ldap_pass }}", - "ldap_base_dn": "{{ ldap_base_dn }}", - "oidc_server": "{{ password.oidc_server }}", - "oidc_client_id": "{{ password.oidc_client_id }}", - "oidc_client_secret": "{{ password.oidc_client_secret }}", - "wg_net": "{{ wg_net }}" -}