diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 497b6f04..82e12aa8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -84,7 +84,7 @@ fi # equality checks with numbers are done # with -eq/-ne/-lt/-ge, not != or == -if [[ $VAR -ne 42 ]] || [[ $SOME_VAR -eq 6 ]] +if [[ ${VAR} -ne 42 ]] || [[ ${SOME_VAR} -eq 6 ]] then fi diff --git a/test/default_relay_host.bats b/test/default_relay_host.bats index ff39881c..7f865e62 100644 --- a/test/default_relay_host.bats +++ b/test/default_relay_host.bats @@ -10,7 +10,7 @@ function setup() { --cap-add=SYS_PTRACE \ -e PERMIT_DOCKER=host \ -e DMS_DEBUG=0 \ - -h mail.my-domain.com -t ${NAME} + -h mail.my-domain.com -t "${NAME}" wait_for_finished_setup_in_container mail_with_default_relay } diff --git a/test/helper_functions.bats b/test/helper_functions.bats index 4700908d..22036da1 100644 --- a/test/helper_functions.bats +++ b/test/helper_functions.bats @@ -2,6 +2,7 @@ load 'test_helper/bats-support/load' load 'test_helper/bats-assert/load' # load the helper function into current context +# shellcheck source=../target/helper-functions.sh . ./target/helper-functions.sh @test "check helper function: _sanitize_ipv4_to_subnet_cidr" { diff --git a/test/linting/lint.sh b/test/linting/lint.sh index 72fb301e..888eef90 100755 --- a/test/linting/lint.sh +++ b/test/linting/lint.sh @@ -90,7 +90,7 @@ function _eclint return 102 fi - __log_info 'linter version:' "$(${LINT[0]} --version))" + __log_info 'linter version:' "$(${LINT[0]} --version)" if "${LINT[@]}" then @@ -113,7 +113,7 @@ function _hadolint fi __log_info 'linter version:' \ - "$(${LINT[0]} --version | grep -E -o "v[0-9\.]*"))" + "$(${LINT[0]} --version | grep -E -o "v[0-9\.]*")" if git ls-files --exclude='Dockerfile*' --ignored | \ xargs --max-lines=1 "${LINT[@]}" @@ -138,7 +138,7 @@ function _shellcheck fi __log_info 'linter version:' \ - "$(${LINT[0]} --version | grep -m 2 -o "[0-9.]*"))" + "$(${LINT[0]} --version | grep -m 2 -o "[0-9.]*")" # an overengineered solution to allow shellcheck -x to # properly follow `source=` when sourcing @@ -176,21 +176,19 @@ function _shellcheck done < <(find target/bin -executable -type f) # the same for all test files - # while read -r FILE - # do - # if ! ( - # cd "$(realpath "$(dirname "$(readlink -f "${FILE}")")")" - # if ! "${LINT[@]}" "$(basename -- "${FILE}")" - # then - # return 1 - # fi - # ) - # then - # # ! Errors / warnings found here are - # # ! currently NOT accounted for. - # : - # fi - # done < <(find test/ -maxdepth 1 -type f -iname "*.bats") + while read -r FILE + do + if ! ( + cd "$(realpath "$(dirname "$(readlink -f "${FILE}")")")" + if ! "${LINT[@]}" "$(basename -- "${FILE}")" + then + return 1 + fi + ) + then + ERR=1 + fi + done < <(find test/ -maxdepth 1 -type f -iname "*.bats") if [[ ERR -eq 1 ]] then diff --git a/test/mail_dhparams_default.bats b/test/mail_dhparams_default.bats index 1444120c..67c2857e 100644 --- a/test/mail_dhparams_default.bats +++ b/test/mail_dhparams_default.bats @@ -28,7 +28,7 @@ function setup_file() { -v "$(pwd)/test/test-files":/tmp/docker-mailserver-test:ro \ -e DMS_DEBUG=0 \ -e ONE_DIR=1 \ - -h mail.my-domain.com -t ${NAME} + -h mail.my-domain.com -t "${NAME}" wait_for_finished_setup_in_container mail_default_dhparams_one_dir PRIVATE_CONFIG="$(duplicate_config_for_container . mail_default_dhparams_both_not_one_dir)" @@ -37,7 +37,7 @@ function setup_file() { -v "$(pwd)/test/test-files":/tmp/docker-mailserver-test:ro \ -e DMS_DEBUG=0 \ -e ONE_DIR=0 \ - -h mail.my-domain.com -t ${NAME} + -h mail.my-domain.com -t "${NAME}" wait_for_finished_setup_in_container mail_default_dhparams_not_one_dir } @@ -54,25 +54,25 @@ function teardown_file() { # reference used: (22/04/2020) https://english.ncsc.nl/publications/publications/2019/juni/01/it-security-guidelines-for-transport-layer-security-tls # check ffdhe params are inchanged - repo_checksum=$(sha512sum "$(pwd)/target/shared/ffdhe4096.pem" | awk '{print $1}') - mozilla_checksum=$(curl https://ssl-config.mozilla.org/ffdhe4096.txt -s | sha512sum | awk '{print $1}') - assert_equal "$repo_checksum" "$mozilla_checksum" - run echo "$repo_checksum" + REPO_CHECKSUM=$(sha512sum "$(pwd)/target/shared/ffdhe4096.pem" | awk '{print $1}') + MOZILLA_CHECKSUM=$(curl https://ssl-config.mozilla.org/ffdhe4096.txt -s | sha512sum | awk '{print $1}') + assert_equal "${REPO_CHECKSUM}" "${MOZILLA_CHECKSUM}" + run echo "${REPO_CHECKSUM}" refute_output '' # checksum must not be empty # by default, ffdhe4096 should be used # ONE_DIR=1 - docker_dovecot_checksum_one_dir=$(docker exec mail_default_dhparams_one_dir sha512sum /etc/dovecot/dh.pem | awk '{print $1}') - docker_postfix_checksum_one_dir=$(docker exec mail_default_dhparams_one_dir sha512sum /etc/postfix/dhparams.pem | awk '{print $1}') - assert_equal "$docker_dovecot_checksum_one_dir" "$repo_checksum" - assert_equal "$docker_postfix_checksum_one_dir" "$repo_checksum" + DOCKER_DOVECOT_CHECKSUM_ONE_DIR=$(docker exec mail_default_dhparams_one_dir sha512sum /etc/dovecot/dh.pem | awk '{print $1}') + DOCKER_POSTFIX_CHECKSUM_ONE_DIR=$(docker exec mail_default_dhparams_one_dir sha512sum /etc/postfix/dhparams.pem | awk '{print $1}') + assert_equal "${DOCKER_DOVECOT_CHECKSUM_ONE_DIR}" "${REPO_CHECKSUM}" + assert_equal "${DOCKER_POSTFIX_CHECKSUM_ONE_DIR}" "${REPO_CHECKSUM}" # ONE_DIR=0 - docker_dovecot_checksum_not_one_dir=$(docker exec mail_default_dhparams_not_one_dir sha512sum /etc/dovecot/dh.pem | awk '{print $1}') - docker_postfix_checksum_not_one_dir=$(docker exec mail_default_dhparams_not_one_dir sha512sum /etc/postfix/dhparams.pem | awk '{print $1}') - assert_equal "$docker_dovecot_checksum_not_one_dir" "$repo_checksum" - assert_equal "$docker_postfix_checksum_not_one_dir" "$repo_checksum" + DOCKER_DOVECOT_CHECKSUM_NOT_ONE_DIR=$(docker exec mail_default_dhparams_not_one_dir sha512sum /etc/dovecot/dh.pem | awk '{print $1}') + DOCKER_POSTFIX_CHECKSUM_NOT_ONE_DIR=$(docker exec mail_default_dhparams_not_one_dir sha512sum /etc/postfix/dhparams.pem | awk '{print $1}') + assert_equal "${DOCKER_DOVECOT_CHECKSUM_NOT_ONE_DIR}" "${REPO_CHECKSUM}" + assert_equal "${DOCKER_POSTFIX_CHECKSUM_NOT_ONE_DIR}" "${REPO_CHECKSUM}" } diff --git a/test/mail_dhparams_manual_not_one_dir.bats b/test/mail_dhparams_manual_not_one_dir.bats index 1569f67c..1300c212 100644 --- a/test/mail_dhparams_manual_not_one_dir.bats +++ b/test/mail_dhparams_manual_not_one_dir.bats @@ -31,7 +31,7 @@ function setup_file() { -v "$(pwd)/test/test-files":/tmp/docker-mailserver-test:ro \ -e DMS_DEBUG=0 \ -e ONE_DIR=0 \ - -h mail.my-domain.com -t ${NAME} + -h mail.my-domain.com -t "${NAME}" wait_for_finished_setup_in_container mail_manual_dhparams_not_one_dir } @@ -45,13 +45,13 @@ function teardown_file() { @test "checking dhparams: ONE_DIR=0 check manual dhparams is used" { test_checksum=$(sha512sum "$(pwd)/test/test-files/ssl/custom-dhe-params.pem" | awk '{print $1}') - run echo "$test_checksum" + run echo "${test_checksum}" refute_output '' # checksum must not be empty docker_dovecot_checksum=$(docker exec mail_manual_dhparams_not_one_dir sha512sum /etc/dovecot/dh.pem | awk '{print $1}') docker_postfix_checksum=$(docker exec mail_manual_dhparams_not_one_dir sha512sum /etc/postfix/dhparams.pem | awk '{print $1}') - assert_equal "$docker_dovecot_checksum" "$test_checksum" - assert_equal "$docker_postfix_checksum" "$test_checksum" + assert_equal "${docker_dovecot_checksum}" "${test_checksum}" + assert_equal "${docker_postfix_checksum}" "${test_checksum}" } @test "checking dhparams: ONE_DIR=0 check warning output when using manual dhparams" { diff --git a/test/mail_dhparams_manual_one_dir.bats b/test/mail_dhparams_manual_one_dir.bats index 56971a86..9232db77 100644 --- a/test/mail_dhparams_manual_one_dir.bats +++ b/test/mail_dhparams_manual_one_dir.bats @@ -28,7 +28,7 @@ function setup_file() { -v "$(pwd)/test/test-files/ssl/custom-dhe-params.pem":/var/mail-state/lib-shared/dhparams.pem:ro \ -e DMS_DEBUG=0 \ -e ONE_DIR=1 \ - -h mail.my-domain.com -t ${NAME} + -h mail.my-domain.com -t "${NAME}" wait_for_finished_setup_in_container mail_manual_dhparams_one_dir } @@ -42,13 +42,13 @@ function teardown_file() { @test "checking dhparams: ONE_DIR=1 check manual dhparams is used" { test_checksum=$(sha512sum "$(pwd)/test/test-files/ssl/custom-dhe-params.pem" | awk '{print $1}') - run echo "$test_checksum" + run echo "${test_checksum}" refute_output '' # checksum must not be empty docker_dovecot_checksum=$(docker exec mail_manual_dhparams_one_dir sha512sum /etc/dovecot/dh.pem | awk '{print $1}') docker_postfix_checksum=$(docker exec mail_manual_dhparams_one_dir sha512sum /etc/postfix/dhparams.pem | awk '{print $1}') - assert_equal "$docker_dovecot_checksum" "$test_checksum" - assert_equal "$docker_postfix_checksum" "$test_checksum" + assert_equal "${docker_dovecot_checksum}" "${test_checksum}" + assert_equal "${docker_postfix_checksum}" "${test_checksum}" } @test "checking dhparams: ONE_DIR=1 check warning output when using manual dhparams" { diff --git a/test/mail_disabled_clamav_spamassassin.bats b/test/mail_disabled_clamav_spamassassin.bats index 506be7cb..90dc3e85 100644 --- a/test/mail_disabled_clamav_spamassassin.bats +++ b/test/mail_disabled_clamav_spamassassin.bats @@ -17,7 +17,7 @@ setup_file() { -e ENABLE_CLAMAV=0 \ -e ENABLE_SPAMASSASSIN=0 \ -e DMS_DEBUG=0 \ - -h mail.my-domain.com -t ${NAME} + -h mail.my-domain.com -t "${NAME}" # TODO: find a better way to know when we have waited long enough # for clamav to should have come up, if it were enabled wait_for_smtp_port_in_container mail_disabled_clamav_spamassassin diff --git a/test/mail_fail2ban.bats b/test/mail_fail2ban.bats index dfcc423f..b92da282 100644 --- a/test/mail_fail2ban.bats +++ b/test/mail_fail2ban.bats @@ -17,13 +17,13 @@ function setup_file() { -e ENABLE_FAIL2BAN=1 \ -e POSTSCREEN_ACTION=ignore \ --cap-add=NET_ADMIN \ - -h mail.my-domain.com -t ${NAME} + -h mail.my-domain.com -t "${NAME}" # Create a container which will send wrong authentications and should get banned docker run --name fail-auth-mailer \ - -e MAIL_FAIL2BAN_IP=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' mail_fail2ban) \ + -e MAIL_FAIL2BAN_IP="$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' mail_fail2ban)" \ -v "$(pwd)/test/test-files":/tmp/docker-mailserver-test \ - -d ${NAME} \ + -d "${NAME}" \ tail -f /var/log/faillog wait_for_finished_setup_in_container mail_fail2ban @@ -67,26 +67,28 @@ function teardown_file() { FILTERS=(sshd postfix dovecot postfix-sasl) for FILTER in "${FILTERS[@]}"; do - run docker exec mail_fail2ban /bin/sh -c "fail2ban-client get $FILTER bantime" + run docker exec mail_fail2ban /bin/sh -c "fail2ban-client get ${FILTER} bantime" assert_output 1234 - run docker exec mail_fail2ban /bin/sh -c "fail2ban-client get $FILTER findtime" + run docker exec mail_fail2ban /bin/sh -c "fail2ban-client get ${FILTER} findtime" assert_output 321 - run docker exec mail_fail2ban /bin/sh -c "fail2ban-client get $FILTER maxretry" + run docker exec mail_fail2ban /bin/sh -c "fail2ban-client get ${FILTER} maxretry" assert_output 2 done } @test "checking fail2ban: ban ip on multiple failed login" { # can't pipe the file as usual due to postscreen. (respecting postscreen_greet_wait time and talking in turn): - for i in {1,2}; do + # shellcheck disable=SC1004 + for _ in {1,2} + do docker exec fail-auth-mailer /bin/bash -c \ - 'exec 3<>/dev/tcp/$MAIL_FAIL2BAN_IP/25 && \ + 'exec 3<>/dev/tcp/${MAIL_FAIL2BAN_IP}/25 && \ while IFS= read -r cmd; do \ head -1 <&3; \ - [[ "$cmd" == "EHLO"* ]] && sleep 6; \ - echo $cmd >&3; \ + [[ "${cmd}" == "EHLO"* ]] && sleep 6; \ + echo ${cmd} >&3; \ done < "/tmp/docker-mailserver-test/auth/smtp-auth-login-wrong.txt"' done @@ -94,26 +96,26 @@ function teardown_file() { FAIL_AUTH_MAILER_IP=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' fail-auth-mailer) # Checking that FAIL_AUTH_MAILER_IP is banned in mail_fail2ban - run docker exec mail_fail2ban /bin/sh -c "fail2ban-client status postfix-sasl | grep '$FAIL_AUTH_MAILER_IP'" + run docker exec mail_fail2ban /bin/sh -c "fail2ban-client status postfix-sasl | grep '${FAIL_AUTH_MAILER_IP}'" assert_success # Checking that FAIL_AUTH_MAILER_IP is banned by iptables - run docker exec mail_fail2ban /bin/sh -c "iptables -L f2b-postfix-sasl -n | grep REJECT | grep '$FAIL_AUTH_MAILER_IP'" + run docker exec mail_fail2ban /bin/sh -c "iptables -L f2b-postfix-sasl -n | grep REJECT | grep '${FAIL_AUTH_MAILER_IP}'" assert_success } @test "checking fail2ban: unban ip works" { FAIL_AUTH_MAILER_IP=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' fail-auth-mailer) - docker exec mail_fail2ban fail2ban-client set postfix-sasl unbanip $FAIL_AUTH_MAILER_IP + docker exec mail_fail2ban fail2ban-client set postfix-sasl unbanip "${FAIL_AUTH_MAILER_IP}" sleep 5 - run docker exec mail_fail2ban /bin/sh -c "fail2ban-client status postfix-sasl | grep 'IP list:.*$FAIL_AUTH_MAILER_IP'" + run docker exec mail_fail2ban /bin/sh -c "fail2ban-client status postfix-sasl | grep 'IP list:.*${FAIL_AUTH_MAILER_IP}'" assert_failure # Checking that FAIL_AUTH_MAILER_IP is unbanned by iptables - run docker exec mail_fail2ban /bin/sh -c "iptables -L f2b-postfix-sasl -n | grep REJECT | grep '$FAIL_AUTH_MAILER_IP'" + run docker exec mail_fail2ban /bin/sh -c "iptables -L f2b-postfix-sasl -n | grep REJECT | grep '${FAIL_AUTH_MAILER_IP}'" assert_failure } diff --git a/test/mail_fetchmail.bats b/test/mail_fetchmail.bats index 90a23f99..dd84e579 100644 --- a/test/mail_fetchmail.bats +++ b/test/mail_fetchmail.bats @@ -17,7 +17,7 @@ function setup_file() { -e ENABLE_FETCHMAIL=1 \ --cap-add=NET_ADMIN \ -e DMS_DEBUG=0 \ - -h mail.my-domain.com -t ${NAME} + -h mail.my-domain.com -t "${NAME}" wait_for_finished_setup_in_container mail_fetchmail } diff --git a/test/mail_lmtp_ip.bats b/test/mail_lmtp_ip.bats index 415739a0..d4f105bd 100644 --- a/test/mail_lmtp_ip.bats +++ b/test/mail_lmtp_ip.bats @@ -19,7 +19,7 @@ setup_file() { -e ENABLE_POSTFIX_VIRTUAL_TRANSPORT=1 \ -e POSTFIX_DAGENT=lmtp:127.0.0.1:24 \ -e DMS_DEBUG=0 \ - -h mail.my-domain.com -t ${NAME} + -h mail.my-domain.com -t "${NAME}" wait_for_finished_setup_in_container mail_lmtp_ip } diff --git a/test/mail_override_hostname.bats b/test/mail_override_hostname.bats index 91fc6799..3eb2406b 100644 --- a/test/mail_override_hostname.bats +++ b/test/mail_override_hostname.bats @@ -15,7 +15,7 @@ function setup_file() { -e ENABLE_SRS=1 \ -e OVERRIDE_HOSTNAME=mail.my-domain.com \ -h unknown.domain.tld \ - -t ${NAME} + -t "${NAME}" wait_for_smtp_port_in_container mail_override_hostname # postfix virtual transport lmtp diff --git a/test/mail_pop3.bats b/test/mail_pop3.bats index d07514c2..357367ef 100644 --- a/test/mail_pop3.bats +++ b/test/mail_pop3.bats @@ -16,7 +16,7 @@ function setup_file() { -v "$(pwd)/test/test-files":/tmp/docker-mailserver-test:ro \ -e ENABLE_POP3=1 \ -e DMS_DEBUG=0 \ - -h mail.my-domain.com -t ${NAME} + -h mail.my-domain.com -t "${NAME}" wait_for_finished_setup_in_container mail_pop3 } diff --git a/test/mail_postscreen.bats b/test/mail_postscreen.bats index 553e763a..bb39270b 100644 --- a/test/mail_postscreen.bats +++ b/test/mail_postscreen.bats @@ -19,11 +19,11 @@ setup_file() { -v "$(pwd)/test/test-files":/tmp/docker-mailserver-test:ro \ -e POSTSCREEN_ACTION=enforce \ --cap-add=NET_ADMIN \ - -h mail.my-domain.com -t ${NAME} + -h mail.my-domain.com -t "${NAME}" docker run --name mail_postscreen_sender \ -v "$(pwd)/test/test-files":/tmp/docker-mailserver-test:ro \ - -d ${NAME} \ + -d "${NAME}" \ tail -f /var/log/faillog wait_for_smtp_port_in_container mail_postscreen @@ -38,20 +38,21 @@ teardown_file() { } @test "checking postscreen: talk too fast" { - docker exec mail_postscreen_sender /bin/sh -c "nc $MAIL_POSTSCREEN_IP 25 < /tmp/docker-mailserver-test/auth/smtp-auth-login.txt" + docker exec mail_postscreen_sender /bin/sh -c "nc ${MAIL_POSTSCREEN_IP} 25 < /tmp/docker-mailserver-test/auth/smtp-auth-login.txt" repeat_until_success_or_timeout 10 run docker exec mail_postscreen grep 'COMMAND PIPELINING' /var/log/mail/mail.log assert_success } @test "checking postscreen: positive test (respecting postscreen_greet_wait time and talking in turn)" { - for i in {1,2}; do + for _ in {1,2}; do + # shellcheck disable=SC1004 docker exec mail_postscreen_sender /bin/bash -c \ - 'exec 3<>/dev/tcp/'$MAIL_POSTSCREEN_IP'/25 && \ + 'exec 3<>/dev/tcp/'"${MAIL_POSTSCREEN_IP}"'/25 && \ while IFS= read -r cmd; do \ head -1 <&3; \ - [[ "$cmd" == "EHLO"* ]] && sleep 6; \ - echo $cmd >&3; \ + [[ "${cmd}" == "EHLO"* ]] && sleep 6; \ + echo ${cmd} >&3; \ done < "/tmp/docker-mailserver-test/auth/smtp-auth-login.txt"' done diff --git a/test/mail_privacy.bats b/test/mail_privacy.bats index 01949979..c824f1e7 100644 --- a/test/mail_privacy.bats +++ b/test/mail_privacy.bats @@ -19,7 +19,7 @@ function setup_file() { --cap-add=SYS_PTRACE \ -e PERMIT_DOCKER=host \ -e DMS_DEBUG=0 \ - -h mail.my-domain.com -t ${NAME} + -h mail.my-domain.com -t "${NAME}" wait_for_amavis_port_in_container mail_privacy wait_for_smtp_port_in_container mail_privacy @@ -41,12 +41,13 @@ function teardown_file() { @test "checking postfix: remove privacy details of the sender" { docker exec mail_privacy /bin/sh -c "openssl s_client -quiet -starttls smtp -connect 0.0.0.0:587 < /tmp/docker-mailserver-test/email-templates/send-privacy-email.txt" - repeat_until_success_or_timeout 120 docker exec mail_privacy /bin/sh -c '[ $(ls /var/mail/localhost.localdomain/user1/new | wc -l) -eq 1 ]' + # shellcheck disable=SC2016 + repeat_until_success_or_timeout 120 docker exec mail_privacy /bin/bash -c '[[ $(ls /var/mail/localhost.localdomain/user1/new | wc -l) -eq 1 ]]' docker logs mail_privacy run docker exec mail_privacy /bin/sh -c "ls /var/mail/localhost.localdomain/user1/new | wc -l" assert_success assert_output 1 - run docker exec mail_privacy /bin/sh -c "grep -rE "^User-Agent:" /var/mail/localhost.localdomain/user1/new | wc -l" + run docker exec mail_privacy /bin/sh -c 'grep -rE "^User-Agent:" /var/mail/localhost.localdomain/user1/new | wc -l' assert_success assert_output 0 } diff --git a/test/mail_smtponly.bats b/test/mail_smtponly.bats index d8eb7a30..6134ffba 100644 --- a/test/mail_smtponly.bats +++ b/test/mail_smtponly.bats @@ -18,7 +18,7 @@ function setup_file() { -e PERMIT_DOCKER=network \ -e DMS_DEBUG=0 \ -e OVERRIDE_HOSTNAME=mail.my-domain.com \ - -t ${NAME} + -t "${NAME}" wait_for_finished_setup_in_container mail_smtponly } @@ -66,7 +66,7 @@ function teardown_file() { run docker exec mail_smtponly /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/smtp-only.txt" assert_success run docker exec mail_smtponly /bin/sh -c 'grep -cE "to=.*status\=sent" /var/log/mail/mail.log' - [ "$status" -ge 0 ] + [ "${status}" -ge 0 ] } # diff --git a/test/mail_special_use_folders.bats b/test/mail_special_use_folders.bats index 888b2fce..2fd7bdcd 100644 --- a/test/mail_special_use_folders.bats +++ b/test/mail_special_use_folders.bats @@ -20,7 +20,7 @@ setup_file() { --cap-add=SYS_PTRACE \ -e PERMIT_DOCKER=host \ -e DMS_DEBUG=0 \ - -h mail.my-domain.com -t ${NAME} + -h mail.my-domain.com -t "${NAME}" wait_for_smtp_port_in_container mail_special_use_folders } @@ -37,6 +37,7 @@ teardown_file() { run docker exec mail_special_use_folders /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/existing-user1.txt" assert_success + # shellcheck disable=SC2016 repeat_until_success_or_timeout 30 docker exec mail_special_use_folders /bin/sh -c '[ $(ls /var/mail/localhost.localdomain/user1/new | wc -l) -eq 1 ]' } diff --git a/test/mail_srs_domainname.bats b/test/mail_srs_domainname.bats index b6f38761..aa730476 100644 --- a/test/mail_srs_domainname.bats +++ b/test/mail_srs_domainname.bats @@ -12,7 +12,7 @@ load 'test_helper/common' -e SRS_DOMAINNAME=srs.my-domain.com \ -e DOMAINNAME=my-domain.com \ -h unknown.domain.tld \ - -t ${NAME} + -t "${NAME}" teardown() { docker rm -f mail_srs_domainname; } @@ -30,7 +30,7 @@ load 'test_helper/common' -e ENABLE_SRS=1 \ -e DOMAINNAME=my-domain.com \ -h unknown.domain.tld \ - -t ${NAME} + -t "${NAME}" teardown() { docker rm -f mail_domainname; } diff --git a/test/mail_ssl_letsencrypt.bats b/test/mail_ssl_letsencrypt.bats index 45694923..5aec6753 100644 --- a/test/mail_ssl_letsencrypt.bats +++ b/test/mail_ssl_letsencrypt.bats @@ -18,7 +18,7 @@ function setup_file() { -v "${PRIVATE_CONFIG}/letsencrypt/my-domain.com":/etc/letsencrypt/live/my-domain.com \ -e DMS_DEBUG=0 \ -e SSL_TYPE=letsencrypt \ - -h mail.my-domain.com -t ${NAME} + -h mail.my-domain.com -t "${NAME}" wait_for_finished_setup_in_container mail_lets_domain PRIVATE_CONFIG="$(duplicate_config_for_container . mail_lets_hostname)" @@ -28,7 +28,7 @@ function setup_file() { -v "${PRIVATE_CONFIG}/letsencrypt/mail.my-domain.com":/etc/letsencrypt/live/mail.my-domain.com \ -e DMS_DEBUG=0 \ -e SSL_TYPE=letsencrypt \ - -h mail.my-domain.com -t ${NAME} + -h mail.my-domain.com -t "${NAME}" wait_for_finished_setup_in_container mail_lets_hostname PRIVATE_CONFIG="$(duplicate_config_for_container . mail_lets_acme_json)" @@ -40,7 +40,7 @@ function setup_file() { -e DMS_DEBUG=0 \ -e SSL_TYPE=letsencrypt \ -e "SSL_DOMAIN=*.example.com" \ - -h mail.my-domain.com -t ${NAME} + -h mail.my-domain.com -t "${NAME}" wait_for_finished_setup_in_container mail_lets_acme_json } diff --git a/test/mail_ssl_manual.bats b/test/mail_ssl_manual.bats index 5ad6e7a8..a65f041f 100644 --- a/test/mail_ssl_manual.bats +++ b/test/mail_ssl_manual.bats @@ -18,7 +18,7 @@ function setup_file() { -e SSL_CERT_PATH=/tmp/docker-mailserver/letsencrypt/mail.my-domain.com/fullchain.pem \ -e SSL_KEY_PATH=/tmp/docker-mailserver/letsencrypt/mail.my-domain.com/privkey.pem \ -e DMS_DEBUG=0 \ - -h mail.my-domain.com -t ${NAME} + -h mail.my-domain.com -t "${NAME}" wait_for_finished_setup_in_container mail_manual_ssl } diff --git a/test/mail_undef_spam_subject.bats b/test/mail_undef_spam_subject.bats index a12e3dd5..aa08fd0b 100644 --- a/test/mail_undef_spam_subject.bats +++ b/test/mail_undef_spam_subject.bats @@ -8,7 +8,7 @@ function setup() { -v "$(pwd)/test/test-files":/tmp/docker-mailserver-test:ro \ -e ENABLE_SPAMASSASSIN=1 \ -e SA_SPAM_SUBJECT="undef" \ - -h mail.my-domain.com -t ${NAME} + -h mail.my-domain.com -t "${NAME}" PRIVATE_CONFIG="$(duplicate_config_for_container . mail_undef_spam_subject_2)" CONTAINER=$(docker run -d \ @@ -31,23 +31,23 @@ function setup() { --cap-add=SYS_PTRACE \ -e PERMIT_DOCKER=host \ -e DMS_DEBUG=0 \ - -h mail.my-domain.com -t ${NAME}) + -h mail.my-domain.com -t "${NAME}") wait_for_finished_setup_in_container mail_undef_spam_subject - wait_for_finished_setup_in_container "$CONTAINER" + wait_for_finished_setup_in_container "${CONTAINER}" } function teardown() { - docker rm -f mail_undef_spam_subject "$CONTAINER" + docker rm -f mail_undef_spam_subject "${CONTAINER}" } @test "checking spamassassin: docker env variables are set correctly (custom)" { - run docker exec "$CONTAINER" /bin/sh -c "grep '\$sa_tag_level_deflt' /etc/amavis/conf.d/20-debian_defaults | grep '= -5.0'" + run docker exec "${CONTAINER}" /bin/sh -c "grep '\$sa_tag_level_deflt' /etc/amavis/conf.d/20-debian_defaults | grep '= -5.0'" assert_success - run docker exec "$CONTAINER" /bin/sh -c "grep '\$sa_tag2_level_deflt' /etc/amavis/conf.d/20-debian_defaults | grep '= 2.0'" + run docker exec "${CONTAINER}" /bin/sh -c "grep '\$sa_tag2_level_deflt' /etc/amavis/conf.d/20-debian_defaults | grep '= 2.0'" assert_success - run docker exec "$CONTAINER" /bin/sh -c "grep '\$sa_kill_level_deflt' /etc/amavis/conf.d/20-debian_defaults | grep '= 3.0'" + run docker exec "${CONTAINER}" /bin/sh -c "grep '\$sa_kill_level_deflt' /etc/amavis/conf.d/20-debian_defaults | grep '= 3.0'" assert_success - run docker exec "$CONTAINER" /bin/sh -c "grep '\$sa_spam_subject_tag' /etc/amavis/conf.d/20-debian_defaults | grep '= .SPAM: .'" + run docker exec "${CONTAINER}" /bin/sh -c "grep '\$sa_spam_subject_tag' /etc/amavis/conf.d/20-debian_defaults | grep '= .SPAM: .'" assert_success run docker exec mail_undef_spam_subject /bin/sh -c "grep '\$sa_spam_subject_tag' /etc/amavis/conf.d/20-debian_defaults | grep '= undef'" assert_success diff --git a/test/mail_with_imap.bats b/test/mail_with_imap.bats index 1fc51af4..a029603e 100644 --- a/test/mail_with_imap.bats +++ b/test/mail_with_imap.bats @@ -20,7 +20,7 @@ setup_file() { -e SASLAUTHD_MECH_OPTIONS=127.0.0.1 \ -e POSTMASTER_ADDRESS=postmaster@localhost.localdomain \ -e DMS_DEBUG=0 \ - -h mail.my-domain.com -t ${NAME} + -h mail.my-domain.com -t "${NAME}" wait_for_smtp_port_in_container mail_with_imap } diff --git a/test/mail_with_ldap.bats b/test/mail_with_ldap.bats index 04a2b33f..408a7188 100644 --- a/test/mail_with_ldap.bats +++ b/test/mail_with_ldap.bats @@ -9,9 +9,9 @@ function teardown() { } function setup_file() { - pushd test/docker-openldap/ + pushd test/docker-openldap/ || return 1 docker build -f Dockerfile -t ldap --no-cache . - popd + popd || return 1 docker run -d --name ldap_for_mail \ -e LDAP_DOMAIN="localhost.localdomain" \ @@ -46,7 +46,7 @@ function setup_file() { -e POSTMASTER_ADDRESS=postmaster@localhost.localdomain \ -e DMS_DEBUG=0 \ --link ldap_for_mail:ldap \ - -h mail.my-domain.com -t ${NAME} + -h mail.my-domain.com -t "${NAME}" wait_for_smtp_port_in_container mail_with_ldap } @@ -55,7 +55,7 @@ function teardown_file() { } @test "first" { - # this test must come first to reliably identify when to run setup_file + skip 'only used to call setup_file from setup' } # processes @@ -236,5 +236,5 @@ function teardown_file() { } @test "last" { - # this test is only there to reliably mark the end for the teardown_file + skip 'only used to call teardown_file from teardown' } diff --git a/test/mail_with_mdbox.bats b/test/mail_with_mdbox.bats index 7bc28285..8857cda6 100644 --- a/test/mail_with_mdbox.bats +++ b/test/mail_with_mdbox.bats @@ -21,16 +21,16 @@ setup_file() { --cap-add=SYS_PTRACE \ -e PERMIT_DOCKER=host \ -e DMS_DEBUG=0 \ - -h mail.my-domain.com -t ${NAME} + -h mail.my-domain.com -t "${NAME}" wait_for_smtp_port_in_container mail_with_mdbox_format } teardown_file() { - docker rm -f mail_with_mdbox_format + docker rm -f mail_with_mdbox_format } @test "first" { - skip 'only used to call setup_file from setup' + skip 'this test must come first to reliably identify when to run setup_file' } @@ -38,6 +38,7 @@ teardown_file() { run docker exec mail_with_mdbox_format /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/existing-user1.txt" assert_success + # shellcheck disable=SC2016 repeat_until_success_or_timeout 30 docker exec mail_with_mdbox_format /bin/sh -c '[ $(ls /var/mail/localhost.localdomain/user1/storage/m.1 | wc -l) -eq 1 ]' } diff --git a/test/mail_with_postgrey.bats b/test/mail_with_postgrey.bats index a7aaf2c3..dfc49806 100644 --- a/test/mail_with_postgrey.bats +++ b/test/mail_with_postgrey.bats @@ -20,7 +20,7 @@ function setup_file() { -e POSTGREY_AUTO_WHITELIST_CLIENTS=5 \ -e POSTGREY_TEXT="Delayed by postgrey" \ -e DMS_DEBUG=0 \ - -h mail.my-domain.com -t ${NAME} + -h mail.my-domain.com -t "${NAME}" # using postfix availability as start indicator, this might be insufficient for postgrey wait_for_smtp_port_in_container mail_with_postgrey } @@ -30,7 +30,7 @@ function teardown_file() { } @test "first" { - # this test must come first to reliably identify when to run setup_file + skip 'this test must come first to reliably identify when to run setup_file' } @test "checking postgrey: /etc/postfix/main.cf correctly edited" { @@ -99,5 +99,5 @@ function teardown_file() { } @test "last" { - # this test is only there to reliably mark the end for the teardown_file + skip 'this test is only there to reliably mark the end for the teardown_file' } diff --git a/test/mail_with_postgrey_disabled_by_default.bats b/test/mail_with_postgrey_disabled_by_default.bats index 9dec8022..f7b96e6b 100644 --- a/test/mail_with_postgrey_disabled_by_default.bats +++ b/test/mail_with_postgrey_disabled_by_default.bats @@ -7,16 +7,16 @@ function setup() { -v "${PRIVATE_CONFIG}":/tmp/docker-mailserver \ -v "$(pwd)/test/test-files":/tmp/docker-mailserver-test:ro \ -e DMS_DEBUG=0 \ - -h mail.my-domain.com -t ${NAME}) + -h mail.my-domain.com -t "${NAME}") # using postfix availability as start indicator, this might be insufficient for postgrey - wait_for_smtp_port_in_container $CONTAINER + wait_for_smtp_port_in_container "${CONTAINER}" } function teardown() { - docker rm -f $CONTAINER + docker rm -f "${CONTAINER}" } @test "checking process: postgrey (disabled in default configuration)" { - run docker exec $CONTAINER /bin/bash -c "ps aux --forest | grep -v grep | grep 'postgrey'" + run docker exec "${CONTAINER}" /bin/bash -c "ps aux --forest | grep -v grep | grep 'postgrey'" assert_failure } diff --git a/test/mail_with_relays.bats b/test/mail_with_relays.bats index a374efd4..27525fd7 100644 --- a/test/mail_with_relays.bats +++ b/test/mail_with_relays.bats @@ -12,10 +12,10 @@ function setup_file() { # We use a temporary config directory since we'll be dynamically editing # it with setup.sh. tmp_confdir=$(mktemp -d /tmp/docker-mailserver-config-relay-hosts-XXXXX) - cp -aT test/config/relay-hosts "$tmp_confdir" + cp -aT test/config/relay-hosts "${tmp_confdir}" docker run -d --name mail_with_relays \ - -v "$tmp_confdir":/tmp/docker-mailserver \ + -v "${tmp_confdir}":/tmp/docker-mailserver \ -v "$(pwd)/test/test-files":/tmp/docker-mailserver-test:ro \ -e RELAY_HOST=default.relay.com \ -e RELAY_PORT=2525 \ @@ -24,17 +24,17 @@ function setup_file() { --cap-add=SYS_PTRACE \ -e PERMIT_DOCKER=host \ -e DMS_DEBUG=0 \ - -h mail.my-domain.com -t ${NAME} + -h mail.my-domain.com -t "${NAME}" wait_for_finished_setup_in_container mail_with_relays } function teardown_file() { docker rm -f mail_with_relays - rm -rf "$tmp_confdir" + rm -rf "${tmp_confdir}" } @test "first" { - # this test must come first to reliably identify when to run setup_file + skip 'this test must come first to reliably identify when to run setup_file' } @test "checking relay hosts: default mapping is added from env vars" { @@ -87,5 +87,5 @@ function teardown_file() { } @test "last" { - # this test is only there to reliably mark the end for the teardown_file + skip 'this test is only there to reliably mark the end for the teardown_file' } diff --git a/test/mail_with_sdbox.bats b/test/mail_with_sdbox.bats index 3391bd9b..d4f8416e 100644 --- a/test/mail_with_sdbox.bats +++ b/test/mail_with_sdbox.bats @@ -21,7 +21,7 @@ setup_file() { --cap-add=SYS_PTRACE \ -e PERMIT_DOCKER=host \ -e DMS_DEBUG=0 \ - -h mail.my-domain.com -t ${NAME} + -h mail.my-domain.com -t "${NAME}" wait_for_smtp_port_in_container mail_with_sdbox_format } @@ -30,7 +30,7 @@ teardown_file() { } @test "first" { - skip 'only used to call setup_file from setup' + skip 'this test must come first to reliably identify when to run setup_file' } @@ -38,10 +38,11 @@ teardown_file() { run docker exec mail_with_sdbox_format /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/existing-user1.txt" assert_success + # shellcheck disable=SC2016 repeat_until_success_or_timeout 30 docker exec mail_with_sdbox_format /bin/sh -c '[ $(ls /var/mail/localhost.localdomain/user1/mailboxes/INBOX/dbox-Mails/u.1 | wc -l) -eq 1 ]' } @test "last" { - skip 'only used to call teardown_file from teardown' + skip 'this test is only there to reliably mark the end for the teardown_file' } diff --git a/test/permit_docker.bats b/test/permit_docker.bats index 8d889e06..740455bf 100644 --- a/test/permit_docker.bats +++ b/test/permit_docker.bats @@ -2,8 +2,8 @@ load 'test_helper/common' NON_DEFAULT_DOCKER_MAIL_NETWORK_NAME=non-default-docker-mail-network setup() { - docker network create --driver bridge ${NON_DEFAULT_DOCKER_MAIL_NETWORK_NAME} - docker network create --driver bridge ${NON_DEFAULT_DOCKER_MAIL_NETWORK_NAME}2 + docker network create --driver bridge "${NON_DEFAULT_DOCKER_MAIL_NETWORK_NAME}" + docker network create --driver bridge "${NON_DEFAULT_DOCKER_MAIL_NETWORK_NAME}2" # use two networks (default ("bridge") and our custom network) to recreate problematic test case where PERMIT_DOCKER=host would not help # currently we cannot use --network in `docker run` multiple times, it will just use the last one # instead we need to use create, network connect and start (see https://success.docker.com/article/multiple-docker-networks) @@ -39,15 +39,15 @@ teardown() { docker logs mail_smtponly_second_network docker rm -f mail_smtponly_second_network \ mail_smtponly_second_network_sender - docker network rm ${NON_DEFAULT_DOCKER_MAIL_NETWORK_NAME} ${NON_DEFAULT_DOCKER_MAIL_NETWORK_NAME}2 + docker network rm "${NON_DEFAULT_DOCKER_MAIL_NETWORK_NAME}" "${NON_DEFAULT_DOCKER_MAIL_NETWORK_NAME}2" } @test "checking PERMIT_DOCKER: connected-networks" { - ipnet1=$(docker network inspect --format '{{(index .IPAM.Config 0).Subnet}}' non-default-docker-mail-network) - ipnet2=$(docker network inspect --format '{{(index .IPAM.Config 0).Subnet}}' non-default-docker-mail-network2) + IPNET1=$(docker network inspect --format '{{(index .IPAM.Config 0).Subnet}}' non-default-docker-mail-network) + IPNET2=$(docker network inspect --format '{{(index .IPAM.Config 0).Subnet}}' non-default-docker-mail-network2) run docker exec mail_smtponly_second_network /bin/sh -c "postconf | grep '^mynetworks ='" - assert_output --partial $ipnet1 - assert_output --partial $ipnet2 + assert_output --partial "${IPNET1}" + assert_output --partial "${IPNET2}" run docker exec mail_smtponly_second_network /bin/sh -c "postconf -e smtp_host_lookup=no" assert_success @@ -58,5 +58,5 @@ teardown() { assert_output --partial "250 2.0.0 Ok: queued as " repeat_until_success_or_timeout 60 run docker exec mail_smtponly_second_network /bin/sh -c 'grep -cE "to=.*status\=sent" /var/log/mail/mail.log' - [ "$status" -ge 0 ] + [ "${status}" -ge 0 ] } diff --git a/test/test_helper.bats b/test/test_helper.bats index 7473241d..e61f2418 100644 --- a/test/test_helper.bats +++ b/test/test_helper.bats @@ -112,14 +112,14 @@ load 'test_helper/common' # but it will finish eventually SECONDS=1 wait_for_finished_setup_in_container "${CONTAINER_NAME}" - [[ $SECONDS -gt 0 ]] + [[ ${SECONDS} -gt 0 ]] } @test "duplicate_config_for_container" { local path path="$(duplicate_config_for_container duplicate_config_test)" - run cat "$path/marker" + run cat "${path}/marker" assert_line "This marker file is there to identify the correct config being copied" run duplicate_config_for_container non-existant-source-folder "${BATS_TEST_NAME}2" @@ -138,7 +138,7 @@ load 'test_helper/common' # pick a service that was not started ! container_has_service_running "${CONTAINER_NAME}" clamav - + # wait for a service that should be started wait_for_service "${CONTAINER_NAME}" postfix @@ -148,7 +148,7 @@ load 'test_helper/common' # now it should be off SECONDS=0 TEST_TIMEOUT_IN_SECONDS=5 run wait_for_service "${CONTAINER_NAME}" postfix - [[ $SECONDS -ge 5 ]] + [[ ${SECONDS} -ge 5 ]] assert_failure } @@ -194,7 +194,7 @@ load 'test_helper/common' # that should eventually be detected SECONDS=0 wait_for_changes_to_be_detected_in_container "${CONTAINER_NAME}" - [[ $SECONDS -gt 0 ]] + [[ ${SECONDS} -gt 0 ]] } @test "wait_for_empty_mail_queue_in_container fails when timeout reached" { @@ -208,7 +208,7 @@ load 'test_helper/common' -e ENABLE_CLAMAV=1 \ -h mail.my-domain.com \ -t "${NAME}")" - + teardown() { docker rm -f "${CONTAINER_NAME}"; } wait_for_smtp_port_in_container "${CONTAINER_NAME}" || docker logs "${CONTAINER_NAME}" @@ -216,11 +216,11 @@ load 'test_helper/common' SECONDS=0 # no mails -> should return immediately TEST_TIMEOUT_IN_SECONDS=5 wait_for_empty_mail_queue_in_container "${CONTAINER_NAME}" - [[ $SECONDS -lt 5 ]] + [[ ${SECONDS} -lt 5 ]] # fill the queue with a message docker exec "${CONTAINER_NAME}" /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/amavis-virus.txt" - + # that should still be stuck in the queue ! TEST_TIMEOUT_IN_SECONDS=0 wait_for_empty_mail_queue_in_container "${CONTAINER_NAME}" } @@ -236,7 +236,7 @@ load 'test_helper/common' -e ENABLE_CLAMAV=1 \ -h mail.my-domain.com \ -t "${NAME}")" - + teardown() { docker rm -f "${CONTAINER_NAME}"; } wait_for_smtp_port_in_container "${CONTAINER_NAME}" || docker logs "${CONTAINER_NAME}" @@ -247,5 +247,5 @@ load 'test_helper/common' # give it some time to clear the queue SECONDS=0 wait_for_empty_mail_queue_in_container "${CONTAINER_NAME}" - [[ $SECONDS -gt 0 ]] + [[ ${SECONDS} -gt 0 ]] } diff --git a/test/tests.bats b/test/tests.bats index 803ef294..b2016316 100644 --- a/test/tests.bats +++ b/test/tests.bats @@ -745,6 +745,7 @@ EOF } @test "checking amavis: VIRUSMAILS_DELETE_DELAY override works as expected" { + # shellcheck disable=SC2016 run docker run --rm -e VIRUSMAILS_DELETE_DELAY=2 "${IMAGE_NAME:?}" /bin/bash -c 'echo "${VIRUSMAILS_DELETE_DELAY}"' assert_output 2 } @@ -921,7 +922,7 @@ EOF sleep 2 changepass=$(docker exec mail /bin/sh -c "grep '^user4@domain\.tld' -i /tmp/docker-mailserver/postfix-accounts.cf") - [ "$initialpass" != "$changepass" ] + [ "${initialpass}" != "${changepass}" ] docker exec mail /bin/sh -c "delmailuser -y auser3@domain.tld" @@ -1592,5 +1593,5 @@ EOF } @test "last" { - # this test is only there to reliably mark the end for the teardown_file + skip 'this test is only there to reliably mark the end for the teardown_file (test.bats finished)' }