From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail02.haj.ipfire.org (localhost [IPv6:::1]) by mail02.haj.ipfire.org (Postfix) with ESMTP id 4hBMcx29tWz371D for ; Fri, 31 Jul 2026 10:24:33 +0000 (UTC) Received: from mail01.ipfire.org (mail01.haj.ipfire.org [IPv6:2001:678:b28::25]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature ECDSA (secp384r1 raw public key) server-digest SHA384 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mail01.haj.ipfire.org", Issuer "YR2" (not verified)) by mail02.haj.ipfire.org (Postfix) with ESMTPS id 4hBMcs6Fxhz2xJG for ; Fri, 31 Jul 2026 10:24:29 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail01.ipfire.org (Postfix) with ESMTPSA id 4hBMcj3zYcz2S7; Fri, 31 Jul 2026 10:24:21 +0000 (UTC) DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=ipfire.org; s=202003ed25519; t=1785493461; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=MX5JxIxj/7blFH4399/KJE0kziBSZaLZEWZ8LXOCCVo=; b=tVgGwRQoFdK67qLD01vUa1bkgCd4iu6Ya/7hLyJfqJ+EUGlmSxntTIxSteU6OgMs4HJckG SQgrkndpYRqC5HDQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ipfire.org; s=202003rsa; t=1785493461; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=MX5JxIxj/7blFH4399/KJE0kziBSZaLZEWZ8LXOCCVo=; b=q/NnuIIfCCzEsQlKZ9u6+BUbZwVSa8Aux4GZw+qaeWzTkgF2iofmXgBr8R+CAOxLFXobjx xycJef95S7BUHN0PIsT6U+PIWJNFxesO3NI7dnIvrx7yN3XO6NGSd8TqzSxl3Vt4IbcF1U wX1delJA2urw64hUQbjGtBcZvpJwZBH049lcs/+EG7hXyEMrL0WqNycYN6EjZ18DJVSprM W58SOz1a0HqvpdzhnNZ1L21bb+JtPKkBupGiEnHeK3BYhWS2oJDr0mHouoAF7EZfhqJRAB CmTtqV14EWXEm3UqH+D1wjEXEgIW34W7QRrUhDjHH+0sk6hoec3vcQxBn2mOxw== Content-Type: text/plain; charset=utf-8 Precedence: list List-Id: List-Subscribe: , List-Unsubscribe: , List-Post: List-Help: Sender: Mail-Followup-To: Mime-Version: 1.0 Subject: Re: [PATCH 1/5] Initialize async zabbix sender from zabbix_utils From: Michael Tremer In-Reply-To: <20260730195148.3278295-2-robin.roevens@disroot.org> Date: Fri, 31 Jul 2026 11:24:17 +0100 Cc: development@lists.ipfire.org Content-Transfer-Encoding: quoted-printable Message-Id: References: <20260730195148.3278295-1-robin.roevens@disroot.org> <20260730195148.3278295-2-robin.roevens@disroot.org> To: Robin Roevens Hello, Just as a warning, I am going to be picky :) > On 30 Jul 2026, at 20:15, Robin Roevens = wrote: >=20 > When Zabbix is enabled in new config section [zabbix], and the = zabbix_utils=20 > python module is available, a zabbix AsyncSender object will be = initialized=20 > for sending alerts to Zabbix using parameters from the new config = section. >=20 > Signed-off-by: Robin Roevens > --- > src/reporter.conf.in | 23 +++++++++++++++++++++++ > src/suricata-reporter.in | 37 +++++++++++++++++++++++++++++++++++++ > 2 files changed, 60 insertions(+) >=20 > diff --git a/src/reporter.conf.in b/src/reporter.conf.in > index 5943006..bab01b6 100644 > --- a/src/reporter.conf.in > +++ b/src/reporter.conf.in > @@ -45,3 +45,26 @@ > ; 3 =3D Low Severity > ; 4 =3D Informational > ;severity =3D 3 > + > +[zabbix] > +; Enable sending alerts to Zabbix > +;enabled =3D false > + > +; Path to the Zabbix agent configuration file > +;zabbix_agentd_config =3D /etc/zabbix_agentd/zabbix_agentd.conf > + > +; Zabbix server ip or hostname (required if zabbix_agentd_config is = not set) > +;zabbix_server_host =3D 127.0.0.1 > + > +; Zabbix server port (defaults to 10051 if not set) > +;zabbix_server_port =3D 10051 You seem to like loooong variable names which I would shorten. You are already in the [zabbix] section of the file, so you could simply = call it =E2=80=9Chost=E2=80=9D and =E2=80=9Cport=E2=80=9D. Simple names. > + > +; Hostname as defined in Zabbix server to send alerts to (defaults to = either the > +; Hostname directive in Zabbix Agent config or system hostname) > +;alert_item_hostname =3D IPFire > + > +; Zabbix item key to send alerts to > +;alert_item_key =3D ipfire.suricata.event.get > + > +; Max age (seconds) to retry sending alerts to Zabbix > +;alert_max_age =3D 3600 > \ No newline at end of file > diff --git a/src/suricata-reporter.in b/src/suricata-reporter.in > index 28b55bc..f9da7b4 100644 > --- a/src/suricata-reporter.in > +++ b/src/suricata-reporter.in > @@ -37,6 +37,13 @@ import socket > import sqlite3 > import sys >=20 > +# Load zabbix_utils module if available=20 > +zabbix_utils_available =3D True > +try: > + from zabbix_utils import AsyncSender, ItemValue > +except ImportError: > + zabbix_utils_available =3D False > + To keep the logic in one block, you could add the =E2=80=9CTrue=E2=80=9D = statement to the else: clause of the block. > # Fetch the hostname > HOSTNAME =3D socket.gethostname() >=20 > @@ -75,6 +82,10 @@ class Reporter(object): > # Remember the last time the database was cleaned > self.last_cleanup_at =3D None >=20 > + # Initialize Zabbix sender > + self.zabbix_sender =3D None > + self.init_zabbix_sender() I would have the function just return the sender object. That way, you = can make it one line here and you don=E2=80=99t have to remember the = name of the class variable in the function below. > + > # Register any signals > for signo in (signal.SIGINT, signal.SIGTERM): > self.loop.add_signal_handler(signo, self.terminate) > @@ -97,6 +108,32 @@ class Reporter(object): >=20 > return config >=20 > + def init_zabbix_sender(self): > + """ > + Initialize the Zabbix async sender if configured > + """ > + if not self.config.getboolean('zabbix', 'enabled', fallback=3DFalse): > + return > + > + if not zabbix_utils_available: > + log.error("zabbix-utils is not installed. Zabbix alerts will not be = sent.") > + return > + > + zabbix_config =3D self.config.get('zabbix', 'zabbix_agentd_config', = fallback=3D'') > + zabbix_server_host =3D self.config.get('zabbix', = 'zabbix_server_host', fallback=3D'') > + zabbix_server_port =3D self.config.getint('zabbix', = 'zabbix_server_port', fallback=3D10051) Here you are being bitten by the long names again. This would be much = shorter: host =3D self.config.get('zabbix', 'host', fallback=3D=E2=80=98') Oh, and you seem to be mixing =E2=80=9C and =E2=80=98 a lot in the code = :) Both work, but just =E2=80=9C would be fine for me. > + > + if zabbix_config: > + if not os.path.isfile(zabbix_config): > + log.error(f"Zabbix agent config file {zabbix_config} does not = exist.") > + return > + self.zabbix_sender =3D AsyncSender(use_config=3DTrue, = config_path=3Dzabbix_config) > + else: > + if not zabbix_server_host: > + log.error("zabbix_server_host must be specified when = zabbix_agentd_config is not provided.") > + return > + self.zabbix_sender =3D AsyncSender(server=3Dzabbix_server_host, = port=3Dzabbix_server_port) > + > def _open_database(self): > """ > Opens the database > --=20 > 2.54.0 >=20 >=20 > --=20 > Dit bericht is gescanned op virussen en andere gevaarlijke > inhoud door MailScanner en lijkt schoon te zijn. >=20 >=20