docker-mailserver/test/tests/parallel/set1/spam_virus/rspamd_dkim.bats

278 lines
10 KiB
Plaintext
Raw Normal View History

load "${REPOSITORY_ROOT}/test/helper/common"
load "${REPOSITORY_ROOT}/test/helper/setup"
BATS_TEST_NAME_PREFIX='[Rspamd] (DKIM) '
CONTAINER_NAME='dms-test_rspamd-dkim'
DOMAIN_NAME='example.test'
SIGNING_CONF_FILE='/tmp/docker-mailserver/rspamd/override.d/dkim_signing.conf'
function setup_file() {
_init_with_defaults
# Comment for maintainers about `PERMIT_DOCKER=host`:
# https://github.com/docker-mailserver/docker-mailserver/pull/2815/files#r991087509
local CUSTOM_SETUP_ARGUMENTS=(
--env ENABLE_RSPAMD=1
--env ENABLE_OPENDKIM=0
--env ENABLE_OPENDMARC=0
--env ENABLE_POLICYD_SPF=0
--env LOG_LEVEL=trace
--env OVERRIDE_HOSTNAME="mail.${DOMAIN_NAME}"
)
_common_container_setup 'CUSTOM_SETUP_ARGUMENTS'
_wait_for_service rspamd-redis
_wait_for_service rspamd
}
# We want each test to start with a clean state.
function teardown() {
__remove_signing_config_file
_run_in_container rm -rf /tmp/docker-mailserver/rspamd/dkim
assert_success
}
function teardown_file() { _default_teardown ; }
@test 'log level is applied correctly' {
_run_in_container setup config dkim -vv help
__log_is_free_of_warnings_and_errors
assert_output --partial 'Enabled trace-logging'
_run_in_container setup config dkim -v help
__log_is_free_of_warnings_and_errors
assert_output --partial 'Enabled debug-logging'
}
@test 'help message is properly shown' {
_run_in_container setup config dkim help
__log_is_free_of_warnings_and_errors
assert_output --partial 'Showing usage message now'
chore: Change `setup config dkim` default key size to `2048` (`open-dkim`) (#3508) * chore: Adjust default DKIM size (`open-dkim`) from 4096-bit to 2048-bit 4096-bit is excessive in size for DKIM key. 2048-bit is plenty. * chore: Additional revisions to `open-dkim` command help output - The examples use `keysize 2048`, but as that's the new default it makes sense to change that. - Other help text was also revised. - Last example for domains did not need to demonstrate the other options. Changed example domains to more appropriate values. * docs: Revise DKIM docs Primarily for the change in default key size, but does revise some text to better communicate to the user. - While the referenced RFC advises 512-bit to 2048-bit key size, we now explicitly discourage `512-bit` as it's not secure. `1024-bit` is still likely safe for most, but `2048-bit` is a good default for those not rotating their keys. - Adjusted the domains example to match the new `setup config dkim domain` domains example. - Tip for changing default key size changed to "info" with added clarity of lowering security or increasing it (excessively). - Rspamd section is minor formatting changes, with the exception of clarifying the "main domain" for the mail accounts is assumed as the DMS FQDN with any subdomain (like `mail.`) stripped away. This is not great, but a legacy issue that needs to be addressed in future. - `docs-rspamd-override-d` ref removed, and usage replaced with equivalent ref `docs-rspamd-config-dropin`, while `docs-rspamd-config-declarative` ref was not in use and also removed. - Revised the `<selector>.txt` DNS formatting info section to better communicate with the reader. Additionally it had mixed usage of default `mail` and custom `dkim-rsa` selectors (_file content and output_). * docs: Sync DKIM commands help messages and update DKIM docs for LDAP - Adopt the help options format style from the `rspamd-dkim` into `open-dkim` command. And convert `./setup.sh` to `setup`. `selector` option has been implemented. for a while now. - Update `rspamd-dkim` examples help output to align with `open-dkim` command examples. - Give both DKIM command tools a consistent description. The two tools differ in support for the `domain` option (_implicit domain sourcing for default account provisioner, and support for multiple domains as input_). - DKIM docs for LDAP domain support revised to better communicate when explicit domain config is necessary. * tests: Adjust test-cases for `setup config dkim` change `rspamd_dkim.bats`: - Update assert for command help output. - Don't bother creating a DKIM key at 512-bit size. `setup_cli.bats`: - Update assert for command help output of the `setup config dkim` (OpenDKIM) command. * docs: Update DKIM section for large keys to newer RFC The linked discussion from 2021 does mention this updated RFC over the original. That removes outdated advice about `512-bit` key length support. The discussion link is still kept to reference a comment for the reader to better understand the security strength of 2048-bit RSA keys and why larger keys are not worthwhile, especially for DKIM. * docs: Extract out common DKIM generation command from content tabs Should be fine to be DRY here, not specific to `open-dkim` or `rspamd` generation/support. Previously rspamd lacked support of an equivalent command in DMS. * docs: DKIM refactoring - Shifted out the info admonition on key size advice out of the content tabs as it's now generic information. - Indented the 4096-bit warning into this, which is less of a concern as the default for our DKIM generation tools is consistently 2048-bit now. - Reworked the LDAP and Rspamd multi-domain advice. To avoid causing a bad diff, these sections haven't been moved/merged yet. * docs: Revise DKIM docs Advice for managing domains individually with LDAP and Rspamd extracted out of the content tabs. Default domain behaviour explained with extra info about OpenDKIM + FILE provisioner sourcing extra domains implicitly.
2023-08-28 21:40:02 +00:00
assert_output --partial 'rspamd-dkim - Configure DKIM (DomainKeys Identified Mail)'
}
@test 'default signing config is created if it does not exist and not overwritten' {
# Required pre-condition: no default configuration is present
__remove_signing_config_file
__create_key
assert_success
__log_is_free_of_warnings_and_errors
assert_output --partial "Supplying a default configuration (to '${SIGNING_CONF_FILE}')"
refute_output --partial "'${SIGNING_CONF_FILE}' exists, not supplying a default"
assert_output --partial "Finished DKIM key creation"
_run_in_container_bash "[[ -f ${SIGNING_CONF_FILE} ]]"
assert_success
_exec_in_container_bash "echo 'blabla' >${SIGNING_CONF_FILE}"
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}")
assert_equal "${INITIAL_SHA512_SUM}" "${SECOND_SHA512_SUM}"
}
@test 'default directories and files are created' {
__create_key
assert_success
_count_files_in_directory_in_container /tmp/docker-mailserver/rspamd/dkim/ 3
_run_in_container_bash "[[ -f ${SIGNING_CONF_FILE} ]]"
assert_success
__check_path_in_signing_config "/tmp/docker-mailserver/rspamd/dkim/rsa-2048-mail-${DOMAIN_NAME}.private.txt"
__check_selector_in_signing_config 'mail'
}
@test "argument 'domain' is applied correctly" {
2023-05-26 12:00:40 +00:00
for DOMAIN in 'blabla.org' 'someother.com' 'random.de'; do
_run_in_container setup config dkim domain "${DOMAIN}"
assert_success
assert_line --partial "Domain set to '${DOMAIN}'"
local BASE_FILE_NAME="/tmp/docker-mailserver/rspamd/dkim/rsa-2048-mail-${DOMAIN}"
__check_key_files_are_present "${BASE_FILE_NAME}"
__check_path_in_signing_config "${BASE_FILE_NAME}.private.txt"
__remove_signing_config_file
done
}
@test "argument 'keytype' is applied correctly" {
_run_in_container setup config dkim keytype foobar
assert_failure
assert_line --partial "Unknown keytype 'foobar'"
2023-05-26 12:00:40 +00:00
for KEYTYPE in 'rsa' 'ed25519'; do
_run_in_container setup config dkim keytype "${KEYTYPE}"
assert_success
assert_line --partial "Keytype set to '${KEYTYPE}'"
local BASE_FILE_NAME="/tmp/docker-mailserver/rspamd/dkim/ed25519-mail-${DOMAIN_NAME}"
[[ ${KEYTYPE} == 'rsa' ]] && BASE_FILE_NAME="/tmp/docker-mailserver/rspamd/dkim/rsa-2048-mail-${DOMAIN_NAME}"
__check_key_files_are_present "${BASE_FILE_NAME}"
_run_in_container grep ".*k=${KEYTYPE};.*" "${BASE_FILE_NAME}.public.txt"
assert_success
_run_in_container grep ".*k=${KEYTYPE};.*" "${BASE_FILE_NAME}.public.dns.txt"
assert_success
__check_path_in_signing_config "${BASE_FILE_NAME}.private.txt"
__remove_signing_config_file
done
}
@test "argument 'selector' is applied correctly" {
2023-05-26 12:00:40 +00:00
for SELECTOR in 'foo' 'bar' 'baz'; do
__create_key 'rsa' "${SELECTOR}"
assert_success
assert_line --partial "Selector set to '${SELECTOR}'"
local BASE_FILE_NAME="/tmp/docker-mailserver/rspamd/dkim/rsa-2048-${SELECTOR}-${DOMAIN_NAME}"
__check_key_files_are_present "${BASE_FILE_NAME}"
_run_in_container grep "^${SELECTOR}\._domainkey.*" "${BASE_FILE_NAME}.public.txt"
assert_success
__check_rsa_keys 2048 "${SELECTOR}-${DOMAIN_NAME}"
__check_path_in_signing_config "${BASE_FILE_NAME}.private.txt"
__check_selector_in_signing_config "${SELECTOR}"
__remove_signing_config_file
done
}
@test "argument 'keysize' is applied correctly for RSA keys" {
chore: Change `setup config dkim` default key size to `2048` (`open-dkim`) (#3508) * chore: Adjust default DKIM size (`open-dkim`) from 4096-bit to 2048-bit 4096-bit is excessive in size for DKIM key. 2048-bit is plenty. * chore: Additional revisions to `open-dkim` command help output - The examples use `keysize 2048`, but as that's the new default it makes sense to change that. - Other help text was also revised. - Last example for domains did not need to demonstrate the other options. Changed example domains to more appropriate values. * docs: Revise DKIM docs Primarily for the change in default key size, but does revise some text to better communicate to the user. - While the referenced RFC advises 512-bit to 2048-bit key size, we now explicitly discourage `512-bit` as it's not secure. `1024-bit` is still likely safe for most, but `2048-bit` is a good default for those not rotating their keys. - Adjusted the domains example to match the new `setup config dkim domain` domains example. - Tip for changing default key size changed to "info" with added clarity of lowering security or increasing it (excessively). - Rspamd section is minor formatting changes, with the exception of clarifying the "main domain" for the mail accounts is assumed as the DMS FQDN with any subdomain (like `mail.`) stripped away. This is not great, but a legacy issue that needs to be addressed in future. - `docs-rspamd-override-d` ref removed, and usage replaced with equivalent ref `docs-rspamd-config-dropin`, while `docs-rspamd-config-declarative` ref was not in use and also removed. - Revised the `<selector>.txt` DNS formatting info section to better communicate with the reader. Additionally it had mixed usage of default `mail` and custom `dkim-rsa` selectors (_file content and output_). * docs: Sync DKIM commands help messages and update DKIM docs for LDAP - Adopt the help options format style from the `rspamd-dkim` into `open-dkim` command. And convert `./setup.sh` to `setup`. `selector` option has been implemented. for a while now. - Update `rspamd-dkim` examples help output to align with `open-dkim` command examples. - Give both DKIM command tools a consistent description. The two tools differ in support for the `domain` option (_implicit domain sourcing for default account provisioner, and support for multiple domains as input_). - DKIM docs for LDAP domain support revised to better communicate when explicit domain config is necessary. * tests: Adjust test-cases for `setup config dkim` change `rspamd_dkim.bats`: - Update assert for command help output. - Don't bother creating a DKIM key at 512-bit size. `setup_cli.bats`: - Update assert for command help output of the `setup config dkim` (OpenDKIM) command. * docs: Update DKIM section for large keys to newer RFC The linked discussion from 2021 does mention this updated RFC over the original. That removes outdated advice about `512-bit` key length support. The discussion link is still kept to reference a comment for the reader to better understand the security strength of 2048-bit RSA keys and why larger keys are not worthwhile, especially for DKIM. * docs: Extract out common DKIM generation command from content tabs Should be fine to be DRY here, not specific to `open-dkim` or `rspamd` generation/support. Previously rspamd lacked support of an equivalent command in DMS. * docs: DKIM refactoring - Shifted out the info admonition on key size advice out of the content tabs as it's now generic information. - Indented the 4096-bit warning into this, which is less of a concern as the default for our DKIM generation tools is consistently 2048-bit now. - Reworked the LDAP and Rspamd multi-domain advice. To avoid causing a bad diff, these sections haven't been moved/merged yet. * docs: Revise DKIM docs Advice for managing domains individually with LDAP and Rspamd extracted out of the content tabs. Default domain behaviour explained with extra info about OpenDKIM + FILE provisioner sourcing extra domains implicitly.
2023-08-28 21:40:02 +00:00
for KEYSIZE in 1024 2048 4096; do
__create_key 'rsa' 'mail' "${DOMAIN_NAME}" "${KEYSIZE}"
assert_success
__log_is_free_of_warnings_and_errors
assert_line --partial "Keysize set to '${KEYSIZE}'"
__check_rsa_keys "${KEYSIZE}" "mail-${DOMAIN_NAME}"
__remove_signing_config_file
done
}
@test "when 'keytype=ed25519' is set, setting custom 'keysize' is rejected" {
__create_key 'ed25519' 'mail' "${DOMAIN_NAME}" 4096
assert_failure
assert_line --partial "Chosen keytype does not accept the 'keysize' argument"
}
@test "setting all arguments to a custom value works" {
local KEYTYPE='ed25519'
local SELECTOR='someselector'
local DOMAIN='dms.org'
__create_key "${KEYTYPE}" "${SELECTOR}" "${DOMAIN}"
assert_success
__log_is_free_of_warnings_and_errors
assert_line --partial "Keytype set to '${KEYTYPE}'"
assert_line --partial "Selector set to '${SELECTOR}'"
assert_line --partial "Domain set to '${DOMAIN}'"
local BASE_FILE_NAME="/tmp/docker-mailserver/rspamd/dkim/${KEYTYPE}-${SELECTOR}-${DOMAIN}"
__check_path_in_signing_config "${BASE_FILE_NAME}.private.txt"
__check_selector_in_signing_config 'someselector'
}
# Create DKIM keys.
#
# @param ${1} = keytype (default: rsa)
# @param ${2} = selector (default: mail)
# @param ${3} = domain (default: ${DOMAIN})
# @param ${4} = keysize (default: 2048)
function __create_key() {
local KEYTYPE=${1:-rsa}
local SELECTOR=${2:-mail}
local DOMAIN=${3:-${DOMAIN_NAME}}
local KEYSIZE=${4:-2048}
local FORCE=${5:-}
# 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}"
}
# Check whether an RSA key is created successfully and correctly
# for a specific key size.
#
# @param ${1} = key size
# @param ${2} = name of the selector and domain name (as one string)
function __check_rsa_keys() {
local KEYSIZE=${1:?Keysize must be supplied to __check_rsa_keys}
local SELECTOR_AND_DOMAIN=${2:?Selector and domain name must be supplied to __check_rsa_keys}
local BASE_FILE_NAME="/tmp/docker-mailserver/rspamd/dkim/rsa-${KEYSIZE}-${SELECTOR_AND_DOMAIN}"
__check_key_files_are_present "${BASE_FILE_NAME}"
__check_path_in_signing_config "${BASE_FILE_NAME}.private.txt"
# Check the private key matches the specification
_run_in_container_bash "openssl rsa -in '${BASE_FILE_NAME}.private.txt' -noout -text"
assert_success
assert_line --index 0 "RSA Private-Key: (${KEYSIZE} bit, 2 primes)"
# Check the public key matches the specification
#
# We utilize the file for the DNS record contents which is already created
# by the Rspamd DKIM helper script. This makes parsing easier here.
local PUBKEY PUBKEY_INFO
PUBKEY=$(_exec_in_container_bash "grep -o 'p=.*' ${BASE_FILE_NAME}.public.dns.txt")
_run_in_container_bash "openssl enc -base64 -d <<< ${PUBKEY#p=} | openssl pkey -inform DER -pubin -noout -text"
assert_success
assert_line --index 0 "RSA Public-Key: (${KEYSIZE} bit)"
}
# Verify that all DKIM key files are present.
#
# @param ${1} = base file name that all DKIM key files have
function __check_key_files_are_present() {
local BASE_FILE_NAME="${1:?Base file name must be supplied to __check_key_files_are_present}"
2023-05-26 12:00:40 +00:00
for FILE in ${BASE_FILE_NAME}.{public.txt,public.dns.txt,private.txt}; do
_run_in_container_bash "[[ -f ${FILE} ]]"
assert_success
done
}
# Check whether `path = .*` is set correctly in the signing configuration file.
#
# @param ${1} = file name that `path` should be set to
function __check_path_in_signing_config() {
local BASE_FILE_NAME=${1:?Base file name must be supplied to __check_path_in_signing_config}
_run_in_container grep "[[:space:]]*path = \"${BASE_FILE_NAME}\";" "${SIGNING_CONF_FILE}"
assert_success
}
# Check whether `selector = .*` is set correctly in the signing configuration file.
#
# @param ${1} = name that `selector` should be set to
function __check_selector_in_signing_config() {
local SELECTOR=${1:?Selector name must be supplied to __check_selector_in_signing_config}
_run_in_container grep "[[:space:]]*selector = \"${SELECTOR}\";" "${SIGNING_CONF_FILE}"
assert_success
}
# Check whether the script output is free of warnings and errors.
function __log_is_free_of_warnings_and_errors() {
assert_success
refute_output --partial '[ WARN ]'
refute_output --partial '[ ERROR ]'
}
# Remove the signing configuration file inside the container.
function __remove_signing_config_file() {
_exec_in_container rm -f "${SIGNING_CONF_FILE}"
}