1
1
mirror of https://github.com/docker-mailserver/docker-mailserver synced 2024-12-18 14:04:17 +01:00
docker-mailserver/target/bin/rspamd-dkim

295 lines
9.6 KiB
Bash
Executable File

#!/bin/bash
# shellcheck source=../scripts/helpers/index.sh
source /usr/local/bin/helpers/index.sh
_trap_err_signal
set -u -eE -o pipefail
shopt -s inherit_errexit
# shellcheck source=/dev/null
source /etc/dms-settings
function __usage() {
_log 'trace' 'Showing usage message now'
echo -e "${PURPLE}RSPAMD-DKIM${RED}(${YELLOW}8${RED})
${ORANGE}NAME${RESET}
rspamd-dkim - Configure DKIM (DomainKeys Identified Mail)
${ORANGE}SYNOPSIS${RESET}
setup config dkim [ OPTIONS${RED}...${RESET} ]
${ORANGE}DESCRIPTION${RESET}
Creates DKIM keys and configures them within DMS for Rspamd.
OPTIONS can be used when your requirements are not met by the defaults.
${ORANGE}OPTIONS${RESET}
${BLUE}Generic Program Information${RESET}
-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.
Possible values: rsa, ed25519
Default: rsa
keysize Set the size of the keys to be generated.
Possible values: 1024, 2048 and 4096
Default: 2048
Only applies when using keytype=rsa
selector Set a manual selector for the key.
Default: mail
domain Provide the domain for which to generate keys for.
Default: The FQDN assigned to DMS, excluding any subdomain.
${ORANGE}EXAMPLES${RESET}
${LWHITE}setup config dkim keysize 4096${RESET}
Creates keys with their length increased to a size of 4096-bit.
${LWHITE}setup config dkim keysize 1024 selector 2023-dkim${RESET}
Creates 1024-bit sized keys, and changes the DKIM selector to '2023-dkim'.
${LWHITE}setup config dkim domain example.com${RESET}
Generate the DKIM key for a different domain (example.com).
${LWHITE}setup config dkim keytype ed25519 domain edward.com selector elliptic-test${RESET}
Generate the DKIM key using the ED25519 elliptic curve for the domain
edward.com and the selector elliptic-test.
${ORANGE}EXIT STATUS${RESET}
Exit status is 0 if command was successful. If wrong arguments are provided or arguments contain
errors, the script will exit early with a non-zero exit status.
"
}
function _parse_arguments() {
FORCE=0
KEYTYPE='rsa'
KEYSIZE='2048'
SELECTOR='mail'
DOMAIN=${DOMAINNAME}
_log 'trace' "Options given to this script: '${*}'"
while [[ ${#} -gt 0 ]]; do
case "${1}" in
( 'keytype' )
[[ -n ${2:-} ]] || _exit_with_error "No keytype provided after 'keytype' argument"
if [[ ${2} == 'rsa' ]] || [[ ${2} == 'ed25519' ]]; then
KEYTYPE=${2}
_log 'debug' "Keytype set to '${KEYTYPE}'"
else
_exit_with_error "Unknown keytype '${2}'"
fi
;;
( 'keysize' )
[[ -n ${2:-} ]] || _exit_with_error "No keysize provided after 'keysize' argument"
KEYSIZE=${2}
_log 'debug' "Keysize set to '${KEYSIZE}'"
;;
( 'selector' )
[[ -n ${2:-} ]] || _exit_with_error "No selector provided after 'selector' argument"
SELECTOR=${2}
_log 'debug' "Selector set to '${SELECTOR}'"
;;
( 'domain' )
[[ -n ${2:-} ]] || _exit_with_error "No domain provided after 'domain' argument"
DOMAIN=${2}
_log 'debug' "Domain set to '${DOMAIN}'"
;;
( 'help' )
__usage
exit 0
;;
( '-f' | '--force' )
FORCE=1
shift 1
continue
;;
( '-vv' )
# shellcheck disable=SC2034
LOG_LEVEL='trace'
shift 1
_log 'trace' 'Enabled trace-logging'
continue
;;
( '-v' )
# shellcheck disable=SC2034
LOG_LEVEL='debug'
shift 1
_log 'debug' 'Enabled debug-logging'
continue
;;
( * )
__usage
_exit_with_error "Unknown option(s) '${1}' ${2:+"and '${2}'"}"
;;
esac
shift 2
done
return 0
}
function _preflight_checks() {
if [[ ${KEYTYPE} == 'ed25519' ]] && [[ ${KEYSIZE} -ne 2048 ]]; then
_exit_with_error "Chosen keytype does not accept the 'keysize' argument"
fi
if [[ ! -d /tmp/docker-mailserver ]]; then
_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
_rspamd_get_envs
mkdir -p "${RSPAMD_DMS_DKIM_D}" "${RSPAMD_DMS_OVERRIDE_D}"
chown _rspamd:_rspamd "${RSPAMD_DMS_DKIM_D}"
}
function _create_keys() {
if [[ ${KEYTYPE} == 'rsa' ]]; then
local BASE_FILE_NAME="${RSPAMD_DMS_DKIM_D}/${KEYTYPE}-${KEYSIZE}-${SELECTOR}-${DOMAIN}"
KEYTYPE_OPTIONS=('-b' "${KEYSIZE}")
_log 'info' "Creating DKIM keys of type '${KEYTYPE}' and length '${KEYSIZE}' with selector '${SELECTOR}' for domain '${DOMAIN}'"
else
local BASE_FILE_NAME="${RSPAMD_DMS_DKIM_D}/${KEYTYPE}-${SELECTOR}-${DOMAIN}"
KEYTYPE_OPTIONS=('-t' "${KEYTYPE}")
_log 'info' "Creating DKIM keys of type '${KEYTYPE}' with selector '${SELECTOR}' for domain '${DOMAIN}'"
fi
PUBLIC_KEY_FILE="${BASE_FILE_NAME}.public.txt"
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"
[[ -f ${PUBLIC_KEY_FILE} ]] && rm "${PUBLIC_KEY_FILE}"
[[ -f ${PUBLIC_KEY_DNS_FILE} ]] && rm "${PUBLIC_KEY_DNS_FILE}"
[[ -f ${PRIVATE_KEY_FILE} ]] && rm "${PRIVATE_KEY_FILE}"
fi
fi
__create_rspamd_err_log
# shellcheck disable=SC2310
if __do_as_rspamd_user rspamadm \
dkim_keygen \
-s "${SELECTOR}" \
-d "${DOMAIN}" \
"${KEYTYPE_OPTIONS[@]}" \
-k "${PRIVATE_KEY_FILE}" \
>"${PUBLIC_KEY_FILE}" \
&& ! __filter_rspamd_err_log 'Permission denied' # we also need to check the log for error messages
then
_log 'info' 'Successfully created DKIM keys'
_log 'debug' "Public key written to '${PUBLIC_KEY_FILE}'"
_log 'debug' "Private key written to '${PRIVATE_KEY_FILE}'"
else
__print_rspamd_err_log
_exit_with_error 'Creating keys failed'
fi
}
function _check_permissions() {
# shellcheck disable=SC2310
if ! __do_as_rspamd_user ls "${RSPAMD_DMS_DKIM_D}" >/dev/null; then
_log 'warn' "The Rspamd user ('_rspamd') seems to be unable to list files in the keys directory ('${RSPAMD_DMS_DKIM_D}') - Rspamd may experience permission errors later"
elif ! __do_as_rspamd_user cat "${PRIVATE_KEY_FILE}" >/dev/null; then
_log 'warn' "The Rspamd user ('_rspamd') seems to be unable to read the private key file - Rspamd may experience permission errors later"
else
_log 'debug' 'Permissions on files and directories seem ok'
fi
}
function _setup_default_signing_conf() {
local DEFAULT_CONFIG_FILE="${RSPAMD_DMS_OVERRIDE_D}/dkim_signing.conf"
if [[ -f ${DEFAULT_CONFIG_FILE} ]]; then
_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
# documentation: https://rspamd.com/doc/modules/dkim_signing.html
enabled = true;
sign_authenticated = true;
sign_local = false;
try_fallback = false;
use_domain = "header";
use_redis = false; # don't change unless Redis also provides the DKIM keys
use_esld = true;
allow_username_mismatch = true;
check_pubkey = true; # you want to use this in the beginning
domain {
${DOMAIN} {
path = "${PRIVATE_KEY_FILE}";
selector = "${SELECTOR}";
}
}
EOF
# 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
}
function _transform_public_key_file_to_dns_record_contents() {
_log 'trace' 'Transforming DNS zone format to DNS record content now'
: >"${PUBLIC_KEY_DNS_FILE}"
grep -o '".*"' "${PUBLIC_KEY_FILE}" | tr -d '"\n' >>"${PUBLIC_KEY_DNS_FILE}"
echo '' >>"${PUBLIC_KEY_DNS_FILE}"
if ! _log_level_is '(warn|error)'; then
_log 'info' "Here is the content of the TXT DNS record ${SELECTOR}._domainkey.${DOMAIN} that you need to create:\n"
cat "${PUBLIC_KEY_DNS_FILE}"
printf '\n'
fi
}
function _final_steps() {
# We need to restart Rspamd so the changes take effect immediately.
if ! supervisorctl restart rspamd; then
_log 'warn' 'Could not restart Rspamd via Supervisord'
fi
_log 'trace' 'Finished DKIM key creation'
}
_obtain_hostname_and_domainname
_require_n_parameters_or_print_usage 0 "${@}"
_parse_arguments "${@}"
_preflight_checks
_create_keys
_check_permissions
_setup_default_signing_conf
_transform_public_key_file_to_dns_record_contents
_final_steps