From f674232f7116acd1d5b2758c52ab5f5827d4d928 Mon Sep 17 00:00:00 2001 From: Georg Lauterbach <44545919+georglauterbach@users.noreply.github.com> Date: Mon, 30 Oct 2023 10:20:37 +0100 Subject: [PATCH] misc: final Rspamd adjustments for v13 (#3599) * outsource Rspamd ENVs into explicit helper This will allow us to uniformly source the helper and get the values from everywhere consistently. This is more than desirable since we will be using these values not only for the Rspamd setup, but also for DKIM management and during change-detection. * integrate Rspamd into changedetection We outsource one more function to reside in the helper script for Rspamd so that we can call this function from the Rspamd setup and from the changedetection functionality too. * realize deprecation of old commands file for Rspamd THIS IS A BREAKING CHANGE! This change realizes the log message: "Using old file location now (deprecated) - this will prevent startup in v13.0.0" Startup will now fail. * added '--force' option to Rspamd DKIM script * use new helper to get ENVs for Rspamd in DKIM script * remove the need for linking directories This was unnecessary, as explained in https://github.com/docker-mailserver/docker-mailserver/pull/3597#discussion_r1369413599 * Apply suggestions from code review review by @polarathene * apply more review feedback from @polarathene - - * update documentation --------- Co-authored-by: Brennan Kinney <5098581+polarathene@users.noreply.github.com> --- CHANGELOG.md | 4 +- docs/content/config/security/rspamd.md | 4 +- target/bin/rspamd-dkim | 63 ++++----- target/scripts/check-for-changes.sh | 32 +++++ target/scripts/helpers/change-detection.sh | 6 + target/scripts/helpers/index.sh | 1 + target/scripts/helpers/rspamd.sh | 105 +++++++++++++++ .../startup/setup.d/security/rspamd.sh | 123 ++---------------- .../parallel/set1/spam_virus/rspamd_dkim.bats | 18 ++- .../parallel/set1/spam_virus/rspamd_full.bats | 5 +- 10 files changed, 205 insertions(+), 156 deletions(-) create mode 100644 target/scripts/helpers/rspamd.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index a2e15c77..0b875e2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,11 +16,13 @@ All notable changes to this project will be documented in this file. The format If necessary, DSNs for authenticated users can be disabled via the `postfix-master.cf` override with the following contents: - ``` + ```cf submission/inet/smtpd_discard_ehlo_keywords=silent-discard,dsn submissions/inet/smtpd_discard_ehlo_keywords=silent-discard,dsn ``` +- using the old path for the Rspamd custom commands file (`/tmp/docker-mailserver/rspamd-modules.conf`), which was deprecated, will now prevent startup; use `/tmp/docker-mailserver/rspamd/custom-commands.conf` instead + ### Added - New environment variable `MARK_SPAM_AS_READ`. When set to `1`, marks incoming junk as "read" to avoid unwanted notification of junk as new mail ([#3489](https://github.com/docker-mailserver/docker-mailserver/pull/3489)) diff --git a/docs/content/config/security/rspamd.md b/docs/content/config/security/rspamd.md index 94be2db9..5867b1e8 100644 --- a/docs/content/config/security/rspamd.md +++ b/docs/content/config/security/rspamd.md @@ -107,11 +107,11 @@ DMS brings sane default settings for Rspamd. They are located at `/etc/rspamd/lo !!! question "What is [`docker-data/dms/config/`][docs-dms-config-volume]?" -If you want to overwrite the default settings and / or provide your own settings, you can place files at `docker-data/dms/config/rspamd/override.d/` (a directory that is linked to `/etc/rspamd/override.d/`, if it exists) to override Rspamd and DMS default settings. This directory will not do a complete file override, but a [forced override of the specific settings in that file][rspamd-docs-override-dir]. +If you want to overwrite the default settings and / or provide your own settings, you can place files at `docker-data/dms/config/rspamd/override.d/`. Files from this directory are copied to `/etc/rspamd/override.d/` during startup. These files [forcibly override][rspamd-docs-override-dir] Rspamd and DMS default settings. !!! warning "Clashing Overrides" - Note that when also [using the `rspamd-commands` file](#with-the-help-of-a-custom-file), files in `override.d` may be overwritten in case you adjust them manually and with the help of the file. + Note that when also [using the `custom-commands.conf` file](#with-the-help-of-a-custom-file), files in `override.d` may be overwritten in case you adjust them manually and with the help of the file. [rspamd-docs-override-dir]: https://www.rspamd.com/doc/faq.html#what-are-the-locald-and-overrided-directories [docs-dms-config-volume]: ../../faq.md#what-about-the-docker-datadmsconfig-directory diff --git a/target/bin/rspamd-dkim b/target/bin/rspamd-dkim index 576c55ab..357c2a9c 100755 --- a/target/bin/rspamd-dkim +++ b/target/bin/rspamd-dkim @@ -27,9 +27,10 @@ ${ORANGE}DESCRIPTION${RESET} ${ORANGE}OPTIONS${RESET} ${BLUE}Generic Program Information${RESET} - -v Enable verbose logging (setting the log level to 'debug'). - -vv Enable very verbose logging (setting the log level to 'trace'). - help Print the usage information. + -f | --force Overwrite existing files if there are any + -v Enable verbose logging (setting the log level to 'debug'). + -vv Enable very verbose logging (setting the log level to 'trace'). + help Print the usage information. ${BLUE}Configuration adjustments${RESET} keytype Set the type of key you want to use. @@ -69,6 +70,7 @@ function __do_as_rspamd_user() { } function _parse_arguments() { + FORCE=0 KEYTYPE='rsa' KEYSIZE='2048' SELECTOR='mail' @@ -112,6 +114,12 @@ function _parse_arguments() { exit 0 ;; + ( '-f' | '--force' ) + FORCE=1 + shift 1 + continue + ;; + ( '-vv' ) # shellcheck disable=SC2034 LOG_LEVEL='trace' @@ -132,7 +140,6 @@ function _parse_arguments() { __usage _exit_with_error "Unknown option(s) '${1}' ${2:+"and '${2}'"}" ;; - esac shift 2 @@ -150,34 +157,10 @@ function _preflight_checks() { _log 'warn' "The directory '/tmp/docker-mailserver' does not seem to be mounted by a volume - the Rspamd (DKIM) configuration will not be persisted" fi - # Note: Variables not marked with `local` are used - # in other functions (after this function was called). - # Also keep in sync with: target/scripts/startup/setup.d/security/rspamd.sh:__rspamd__run_early_setup_and_checks - local RSPAMD_DMS_D='/tmp/docker-mailserver/rspamd' - local RSPAMD_OVERRIDE_D='/etc/rspamd/override.d' - readonly RSPAMD_DMS_DKIM_D="${RSPAMD_DMS_D}/dkim" - readonly RSPAMD_DMS_OVERRIDE_D="${RSPAMD_DMS_D}/override.d" + _rspamd_get_envs mkdir -p "${RSPAMD_DMS_DKIM_D}" "${RSPAMD_DMS_OVERRIDE_D}" chown _rspamd:_rspamd "${RSPAMD_DMS_DKIM_D}" - - # Mimmick target/scripts/startup/setup.d/security/rspamd.sh:__rspamd__run_early_setup_and_checks where - # ${RSPAMD_OVERRIDE_D} is linked to ${RSPAMD_DMS_OVERRIDE_D}, but not if - # - # 1. ${RSPAMD_OVERRIDE_D} has already been linked to ${RSPAMD_DMS_OVERRIDE_D} - # 2. ${RSPAMD_OVERRIDE_D} has contents already - # - # If 1. is true, then we're good since DMS' default setup linked the directory already and we will save - # a persisted location in every case. If 1. is false, 2. should be false as well since by default, - # ${RSPAMD_OVERRIDE_D} has no contents - we're good as well. What should logically never happen is - # that 1. is false but 2. is true; this case is caught nevertheless and a warning is emitted. - if [[ ! -h "${RSPAMD_OVERRIDE_D}" ]]; then - if rmdir "${RSPAMD_OVERRIDE_D}" &>/dev/null; then - ln -s "${RSPAMD_DMS_OVERRIDE_D}" "${RSPAMD_OVERRIDE_D}" - else - _log 'warn' "Could not link '${RSPAMD_OVERRIDE_D}' to '${RSPAMD_DMS_OVERRIDE_D}' (as '${RSPAMD_OVERRIDE_D}' does not appear to be empty, which is unexpected) - you will need to restart DMS for changes to take effect" - fi - fi } function _create_keys() { @@ -195,6 +178,16 @@ function _create_keys() { PUBLIC_KEY_DNS_FILE="${BASE_FILE_NAME}.public.dns.txt" PRIVATE_KEY_FILE="${BASE_FILE_NAME}.private.txt" + if [[ -f ${PUBLIC_KEY_FILE} ]] || [[ -f ${PUBLIC_KEY_DNS_FILE} ]] || [[ -f ${PRIVATE_KEY_FILE} ]]; then + if [[ ${FORCE} -eq 0 ]]; then + _log 'error' "Not overwriting existing files (use '--force' to overwrite existing files)" + exit 1 + else + _log 'info' "Overwriting existing files as the '--force' option was supplied" + rm "${PUBLIC_KEY_FILE}" "${PUBLIC_KEY_DNS_FILE}" "${PRIVATE_KEY_FILE}" + fi + fi + # shellcheck disable=SC2310 if __do_as_rspamd_user rspamadm \ dkim_keygen \ @@ -226,7 +219,7 @@ function _check_permissions() { function _setup_default_signing_conf() { local DEFAULT_CONFIG_FILE="${RSPAMD_DMS_OVERRIDE_D}/dkim_signing.conf" if [[ -f ${DEFAULT_CONFIG_FILE} ]]; then - _log 'debug' "'${DEFAULT_CONFIG_FILE}' exists, not supplying a default" + _log 'info' "'${DEFAULT_CONFIG_FILE}' exists, not supplying a default ('--force' does not overwrite this file, manual adjustment required)" else _log 'info' "Supplying a default configuration (to '${DEFAULT_CONFIG_FILE}')" cat >"${DEFAULT_CONFIG_FILE}" << EOF @@ -253,7 +246,15 @@ domain { } EOF - chown _rspamd:_rspamd "${DEFAULT_CONFIG_FILE}" + + # We copy here immediately in order to not rely on the changedetector - this way, users + # can immediately use the new keys. The file should not already exist in ${RSPAMD_OVERRIDE_D} + # since it would have been copied already. + cp "${DEFAULT_CONFIG_FILE}" "${RSPAMD_OVERRIDE_D}/dkim_signing.conf" + chown _rspamd:_rspamd "${DEFAULT_CONFIG_FILE}" "${RSPAMD_OVERRIDE_D}/dkim_signing.conf" + + _log 'debug' 'Restarting Rspamd as initial DKIM configuration was suppplied' + supervisorctl restart rspamd fi } diff --git a/target/scripts/check-for-changes.sh b/target/scripts/check-for-changes.sh index a8cdeb68..66417c09 100755 --- a/target/scripts/check-for-changes.sh +++ b/target/scripts/check-for-changes.sh @@ -21,6 +21,10 @@ source /etc/dms-settings # usage with DMS_HOSTNAME, which should remove the need to call this: _obtain_hostname_and_domainname +# This is a helper to properly set all Rspamd-related environment variables +# correctly and in one place. +_rspamd_get_envs + # verify checksum file exists; must be prepared by start-mailserver.sh if [[ ! -f ${CHKSUM_FILE} ]]; then _exit_with_error "'${CHKSUM_FILE}' is missing" 0 @@ -49,6 +53,7 @@ function _check_for_changes() { # Handle any changes _ssl_changes _postfix_dovecot_changes + _rspamd_changes _log_with_date 'debug' 'Reloading services due to detected changes' @@ -174,6 +179,33 @@ function _ssl_changes() { # They presently have no special handling other than to trigger a change that will restart Postfix/Dovecot. } +function _rspamd_changes() { + # RSPAMD_DMS_D='/tmp/docker-mailserver/rspamd' + if [[ ${CHANGED} =~ ${RSPAMD_DMS_D}/.* ]]; then + + # "${RSPAMD_DMS_D}/override.d" + if [[ ${CHANGED} =~ ${RSPAMD_DMS_OVERRIDE_D}/.* ]]; then + _log_with_date 'trace' 'Rspamd - Copying configuration overrides' + rm "${RSPAMD_OVERRIDE_D}"/* + cp "${RSPAMD_DMS_OVERRIDE_D}"/* "${RSPAMD_OVERRIDE_D}" + fi + + # "${RSPAMD_DMS_D}/custom-commands.conf" + if [[ ${CHANGED} =~ ${RSPAMD_DMS_CUSTOM_COMMANDS_F} ]]; then + _log_with_date 'trace' 'Rspamd - Generating new configuration from custom commands' + _rspamd_handle_user_modules_adjustments + fi + + # "${RSPAMD_DMS_D}/dkim" + if [[ ${CHANGED} =~ ${RSPAMD_DMS_DKIM_D} ]]; then + _log_with_date 'trace' 'Rspamd - DKIM files updated' + fi + + _log_with_date 'debug' 'Rspamd configuration has changed - restarting service' + supervisorctl restart rspamd + fi +} + while true; do _check_for_changes sleep 2 diff --git a/target/scripts/helpers/change-detection.sh b/target/scripts/helpers/change-detection.sh index e396bfe2..08f6906c 100644 --- a/target/scripts/helpers/change-detection.sh +++ b/target/scripts/helpers/change-detection.sh @@ -40,6 +40,12 @@ function _monitored_files_checksums() { "${DMS_DIR}/dovecot-quotas.cf" "${DMS_DIR}/dovecot-masters.cf" ) + + # Check whether Rspamd is used and if so, monitor it's changes as well + if [[ ${ENABLE_RSPAMD} -eq 1 ]] && [[ -d ${RSPAMD_DMS_D} ]]; then + readarray -d '' STAGING_FILES_RSPAMD < <(find "${RSPAMD_DMS_D}" -type f -name "*.sh" -print0) + STAGING_FILES+=("${STAGING_FILES_RSPAMD[@]}") + fi fi # SSL certs: diff --git a/target/scripts/helpers/index.sh b/target/scripts/helpers/index.sh index 8d876739..0d77c9c4 100644 --- a/target/scripts/helpers/index.sh +++ b/target/scripts/helpers/index.sh @@ -16,6 +16,7 @@ function _import_scripts() { source "${PATH_TO_SCRIPTS}/network.sh" source "${PATH_TO_SCRIPTS}/postfix.sh" source "${PATH_TO_SCRIPTS}/relay.sh" + source "${PATH_TO_SCRIPTS}/rspamd.sh" source "${PATH_TO_SCRIPTS}/ssl.sh" source "${PATH_TO_SCRIPTS}/utils.sh" diff --git a/target/scripts/helpers/rspamd.sh b/target/scripts/helpers/rspamd.sh new file mode 100644 index 00000000..868e3d3a --- /dev/null +++ b/target/scripts/helpers/rspamd.sh @@ -0,0 +1,105 @@ +#! /bin/bash + +# shellcheck disable=SC2034 # VAR appears unused. + +function _rspamd_get_envs() { + readonly RSPAMD_LOCAL_D='/etc/rspamd/local.d' + readonly RSPAMD_OVERRIDE_D='/etc/rspamd/override.d' + + readonly RSPAMD_DMS_D='/tmp/docker-mailserver/rspamd' + readonly RSPAMD_DMS_DKIM_D="${RSPAMD_DMS_D}/dkim" + readonly RSPAMD_DMS_OVERRIDE_D="${RSPAMD_DMS_D}/override.d" + + readonly RSPAMD_DMS_CUSTOM_COMMANDS_F="${RSPAMD_DMS_D}/custom-commands.conf" +} + +# Parses `RSPAMD_DMS_CUSTOM_COMMANDS_F` and executed the directives given by the file. +# To get a detailed explanation of the commands and how the file works, visit +# https://docker-mailserver.github.io/docker-mailserver/latest/config/security/rspamd/#with-the-help-of-a-custom-file +function _rspamd_handle_user_modules_adjustments() { + # Adds an option with a corresponding value to a module, or, in case the option + # is already present, overwrites it. + # + # @param ${1} = file name in ${RSPAMD_OVERRIDE_D}/ + # @param ${2} = module name as it should appear in the log + # @param ${3} = option name in the module + # @param ${4} = value of the option + # + # ## Note + # + # While this function is currently bound to the scope of `_rspamd_handle_user_modules_adjustments`, + # it is written in a versatile way (taking 4 arguments instead of assuming `ARGUMENT2` / `ARGUMENT3` + # are set) so that it may be used elsewhere if needed. + function __add_or_replace() { + local MODULE_FILE=${1:?Module file name must be provided} + local MODULE_LOG_NAME=${2:?Module log name must be provided} + local OPTION=${3:?Option name must be provided} + local VALUE=${4:?Value belonging to an option must be provided} + # remove possible whitespace at the end (e.g., in case ${ARGUMENT3} is empty) + VALUE=${VALUE% } + local FILE="${RSPAMD_OVERRIDE_D}/${MODULE_FILE}" + + readonly MODULE_FILE MODULE_LOG_NAME OPTION VALUE FILE + + [[ -f ${FILE} ]] || touch "${FILE}" + + if grep -q -E "${OPTION}.*=.*" "${FILE}"; then + __rspamd__log 'trace' "Overwriting option '${OPTION}' with value '${VALUE}' for ${MODULE_LOG_NAME}" + sed -i -E "s|([[:space:]]*${OPTION}).*|\1 = ${VALUE};|g" "${FILE}" + else + __rspamd__log 'trace' "Setting option '${OPTION}' for ${MODULE_LOG_NAME} to '${VALUE}'" + echo "${OPTION} = ${VALUE};" >>"${FILE}" + fi + } + + # We check for usage of the previous location of the commands file. + # TODO This can be removed after the release of v14.0.0. + local RSPAMD_DMS_CUSTOM_COMMANDS_F_OLD="${RSPAMD_DMS_D}-modules.conf" + readonly RSPAMD_DMS_CUSTOM_COMMANDS_F_OLD + if [[ -f ${RSPAMD_DMS_CUSTOM_COMMANDS_F_OLD} ]]; then + _dms_panic__general "Old custom command file location '${RSPAMD_DMS_CUSTOM_COMMANDS_F_OLD}' is deprecated (use '${RSPAMD_DMS_CUSTOM_COMMANDS_F}' now)" 'Rspamd setup' + fi + + if [[ -f "${RSPAMD_DMS_CUSTOM_COMMANDS_F}" ]]; then + __rspamd__log 'debug' "Found file '${RSPAMD_DMS_CUSTOM_COMMANDS_F}' - parsing and applying it" + + local COMMAND ARGUMENT1 ARGUMENT2 ARGUMENT3 + while read -r COMMAND ARGUMENT1 ARGUMENT2 ARGUMENT3; do + case "${COMMAND}" in + ('disable-module') + __rspamd__helper__enable_disable_module "${ARGUMENT1}" 'false' 'override' + ;; + + ('enable-module') + __rspamd__helper__enable_disable_module "${ARGUMENT1}" 'true' 'override' + ;; + + ('set-option-for-module') + __add_or_replace "${ARGUMENT1}.conf" "module '${ARGUMENT1}'" "${ARGUMENT2}" "${ARGUMENT3}" + ;; + + ('set-option-for-controller') + __add_or_replace 'worker-controller.inc' 'controller worker' "${ARGUMENT1}" "${ARGUMENT2} ${ARGUMENT3}" + ;; + + ('set-option-for-proxy') + __add_or_replace 'worker-proxy.inc' 'proxy worker' "${ARGUMENT1}" "${ARGUMENT2} ${ARGUMENT3}" + ;; + + ('set-common-option') + __add_or_replace 'options.inc' 'common options' "${ARGUMENT1}" "${ARGUMENT2} ${ARGUMENT3}" + ;; + + ('add-line') + __rspamd__log 'trace' "Adding complete line to '${ARGUMENT1}'" + echo "${ARGUMENT2}${ARGUMENT3+ ${ARGUMENT3}}" >>"${RSPAMD_OVERRIDE_D}/${ARGUMENT1}" + ;; + + (*) + __rspamd__log 'warn' "Command '${COMMAND}' is invalid" + continue + ;; + esac + done < <(_get_valid_lines_from_file "${RSPAMD_DMS_CUSTOM_COMMANDS_F}") + fi +} diff --git a/target/scripts/startup/setup.d/security/rspamd.sh b/target/scripts/startup/setup.d/security/rspamd.sh index 38b83444..19ce75dc 100644 --- a/target/scripts/startup/setup.d/security/rspamd.sh +++ b/target/scripts/startup/setup.d/security/rspamd.sh @@ -1,12 +1,17 @@ #!/bin/bash -# Function called during global setup to handle the complete setup of Rspamd. +# This file is executed during startup of DMS. Hence, the `index.sh` helper has already +# been sourced, and thus, all helper functions from `rspamd.sh` are available. + +# Function called during global setup to handle the complete setup of Rspamd. Functions +# with a single `_` prefix are sourced from the `rspamd.sh` helper. function _setup_rspamd() { if _env_var_expect_zero_or_one 'ENABLE_RSPAMD' && [[ ${ENABLE_RSPAMD} -eq 1 ]]; then _log 'debug' 'Enabling and configuring Rspamd' __rspamd__log 'trace' '---------- Setup started ----------' - __rspamd__run_early_setup_and_checks # must run first + _rspamd_get_envs # must run first + __rspamd__run_early_setup_and_checks # must run second __rspamd__setup_logfile __rspamd__setup_redis __rspamd__setup_postfix @@ -16,7 +21,7 @@ function _setup_rspamd() { __rspamd__setup_greylisting __rspamd__setup_hfilter_group __rspamd__setup_check_authenticated - __rspamd__handle_user_modules_adjustments # must run last + _rspamd_handle_user_modules_adjustments # must run last __rspamd__log 'trace' '---------- Setup finished ----------' else @@ -64,26 +69,11 @@ EOF # Run miscellaneous early setup tasks and checks, such as creating files needed at runtime # or checking for other anti-spam/anti-virus software. function __rspamd__run_early_setup_and_checks() { - # Note: Variables not marked with `local` are - # used in other functions as well. - readonly RSPAMD_LOCAL_D='/etc/rspamd/local.d' - readonly RSPAMD_OVERRIDE_D='/etc/rspamd/override.d' - readonly RSPAMD_DMS_D='/tmp/docker-mailserver/rspamd' - - local RSPAMD_DMS_OVERRIDE_D="${RSPAMD_DMS_D}/override.d" - readonly RSPAMD_DMS_OVERRIDE_D - mkdir -p /var/lib/rspamd/ : >/var/lib/rspamd/stats.ucl if [[ -d ${RSPAMD_DMS_OVERRIDE_D} ]]; then - __rspamd__log 'debug' "Found directory '${RSPAMD_DMS_OVERRIDE_D}' - linking it to '${RSPAMD_OVERRIDE_D}'" - if rmdir "${RSPAMD_OVERRIDE_D}" 2>/dev/null; then - ln -s "${RSPAMD_DMS_OVERRIDE_D}" "${RSPAMD_OVERRIDE_D}" - else - __rspamd__log 'warn' "Could not remove '${RSPAMD_OVERRIDE_D}' (not empty?; not a directory?; did you restart properly?) - not linking '${RSPAMD_DMS_OVERRIDE_D}'" - __rspamd__log 'warn' "Note that using '${RSPAMD_DMS_OVERRIDE_D}' and placing files manually in '${RSPAMD_OVERRIDE_D}' is not supported" - fi + cp "${RSPAMD_DMS_OVERRIDE_D}"/* "${RSPAMD_OVERRIDE_D}" fi if [[ ${ENABLE_AMAVIS} -eq 1 ]] || [[ ${ENABLE_SPAMASSASSIN} -eq 1 ]]; then @@ -304,98 +294,3 @@ function __rspamd__setup_check_authenticated() { "${MODULE_FILE}" fi } - -# Parses `RSPAMD_CUSTOM_COMMANDS_FILE` and executed the directives given by the file. -# To get a detailed explanation of the commands and how the file works, visit -# https://docker-mailserver.github.io/docker-mailserver/edge/config/security/rspamd/#with-the-help-of-a-custom-file -function __rspamd__handle_user_modules_adjustments() { - # Adds an option with a corresponding value to a module, or, in case the option - # is already present, overwrites it. - # - # @param ${1} = file name in ${RSPAMD_OVERRIDE_D}/ - # @param ${2} = module name as it should appear in the log - # @param ${3} = option name in the module - # @param ${4} = value of the option - # - # ## Note - # - # While this function is currently bound to the scope of `__rspamd__handle_user_modules_adjustments`, - # it is written in a versatile way (taking 4 arguments instead of assuming `ARGUMENT2` / `ARGUMENT3` - # are set) so that it may be used elsewhere if needed. - function __add_or_replace() { - local MODULE_FILE=${1:?Module file name must be provided} - local MODULE_LOG_NAME=${2:?Module log name must be provided} - local OPTION=${3:?Option name must be provided} - local VALUE=${4:?Value belonging to an option must be provided} - # remove possible whitespace at the end (e.g., in case ${ARGUMENT3} is empty) - VALUE=${VALUE% } - local FILE="${RSPAMD_OVERRIDE_D}/${MODULE_FILE}" - - readonly MODULE_FILE MODULE_LOG_NAME OPTION VALUE FILE - - [[ -f ${FILE} ]] || touch "${FILE}" - - if grep -q -E "${OPTION}.*=.*" "${FILE}"; then - __rspamd__log 'trace' "Overwriting option '${OPTION}' with value '${VALUE}' for ${MODULE_LOG_NAME}" - sed -i -E "s|([[:space:]]*${OPTION}).*|\1 = ${VALUE};|g" "${FILE}" - else - __rspamd__log 'trace' "Setting option '${OPTION}' for ${MODULE_LOG_NAME} to '${VALUE}'" - echo "${OPTION} = ${VALUE};" >>"${FILE}" - fi - } - - local RSPAMD_CUSTOM_COMMANDS_FILE="${RSPAMD_DMS_D}/custom-commands.conf" - local RSPAMD_CUSTOM_COMMANDS_FILE_OLD="${RSPAMD_DMS_D}-modules.conf" - readonly RSPAMD_CUSTOM_COMMANDS_FILE RSPAMD_CUSTOM_COMMANDS_FILE_OLD - - # We check for usage of the previous location of the commands file. - # This can be removed after the release of v14.0.0. - if [[ -f ${RSPAMD_CUSTOM_COMMANDS_FILE_OLD} ]]; then - __rspamd__log 'warn' "Detected usage of old file location for modules adjustment ('${RSPAMD_CUSTOM_COMMANDS_FILE_OLD}') - please use the new location ('${RSPAMD_CUSTOM_COMMANDS_FILE}')" - __rspamd__log 'warn' "Using old file location now (deprecated) - this will prevent startup in v13.0.0" - RSPAMD_CUSTOM_COMMANDS_FILE=${RSPAMD_CUSTOM_COMMANDS_FILE_OLD} - fi - - if [[ -f "${RSPAMD_CUSTOM_COMMANDS_FILE}" ]]; then - __rspamd__log 'debug' "Found file '${RSPAMD_CUSTOM_COMMANDS_FILE}' - parsing and applying it" - - local COMMAND ARGUMENT1 ARGUMENT2 ARGUMENT3 - while read -r COMMAND ARGUMENT1 ARGUMENT2 ARGUMENT3; do - case "${COMMAND}" in - ('disable-module') - __rspamd__helper__enable_disable_module "${ARGUMENT1}" 'false' 'override' - ;; - - ('enable-module') - __rspamd__helper__enable_disable_module "${ARGUMENT1}" 'true' 'override' - ;; - - ('set-option-for-module') - __add_or_replace "${ARGUMENT1}.conf" "module '${ARGUMENT1}'" "${ARGUMENT2}" "${ARGUMENT3}" - ;; - - ('set-option-for-controller') - __add_or_replace 'worker-controller.inc' 'controller worker' "${ARGUMENT1}" "${ARGUMENT2} ${ARGUMENT3}" - ;; - - ('set-option-for-proxy') - __add_or_replace 'worker-proxy.inc' 'proxy worker' "${ARGUMENT1}" "${ARGUMENT2} ${ARGUMENT3}" - ;; - - ('set-common-option') - __add_or_replace 'options.inc' 'common options' "${ARGUMENT1}" "${ARGUMENT2} ${ARGUMENT3}" - ;; - - ('add-line') - __rspamd__log 'trace' "Adding complete line to '${ARGUMENT1}'" - echo "${ARGUMENT2}${ARGUMENT3+ ${ARGUMENT3}}" >>"${RSPAMD_OVERRIDE_D}/${ARGUMENT1}" - ;; - - (*) - __rspamd__log 'warn' "Command '${COMMAND}' is invalid" - continue - ;; - esac - done < <(_get_valid_lines_from_file "${RSPAMD_CUSTOM_COMMANDS_FILE}") - fi -} diff --git a/test/tests/parallel/set1/spam_virus/rspamd_dkim.bats b/test/tests/parallel/set1/spam_virus/rspamd_dkim.bats index 76c301ea..215b334d 100644 --- a/test/tests/parallel/set1/spam_virus/rspamd_dkim.bats +++ b/test/tests/parallel/set1/spam_virus/rspamd_dkim.bats @@ -68,8 +68,14 @@ function teardown_file() { _default_teardown ; } local INITIAL_SHA512_SUM=$(_exec_in_container sha512sum "${SIGNING_CONF_FILE}") __create_key + assert_failure + assert_output --partial "Not overwriting existing files (use '--force' to overwrite existing files)" + + # the same as before, but with the '--force' option + __create_key 'rsa' 'mail' "${DOMAIN_NAME}" '2048' '--force' __log_is_free_of_warnings_and_errors refute_output --partial "Supplying a default configuration ('${SIGNING_CONF_FILE}')" + assert_output --partial "Overwriting existing files as the '--force' option was supplied" assert_output --partial "'${SIGNING_CONF_FILE}' exists, not supplying a default" assert_output --partial "Finished DKIM key creation" local SECOND_SHA512_SUM=$(_exec_in_container sha512sum "${SIGNING_CONF_FILE}") @@ -188,11 +194,15 @@ function __create_key() { local SELECTOR=${2:-mail} local DOMAIN=${3:-${DOMAIN_NAME}} local KEYSIZE=${4:-2048} + local FORCE=${5:-} - _run_in_container setup config dkim \ - keytype "${KEYTYPE}" \ - keysize "${KEYSIZE}" \ - selector "${SELECTOR}" \ + # Not quoting is intended here as we would othewise provide + # the argument "''" (empty string), which would cause errors + # shellcheck disable=SC2086 + _run_in_container setup config dkim ${FORCE} \ + keytype "${KEYTYPE}" \ + keysize "${KEYSIZE}" \ + selector "${SELECTOR}" \ domain "${DOMAIN}" } diff --git a/test/tests/parallel/set1/spam_virus/rspamd_full.bats b/test/tests/parallel/set1/spam_virus/rspamd_full.bats index 3fbf59d2..09d42d46 100644 --- a/test/tests/parallel/set1/spam_virus/rspamd_full.bats +++ b/test/tests/parallel/set1/spam_virus/rspamd_full.bats @@ -66,12 +66,9 @@ function teardown_file() { _default_teardown ; } assert_output 'rspamd_milter = inet:localhost:11332' } -@test "'/etc/rspamd/override.d/' is linked correctly" { +@test "contents of '/etc/rspamd/override.d/' are copied" { local OVERRIDE_D='/etc/rspamd/override.d' - _run_in_container_bash "[[ -h ${OVERRIDE_D} ]]" - assert_success - _run_in_container_bash "[[ -f ${OVERRIDE_D}/testmodule_complicated.conf ]]" assert_success }