From 6e2c24c9e4421a690543d23b3ca0c94e8fef6681 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Tue, 8 Feb 2022 11:46:32 -0800 Subject: [PATCH] email: rspamd: Simplify installing configuration Existing implementation expects configuration files installed by FreedomBox to be edited at the top and the bottom. When re-installing, it tries to keep the edited parts while reinstalling the FreedomBox managed section in the middle to be overwritten with (new) FreedomBox defaults. Instead, simply ship the two files to rspamd configuration directories. These can be easily overridden by the user if they desire due to flexible configuration file priorities by rspamd. Signed-off-by: Sunil Mohan Adapa Reviewed-by: James Valleroy --- plinth/modules/email/audit/spam.py | 22 ------ .../local.d/freedombox-milter-headers.conf} | 0 .../override.d/freedombox-options.inc} | 0 plinth/modules/email/modconf.py | 78 ------------------- 4 files changed, 100 deletions(-) rename plinth/modules/email/data/etc/{plinth/rspamd-config/local_milter_headers.conf => rspamd/local.d/freedombox-milter-headers.conf} (100%) rename plinth/modules/email/data/etc/{plinth/rspamd-config/override_options.inc => rspamd/override.d/freedombox-options.inc} (100%) delete mode 100644 plinth/modules/email/modconf.py diff --git a/plinth/modules/email/audit/spam.py b/plinth/modules/email/audit/spam.py index a164cdca4..5b3279609 100644 --- a/plinth/modules/email/audit/spam.py +++ b/plinth/modules/email/audit/spam.py @@ -3,14 +3,12 @@ import glob import logging -import re import subprocess from django.utils.translation import gettext_lazy as _ from plinth import actions from plinth.modules.email import interproc, lock, postconf -from plinth.modules.email.modconf import ConfigInjector from . import models @@ -73,12 +71,6 @@ egress_filter_cleanup_options = { 'nested_header_checks': '' } -# Rspamd config - -rspamd_re = re.compile('#[ ]*--[ ]*([A-Z]{3,5})[ ]+FREEDOMBOX CONFIG$') -rspamd_format = '#-- {} FREEDOMBOX CONFIG' - -rspamd_mutex = lock.Mutex('rspamd-config') logger = logging.getLogger(__name__) @@ -116,20 +108,6 @@ def action_set_filter(): with postconf.mutex.lock_all(): fix_filter(check_filter()) - injector = ConfigInjector(rspamd_re, rspamd_format) - with rspamd_mutex.lock_all(): - # XXX Maybe use globbing? - _inject_rspamd_config(injector, 'override', 'options.inc') - _inject_rspamd_config(injector, 'local', 'milter_headers.conf') - - -def _inject_rspamd_config(injector, type, name): - template_path = '/etc/plinth/rspamd-config/%s_%s' % (type, name) - config_path = '/etc/rspamd/%s.d/%s' % (type, name) - - logger.info('Opening Rspamd config file %s', config_path) - injector.do_template_file(template_path, config_path) - def _compile_sieve(): sieve_list = glob.glob('/etc/dovecot/freedombox-sieve-after/*.sieve') diff --git a/plinth/modules/email/data/etc/plinth/rspamd-config/local_milter_headers.conf b/plinth/modules/email/data/etc/rspamd/local.d/freedombox-milter-headers.conf similarity index 100% rename from plinth/modules/email/data/etc/plinth/rspamd-config/local_milter_headers.conf rename to plinth/modules/email/data/etc/rspamd/local.d/freedombox-milter-headers.conf diff --git a/plinth/modules/email/data/etc/plinth/rspamd-config/override_options.inc b/plinth/modules/email/data/etc/rspamd/override.d/freedombox-options.inc similarity index 100% rename from plinth/modules/email/data/etc/plinth/rspamd-config/override_options.inc rename to plinth/modules/email/data/etc/rspamd/override.d/freedombox-options.inc diff --git a/plinth/modules/email/modconf.py b/plinth/modules/email/modconf.py deleted file mode 100644 index d78f9b194..000000000 --- a/plinth/modules/email/modconf.py +++ /dev/null @@ -1,78 +0,0 @@ -# SPDX-License-Identifier: AGPL-3.0-or-later -"""Generic config modifying utilities""" - -import contextlib -import io -import re - -from . import interproc - - -class ConfigInjector: - def __init__(self, match, generate): - self.re_pattern = re.compile(match) - self.boundary_fmt = generate + '\n' - - def do_file_des(self, template, config, scratch): - """Write modified config to the `scratch` stream""" - if not isinstance(template, io.TextIOBase): - raise TypeError('Not a text IO stream: template') - self._inject_config3(template, config, scratch) - - def _inject_config3(self, template, config, scratch): - # Copy the original config up to header line - for line in config: - match = self.re_pattern.match(line.strip()) - if match and match.group(1) == 'BEGIN': - break - scratch.write(line) - if not line.endswith('\n'): # in case no new line was at the eof - scratch.write('\n') - - # Write header line - scratch.write(self.boundary_fmt.format('BEGIN')) - # Write template to scratch - for line in template: - scratch.write(line) - # in case no new line was at the eof - if not line.endswith('\n'): - scratch.write('\n') - # Write footer line - scratch.write(self.boundary_fmt.format('END')) - - # Find the trailer line in config - for line in config: - match = self.re_pattern.match(line.strip()) - if match and match.group(1) == 'END': - break - - # Copy the original - for line in config: - scratch.write(line) # keep original file ending style - - def do_template_file(self, template_path, config_path): - with open(template_path, 'r') as template: - with self._open_config(config_path) as (config, scratch): - self._inject_config3(template, config, scratch) - - def do_template_string(self, template_string, config_path): - with self._open_config(config_path) as (config, scratch): - self._inject_config3([template_string], config, scratch) - - @contextlib.contextmanager - def _open_config(self, config_path): - with open(config_path, 'a+') as config: - with interproc.atomically_rewrite(config_path) as scratch: - config.seek(0) - yield config, scratch - - def has_header_line(self, config_path): - with open(config_path, 'r') as config_fd: - return self._has_header_line(config_fd) - - def _has_header_line(self, config_fd): - for line in config_fd: - match = self.re_pattern.match(line.strip()) - if match and match.group(1) == 'BEGIN': - return True - return False