scripts: refactored scripts located under target/bin/ (#2500)

* refactored scripts located under `target/bin/`

The scripts under `target/bin/` now use the new log and I replaced some
`""` with `''` on the way. The functionality stays the same, this mostly
style and log.

* corrected fail2ban (script and tests)

* corrected OpenDKIM log output in tests

* reverted (some) changes to `sedfile`

Moreover, a few messages for BATS were streamlined and a regression in
the linting script reverted.

* apple PR feedback

* improve log output from `fail2ban` script

The new output has a single, clear message with the '[  ERROR  ]  '
prefix, and then output that explains the error afterwards. This is
coherent with the logging style which should be used while providing
more information than just a single line about IPTables not functioning.

* simplified `setquota` script

* consistently named the `__usage` function

Before, scripts located under `target/bin/` were using `usage` or
`__usage`. Now, they're using `__usage` as they should.

* improved `sedfile`

With `sedfile`, we cannot use the helper functions in a nice way because
it is used early in the Dockerfile at a stage where the helper scripts
are not yet copied. The script has been adjusted to be canonical with
all the other scripts under `target/bin/`.

* fixed tests

* removed `__usage` from places where it does not belong

`__usage` is to be used on wrong user input, not on other failures as
well. This was fixed in `delquota` and `setquota`.

* apply PR review feedback
This commit is contained in:
Georg Lauterbach 2022-03-26 09:30:09 +01:00 committed by GitHub
parent f22d75fa62
commit b9dbec3276
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 167 additions and 149 deletions

View file

@ -46,8 +46,7 @@ touch "${DATABASE}"
_create_lock # Protect config file with lock to avoid race conditions
if grep -qi "^$(_escape "${FULL_EMAIL}")|" "${DATABASE}"
then
echo "User '${FULL_EMAIL}' already exists."
exit 1
_exit_with_error "User '${FULL_EMAIL}' already exists"
fi
if [[ -z ${PASSWD} ]]
@ -64,11 +63,11 @@ USER="${FULL_EMAIL%@*}"
DOMAIN="${FULL_EMAIL#*@}"
# Tests fail if the creation of /var/mail/${DOMAIN}/${USER} doesn't happen fast enough after addmailuser executes (check-for-changes.sh race-condition)
if [[ -e "/tmp/docker-mailserver-config-chksum" ]] # Prevent infinite loop in tests like "checking accounts: user3 should have been added to /tmp/docker-mailserver/postfix-accounts.cf even when that file does not exist"
if [[ -e /tmp/docker-mailserver-config-chksum ]] # Prevent infinite loop in tests like "checking accounts: user3 should have been added to /tmp/docker-mailserver/postfix-accounts.cf even when that file does not exist"
then
while [[ ! -d "/var/mail/${DOMAIN}/${USER}" ]]
do
echo "Waiting for dovecot to create /var/mail/${DOMAIN}/${USER}..."
_log 'info' "Waiting for dovecot to create '/var/mail/${DOMAIN}/${USER}/'"
sleep 1
done
fi

View file

@ -12,8 +12,8 @@ function __usage { echo "Usage: delalias <alias@domain> <recipient@other>" ; }
[[ ${1:-} == 'help' ]] && { __usage ; exit 0 ; }
[[ -z ${EMAIL} ]] && { __usage ; _exit_with_error "Error: No alias specified" ; }
[[ -z ${RECIPIENT} ]] && { __usage ; _exit_with_error "Error: No recipient specified" ; }
[[ -z ${EMAIL} ]] && { __usage ; _exit_with_error 'No alias specified' ; }
[[ -z ${RECIPIENT} ]] && { __usage ; _exit_with_error 'No recipient specified' ; }
[[ -s ${DATABASE} ]] || exit 0
sed -i \

View file

@ -55,31 +55,31 @@ fi
while getopts ":yYh" OPT
do
case ${OPT} in
y | Y )
case "${OPT}" in
( 'y' | 'Y' )
MAILDEL=true
;;
h )
( 'h' )
__usage
exit 0
;;
* )
( * )
__usage
_exit_with_error "The option ${OPT} is unknown."
_exit_with_error "The option '${OPT}' is unknown"
;;
esac
done
shift $((OPTIND-1))
[[ -z ${*} ]] && { __usage ; _exit_with_error "No user specifed" ; }
[[ -z ${*} ]] && { __usage ; _exit_with_error 'No user specified' ; }
[[ -s ${DATABASE} ]] || exit 0
if ! ${MAILDEL}
then
read -r -p "Do you want to delete the mailbox as well (removing all mails) ? [Y/n] " MAILDEL_CHOSEN
read -r -p "Do you want to delete the mailbox as well (removing all mails)? [Y/n] " MAILDEL_CHOSEN
if [[ ${MAILDEL_CHOSEN} =~ (y|Y|yes|Yes) ]] || [[ -z ${MAILDEL_CHOSEN} ]]
then
MAILDEL=true
@ -103,7 +103,7 @@ do
then
if ! sedfile --strict -i "/^${EMAIL}|/d" "${DATABASE}"
then
echo "${UNESCAPED_EMAIL} couldn't be deleted in ${DATABASE}." >&2
_log 'error' "'${UNESCAPED_EMAIL}' couldn't be deleted in '${DATABASE}'"
ERROR=true
fi
fi
@ -116,9 +116,9 @@ do
-e "/ ${EMAIL}$/d" -e "s/,${EMAIL}//g" -e "s/${EMAIL},//g" \
"${ALIAS_DATABASE}"
then
echo "${UNESCAPED_EMAIL} and potential aliases deleted."
_log 'info' "'${UNESCAPED_EMAIL}' and potential aliases deleted"
else
echo "Aliases for ${UNESCAPED_EMAIL} couldn't be deleted in ${ALIAS_DATABASE}." >&2
_log 'error' "Aliases for '${UNESCAPED_EMAIL}' couldn't be deleted in '${ALIAS_DATABASE}'"
ERROR=true
fi
fi
@ -128,7 +128,7 @@ do
then
if ! sedfile --strict -i -e "/^${EMAIL}:.*$/d" "${QUOTA_DATABASE}"
then
echo "Quota for ${UNESCAPED_EMAIL} couldn't be deleted in ${QUOTA_DATABASE}." >&2
_log 'warn' "Quota for '${UNESCAPED_EMAIL}' couldn't be deleted in '${QUOTA_DATABASE}'"
fi
fi
@ -144,17 +144,18 @@ use 'sudo docker exec mailserver rm -R /var/mail/${DOMAIN}/${USER}'"
then
if rm -R "/var/mail/${DOMAIN}/${USER}"
then
echo "Mailbox deleted."
_log 'info' 'Mailbox deleted'
else
echo "Mailbox couldn't be deleted." >&2
_log 'error' 'Mailbox could not be deleted'
ERROR=true
fi
rmdir "/var/mail/${DOMAIN}" 2>/dev/null || true
rmdir "/var/mail/${DOMAIN}" &>/dev/null
else
echo "Mailbox directory '/var/mail/${DOMAIN}/${USER}' did not exist." >&2
log 'error' "Mailbox directory '/var/mail/${DOMAIN}/${USER}' did not exist"
ERROR=true
fi
${ERROR} && _exit_with_error 'See the messages above.'
done
exit 0

View file

@ -6,20 +6,16 @@ source /usr/local/bin/helpers/index.sh
DATABASE=${DATABASE:-/tmp/docker-mailserver/dovecot-quotas.cf}
USER_DATABASE=${USER_DATABASE:-/tmp/docker-mailserver/postfix-accounts.cf}
function __usage { echo "Usage: delquota <username@domain>" ; }
function __usage { echo 'Usage: delquota <username@domain>' ; }
[[ ${1:-} == 'help' ]] && { __usage ; exit 0 ; }
USER="${1}"
[[ -z ${USER} ]] && { __usage ; _exit_with_error "No username specified" ; }
[[ ${USER} =~ .*\@.* ]] || { __usage ; _exit_with_error "Username must include the domain"; }
[[ -z ${USER} ]] && { __usage ; _exit_with_error 'No username specified' ; }
[[ ${USER} =~ .*\@.* ]] || { __usage ; _exit_with_error 'Username must include the domain' ; }
if ! grep -qE "^${USER}\|" "${USER_DATABASE}"
then
__usage
_exit_with_error "user ${USER} does not exist"
fi
grep -qE "^${USER}\|" "${USER_DATABASE}" || _exit_with_error "User '${USER}' does not exist"
[[ -s ${DATABASE} ]] || exit 0

View file

@ -7,9 +7,9 @@ DATABASE=${DATABASE:-/tmp/docker-mailserver/postfix-relaymap.cf}
DOMAIN="${1}"
function usage { echo "Usage: excluderelayhost <domain>" ; }
function __usage { echo 'Usage: excluderelayhost <domain>' ; }
[[ -z ${DOMAIN} ]] && { usage ; _exit_with_error "no domain specified" ; }
[[ -z ${DOMAIN} ]] && { __usage ; _exit_with_error "no domain specified" ; }
if grep -qi "^@${DOMAIN}" "${DATABASE}" 2>/dev/null
then

View file

@ -5,7 +5,9 @@ source /usr/local/bin/helpers/index.sh
if ! IPTABLES_OUTPUT=$(iptables -L -n 2>&1)
then
echo "IPTables is not functioning correctly. The output of \`iptables -L\` was:
_exit_with_error "IPTables is not functioning correctly
The output of \`iptables -L\` was:
${IPTABLES_OUTPUT}
@ -14,14 +16,10 @@ Possible causes for this error are
1. Missing capabilities (you need CAP_NET_RAW & CAP_NET_ADMIN, see \`capsh --print\`)
2. Modifications caused by user-patches.sh
3. Host is configured incorrectly
Aborting...
"
exit 1
fi
function usage { echo "Usage: ${0} [<unban> <ip-address>]" ; }
function __usage { echo "Usage: ${0} [<unban> <ip-address>]" ; }
unset JAILS
declare -a JAILS
@ -48,14 +46,14 @@ then
if [[ ${IP_COUNT} -eq 0 ]]
then
echo "No IPs have been banned."
_log 'info' 'No IPs have been banned'
fi
else
case ${1} in
case "${1}" in
unban)
( 'unban' )
shift
if [[ -n ${1} ]]
then
@ -68,14 +66,14 @@ else
done
else
echo "You need to specify an IP address. Run './setup.sh debug fail2ban' to get a list of banned IP addresses." >&2
_log 'warn' "You need to specify an IP address: Run './setup.sh debug fail2ban' to get a list of banned IP addresses"
exit 0
fi
;;
*)
usage
_exit_with_error "unknown command: ${1}"
( * )
__usage
_exit_with_error "Unknown command '${1}'"
;;
esac

View file

@ -14,7 +14,7 @@ DEFAULT_FILE="${FETCHMAILRCD}/defaults"
if [[ ! -r "${FETCHMAILRC}" ]]
then
echo "Error: File ${FETCHMAILRC} not found"
_log 'error' "File '${FETCHMAILRC}' not found"
exit 1
fi
@ -22,7 +22,7 @@ if [[ ! -d ${FETCHMAILRCD} ]]
then
if ! mkdir "${FETCHMAILRCD}"
then
echo "Error: Unable to create folder ${FETCHMAILRCD}"
_log 'error' "Unable to create folder '${FETCHMAILRCD}'"
exit 1
fi
fi

View file

@ -5,8 +5,8 @@ source /usr/local/bin/helpers/index.sh
DATABASE=${DATABASE:-/tmp/docker-mailserver/postfix-virtual.cf}
[[ -f ${DATABASE} ]] || _exit_with_error "Error: No postfix-virtual.cf file"
[[ -s ${DATABASE} ]] || _exit_with_error "Error: Empty postfix-virtual.cf - no aliases have been added"
[[ -f ${DATABASE} ]] || _exit_with_error "No 'postfix-virtual.cf' file"
[[ -s ${DATABASE} ]] || _exit_with_error "Empty 'postfix-virtual.cf' - no aliases have been added"
grep -v "^\s*$\|^\s*\#" "${DATABASE}"
exit 0

View file

@ -7,7 +7,7 @@ source /usr/local/bin/helpers/index.sh
# shellcheck source=/dev/null
source /etc/dms-settings 2>/dev/null
function dovecot_quota_to_hr()
function dovecot_quota_to_hr
{
if [[ ${1:-} == "-" ]]
then
@ -16,15 +16,15 @@ function dovecot_quota_to_hr()
then
echo $(( 1024 * ${1} )) | numfmt --to=iec
else
notify 'err' "Supplied non-number argument '${1:-}' to 'dovecot_quota_to_hr()' in script 'listmailuser'"
_exit_with_error "Supplied non-number argument '${1:-}' to 'dovecot_quota_to_hr()' in script 'listmailuser'"
fi
}
DATABASE="/tmp/docker-mailserver/postfix-accounts.cf"
ALIASES="/tmp/docker-mailserver/postfix-virtual.cf"
DATABASE='/tmp/docker-mailserver/postfix-accounts.cf'
ALIASES='/tmp/docker-mailserver/postfix-virtual.cf'
[[ -f ${DATABASE} ]] || _exit_with_error "Error: No postfix-accounts.cf file"
[[ -s ${DATABASE} ]] || _exit_with_error "Error: Empty postfix-accounts.cf - no accounts have been added"
[[ -f ${DATABASE} ]] || _exit_with_error "No 'postfix-accounts.cf' file"
[[ -s ${DATABASE} ]] || _exit_with_error "Empty 'postfix-accounts.cf' - no accounts have been added"
while read -r LINE
do

View file

@ -1,5 +1,8 @@
#! /bin/bash
# shellcheck source=../scripts/helpers/index.sh
source /usr/local/bin/helpers/index.sh
KEYSIZE=4096
SELECTOR=mail
DOMAINS=
@ -52,48 +55,44 @@ function __usage
while [[ ${#} -gt 0 ]]
do
case ${1} in
keysize )
if [[ -n ${2+'set'} ]]
case "${1}" in
( 'keysize' )
if [[ -n ${2+set} ]]
then
KEYSIZE="${2}"
shift
shift
else
echo "No keysize provided after 'keysize' argument. Aborting." >&2
exit 2
_exit_with_error "No keysize provided after 'keysize' argument"
fi
;;
selector )
if [[ -n ${2+'set'} ]]
( 'selector' )
if [[ -n ${2+set} ]]
then
# shellcheck disable=SC2034
SELECTOR="${2}"
shift
shift
else
echo "No selector provided after 'selector' argument. Aborting." >&2
exit 2
_exit_with_error "No selector provided after 'selector' argument"
fi
;;
domain )
if [[ -n ${2+'set'} ]]
( 'domain' )
if [[ -n ${2+set} ]]
then
DOMAINS="${2}"
shift
shift
else
echo "No domain(s) provided after 'domain' argument. Aborting." >&2
exit 2
_exit_with_error "No domain(s) provided after 'domain' argument"
fi
;;
* )
( * )
__usage
echo -e "\nUnknown options ${1} ${2:-}. Aborting." >&2
exit 2
_exit_with_error "Unknown options '${1}' ${2:+and \'${2}\'}"
;;
esac
@ -127,7 +126,7 @@ then
done < <(grep -v "^\s*$\|^\s*\#" /tmp/docker-mailserver/postfix-virtual.cf || true)
fi
else
tr ',' '\n' <<< "${DOMAINS}" > /tmp/vhost.dkim.tmp
tr ',' '\n' <<< "${DOMAINS}" >/tmp/vhost.dkim.tmp
fi
sort < /tmp/vhost.dkim.tmp | uniq >/tmp/vhost
@ -135,7 +134,7 @@ rm /tmp/vhost.dkim.tmp
if [[ ! -s /tmp/vhost ]]
then
echo "No entries found, no keys to make."
_log 'warn' 'No entries found, no keys to make'
exit 0
fi
@ -145,7 +144,7 @@ do
if [[ ! -f "/tmp/docker-mailserver/opendkim/keys/${DKIM_DOMAIN}/${SELECTOR}.private" ]]
then
echo "Creating DKIM private key /tmp/docker-mailserver/opendkim/keys/${DKIM_DOMAIN}/${SELECTOR}.private"
_log 'info' "Creating DKIM private key '/tmp/docker-mailserver/opendkim/keys/${DKIM_DOMAIN}/${SELECTOR}.private'"
opendkim-genkey \
--bits="${KEYSIZE}" \
@ -159,7 +158,7 @@ do
KEYTABLEENTRY="${SELECTOR}._domainkey.${DKIM_DOMAIN} ${DKIM_DOMAIN}:${SELECTOR}:/etc/opendkim/keys/${DKIM_DOMAIN}/${SELECTOR}.private"
if [[ ! -f "/tmp/docker-mailserver/opendkim/KeyTable" ]]
then
echo "Creating DKIM KeyTable"
_log 'debug' 'Creating DKIM KeyTable'
echo "${KEYTABLEENTRY}" >/tmp/docker-mailserver/opendkim/KeyTable
else
if ! grep -q "${KEYTABLEENTRY}" "/tmp/docker-mailserver/opendkim/KeyTable"
@ -172,7 +171,7 @@ do
SIGNINGTABLEENTRY="*@${DKIM_DOMAIN} ${SELECTOR}._domainkey.${DKIM_DOMAIN}"
if [[ ! -f /tmp/docker-mailserver/opendkim/SigningTable ]]
then
echo "Creating DKIM SigningTable"
_log 'debug' 'Creating DKIM SigningTable'
echo "*@${DKIM_DOMAIN} ${SELECTOR}._domainkey.${DKIM_DOMAIN}" >/tmp/docker-mailserver/opendkim/SigningTable
else
if ! grep -q "${SIGNINGTABLEENTRY}" /tmp/docker-mailserver/opendkim/SigningTable
@ -185,7 +184,7 @@ done < <(grep -vE '^(\s*$|#)' /tmp/vhost)
# create TrustedHosts if missing
if [[ -d /tmp/docker-mailserver/opendkim ]] && [[ ! -f /tmp/docker-mailserver/opendkim/TrustedHosts ]]
then
echo "Creating DKIM TrustedHosts"
_log 'debug' 'Creating DKIM TrustedHosts'
echo "127.0.0.1" >/tmp/docker-mailserver/opendkim/TrustedHosts
echo "localhost" >>/tmp/docker-mailserver/opendkim/TrustedHosts
fi

View file

@ -7,7 +7,7 @@ HOSTNAME=${1}
RECIPIENT=${2}
SENDER=${3}
[[ -x /usr/sbin/pflogsumm ]] || _exit_with_error "Critical: /usr/sbin/pflogsumm not found"
[[ -x /usr/sbin/pflogsumm ]] || _exit_with_error "'/usr/sbin/pflogsumm' not found or executable"
# The case that the mail.log.1 file isn't readable shouldn't
# actually be possible with logrotate not rotating empty files..

View file

@ -11,7 +11,7 @@ HOSTNAME=${1}
RECIPIENT=${2}
SENDER=${3}
[[ -x /usr/sbin/pflogsumm ]] || _exit_with_error "Critical: /usr/sbin/pflogsumm not found"
[[ -x /usr/sbin/pflogsumm ]] || _exit_with_error "'/usr/sbin/pflogsumm' not found or executable"
# shellcheck disable=SC2046
BODY=$(gzip -cdfq $(ls -tr /var/log/mail/mail.log*) | /usr/sbin/pflogsumm --problems_first -d yesterday)

View file

@ -6,33 +6,36 @@ source /usr/local/bin/helpers/index.sh
MODE="${1}"
USER="${3}"
function usage { echo "Usage: ${0} <add|del|list> <send|receive> [<email@domain.com>]" ; }
function __usage { echo "Usage: ${0} <add|del|list> <send|receive> [<email@domain.com>]" ; }
[[ -z ${MODE} ]] && _exit_with_error "missing parameters: <add|del|list> <send|receive> [<email@domain.com>]"
[[ -z ${MODE} ]] && _exit_with_error 'Missing parameters: <add|del|list> <send|receive> [<email@domain.com>]'
case ${2} in
send)
case "${2}" in
( 'send' )
DATABASE="/tmp/docker-mailserver/postfix-send-access.cf"
;;
receive)
( 'receive' )
DATABASE="/tmp/docker-mailserver/postfix-receive-access.cf"
;;
*)
usage
_exit_with_error "missing parameters. Specify \"send\" or \"receive\""
( * )
__usage
_exit_with_error "Missing parameters: specify 'send' or 'receive'"
;;
esac
if [[ -z ${USER} ]] && [[ ${MODE} != list ]]
then
read -r -p "User(user@domain.com): " USER
read -r -p 'User(user@domain.com): ' USER
echo
[[ -z ${USER} ]] && _exit_with_error "User must not be empty"
[[ -z ${USER} ]] && _exit_with_error 'User must not be empty'
fi
case ${MODE} in
add)
grep -qi "^$(_escape "${USER}")" "${DATABASE}" 2>/dev/null && _exit_with_error "User \"${USER}\" already denied to ${2} mails"
case "${MODE}" in
( 'add' )
grep -qi "^$(_escape "${USER}")" "${DATABASE}" 2>/dev/null && _exit_with_error "User '${USER}' already denied to ${2} mails"
if [[ ! -f ${DATABASE} ]]
then
@ -45,18 +48,19 @@ case ${MODE} in
fi
echo -e "${USER} \t\t REJECT" >>"${DATABASE}"
;;
del)
sed -ie "/^$(_escape "${USER}")/d" "${DATABASE}" 2>/dev/null || _exit_with_error "User \"${USER}\" not found."
;;
list)
grep "REJECT" "${DATABASE}" 2>/dev/null || echo "Everyone is allowed to ${2} mails."
;;
*)
usage
_exit_with_error "missing mode. Specify \"add\", \"del\" or \"list\""
;;
( 'del' )
sed -ie "/^$(_escape "${USER}")/d" "${DATABASE}" 2>/dev/null || _exit_with_error "User '${USER}' not found."
;;
( 'list' )
grep "REJECT" "${DATABASE}" 2>/dev/null || _log 'info' "Everyone is allowed to ${2} mails"
;;
( * )
__usage
_exit_with_error "Missing mode: specify 'add', 'del' or 'list'"
;;
esac

View file

@ -11,19 +11,21 @@
set -ueo pipefail
HASHTOOL="sha1sum"
function __usage { echo "Usage: ${0} -i <replace/delete operation> <file>" ; }
HASHTOOL='sha1sum'
SKIP_ERROR=0
if [[ $# -lt 3 ]]
if [[ ${#} -lt 3 ]]
then
echo "Error: At least, three parameters must be given."
echo "Syntax: sedfile -i <replace/delete operation> <file>"
echo 'Error: At least three parameters must be given'
__usage
echo
exit 1
fi >&2
[[ -f /CONTAINER_START ]] && SKIP_ERROR=1 # Hide error, if container was restarted.
if [[ "${1}" == "--strict" ]] # Show error every time.
[[ -f /CONTAINER_START ]] && SKIP_ERROR=1 # hide error if container was restarted
if [[ ${1} == '--strict' ]] # show error every time
then
SKIP_ERROR=0
shift
@ -33,14 +35,14 @@ fi
FILE=${*: -1}
OLD=$(${HASHTOOL} "${FILE}")
sed "$@"
sed "${@}"
NEW=$(${HASHTOOL} "${FILE}")
# fail if file was not modified
if [[ ${OLD} == "${NEW}" ]] && [[ ${SKIP_ERROR} -eq 0 ]]
then
echo "Error: sed $*"
echo "Error: No difference after call to 'sed' in 'sedfile' (sed ${*})" >&2
exit 1
fi >&2
fi
exit 0

View file

@ -15,39 +15,29 @@ USER="${1}"
shift
QUOTA="${*}"
function usage { echo "Usage: setquota <user@domain> [<quota>]" ; }
function __usage { echo 'Usage: setquota <user@domain> [<quota>]' ; }
[[ -z ${USER} ]] && { usage ; _exit_with_error "no username specified" ; }
[[ ${USER} =~ .*\@.* ]] || { usage ; _exit_with_error "username must include the domain" ; }
[[ -z ${USER} ]] && { __usage ; _exit_with_error "No username specified" ; }
[[ ${USER} =~ .*\@.* ]] || { __usage ; _exit_with_error "Username must include the domain" ; }
if ! grep -qE "^${USER}\|" "${USER_DATABASE}"
grep -qE "^${USER}\|" "${USER_DATABASE}" || _exit_with_error "User '${USER}' does not exist"
if [[ -z ${QUOTA} ]]
then
usage; _exit_with_error "user ${USER} does not exist"
read -r -s 'Enter quota (e.g. 10M): ' QUOTA
echo
[[ -z "${QUOTA}" ]] && _exit_with_error 'Quota must not be empty (use 0 for unlimited quota)'
fi
# check quota
if [[ -n ${QUOTA} ]] && ! echo "${QUOTA}" | grep -qE "^([0-9]+(B|k|M|G|T)|0)\$"
if ! grep -qE "^([0-9]+(B|k|M|G|T)|0)\$" <<< "${QUOTA}"
then
usage
_exit_with_error "invalid quota format. e.g. 302M (B (byte), k (kilobyte), M (megabyte), G (gigabyte) or T (terabyte))"
__usage
_exit_with_error 'Invalid quota format. e.g. 302M (B (byte), k (kilobyte), M (megabyte), G (gigabyte) or T (terabyte))'
fi
_create_lock # Protect config file with lock to avoid race conditions
touch "${DATABASE}"
if [[ -z ${QUOTA} ]]
then
read -r -s "Enter quota (e.g. 10M): " QUOTA
echo
[[ -z "${QUOTA}" ]] && _exit_with_error "Quota must not be empty. Use 0 for unlimited quota"
fi
# check quota
if [[ -n ${QUOTA} ]] && ! echo "${QUOTA}" | grep -qE "^([0-9]+(B|k|M|G|T)|0)\$"
then
usage
_exit_with_error "invalid quota format. e.g. 302M (B (byte), k (kilobyte), M (megabyte), G (gigabyte) or T (terabyte))"
fi
delquota "${USER}"
echo "${USER}:${QUOTA}" >>"${DATABASE}"

View file

@ -14,15 +14,15 @@ USER="${1}"
shift
PASSWD="${*}"
function usage { echo "Usage: updatemailuser <user@domain.tld> [password]" ; }
function __usage { echo 'Usage: updatemailuser <user@domain.tld> [password]' ; }
[[ -z ${USER} ]] && { usage ; _exit_with_error "no username specified" ; }
[[ -z ${USER} ]] && { __usage ; _exit_with_error 'No username specified' ; }
if [[ -z ${PASSWD} ]]
then
read -r -s -p "Enter Password: " PASSWD
read -r -s -p 'Enter Password: ' PASSWD
echo
[[ -z ${PASSWD} ]] && _exit_with_error "Password must not be empty"
[[ -z ${PASSWD} ]] && _exit_with_error 'Password must not be empty'
fi
HASH="$(doveadm pw -s SHA512-CRYPT -u "${USER}" -p "${PASSWD}")"

View file

@ -24,17 +24,17 @@ function _create_lock
done
trap _remove_lock EXIT
_log 'trace' "Creating lock ${LOCK_FILE}"
_log 'trace' "Creating lock '${LOCK_FILE}'"
echo "${LOCK_ID}" >"${LOCK_FILE}"
}
function _remove_lock
{
LOCK_FILE="${LOCK_FILE:-"/tmp/docker-mailserver/${SCRIPT_NAME}.lock"}"
[[ -z "${LOCK_ID}" ]] && _exit_with_error "Cannot remove ${LOCK_FILE} as there is no LOCK_ID set"
[[ -z "${LOCK_ID}" ]] && _exit_with_error "Cannot remove '${LOCK_FILE}' as there is no LOCK_ID set"
if [[ -e "${LOCK_FILE}" ]] && grep -q "${LOCK_ID}" "${LOCK_FILE}" # Ensure we don't delete a lock that's not ours
then
rm -f "${LOCK_FILE}"
_log 'trace' "Removed lock ${LOCK_FILE}"
_log 'trace' "Removed lock '${LOCK_FILE}'"
fi
}

View file

@ -140,7 +140,7 @@ function teardown_file() {
assert_output --partial "Unbanned IP from dovecot: 1"
run ./setup.sh -c mail_fail2ban debug fail2ban unban
assert_output --partial "You need to specify an IP address. Run"
assert_output --partial "You need to specify an IP address: Run"
}
#

View file

@ -4,7 +4,7 @@ export IMAGE_NAME CONTAINER_NAME TEST_FILE
IMAGE_NAME="${NAME:?Image name must be set}"
CONTAINER_NAME='open-dkim'
TEST_FILE='OpenDKIM :: '
TEST_FILE='checking OpenDKIM: '
# WHY IS THIS CONTAINER EVEN CREATED WHEN MOST TESTS DO NOT USE IT?
function setup_file
@ -20,6 +20,7 @@ function setup_file
-e DEFAULT_RELAY_HOST=default.relay.host.invalid:25 \
-e PERMIT_DOCKER=host \
-e DMS_DEBUG=0 \
-e LOG_LEVEL='trace' \
-h mail.my-domain.com \
-t "${IMAGE_NAME}"
@ -69,6 +70,7 @@ function teardown_file
mkdir -p "${PRIVATE_CONFIG}/keyDefault"
run docker run --rm \
-e LOG_LEVEL='trace' \
-v "${PRIVATE_CONFIG}/keyDefault/":/tmp/docker-mailserver/ \
-v "${PRIVATE_CONFIG}/postfix-accounts.cf":/tmp/docker-mailserver/postfix-accounts.cf \
-v "${PRIVATE_CONFIG}/postfix-virtual.cf":/tmp/docker-mailserver/postfix-virtual.cf \
@ -98,6 +100,7 @@ function teardown_file
mkdir -p "${PRIVATE_CONFIG}/config/key4096"
run docker run --rm \
-e LOG_LEVEL='trace' \
-v "${PRIVATE_CONFIG}/key2048/":/tmp/docker-mailserver/ \
-v "${PRIVATE_CONFIG}/postfix-accounts.cf":/tmp/docker-mailserver/postfix-accounts.cf \
-v "${PRIVATE_CONFIG}/postfix-virtual.cf":/tmp/docker-mailserver/postfix-virtual.cf \
@ -126,6 +129,7 @@ function teardown_file
mkdir -p "${PRIVATE_CONFIG}/config/key2048"
run docker run --rm \
-e LOG_LEVEL='trace' \
-v "${PRIVATE_CONFIG}/key2048/":/tmp/docker-mailserver/ \
-v "${PRIVATE_CONFIG}/postfix-accounts.cf":/tmp/docker-mailserver/postfix-accounts.cf \
-v "${PRIVATE_CONFIG}/postfix-virtual.cf":/tmp/docker-mailserver/postfix-virtual.cf \
@ -154,6 +158,7 @@ function teardown_file
mkdir -p "${PRIVATE_CONFIG}/key1024"
run docker run --rm \
-e LOG_LEVEL='trace' \
-v "${PRIVATE_CONFIG}/key1024/":/tmp/docker-mailserver/ \
-v "${PRIVATE_CONFIG}/postfix-accounts.cf":/tmp/docker-mailserver/postfix-accounts.cf \
-v "${PRIVATE_CONFIG}/postfix-virtual.cf":/tmp/docker-mailserver/postfix-virtual.cf \
@ -176,6 +181,7 @@ function teardown_file
rm -rf "${PRIVATE_CONFIG}/empty"
mkdir -p "${PRIVATE_CONFIG}/empty"
run docker run --rm \
-e LOG_LEVEL='trace' \
-v "${PRIVATE_CONFIG}/empty/":/tmp/docker-mailserver/ \
-v "${PRIVATE_CONFIG}/postfix-accounts.cf":/tmp/docker-mailserver/postfix-accounts.cf \
-v "${PRIVATE_CONFIG}/postfix-virtual.cf":/tmp/docker-mailserver/postfix-virtual.cf \
@ -211,6 +217,7 @@ function teardown_file
rm -rf "${PRIVATE_CONFIG}/without-accounts"
mkdir -p "${PRIVATE_CONFIG}/without-accounts"
run docker run --rm \
-e LOG_LEVEL='trace' \
-v "${PRIVATE_CONFIG}/without-accounts/":/tmp/docker-mailserver/ \
-v "${PRIVATE_CONFIG}/postfix-virtual.cf":/tmp/docker-mailserver/postfix-virtual.cf \
"${IMAGE_NAME}" /bin/bash -c 'open-dkim | wc -l'
@ -219,6 +226,7 @@ function teardown_file
# check keys for localhost.localdomain
run docker run --rm \
-e LOG_LEVEL='trace' \
-v "${PRIVATE_CONFIG}/without-accounts/opendkim":/etc/opendkim \
"${IMAGE_NAME}" /bin/bash -c 'ls -1 /etc/opendkim/keys/localhost.localdomain/ | wc -l'
assert_success
@ -232,6 +240,7 @@ function teardown_file
# [ "${output}" -eq 0 ]
# check presence of tables and TrustedHosts
run docker run --rm \
-e LOG_LEVEL='trace' \
-v "${PRIVATE_CONFIG}/without-accounts/opendkim":/etc/opendkim \
"${IMAGE_NAME}" /bin/bash -c "ls -1 /etc/opendkim | grep -E 'KeyTable|SigningTable|TrustedHosts|keys'|wc -l"
assert_success
@ -244,6 +253,7 @@ function teardown_file
rm -rf "${PRIVATE_CONFIG}/without-virtual"
mkdir -p "${PRIVATE_CONFIG}/without-virtual"
run docker run --rm \
-e LOG_LEVEL='trace' \
-v "${PRIVATE_CONFIG}/without-virtual/":/tmp/docker-mailserver/ \
-v "${PRIVATE_CONFIG}/postfix-accounts.cf":/tmp/docker-mailserver/postfix-accounts.cf \
"${IMAGE_NAME}" /bin/bash -c 'open-dkim | wc -l'
@ -252,6 +262,7 @@ function teardown_file
# check keys for localhost.localdomain
run docker run --rm \
-e LOG_LEVEL='trace' \
-v "${PRIVATE_CONFIG}/without-virtual/opendkim":/etc/opendkim \
"${IMAGE_NAME}" /bin/bash -c 'ls -1 /etc/opendkim/keys/localhost.localdomain/ | wc -l'
assert_success
@ -259,6 +270,7 @@ function teardown_file
# check keys for otherdomain.tld
run docker run --rm \
-e LOG_LEVEL='trace' \
-v "${PRIVATE_CONFIG}/without-virtual/opendkim":/etc/opendkim \
"${IMAGE_NAME}" /bin/bash -c 'ls -1 /etc/opendkim/keys/otherdomain.tld | wc -l'
assert_success
@ -266,6 +278,7 @@ function teardown_file
# check presence of tables and TrustedHosts
run docker run --rm \
-e LOG_LEVEL='trace' \
-v "${PRIVATE_CONFIG}/without-virtual/opendkim":/etc/opendkim \
"${IMAGE_NAME}" /bin/bash -c "ls -1 /etc/opendkim | grep -E 'KeyTable|SigningTable|TrustedHosts|keys'|wc -l"
assert_success
@ -279,6 +292,7 @@ function teardown_file
# generate first key
run docker run --rm \
-e LOG_LEVEL='trace' \
-v "${PRIVATE_CONFIG}/with-domain/":/tmp/docker-mailserver/ \
"${IMAGE_NAME}" /bin/bash -c 'open-dkim keysize 2048 domain domain1.tld | wc -l'
assert_success
@ -286,6 +300,7 @@ function teardown_file
# generate two additional keys different to the previous one
run docker run --rm \
-e LOG_LEVEL='trace' \
-v "${PRIVATE_CONFIG}/with-domain/":/tmp/docker-mailserver/ \
"${IMAGE_NAME}" /bin/bash -c 'open-dkim keysize 2048 domain "domain2.tld,domain3.tld" | wc -l'
assert_success
@ -293,6 +308,7 @@ function teardown_file
# generate an additional key whilst providing already existing domains
run docker run --rm \
-e LOG_LEVEL='trace' \
-v "${PRIVATE_CONFIG}/with-domain/":/tmp/docker-mailserver/ \
"${IMAGE_NAME}" /bin/bash -c 'open-dkim keysize 2048 domain "domain3.tld,domain4.tld" | wc -l'
assert_success
@ -300,6 +316,7 @@ function teardown_file
# check keys for domain1.tld
run docker run --rm \
-e LOG_LEVEL='trace' \
-v "${PRIVATE_CONFIG}/with-domain/opendkim":/etc/opendkim \
"${IMAGE_NAME}" /bin/bash -c 'ls -1 /etc/opendkim/keys/domain1.tld/ | wc -l'
assert_success
@ -307,6 +324,7 @@ function teardown_file
# check keys for domain2.tld
run docker run --rm \
-e LOG_LEVEL='trace' \
-v "${PRIVATE_CONFIG}/with-domain/opendkim":/etc/opendkim \
"${IMAGE_NAME}" /bin/bash -c 'ls -1 /etc/opendkim/keys/domain2.tld | wc -l'
assert_success
@ -314,6 +332,7 @@ function teardown_file
# check keys for domain3.tld
run docker run --rm \
-e LOG_LEVEL='trace' \
-v "${PRIVATE_CONFIG}/with-domain/opendkim":/etc/opendkim \
"${IMAGE_NAME}" /bin/bash -c 'ls -1 /etc/opendkim/keys/domain3.tld | wc -l'
assert_success
@ -321,6 +340,7 @@ function teardown_file
# check keys for domain4.tld
run docker run --rm \
-e LOG_LEVEL='trace' \
-v "${PRIVATE_CONFIG}/with-domain/opendkim":/etc/opendkim \
"${IMAGE_NAME}" /bin/bash -c 'ls -1 /etc/opendkim/keys/domain4.tld | wc -l'
assert_success
@ -328,6 +348,7 @@ function teardown_file
# check presence of tables and TrustedHosts
run docker run --rm \
-e LOG_LEVEL='trace' \
-v "${PRIVATE_CONFIG}/with-domain/opendkim":/etc/opendkim \
"${IMAGE_NAME}" /bin/bash -c "ls -1 /etc/opendkim | grep -E 'KeyTable|SigningTable|TrustedHosts|keys' | wc -l"
assert_success
@ -335,6 +356,7 @@ function teardown_file
# check valid entries actually present in KeyTable
run docker run --rm \
-e LOG_LEVEL='trace' \
-v "${PRIVATE_CONFIG}/with-domain/opendkim":/etc/opendkim \
"${IMAGE_NAME}" /bin/bash -c \
"egrep 'domain1.tld|domain2.tld|domain3.tld|domain4.tld' /etc/opendkim/KeyTable | wc -l"
@ -343,6 +365,7 @@ function teardown_file
# check valid entries actually present in SigningTable
run docker run --rm \
-e LOG_LEVEL='trace' \
-v "${PRIVATE_CONFIG}/with-domain/opendkim":/etc/opendkim \
"${IMAGE_NAME}" /bin/bash -c \
"egrep 'domain1.tld|domain2.tld|domain3.tld|domain4.tld' /etc/opendkim/SigningTable | wc -l"
@ -357,6 +380,7 @@ function teardown_file
# Generate first key
run docker run --rm \
-e LOG_LEVEL='trace' \
-v "${PRIVATE_CONFIG}/with-selector/":/tmp/docker-mailserver/ \
"${IMAGE_NAME:?}" /bin/sh -c "open-dkim keysize 2048 domain 'domain1.tld' selector mailer| wc -l"
assert_success
@ -364,6 +388,7 @@ function teardown_file
# Check keys for domain1.tld
run docker run --rm \
-e LOG_LEVEL='trace' \
-v "${PRIVATE_CONFIG}/with-selector/opendkim":/etc/opendkim \
"${IMAGE_NAME:?}" /bin/sh -c 'ls -1 /etc/opendkim/keys/domain1.tld/ | wc -l'
assert_success
@ -371,6 +396,7 @@ function teardown_file
# Check key names with selector for domain1.tld
run docker run --rm \
-e LOG_LEVEL='trace' \
-v "${PRIVATE_CONFIG}/with-selector/opendkim":/etc/opendkim \
"${IMAGE_NAME:?}" /bin/sh -c "ls -1 /etc/opendkim/keys/domain1.tld | grep -E 'mailer.private|mailer.txt' | wc -l"
assert_success
@ -378,6 +404,7 @@ function teardown_file
# Check presence of tables and TrustedHosts
run docker run --rm \
-e LOG_LEVEL='trace' \
-v "${PRIVATE_CONFIG}/with-selector/opendkim":/etc/opendkim \
"${IMAGE_NAME:?}" /bin/sh -c "ls -1 /etc/opendkim | grep -E 'KeyTable|SigningTable|TrustedHosts|keys' | wc -l"
assert_success
@ -385,6 +412,7 @@ function teardown_file
# Check valid entries actually present in KeyTable
run docker run --rm \
-e LOG_LEVEL='trace' \
-v "${PRIVATE_CONFIG}/with-selector/opendkim":/etc/opendkim \
"${IMAGE_NAME:?}" /bin/sh -c \
"grep 'domain1.tld' /etc/opendkim/KeyTable | wc -l"
@ -393,6 +421,7 @@ function teardown_file
# Check valid entries actually present in SigningTable
run docker run --rm \
-e LOG_LEVEL='trace' \
-v "${PRIVATE_CONFIG}/with-selector/opendkim":/etc/opendkim \
"${IMAGE_NAME:?}" /bin/sh -c \
"grep 'domain1.tld' /etc/opendkim/SigningTable | wc -l"

View file

@ -18,7 +18,7 @@ function setup_file() {
@test "checking sedfile parameter count" {
run ${SEDFILE}
assert_failure
assert_output --partial 'Error: At least, three parameters must be given.'
assert_output --partial 'Error: At least three parameters must be given'
}
@test "checking sedfile substitute success" {
@ -35,7 +35,7 @@ function setup_file() {
@test "checking sedfile substitute failure" {
run ${SEDFILE} -i 's|bar|baz|' "${FILE}"
assert_failure
assert_output --partial "Error: sed -i s|bar|baz| /tmp/sedfile-test."
assert_output --partial "Error: No difference after call to 'sed' in 'sedfile' (sed -i s|bar|baz| /tmp/sedfile-test"
# file unchanged?
run test "$(< "${FILE}")" == 'foo baz'
@ -58,7 +58,7 @@ function setup_file() {
@test "checking sedfile substitude failure (strict)" {
run ${SEDFILE} --strict -i 's|bar|baz|' "${FILE}"
assert_failure
assert_output --partial "Error: sed -i s|bar|baz| /tmp/sedfile-test."
assert_output --partial "Error: No difference after call to 'sed' in 'sedfile' (sed -i s|bar|baz| /tmp/sedfile-test"
# file unchanged?
run test "$(< "${FILE}")" == 'foo baz'

View file

@ -935,13 +935,13 @@ EOF
# --- setup.sh ----------------------------------
# -----------------------------------------------
@test "setup.sh :: exit with error when no arguments provided" {
@test "checking setup.sh: exit with error when no arguments provided" {
run ./setup.sh
assert_failure
assert_line --index 0 --partial "The command '' is invalid."
}
@test "setup.sh :: exit with error when wrong arguments provided" {
@test "checking setup.sh: exit with error when wrong arguments provided" {
run ./setup.sh lol troll
assert_failure
assert_line --index 0 --partial "The command 'lol troll' is invalid."
@ -1114,7 +1114,7 @@ EOF
assert_failure
}
@test "setup.sh :: setup.sh config dkim help correctly displayed" {
@test "checking setup.sh: setup.sh config dkim help correctly displayed" {
run ./setup.sh -c mail config dkim help
assert_success
assert_line --index 3 --partial " open-dkim - configure DomainKeys Identified Mail (DKIM)"