[4/4] zabbix_agentd: Add IPFire specific userparameters

Message ID 20210330152830.2859-5-robin.roevens@disroot.org
State Superseded
Headers
Series zabbix_agentd: new maintainer/summary |

Commit Message

Robin Roevens March 30, 2021, 3:28 p.m. UTC
  Provide IPFire specific items for the Zabbix server to monitor:
- Networking stats:
  - ipfire.net.gateway.pingtime: Internet Line Quality
  - ipfire.net.gateway.ping: Internet connection
  - ipfire.net.fw.hits[*]: Firewall hits
- IPFire service states:
  - ipfire.services: JSON formatted state of all IPFire services
    using new ipfire_services.pl script.

Users can install the IPFire 2 Zabbix template-set provided here:
https://share.zabbix.com/network-appliances/ipfire-2
to monitor these metrics. Or create their own template.

Signed-off-by: Robin Roevens <robin.roevens@disroot.org>
---
 config/rootfiles/packages/zabbix_agentd       |   3 +
 config/zabbix_agentd/ipfire_services.pl       | 221 ++++++++++++++++++
 config/zabbix_agentd/sudoers                  |   2 +-
 .../template_module_ipfire_network_stats.conf |   4 +
 .../template_module_ipfire_services.conf      |   2 +
 lfs/zabbix_agentd                             |   8 +-
 src/paks/zabbix_agentd/install.sh             |   5 +
 src/paks/zabbix_agentd/uninstall.sh           |   2 +
 8 files changed, 245 insertions(+), 2 deletions(-)
 create mode 100755 config/zabbix_agentd/ipfire_services.pl
 create mode 100644 config/zabbix_agentd/template_module_ipfire_network_stats.conf
 create mode 100644 config/zabbix_agentd/template_module_ipfire_services.conf
  

Patch

diff --git a/config/rootfiles/packages/zabbix_agentd b/config/rootfiles/packages/zabbix_agentd
index 6945c5ef7..aa3f1846b 100644
--- a/config/rootfiles/packages/zabbix_agentd
+++ b/config/rootfiles/packages/zabbix_agentd
@@ -3,9 +3,12 @@  etc/rc.d/init.d/zabbix_agentd
 etc/sudoers.d/zabbix.ipfirenew
 #etc/zabbix_agentd
 #etc/zabbix_agentd/scripts
+etc/zabbix_agentd/scripts/ipfire_services.pl.ipfirenew
 etc/zabbix_agentd/zabbix_agentd.conf.ipfirenew
 #etc/zabbix_agentd/zabbix_agentd.d
 etc/zabbix_agentd/zabbix_agentd.d/template_app_pakfire.conf.ipfirenew
+etc/zabbix_agentd/zabbix_agentd.d/template_module_ipfire_network_stats.conf.ipfirenew
+etc/zabbix_agentd/zabbix_agentd.d/template_module_ipfire_services.conf.ipfirenew
 usr/bin/zabbix_get
 usr/bin/zabbix_sender
 #usr/lib/modules
diff --git a/config/zabbix_agentd/ipfire_services.pl b/config/zabbix_agentd/ipfire_services.pl
new file mode 100755
index 000000000..dbf8aec56
--- /dev/null
+++ b/config/zabbix_agentd/ipfire_services.pl
@@ -0,0 +1,221 @@ 
+#!/usr/bin/perl
+###############################################################################
+# ipfire_services.pl - Retrieves available IPFire services information and 
+#                      return this as a JSON array suitable for easy processing 
+#                      by Zabbix server
+#
+# Author: robin.roevens (at) disroot.org
+# Version: 1.0
+#
+# Based on: services.cgi by IPFire Team
+# Copyright (C) 2007-2021  IPFire Team  <info@ipfire.org> 
+# 
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License 
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+# 
+###############################################################################
+
+use strict;
+
+# enable only the following on debugging purpose
+# use warnings;
+
+# Maps a nice printable name to the changing part of the pid file, which
+# is also the name of the program
+my %servicenames =(
+        'DHCP Server' => 'dhcpd',
+        'Web Server' => 'httpd',
+        'CRON Server' => 'fcron',
+        'DNS Proxy Server' => 'unbound',
+        'Logging Server' => 'syslogd',
+        'Kernel Logging Server' => 'klogd',
+        'NTP Server' => 'ntpd',
+        'Secure Shell Server' => 'sshd',
+        'VPN' => 'charon',
+        'Web Proxy' => 'squid',
+        'Intrusion Detection System' => 'suricata',
+        'OpenVPN' => 'openvpn'
+);
+
+# Hash to overwrite the process name of a process if it differs from the launch command.
+my %overwrite_exename_hash = (
+        "suricata" => "Suricata-Main"
+);
+
+my $first = 1;
+
+print "[";
+
+# Built-in services
+my $key = '';
+foreach $key (sort keys %servicenames){
+	print "," if not $first;
+	$first = 0;
+
+	print "{";
+	print "\"service\":\"$key\",";
+
+	my $shortname = $servicenames{$key};
+	print &servicestats($shortname);
+	
+	print "}";
+}
+
+# Generate list of installed addon pak's
+my @pak = `find /opt/pakfire/db/installed/meta-* 2>/dev/null | cut -d"-" -f2`;
+foreach (@pak){
+	chomp($_);
+
+	# Check which of the paks are services
+	my @svc = `find /etc/init.d/$_ 2>/dev/null | cut -d"/" -f4`;
+	foreach (@svc){
+		# blacklist some packages
+		#
+		# alsa has trouble with the volume saving and was not really stopped
+		# mdadm should not stopped with webif because this could crash the system
+		#
+		chomp($_);
+		if ( $_ eq 'squid' ) {
+			next;
+		}
+		if ( ($_ ne "alsa") && ($_ ne "mdadm") ) {
+			print ",";
+			print "{";
+
+			print "\"service\":\"Addon: $_\",";
+			print "\"servicename\":\"$_\",";
+
+			my $onboot = isautorun($_);
+			print "\"onboot\":$onboot,";
+
+			print &addonservicestats($_);
+
+			print "}";
+		}
+	}
+}	
+
+print "]";
+
+sub servicestats{
+	my $cmd = $_[0];
+	my $status = "\"servicename\":\"$cmd\",\"state\":\"0\"";
+	my $pid = '';
+	my $testcmd = '';
+        my $exename;
+        my $memory;
+
+
+	$cmd =~ /(^[a-z]+)/;
+	
+	# Check if the exename needs to be overwritten.
+        # This happens if the expected process name string
+        # differs from the real one. This may happened if
+        # a service uses multiple processes or threads.
+        if (exists($overwrite_exename_hash{$cmd})) {
+                # Grab the string which will be reported by
+                # the process from the corresponding hash.
+                $exename = $overwrite_exename_hash{$1};
+        } else {
+                # Directly expect the launched command as
+                # process name.
+                $exename = $1;
+        }
+	
+	if (open(FILE, "/var/run/${cmd}.pid")){
+                $pid = <FILE>; chomp $pid;
+                close FILE;
+                if (open(FILE, "/proc/${pid}/status")){
+                        while (<FILE>){
+                                if (/^Name:\W+(.*)/) {
+                                        $testcmd = $1;
+                                }
+                        }
+                        close FILE;
+                }
+                if (open(FILE, "/proc/${pid}/status")) {
+                        while (<FILE>) {
+                                my ($key, $val) = split(":", $_, 2);
+                                if ($key eq 'VmRSS') {
+					$val =~ /\s*([0-9]*)\s+kB/;
+					# Convert kB to B
+                                        $memory = $1*1024;
+                                        last;
+                                }
+                        }
+                        close(FILE);
+                }
+                if ($testcmd =~ /$exename/){
+			$status = "\"servicename\":\"$cmd\",\"state\":1,\"pid\":$pid,\"memory\":$memory";
+		}
+        }
+        return $status;
+}
+
+sub isautorun{
+        my $cmd = $_[0];
+        my $status = "0";
+        my $init = `find /etc/rc.d/rc3.d/S??${cmd} 2>/dev/null`;
+        chomp ($init);
+        if ($init ne ''){
+                $status = "1";
+        }
+        $init = `find /etc/rc.d/rc3.d/off/S??${cmd} 2>/dev/null`;
+        chomp ($init);
+        if ($init ne ''){
+                $status = "0";
+        }
+
+        return $status;
+}
+
+sub addonservicestats{
+        my $cmd = $_[0];
+        my $status = "0";
+        my $pid = '';
+        my $testcmd = '';
+        my $exename;
+        my @memory = (0);
+
+        $testcmd = `sudo /usr/local/bin/addonctrl $_ status 2>/dev/null`;
+
+        if ( $testcmd =~ /is\ running/ && $testcmd !~ /is\ not\ running/){
+                $status = "\"state\":1";
+
+                $testcmd =~ s/.* //gi;
+                $testcmd =~ s/[a-z_]//gi;
+                $testcmd =~ s/\[[0-1]\;[0-9]+//gi;
+                $testcmd =~ s/[\(\)\.]//gi;
+                $testcmd =~ s/  //gi;
+                $testcmd =~ s///gi;
+
+                my @pid = split(/\s/,$testcmd);
+                $status .=",\"pid\":\"$pid[0]\"";
+
+                my $memory = 0;
+
+                foreach (@pid){
+                        chomp($_);
+                        if (open(FILE, "/proc/$_/statm")){
+                                my $temp = <FILE>;
+                                @memory = split(/ /,$temp);
+                        }
+                        $memory+=$memory[0];
+                }
+		$memory*=1024;
+                $status .=",\"memory\":$memory";
+        }else{
+                $status = "\"state\":0";
+        }
+        return $status;
+}
diff --git a/config/zabbix_agentd/sudoers b/config/zabbix_agentd/sudoers
index 1b362a4fd..340bb8e66 100644
--- a/config/zabbix_agentd/sudoers
+++ b/config/zabbix_agentd/sudoers
@@ -14,4 +14,4 @@ 
 # Append / edit the following list of commands to fit your needs:
 #
 Defaults:zabbix !requiretty
-zabbix ALL=(ALL) NOPASSWD: /opt/pakfire/pakfire status
+zabbix ALL=(ALL) NOPASSWD: /opt/pakfire/pakfire status, /usr/local/bin/addonctrl, /sbin/iptables, /usr/sbin/fping
diff --git a/config/zabbix_agentd/template_module_ipfire_network_stats.conf b/config/zabbix_agentd/template_module_ipfire_network_stats.conf
new file mode 100644
index 000000000..f1658ed07
--- /dev/null
+++ b/config/zabbix_agentd/template_module_ipfire_network_stats.conf
@@ -0,0 +1,4 @@ 
+### Parameters for monitoring IPFire network statistics 
+UserParameter=ipfire.net.gateway.pingtime,sudo /usr/sbin/fping -c 3 gateway 2>&1 | tail -n 1 | awk '{print $NF}' | cut -d '/' -f2
+UserParameter=ipfire.net.gateway.ping,sudo /usr/sbin/fping -q -r 3 gateway; [ ! $? ]; echo $?
+UserParameter=ipfire.net.fw.hits[*],sudo /sbin/iptables -vnxL $1 | grep "\/\* $2 \*\/" | awk '{ print $$2 }';
diff --git a/config/zabbix_agentd/template_module_ipfire_services.conf b/config/zabbix_agentd/template_module_ipfire_services.conf
new file mode 100644
index 000000000..5f95218e3
--- /dev/null
+++ b/config/zabbix_agentd/template_module_ipfire_services.conf
@@ -0,0 +1,2 @@ 
+### Parameter for monitoring IPFire services
+UserParameter=ipfire.services,/etc/zabbix_agentd/scripts/ipfire_services.pl
diff --git a/lfs/zabbix_agentd b/lfs/zabbix_agentd
index badfde3ae..1debfeeb0 100644
--- a/lfs/zabbix_agentd
+++ b/lfs/zabbix_agentd
@@ -33,7 +33,7 @@  DIR_APP    = $(DIR_SRC)/$(THISAPP)
 TARGET     = $(DIR_INFO)/$(THISAPP)
 PROG       = zabbix_agentd
 PAK_VER    = 5
-DEPS       =
+DEPS       = "fping"
 
 ###############################################################################
 # Top-level Rules
@@ -97,6 +97,12 @@  $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
 		/etc/zabbix_agentd/zabbix_agentd.conf.ipfirenew
 	install -v -m 644 $(DIR_SRC)/config/zabbix_agentd/template_app_pakfire.conf \
 		/etc/zabbix_agentd/zabbix_agentd.d/template_app_pakfire.conf.ipfirenew
+	install -v -m 644 $(DIR_SRC)/config/zabbix_agentd/template_module_ipfire_network_stats.conf \
+		/etc/zabbix_agentd/zabbix_agentd.d/template_module_ipfire_network_stats.conf.ipfirenew
+	install -v -m 644 $(DIR_SRC)/config/zabbix_agentd/template_module_ipfire_services.conf \
+		/etc/zabbix_agentd/zabbix_agentd.d/template_module_ipfire_services.conf.ipfirenew
+	install -v -m 755 $(DIR_SRC)/config/zabbix_agentd/ipfire_services.pl \
+		/etc/zabbix_agentd/scripts/ipfire_services.pl.ipfirenew
 
 	# Create directory for additional agent modules
 	-mkdir -pv /usr/lib/zabbix
diff --git a/src/paks/zabbix_agentd/install.sh b/src/paks/zabbix_agentd/install.sh
index 4248a7ec1..ced915c81 100644
--- a/src/paks/zabbix_agentd/install.sh
+++ b/src/paks/zabbix_agentd/install.sh
@@ -66,8 +66,13 @@  restore_backup ${NAME}
 # Put zabbix configfiles in place
 setup_configfile /etc/zabbix_agentd/zabbix_agentd.conf
 setup_configfile /etc/zabbix_agentd/zabbix_agentd.d/template_app_pakfire.conf
+setup_configfile /etc/zabbix_agentd/zabbix_agentd.d/template_module_ipfire_network_stats.conf
+setup_configfile /etc/zabbix_agentd/zabbix_agentd.d/template_module_ipfire_services.conf
 setup_configfile /etc/sudoers.d/zabbix
 
+# Overwrite script if it exists as user should not modify it but it is included in backup
+mv /etc/zabbix_agentd/scripts/ipfire_services.pl.ipfirenew /etc/zabbix_agentd/scripts/ipfire_services.pl
+
 if $review_required; then
 	echo "WARNING: New versions of some configfile(s) where provided as .ipfirenew-files."
 	echo "         They may need manual review in order to take advantage of new features"
diff --git a/src/paks/zabbix_agentd/uninstall.sh b/src/paks/zabbix_agentd/uninstall.sh
index 7a13880c5..ccbc8f7cf 100644
--- a/src/paks/zabbix_agentd/uninstall.sh
+++ b/src/paks/zabbix_agentd/uninstall.sh
@@ -26,6 +26,8 @@  stop_service ${NAME}
 
 # Remove .ipfirenew files in advance so they won't be included in backup
 rm -rfv /etc/zabbix_agentd/*.ipfirenew /etc/zabbix_agentd/*/*.ipfirenew
+# Remove script-file as it should not have been modified by user
+rm -fv /etc/zabbix_agentd/scripts/ipfire_services.pl
 
 make_backup ${NAME}
 remove_files