mirror of
https://github.com/docker-mailserver/docker-mailserver
synced 2024-12-18 23:14:11 +01:00
275 lines
10 KiB
Bash
275 lines
10 KiB
Bash
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'
|
|
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"
|
|
_file_exists_in_container "${SIGNING_CONF_FILE}"
|
|
_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
|
|
_file_exists_in_container "${SIGNING_CONF_FILE}"
|
|
|
|
__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" {
|
|
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'"
|
|
|
|
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" {
|
|
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" {
|
|
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 "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 "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}"
|
|
for FILE in ${BASE_FILE_NAME}.{public.txt,public.dns.txt,private.txt}; do
|
|
_file_exists_in_container "${FILE}"
|
|
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}"
|
|
}
|