From f01102fd3432085367afe81f2afe2776200881dc Mon Sep 17 00:00:00 2001 From: Erik Wramner Date: Sun, 28 Jul 2019 14:33:52 +0200 Subject: [PATCH 01/16] Connect to running container if -c is used --- setup.sh | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/setup.sh b/setup.sh index c5c64b74..4f7dbf5e 100755 --- a/setup.sh +++ b/setup.sh @@ -12,6 +12,7 @@ INFO=$(docker ps \ IMAGE_NAME=$(echo $INFO | awk '{print $1}') CONTAINER_NAME=$(echo $INFO | awk '{print $2}') DEFAULT_CONFIG_PATH="$(pwd)/config" +USE_CONTAINER=false _update_config_path() { VOLUME=$(docker inspect $CONTAINER_NAME \ @@ -98,14 +99,21 @@ _docker_image_exists() { } _docker_image() { - if ! _docker_image_exists "$IMAGE_NAME"; then - echo "Image '$IMAGE_NAME' not found. Pulling ..." - docker pull "$IMAGE_NAME" - fi + if [ "$USE_CONTAINER" = true ]; then + # Reuse existing container specified on command line + docker exec -ti "$CONTAINER_NAME" "$@" + else + # Start temporary container with specified image + if ! _docker_image_exists "$IMAGE_NAME"; then + echo "Image '$IMAGE_NAME' not found. Pulling ..." + docker pull "$IMAGE_NAME" + fi + docker run \ --rm \ -v "$CONFIG_PATH":/tmp/docker-mailserver \ -ti "$IMAGE_NAME" $@ + fi } _docker_container() { @@ -121,6 +129,7 @@ while getopts ":c:i:p:" OPT; do case $OPT in c) CONTAINER_NAME="$OPTARG" + USE_CONTAINER=true # Container specified, connect to running instance ;; i) IMAGE_NAME="$OPTARG" From 7299be1284e6c2f7861c25e8374a1a28746fe6c6 Mon Sep 17 00:00:00 2001 From: Erik Wramner Date: Sun, 28 Jul 2019 19:32:01 +0200 Subject: [PATCH 02/16] Split tests to find out why they fail --- test/tests.bats | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/test/tests.bats b/test/tests.bats index a89b8af7..d0a2ed38 100644 --- a/test/tests.bats +++ b/test/tests.bats @@ -1250,9 +1250,20 @@ load 'test_helper/bats-assert/load' } @test "checking setup.sh: setup.sh email update" { - ./setup.sh -c mail email add lorem@impsum.org test_test && initialpass=$(cat ./test/config/postfix-accounts.cf | grep lorem@impsum.org | awk -F '|' '{print $2}') + run ./setup.sh -c mail email add lorem@impsum.org test_test + assert_success + + initialpass=$(cat ./test/config/postfix-accounts.cf | grep lorem@impsum.org | awk -F '|' '{print $2}') + [ "$initialpass" != "" ] + assert_success + run ./setup.sh -c mail email update lorem@impsum.org my password + assert_success + updatepass=$(cat ./test/config/postfix-accounts.cf | grep lorem@impsum.org | awk -F '|' '{print $2}') + [ "$updatepass" != "" ] + assert_success + [ "$initialpass" != "$updatepass" ] assert_success From 1f298e3a768502e61b8d12bdbf28f940df5f1c3e Mon Sep 17 00:00:00 2001 From: Erik Wramner Date: Mon, 29 Jul 2019 09:48:31 +0200 Subject: [PATCH 03/16] Wait and retry if added user fails to login in tests --- test/tests.bats | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/tests.bats b/test/tests.bats index d0a2ed38..bf561cb2 100644 --- a/test/tests.bats +++ b/test/tests.bats @@ -1434,6 +1434,12 @@ load 'test_helper/bats-assert/load' @test "checking setup.sh: email add login validation" { # validates that the user created previously with setup.sh can login + + if ! (docker exec mail doveadm auth test -x service=smtp setup_email_add@example.com 'test_password' >/dev/null); then + # Possibly the cron job has not had time to run yet, waiting a while is better than a false alarm + sleep 30 + fi + result=$(docker exec mail doveadm auth test -x service=smtp setup_email_add@example.com 'test_password' | grep 'auth succeeded') [ "$result" = "passdb: setup_email_add@example.com auth succeeded" ] } From e47c73f7895d7d0816fd68ddb58f00600605fd1a Mon Sep 17 00:00:00 2001 From: Erik Wramner Date: Mon, 29 Jul 2019 12:27:08 +0200 Subject: [PATCH 04/16] Wait and retry if pre-defined user login fails --- test/tests.bats | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/tests.bats b/test/tests.bats index bf561cb2..7ce954d6 100644 --- a/test/tests.bats +++ b/test/tests.bats @@ -1212,6 +1212,11 @@ load 'test_helper/bats-assert/load' @test "checking user login: predefined user can login" { + # This should really not be necessary, but this test sometimes fails, probably due to timing + if ! (docker exec mail doveadm auth test -x service=smtp pass@localhost.localdomain 'may be \a `p^a.*ssword' >/dev/null); then + sleep 60 + fi + result=$(docker exec mail doveadm auth test -x service=smtp pass@localhost.localdomain 'may be \a `p^a.*ssword' | grep 'auth succeeded') [ "$result" = "passdb: pass@localhost.localdomain auth succeeded" ] } From b58fd30c0a7e848b91294e9d68e5076a82442ad4 Mon Sep 17 00:00:00 2001 From: Erik Wramner Date: Tue, 30 Jul 2019 08:44:37 +0200 Subject: [PATCH 05/16] Sync after update to make sure changes propagate to host --- target/bin/addmailuser | 1 + target/bin/updatemailuser | 1 + 2 files changed, 2 insertions(+) diff --git a/target/bin/addmailuser b/target/bin/addmailuser index 04b40b4b..c679d701 100755 --- a/target/bin/addmailuser +++ b/target/bin/addmailuser @@ -32,3 +32,4 @@ if [ -z "$PASSWD" ]; then fi HASH="$(doveadm pw -s SHA512-CRYPT -u "$USER" -p "$PASSWD")" echo "$USER|$HASH" >> $DATABASE +sync $DATABASE diff --git a/target/bin/updatemailuser b/target/bin/updatemailuser index 1d32d0f0..eb9ef953 100755 --- a/target/bin/updatemailuser +++ b/target/bin/updatemailuser @@ -31,3 +31,4 @@ grep -qi "^$(escape "$USER")|" $DATABASE 2>/dev/null || errex "User \"$USER\" does not exist" sed -i "s ^"$USER"|.* "$USER"|"$HASH" " $DATABASE +sync $DATABASE From 566c28555a2628c28890af870e98823e175a2252 Mon Sep 17 00:00:00 2001 From: Erik Wramner Date: Tue, 30 Jul 2019 13:07:40 +0200 Subject: [PATCH 06/16] Revert "Sync after update to make sure changes propagate to host" This reverts commit 66711cfe5d33a9ce5ae3d78e7b7c04e68edf1571. --- target/bin/addmailuser | 1 - target/bin/updatemailuser | 1 - 2 files changed, 2 deletions(-) diff --git a/target/bin/addmailuser b/target/bin/addmailuser index c679d701..04b40b4b 100755 --- a/target/bin/addmailuser +++ b/target/bin/addmailuser @@ -32,4 +32,3 @@ if [ -z "$PASSWD" ]; then fi HASH="$(doveadm pw -s SHA512-CRYPT -u "$USER" -p "$PASSWD")" echo "$USER|$HASH" >> $DATABASE -sync $DATABASE diff --git a/target/bin/updatemailuser b/target/bin/updatemailuser index eb9ef953..1d32d0f0 100755 --- a/target/bin/updatemailuser +++ b/target/bin/updatemailuser @@ -31,4 +31,3 @@ grep -qi "^$(escape "$USER")|" $DATABASE 2>/dev/null || errex "User \"$USER\" does not exist" sed -i "s ^"$USER"|.* "$USER"|"$HASH" " $DATABASE -sync $DATABASE From f849b46462e8b1dfe0c39e089f4a2f3ef4d62428 Mon Sep 17 00:00:00 2001 From: Erik Wramner Date: Tue, 30 Jul 2019 13:16:23 +0200 Subject: [PATCH 07/16] Moved test files and mounted read-only --- Makefile | 40 +++++++++---------- .../{ => test-files}/auth/added-imap-auth.txt | 0 .../{ => test-files}/auth/added-pop3-auth.txt | 0 .../auth/added-smtp-auth-login-wrong.txt | 0 .../auth/added-smtp-auth-login.txt | 0 .../auth/added-smtp-auth-plain-wrong.txt | 0 .../auth/added-smtp-auth-plain.txt | 0 .../auth/added-smtp-auth-spoofed-alias.txt | 0 .../auth/added-smtp-auth-spoofed.txt | 0 test/{ => test-files}/auth/imap-auth.txt | 0 test/{ => test-files}/auth/imap-ldap-auth.txt | 0 .../auth/ldap-smtp-auth-spoofed-alias.txt | 0 .../auth/ldap-smtp-auth-spoofed.txt | 0 test/{ => test-files}/auth/pop3-auth.txt | 0 .../auth/sasl-ldap-smtp-auth.txt | 0 .../auth/smtp-auth-login-wrong.txt | 0 .../{ => test-files}/auth/smtp-auth-login.txt | 0 .../auth/smtp-auth-plain-wrong.txt | 0 .../{ => test-files}/auth/smtp-auth-plain.txt | 0 .../email-templates/amavis-spam.txt | 0 .../email-templates/amavis-virus.txt | 0 .../email-templates/existing-added.txt | 0 .../existing-alias-external.txt | 0 .../email-templates/existing-alias-local.txt | 0 .../existing-alias-recipient-delimiter.txt | 0 .../existing-catchall-local.txt | 0 .../existing-regexp-alias-external.txt | 0 .../existing-regexp-alias-local.txt | 0 .../existing-user-and-cc-local-alias.txt | 0 .../email-templates/existing-user1.txt | 0 .../email-templates/existing-user2.txt | 0 .../email-templates/non-existing-user.txt | 0 .../email-templates/postgrey.txt | 0 .../email-templates/root-email.txt | 0 .../email-templates/send-privacy-email.txt | 0 .../email-templates/sieve-pipe.txt | 0 .../email-templates/sieve-spam-folder.txt | 0 .../email-templates/smtp-only.txt | 0 .../email-templates/test-email.txt | 0 .../nc_templates/postgrey_whitelist.txt | 0 .../nc_templates/postgrey_whitelist_local.txt | 0 .../postgrey_whitelist_recipients.txt | 0 test/tests.bats | 5 ++- 43 files changed, 24 insertions(+), 21 deletions(-) rename test/{ => test-files}/auth/added-imap-auth.txt (100%) rename test/{ => test-files}/auth/added-pop3-auth.txt (100%) rename test/{ => test-files}/auth/added-smtp-auth-login-wrong.txt (100%) rename test/{ => test-files}/auth/added-smtp-auth-login.txt (100%) rename test/{ => test-files}/auth/added-smtp-auth-plain-wrong.txt (100%) rename test/{ => test-files}/auth/added-smtp-auth-plain.txt (100%) rename test/{ => test-files}/auth/added-smtp-auth-spoofed-alias.txt (100%) rename test/{ => test-files}/auth/added-smtp-auth-spoofed.txt (100%) rename test/{ => test-files}/auth/imap-auth.txt (100%) rename test/{ => test-files}/auth/imap-ldap-auth.txt (100%) rename test/{ => test-files}/auth/ldap-smtp-auth-spoofed-alias.txt (100%) rename test/{ => test-files}/auth/ldap-smtp-auth-spoofed.txt (100%) rename test/{ => test-files}/auth/pop3-auth.txt (100%) rename test/{ => test-files}/auth/sasl-ldap-smtp-auth.txt (100%) rename test/{ => test-files}/auth/smtp-auth-login-wrong.txt (100%) rename test/{ => test-files}/auth/smtp-auth-login.txt (100%) rename test/{ => test-files}/auth/smtp-auth-plain-wrong.txt (100%) rename test/{ => test-files}/auth/smtp-auth-plain.txt (100%) rename test/{ => test-files}/email-templates/amavis-spam.txt (100%) rename test/{ => test-files}/email-templates/amavis-virus.txt (100%) rename test/{ => test-files}/email-templates/existing-added.txt (100%) rename test/{ => test-files}/email-templates/existing-alias-external.txt (100%) rename test/{ => test-files}/email-templates/existing-alias-local.txt (100%) rename test/{ => test-files}/email-templates/existing-alias-recipient-delimiter.txt (100%) rename test/{ => test-files}/email-templates/existing-catchall-local.txt (100%) rename test/{ => test-files}/email-templates/existing-regexp-alias-external.txt (100%) rename test/{ => test-files}/email-templates/existing-regexp-alias-local.txt (100%) rename test/{ => test-files}/email-templates/existing-user-and-cc-local-alias.txt (100%) rename test/{ => test-files}/email-templates/existing-user1.txt (100%) rename test/{ => test-files}/email-templates/existing-user2.txt (100%) rename test/{ => test-files}/email-templates/non-existing-user.txt (100%) rename test/{ => test-files}/email-templates/postgrey.txt (100%) rename test/{ => test-files}/email-templates/root-email.txt (100%) rename test/{ => test-files}/email-templates/send-privacy-email.txt (100%) rename test/{ => test-files}/email-templates/sieve-pipe.txt (100%) rename test/{ => test-files}/email-templates/sieve-spam-folder.txt (100%) rename test/{ => test-files}/email-templates/smtp-only.txt (100%) rename test/{ => test-files}/email-templates/test-email.txt (100%) rename test/{ => test-files}/nc_templates/postgrey_whitelist.txt (100%) rename test/{ => test-files}/nc_templates/postgrey_whitelist_local.txt (100%) rename test/{ => test-files}/nc_templates/postgrey_whitelist_recipients.txt (100%) diff --git a/Makefile b/Makefile index 44762f77..35e7481c 100644 --- a/Makefile +++ b/Makefile @@ -29,7 +29,7 @@ run: # Run containers docker run -d --name mail \ -v "`pwd`/test/config":/tmp/docker-mailserver \ - -v "`pwd`/test":/tmp/docker-mailserver-test \ + -v "`pwd`/test/test-files":/tmp/docker-mailserver-test:ro \ -v "`pwd`/test/onedir":/var/mail-state \ -e ENABLE_CLAMAV=1 \ -e SPOOF_PROTECTION=1 \ @@ -51,7 +51,7 @@ run: sleep 15 docker run -d --name mail_privacy \ -v "`pwd`/test/config":/tmp/docker-mailserver \ - -v "`pwd`/test":/tmp/docker-mailserver-test \ + -v "`pwd`/test/test-files":/tmp/docker-mailserver-test:ro \ -e ENABLE_CLAMAV=1 \ -e ENABLE_SPAMASSASSIN=1 \ -e SA_TAG=-5.0 \ @@ -68,7 +68,7 @@ run: sleep 15 docker run -d --name mail_pop3 \ -v "`pwd`/test/config":/tmp/docker-mailserver \ - -v "`pwd`/test":/tmp/docker-mailserver-test \ + -v "`pwd`/test/test-files":/tmp/docker-mailserver-test:ro \ -v "`pwd`/test/config/letsencrypt":/etc/letsencrypt/live \ -e ENABLE_POP3=1 \ -e DMS_DEBUG=0 \ @@ -77,7 +77,7 @@ run: sleep 15 docker run -d --name mail_smtponly \ -v "`pwd`/test/config":/tmp/docker-mailserver \ - -v "`pwd`/test":/tmp/docker-mailserver-test \ + -v "`pwd`/test/test-files":/tmp/docker-mailserver-test:ro \ -e SMTP_ONLY=1 \ -e PERMIT_DOCKER=network \ -e DMS_DEBUG=0 \ @@ -93,7 +93,7 @@ run: sleep 15 docker run -d --name mail_override_hostname \ -v "`pwd`/test/config":/tmp/docker-mailserver \ - -v "`pwd`/test":/tmp/docker-mailserver-test \ + -v "`pwd`/test/test-files":/tmp/docker-mailserver-test:ro \ -e PERMIT_DOCKER=network \ -e DMS_DEBUG=0 \ -e ENABLE_SRS=1 \ @@ -103,7 +103,7 @@ run: sleep 15 docker run -d --name mail_domainname \ -v "`pwd`/test/config":/tmp/docker-mailserver \ - -v "`pwd`/test":/tmp/docker-mailserver-test \ + -v "`pwd`/test/test-files":/tmp/docker-mailserver-test:ro \ -e PERMIT_DOCKER=network \ -e DMS_DEBUG=0 \ -e ENABLE_SRS=1 \ @@ -113,7 +113,7 @@ run: sleep 15 docker run -d --name mail_srs_domainname \ -v "`pwd`/test/config":/tmp/docker-mailserver \ - -v "`pwd`/test":/tmp/docker-mailserver-test \ + -v "`pwd`/test/test-files":/tmp/docker-mailserver-test:ro \ -e PERMIT_DOCKER=network \ -e DMS_DEBUG=0 \ -e ENABLE_SRS=1 \ @@ -124,7 +124,7 @@ run: sleep 15 docker run -d --name mail_fail2ban \ -v "`pwd`/test/config":/tmp/docker-mailserver \ - -v "`pwd`/test":/tmp/docker-mailserver-test \ + -v "`pwd`/test/test-files":/tmp/docker-mailserver-test:ro \ -e ENABLE_FAIL2BAN=1 \ -e POSTSCREEN_ACTION=ignore \ --cap-add=NET_ADMIN \ @@ -132,7 +132,7 @@ run: sleep 15 docker run -d --name mail_fetchmail \ -v "`pwd`/test/config":/tmp/docker-mailserver \ - -v "`pwd`/test":/tmp/docker-mailserver-test \ + -v "`pwd`/test/test-files":/tmp/docker-mailserver-test:ro \ -e ENABLE_FETCHMAIL=1 \ --cap-add=NET_ADMIN \ -e DMS_DEBUG=0 \ @@ -140,7 +140,7 @@ run: sleep 15 docker run -d --name mail_disabled_clamav_spamassassin \ -v "`pwd`/test/config":/tmp/docker-mailserver \ - -v "`pwd`/test":/tmp/docker-mailserver-test \ + -v "`pwd`/test/test-files":/tmp/docker-mailserver-test:ro \ -e ENABLE_CLAMAV=0 \ -e ENABLE_SPAMASSASSIN=0 \ -e DMS_DEBUG=0 \ @@ -148,7 +148,7 @@ run: sleep 15 docker run -d --name mail_manual_ssl \ -v "`pwd`/test/config":/tmp/docker-mailserver \ - -v "`pwd`/test":/tmp/docker-mailserver-test \ + -v "`pwd`/test/test-files":/tmp/docker-mailserver-test:ro \ -e SSL_TYPE=manual \ -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 \ @@ -161,7 +161,7 @@ run: sleep 15 docker run -d --name mail_with_ldap \ -v "`pwd`/test/config":/tmp/docker-mailserver \ - -v "`pwd`/test":/tmp/docker-mailserver-test \ + -v "`pwd`/test/test-files":/tmp/docker-mailserver-test:ro \ -e ENABLE_LDAP=1 \ -e LDAP_SERVER_HOST=ldap \ -e LDAP_START_TLS=no \ @@ -190,7 +190,7 @@ run: sleep 15 docker run -d --name mail_with_imap \ -v "`pwd`/test/config":/tmp/docker-mailserver \ - -v "`pwd`/test":/tmp/docker-mailserver-test \ + -v "`pwd`/test/test-files":/tmp/docker-mailserver-test:ro \ -e ENABLE_SASLAUTHD=1 \ -e SASLAUTHD_MECHANISMS=rimap \ -e SASLAUTHD_MECH_OPTIONS=127.0.0.1 \ @@ -200,7 +200,7 @@ run: sleep 15 docker run -d --name mail_postscreen \ -v "`pwd`/test/config":/tmp/docker-mailserver \ - -v "`pwd`/test":/tmp/docker-mailserver-test \ + -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) @@ -208,7 +208,7 @@ run: docker run -d --name mail_lmtp_ip \ -v "`pwd`/test/config":/tmp/docker-mailserver \ -v "`pwd`/test/config/dovecot-lmtp":/etc/dovecot \ - -v "`pwd`/test":/tmp/docker-mailserver-test \ + -v "`pwd`/test/test-files":/tmp/docker-mailserver-test:ro \ -e ENABLE_POSTFIX_VIRTUAL_TRANSPORT=1 \ -e POSTFIX_DAGENT=lmtp:127.0.0.1:24 \ -e DMS_DEBUG=0 \ @@ -216,7 +216,7 @@ run: sleep 30 docker run -d --name mail_with_postgrey \ -v "`pwd`/test/config":/tmp/docker-mailserver \ - -v "`pwd`/test":/tmp/docker-mailserver-test \ + -v "`pwd`/test/test-files":/tmp/docker-mailserver-test:ro \ -e ENABLE_POSTGREY=1 \ -e POSTGREY_DELAY=15 \ -e POSTGREY_MAX_AGE=35 \ @@ -227,14 +227,14 @@ run: sleep 20 docker run -d --name mail_undef_spam_subject \ -v "`pwd`/test/config":/tmp/docker-mailserver \ - -v "`pwd`/test":/tmp/docker-mailserver-test \ + -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) sleep 15 docker run -d --name mail_with_relays \ -v "`pwd`/test/config/relay-hosts":/tmp/docker-mailserver \ - -v "`pwd`/test":/tmp/docker-mailserver-test \ + -v "`pwd`/test/test-files":/tmp/docker-mailserver-test:ro \ -e RELAY_HOST=default.relay.com \ -e RELAY_PORT=2525 \ -e RELAY_USER=smtp_user \ @@ -246,7 +246,7 @@ run: sleep 15 docker run -d --name mail_with_default_relay \ -v "`pwd`/test/config/relay-hosts":/tmp/docker-mailserver \ - -v "`pwd`/test":/tmp/docker-mailserver-test \ + -v "`pwd`/test/test-files":/tmp/docker-mailserver-test:ro \ -e DEFAULT_RELAY_HOST=default.relay.host.invalid:25 \ --cap-add=SYS_PTRACE \ -e PERMIT_DOCKER=host \ @@ -329,4 +329,4 @@ clean: sudo rm -rf test/config ;\ mv testconfig.bak test/config ;\ fi - -sudo rm -rf test/onedir test/alias test/relay test/config/dovecot-lmtp/userdb test/config/key* test/config/opendkim/keys/domain.tld/ test/config/opendkim/keys/example.com/ test/config/opendkim/keys/localdomain2.com/ test/config/postfix-aliases.cf test/config/postfix-receive-access.cf test/config/postfix-receive-access.cfe test/config/postfix-send-access.cf test/config/postfix-send-access.cfe test/config/relay-hosts/chksum test/config/relay-hosts/postfix-aliases.cf \ No newline at end of file + -sudo rm -rf test/onedir test/alias test/relay test/config/dovecot-lmtp/userdb test/config/key* test/config/opendkim/keys/domain.tld/ test/config/opendkim/keys/example.com/ test/config/opendkim/keys/localdomain2.com/ test/config/postfix-aliases.cf test/config/postfix-receive-access.cf test/config/postfix-receive-access.cfe test/config/postfix-send-access.cf test/config/postfix-send-access.cfe test/config/relay-hosts/chksum test/config/relay-hosts/postfix-aliases.cf diff --git a/test/auth/added-imap-auth.txt b/test/test-files/auth/added-imap-auth.txt similarity index 100% rename from test/auth/added-imap-auth.txt rename to test/test-files/auth/added-imap-auth.txt diff --git a/test/auth/added-pop3-auth.txt b/test/test-files/auth/added-pop3-auth.txt similarity index 100% rename from test/auth/added-pop3-auth.txt rename to test/test-files/auth/added-pop3-auth.txt diff --git a/test/auth/added-smtp-auth-login-wrong.txt b/test/test-files/auth/added-smtp-auth-login-wrong.txt similarity index 100% rename from test/auth/added-smtp-auth-login-wrong.txt rename to test/test-files/auth/added-smtp-auth-login-wrong.txt diff --git a/test/auth/added-smtp-auth-login.txt b/test/test-files/auth/added-smtp-auth-login.txt similarity index 100% rename from test/auth/added-smtp-auth-login.txt rename to test/test-files/auth/added-smtp-auth-login.txt diff --git a/test/auth/added-smtp-auth-plain-wrong.txt b/test/test-files/auth/added-smtp-auth-plain-wrong.txt similarity index 100% rename from test/auth/added-smtp-auth-plain-wrong.txt rename to test/test-files/auth/added-smtp-auth-plain-wrong.txt diff --git a/test/auth/added-smtp-auth-plain.txt b/test/test-files/auth/added-smtp-auth-plain.txt similarity index 100% rename from test/auth/added-smtp-auth-plain.txt rename to test/test-files/auth/added-smtp-auth-plain.txt diff --git a/test/auth/added-smtp-auth-spoofed-alias.txt b/test/test-files/auth/added-smtp-auth-spoofed-alias.txt similarity index 100% rename from test/auth/added-smtp-auth-spoofed-alias.txt rename to test/test-files/auth/added-smtp-auth-spoofed-alias.txt diff --git a/test/auth/added-smtp-auth-spoofed.txt b/test/test-files/auth/added-smtp-auth-spoofed.txt similarity index 100% rename from test/auth/added-smtp-auth-spoofed.txt rename to test/test-files/auth/added-smtp-auth-spoofed.txt diff --git a/test/auth/imap-auth.txt b/test/test-files/auth/imap-auth.txt similarity index 100% rename from test/auth/imap-auth.txt rename to test/test-files/auth/imap-auth.txt diff --git a/test/auth/imap-ldap-auth.txt b/test/test-files/auth/imap-ldap-auth.txt similarity index 100% rename from test/auth/imap-ldap-auth.txt rename to test/test-files/auth/imap-ldap-auth.txt diff --git a/test/auth/ldap-smtp-auth-spoofed-alias.txt b/test/test-files/auth/ldap-smtp-auth-spoofed-alias.txt similarity index 100% rename from test/auth/ldap-smtp-auth-spoofed-alias.txt rename to test/test-files/auth/ldap-smtp-auth-spoofed-alias.txt diff --git a/test/auth/ldap-smtp-auth-spoofed.txt b/test/test-files/auth/ldap-smtp-auth-spoofed.txt similarity index 100% rename from test/auth/ldap-smtp-auth-spoofed.txt rename to test/test-files/auth/ldap-smtp-auth-spoofed.txt diff --git a/test/auth/pop3-auth.txt b/test/test-files/auth/pop3-auth.txt similarity index 100% rename from test/auth/pop3-auth.txt rename to test/test-files/auth/pop3-auth.txt diff --git a/test/auth/sasl-ldap-smtp-auth.txt b/test/test-files/auth/sasl-ldap-smtp-auth.txt similarity index 100% rename from test/auth/sasl-ldap-smtp-auth.txt rename to test/test-files/auth/sasl-ldap-smtp-auth.txt diff --git a/test/auth/smtp-auth-login-wrong.txt b/test/test-files/auth/smtp-auth-login-wrong.txt similarity index 100% rename from test/auth/smtp-auth-login-wrong.txt rename to test/test-files/auth/smtp-auth-login-wrong.txt diff --git a/test/auth/smtp-auth-login.txt b/test/test-files/auth/smtp-auth-login.txt similarity index 100% rename from test/auth/smtp-auth-login.txt rename to test/test-files/auth/smtp-auth-login.txt diff --git a/test/auth/smtp-auth-plain-wrong.txt b/test/test-files/auth/smtp-auth-plain-wrong.txt similarity index 100% rename from test/auth/smtp-auth-plain-wrong.txt rename to test/test-files/auth/smtp-auth-plain-wrong.txt diff --git a/test/auth/smtp-auth-plain.txt b/test/test-files/auth/smtp-auth-plain.txt similarity index 100% rename from test/auth/smtp-auth-plain.txt rename to test/test-files/auth/smtp-auth-plain.txt diff --git a/test/email-templates/amavis-spam.txt b/test/test-files/email-templates/amavis-spam.txt similarity index 100% rename from test/email-templates/amavis-spam.txt rename to test/test-files/email-templates/amavis-spam.txt diff --git a/test/email-templates/amavis-virus.txt b/test/test-files/email-templates/amavis-virus.txt similarity index 100% rename from test/email-templates/amavis-virus.txt rename to test/test-files/email-templates/amavis-virus.txt diff --git a/test/email-templates/existing-added.txt b/test/test-files/email-templates/existing-added.txt similarity index 100% rename from test/email-templates/existing-added.txt rename to test/test-files/email-templates/existing-added.txt diff --git a/test/email-templates/existing-alias-external.txt b/test/test-files/email-templates/existing-alias-external.txt similarity index 100% rename from test/email-templates/existing-alias-external.txt rename to test/test-files/email-templates/existing-alias-external.txt diff --git a/test/email-templates/existing-alias-local.txt b/test/test-files/email-templates/existing-alias-local.txt similarity index 100% rename from test/email-templates/existing-alias-local.txt rename to test/test-files/email-templates/existing-alias-local.txt diff --git a/test/email-templates/existing-alias-recipient-delimiter.txt b/test/test-files/email-templates/existing-alias-recipient-delimiter.txt similarity index 100% rename from test/email-templates/existing-alias-recipient-delimiter.txt rename to test/test-files/email-templates/existing-alias-recipient-delimiter.txt diff --git a/test/email-templates/existing-catchall-local.txt b/test/test-files/email-templates/existing-catchall-local.txt similarity index 100% rename from test/email-templates/existing-catchall-local.txt rename to test/test-files/email-templates/existing-catchall-local.txt diff --git a/test/email-templates/existing-regexp-alias-external.txt b/test/test-files/email-templates/existing-regexp-alias-external.txt similarity index 100% rename from test/email-templates/existing-regexp-alias-external.txt rename to test/test-files/email-templates/existing-regexp-alias-external.txt diff --git a/test/email-templates/existing-regexp-alias-local.txt b/test/test-files/email-templates/existing-regexp-alias-local.txt similarity index 100% rename from test/email-templates/existing-regexp-alias-local.txt rename to test/test-files/email-templates/existing-regexp-alias-local.txt diff --git a/test/email-templates/existing-user-and-cc-local-alias.txt b/test/test-files/email-templates/existing-user-and-cc-local-alias.txt similarity index 100% rename from test/email-templates/existing-user-and-cc-local-alias.txt rename to test/test-files/email-templates/existing-user-and-cc-local-alias.txt diff --git a/test/email-templates/existing-user1.txt b/test/test-files/email-templates/existing-user1.txt similarity index 100% rename from test/email-templates/existing-user1.txt rename to test/test-files/email-templates/existing-user1.txt diff --git a/test/email-templates/existing-user2.txt b/test/test-files/email-templates/existing-user2.txt similarity index 100% rename from test/email-templates/existing-user2.txt rename to test/test-files/email-templates/existing-user2.txt diff --git a/test/email-templates/non-existing-user.txt b/test/test-files/email-templates/non-existing-user.txt similarity index 100% rename from test/email-templates/non-existing-user.txt rename to test/test-files/email-templates/non-existing-user.txt diff --git a/test/email-templates/postgrey.txt b/test/test-files/email-templates/postgrey.txt similarity index 100% rename from test/email-templates/postgrey.txt rename to test/test-files/email-templates/postgrey.txt diff --git a/test/email-templates/root-email.txt b/test/test-files/email-templates/root-email.txt similarity index 100% rename from test/email-templates/root-email.txt rename to test/test-files/email-templates/root-email.txt diff --git a/test/email-templates/send-privacy-email.txt b/test/test-files/email-templates/send-privacy-email.txt similarity index 100% rename from test/email-templates/send-privacy-email.txt rename to test/test-files/email-templates/send-privacy-email.txt diff --git a/test/email-templates/sieve-pipe.txt b/test/test-files/email-templates/sieve-pipe.txt similarity index 100% rename from test/email-templates/sieve-pipe.txt rename to test/test-files/email-templates/sieve-pipe.txt diff --git a/test/email-templates/sieve-spam-folder.txt b/test/test-files/email-templates/sieve-spam-folder.txt similarity index 100% rename from test/email-templates/sieve-spam-folder.txt rename to test/test-files/email-templates/sieve-spam-folder.txt diff --git a/test/email-templates/smtp-only.txt b/test/test-files/email-templates/smtp-only.txt similarity index 100% rename from test/email-templates/smtp-only.txt rename to test/test-files/email-templates/smtp-only.txt diff --git a/test/email-templates/test-email.txt b/test/test-files/email-templates/test-email.txt similarity index 100% rename from test/email-templates/test-email.txt rename to test/test-files/email-templates/test-email.txt diff --git a/test/nc_templates/postgrey_whitelist.txt b/test/test-files/nc_templates/postgrey_whitelist.txt similarity index 100% rename from test/nc_templates/postgrey_whitelist.txt rename to test/test-files/nc_templates/postgrey_whitelist.txt diff --git a/test/nc_templates/postgrey_whitelist_local.txt b/test/test-files/nc_templates/postgrey_whitelist_local.txt similarity index 100% rename from test/nc_templates/postgrey_whitelist_local.txt rename to test/test-files/nc_templates/postgrey_whitelist_local.txt diff --git a/test/nc_templates/postgrey_whitelist_recipients.txt b/test/test-files/nc_templates/postgrey_whitelist_recipients.txt similarity index 100% rename from test/nc_templates/postgrey_whitelist_recipients.txt rename to test/test-files/nc_templates/postgrey_whitelist_recipients.txt diff --git a/test/tests.bats b/test/tests.bats index 7ce954d6..803c1b88 100644 --- a/test/tests.bats +++ b/test/tests.bats @@ -880,7 +880,10 @@ load 'test_helper/bats-assert/load' MAIL_FAIL2BAN_IP=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' mail_fail2ban) # Create a container which will send wrong authentications and should get banned - docker run --name fail-auth-mailer -e MAIL_FAIL2BAN_IP=$MAIL_FAIL2BAN_IP -v "$(pwd)/test":/tmp/docker-mailserver-test -d $(docker inspect --format '{{ .Config.Image }}' mail) tail -f /var/log/faillog + docker run --name fail-auth-mailer -e MAIL_FAIL2BAN_IP=$MAIL_FAIL2BAN_IP \ + -v "$(pwd)/test/test-files":/tmp/docker-mailserver-test \ + -d $(docker inspect --format '{{ .Config.Image }}' mail) \ + tail -f /var/log/faillog # 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 From 311bdfa1ba5828debd0e298aca07a2057facd37d Mon Sep 17 00:00:00 2001 From: Erik Wramner Date: Tue, 30 Jul 2019 15:03:36 +0200 Subject: [PATCH 08/16] Keep checksum file outside shared/mounted area --- target/check-for-changes.sh | 12 ++++++++---- test/config/chksum | 2 -- 2 files changed, 8 insertions(+), 6 deletions(-) delete mode 100644 test/config/chksum diff --git a/target/check-for-changes.sh b/target/check-for-changes.sh index d16aefc3..74de345c 100755 --- a/target/check-for-changes.sh +++ b/target/check-for-changes.sh @@ -1,4 +1,4 @@ -#! /bin/bash +#!/bin/bash # create date for log output log_date=$(date +"%Y-%m-%d %H:%M:%S ") @@ -6,6 +6,10 @@ log_date=$(date +"%Y-%m-%d %H:%M:%S ") sleep 5 echo "${log_date} Start check-for-changes script." +# create work area outside mounted directory +mkdir -p /tmp/docker-mailserver-work +CHKSUM_FILE=/tmp/docker-mailserver-work/chksum + # change directory cd /tmp/docker-mailserver @@ -33,7 +37,7 @@ done # Update / generate after start echo "${log_date} Makeing new checksum file." -sha512sum ${cf_files[@]/#/--tag } > chksum +sha512sum ${cf_files[@]/#/--tag } >$CHKSUM_FILE # Run forever while true; do @@ -42,7 +46,7 @@ while true; do log_date=$(date +"%Y-%m-%d %H:%M:%S ") # Get chksum and check it. -chksum=$(sha512sum -c --ignore-missing chksum) +chksum=$(sha512sum -c --ignore-missing $CHKSUM_FILE) if [[ $chksum == *"FAIL"* ]]; then echo "${log_date} Change detected" @@ -187,7 +191,7 @@ if [[ $chksum == *"FAIL"* ]]; then fi echo "${log_date} Update checksum" - sha512sum ${cf_files[@]/#/--tag } > chksum + sha512sum ${cf_files[@]/#/--tag } >$CHKSUM_FILE fi sleep 1 diff --git a/test/config/chksum b/test/config/chksum deleted file mode 100644 index c5fd3a96..00000000 --- a/test/config/chksum +++ /dev/null @@ -1,2 +0,0 @@ -SHA512 (postfix-accounts.cf) = 8eba4eedb76e8c3b740ca4eea5d7ad1c8695fd7fd39d3e5d161201101b5b63a1c1471ab85bd79d6ed4ba192c423275a3d1210a9596a06904434ab5707ad3753b -SHA512 (postfix-virtual.cf) = c5bff9b5c50886a72a559ee52b1230b751c3820cd12de3ffe2a632f8d2a7845fa33ddac397c62889f0680d096be24418f22c1b81fb93ad56fd4937869f16954b From 37708b57876e665c615602b2715e2e1d0acff0af Mon Sep 17 00:00:00 2001 From: Erik Wramner Date: Wed, 31 Jul 2019 10:41:32 +0200 Subject: [PATCH 09/16] Added comment explaining chksum file location --- target/check-for-changes.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target/check-for-changes.sh b/target/check-for-changes.sh index 74de345c..c4239dd9 100755 --- a/target/check-for-changes.sh +++ b/target/check-for-changes.sh @@ -7,6 +7,8 @@ sleep 5 echo "${log_date} Start check-for-changes script." # create work area outside mounted directory +# the checksum file should be reused on subsequent runs, +# but only by this container, not by others using same mount mkdir -p /tmp/docker-mailserver-work CHKSUM_FILE=/tmp/docker-mailserver-work/chksum From b23a7ddc1c2ea2ce9c5d520c41a89685964f44d6 Mon Sep 17 00:00:00 2001 From: Erik Wramner Date: Wed, 31 Jul 2019 10:43:12 +0200 Subject: [PATCH 10/16] Added newline as suggested in code review --- test/tests.bats | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/tests.bats b/test/tests.bats index 803c1b88..2b140e88 100644 --- a/test/tests.bats +++ b/test/tests.bats @@ -880,7 +880,8 @@ load 'test_helper/bats-assert/load' MAIL_FAIL2BAN_IP=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' mail_fail2ban) # Create a container which will send wrong authentications and should get banned - docker run --name fail-auth-mailer -e MAIL_FAIL2BAN_IP=$MAIL_FAIL2BAN_IP \ + docker run --name fail-auth-mailer \ + -e MAIL_FAIL2BAN_IP=$MAIL_FAIL2BAN_IP \ -v "$(pwd)/test/test-files":/tmp/docker-mailserver-test \ -d $(docker inspect --format '{{ .Config.Image }}' mail) \ tail -f /var/log/faillog From 573609e011d7ee292d6390f07a49aa677f475622 Mon Sep 17 00:00:00 2001 From: Erik Wramner Date: Wed, 31 Jul 2019 12:56:18 +0200 Subject: [PATCH 11/16] Put checksum file in /tmp as suggested in code review --- target/check-for-changes.sh | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/target/check-for-changes.sh b/target/check-for-changes.sh index c4239dd9..2fbd9683 100755 --- a/target/check-for-changes.sh +++ b/target/check-for-changes.sh @@ -6,11 +6,10 @@ log_date=$(date +"%Y-%m-%d %H:%M:%S ") sleep 5 echo "${log_date} Start check-for-changes script." -# create work area outside mounted directory +# create checksum file outside mounted directory # the checksum file should be reused on subsequent runs, -# but only by this container, not by others using same mount -mkdir -p /tmp/docker-mailserver-work -CHKSUM_FILE=/tmp/docker-mailserver-work/chksum +# but only by this container, not by others +CHKSUM_FILE=/tmp/docker-mailserver-config-chksum # change directory cd /tmp/docker-mailserver From 21c89b336465e824074d34e059f7377dcee600c4 Mon Sep 17 00:00:00 2001 From: Erik Wramner Date: Wed, 31 Jul 2019 12:59:49 +0200 Subject: [PATCH 12/16] Added TODO as per code review and removed one sleep --- test/tests.bats | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/test/tests.bats b/test/tests.bats index 2b140e88..dd5eef9d 100644 --- a/test/tests.bats +++ b/test/tests.bats @@ -1216,11 +1216,6 @@ load 'test_helper/bats-assert/load' @test "checking user login: predefined user can login" { - # This should really not be necessary, but this test sometimes fails, probably due to timing - if ! (docker exec mail doveadm auth test -x service=smtp pass@localhost.localdomain 'may be \a `p^a.*ssword' >/dev/null); then - sleep 60 - fi - result=$(docker exec mail doveadm auth test -x service=smtp pass@localhost.localdomain 'may be \a `p^a.*ssword' | grep 'auth succeeded') [ "$result" = "passdb: pass@localhost.localdomain auth succeeded" ] } @@ -1446,6 +1441,7 @@ load 'test_helper/bats-assert/load' if ! (docker exec mail doveadm auth test -x service=smtp setup_email_add@example.com 'test_password' >/dev/null); then # Possibly the cron job has not had time to run yet, waiting a while is better than a false alarm + # TODO find a better way to detect when the container is ready sleep 30 fi From 7f3e5a22e18e091e2eeabaa47a18a854788e7db8 Mon Sep 17 00:00:00 2001 From: Erik Wramner Date: Thu, 1 Aug 2019 09:58:22 +0200 Subject: [PATCH 13/16] Create checksums in start script, avoid race condition --- target/check-for-changes.sh | 26 ++++++++++++++------------ target/start-mailserver.sh | 26 ++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 12 deletions(-) diff --git a/target/check-for-changes.sh b/target/check-for-changes.sh index 2fbd9683..5a5ab494 100755 --- a/target/check-for-changes.sh +++ b/target/check-for-changes.sh @@ -2,15 +2,8 @@ # create date for log output log_date=$(date +"%Y-%m-%d %H:%M:%S ") -# Prevent a start too early -sleep 5 echo "${log_date} Start check-for-changes script." -# create checksum file outside mounted directory -# the checksum file should be reused on subsequent runs, -# but only by this container, not by others -CHKSUM_FILE=/tmp/docker-mailserver-config-chksum - # change directory cd /tmp/docker-mailserver @@ -18,7 +11,14 @@ cd /tmp/docker-mailserver if [ ! -f postfix-accounts.cf ]; then echo "${log_date} postfix-accounts.cf is missing! This should not run! Exit!" exit -fi +fi + +# Verify checksum file exists; must be prepared by start-mailserver.sh +CHKSUM_FILE=/tmp/docker-mailserver-config-chksum +if [ ! -f $CHKSUM_FILE ]; then + echo "${log_date} ${CHKSUM_FILE} is missing! Start script failed? Exit!" + exit +fi # Determine postmaster address, duplicated from start-mailserver.sh # This script previously didn't work when POSTMASTER_ADDRESS was empty @@ -30,15 +30,15 @@ fi PM_ADDRESS="${POSTMASTER_ADDRESS:=postmaster@${DOMAINNAME}}" echo "${log_date} Using postmaster address ${PM_ADDRESS}" -# create an array of files to monitor (perhaps simple *.cf would be ok here) +# Create an array of files to monitor, must be the same as in start-mailserver.sh declare -a cf_files=() for file in postfix-accounts.cf postfix-virtual.cf postfix-aliases.cf; do [ -f "$file" ] && cf_files+=("$file") done -# Update / generate after start -echo "${log_date} Makeing new checksum file." -sha512sum ${cf_files[@]/#/--tag } >$CHKSUM_FILE +# Wait to make sure server is up before we start +# Plus the files have just been generated, no hurry to process changes +sleep 20 # Run forever while true; do @@ -54,6 +54,8 @@ if [[ $chksum == *"FAIL"* ]]; then # Bug alert! This overwrites the alias set by start-mailserver.sh # Take care that changes in one script are propagated to the other + # Also note that changes are performed in place and are not atomic + # We should fix that and write to temporary files, stop, swap and start #regen postix aliases. echo "root: ${PM_ADDRESS}" > /etc/aliases diff --git a/target/start-mailserver.sh b/target/start-mailserver.sh index 2ccc6566..e715b28b 100644 --- a/target/start-mailserver.sh +++ b/target/start-mailserver.sh @@ -49,6 +49,7 @@ DEFAULT_VARS["VIRUSMAILS_DELETE_DELAY"]="${VIRUSMAILS_DELETE_DELAY:="7"}" ########################################################################## HOSTNAME="$(hostname -f)" DOMAINNAME="$(hostname -d)" +CHKSUM_FILE=/tmp/docker-mailserver-config-chksum ########################################################################## # << GLOBAL VARS ########################################################################## @@ -88,6 +89,7 @@ function register_functions() { ################### >> setup funcs _register_setup_function "_setup_default_vars" + _register_setup_function "_setup_chksum_file" if [ "$ENABLE_ELK_FORWARDER" = 1 ]; then _register_setup_function "_setup_elk_forwarder" @@ -439,6 +441,30 @@ function _setup_default_vars() { done } +function _setup_chksum_file() { + notify 'task' "Setting up configuration checksum file" + + + if [ -d /tmp/docker-mailserver ]; then + pushd /tmp/docker-mailserver + + declare -a cf_files=() + for file in postfix-accounts.cf postfix-virtual.cf postfix-aliases.cf; do + [ -f "$file" ] && cf_files+=("$file") + done + + notify 'inf' "Creating $CHKSUM_FILE" + sha512sum ${cf_files[@]/#/--tag } >$CHKSUM_FILE + + popd + else + # We could just skip the file, but perhaps config can be added later? + # If so it must be processed by the check for changes script + notify 'inf' "Creating empty $CHKSUM_FILE (no config)" + touch $CHKSUM_FILE + fi +} + function _setup_mailname() { notify 'task' 'Setting up Mailname' From ec4661194bf347c69d4e8c2b85625cb95c4d4539 Mon Sep 17 00:00:00 2001 From: Erik Wramner Date: Thu, 1 Aug 2019 12:05:48 +0200 Subject: [PATCH 14/16] Compute checksum after possible in-place sed changes --- target/start-mailserver.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/target/start-mailserver.sh b/target/start-mailserver.sh index e715b28b..c7830312 100644 --- a/target/start-mailserver.sh +++ b/target/start-mailserver.sh @@ -89,7 +89,6 @@ function register_functions() { ################### >> setup funcs _register_setup_function "_setup_default_vars" - _register_setup_function "_setup_chksum_file" if [ "$ENABLE_ELK_FORWARDER" = 1 ]; then _register_setup_function "_setup_elk_forwarder" @@ -167,6 +166,9 @@ function register_functions() { _register_setup_function "_setup_mail_summary" fi + # Compute last as the config files are modified in-place + _register_setup_function "_setup_chksum_file" + ################### << setup funcs ################### >> fix funcs From d6861881abc6cae1ffadcae6b1850909ca42508f Mon Sep 17 00:00:00 2001 From: Erik Wramner Date: Thu, 1 Aug 2019 15:24:47 +0200 Subject: [PATCH 15/16] Parse logs to ensure changes are processed --- test/tests.bats | 58 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 15 deletions(-) diff --git a/test/tests.bats b/test/tests.bats index dd5eef9d..7d6d177c 100644 --- a/test/tests.bats +++ b/test/tests.bats @@ -1,5 +1,28 @@ load 'test_helper/bats-support/load' load 'test_helper/bats-assert/load' + + +# +# shared functions +# + +function wait_for_service() { + containerName=$1 + serviceName=$2 + count=0 + while ! (docker exec $containerName /usr/bin/supervisorctl status $serviceName | grep RUNNING >/dev/null) + do + ((count++)) && ((count==30)) && break + sleep 5 + done + return $(docker exec $containerName /usr/bin/supervisorctl status $serviceName | grep RUNNING >/dev/null) +} + +function count_processed_changes() { + containerName=$1 + docker exec $containerName cat /var/log/supervisor/changedetector.log | grep "Update checksum" | wc -l +} + # # configuration checks # @@ -1238,14 +1261,32 @@ load 'test_helper/bats-assert/load' } # email -@test "checking setup.sh: setup.sh email add" { +@test "checking setup.sh: setup.sh email add and login" { + wait_for_service mail changedetector + assert_success + + originalChangesProcessed=$(count_processed_changes mail) + run ./setup.sh -c mail email add setup_email_add@example.com test_password assert_success value=$(cat ./test/config/postfix-accounts.cf | grep setup_email_add@example.com | awk -F '|' '{print $1}') [ "$value" = "setup_email_add@example.com" ] + assert_success - # we test the login of this user later to let the container digest the addition + # wait until change detector has processed the change + count=0 + while [ "${originalChangesProcessed}" = "$(count_processed_changes mail)" ] + do + ((count++)) && ((count==60)) && break + sleep 1 + done + + [ "${originalChangesProcessed}" != "$(count_processed_changes mail)" ] + assert_success + + result=$(docker exec mail doveadm auth test -x service=smtp setup_email_add@example.com 'test_password' | grep 'auth succeeded') + [ "$result" = "passdb: setup_email_add@example.com auth succeeded" ] } @test "checking setup.sh: setup.sh email list" { @@ -1436,19 +1477,6 @@ load 'test_helper/bats-assert/load' assert_success } -@test "checking setup.sh: email add login validation" { - # validates that the user created previously with setup.sh can login - - if ! (docker exec mail doveadm auth test -x service=smtp setup_email_add@example.com 'test_password' >/dev/null); then - # Possibly the cron job has not had time to run yet, waiting a while is better than a false alarm - # TODO find a better way to detect when the container is ready - sleep 30 - fi - - result=$(docker exec mail doveadm auth test -x service=smtp setup_email_add@example.com 'test_password' | grep 'auth succeeded') - [ "$result" = "passdb: setup_email_add@example.com auth succeeded" ] -} - # # LDAP # From 81e9c7dcffcbce69519e1efa3a24f96142156681 Mon Sep 17 00:00:00 2001 From: Erik Wramner Date: Thu, 1 Aug 2019 19:39:25 +0200 Subject: [PATCH 16/16] Protect user db with flock --- target/bin/addmailuser | 25 ++++++++++++------- target/bin/delmailuser | 50 +++++++++++++++++++++---------------- target/bin/listmailuser | 7 +++++- target/bin/updatemailuser | 12 ++++++--- target/check-for-changes.sh | 12 ++++++--- 5 files changed, 68 insertions(+), 38 deletions(-) diff --git a/target/bin/addmailuser b/target/bin/addmailuser index 04b40b4b..3b486863 100755 --- a/target/bin/addmailuser +++ b/target/bin/addmailuser @@ -22,13 +22,20 @@ escape() { [ -z "$USER" ] && { usage; errex "no username specified"; } expr index "$USER" "@" >/dev/null || { usage; errex "username must include the domain"; } -grep -qi "^$(escape "$USER")|" $DATABASE 2>/dev/null && - errex "User \"$USER\" already exists" +# Protect config file with lock to avoid race conditions +touch $DATABASE +( + flock -e 200 -if [ -z "$PASSWD" ]; then - read -s -p "Enter Password: " PASSWD - echo - [ -z "$PASSWD" ] && errex "Password must not be empty" -fi -HASH="$(doveadm pw -s SHA512-CRYPT -u "$USER" -p "$PASSWD")" -echo "$USER|$HASH" >> $DATABASE + grep -qi "^$(escape "$USER")|" $DATABASE 2>/dev/null && + errex "User \"$USER\" already exists" + + if [ -z "$PASSWD" ]; then + read -s -p "Enter Password: " PASSWD + echo + [ -z "$PASSWD" ] && errex "Password must not be empty" + fi + + HASH="$(doveadm pw -s SHA512-CRYPT -u "$USER" -p "$PASSWD")" + echo "$USER|$HASH" >> $DATABASE +) 200<$DATABASE diff --git a/target/bin/delmailuser b/target/bin/delmailuser index d73db74f..8f4e0368 100755 --- a/target/bin/delmailuser +++ b/target/bin/delmailuser @@ -33,25 +33,31 @@ shift $((OPTIND-1)) [ -z "$@" ] && { usage; errex "No user specifed"; } [ -s "$DATABASE" ] || exit 0 -for USER in "$@"; do - #very simple plausibility check - [[ "$USER" != *"@"*"."* ]] && errex "No valid address: $USER" - MAILARR=(${USER//@/ }) - # XXX $USER must not contain /s and other syntactic characters - USER=$(escape "$USER") - sed -i "/^"$USER"|/d" $DATABASE - [ $? != 0 ] && errex "$USER couldn't be deleted in $DATABASE. $?" - # Delete all aliases where the user is the only recipient( " $USER$" ) - # Delete user only for all aliases that deliver to multiple recipients ( ",$USER" "$USER," ) - sed -i -e "/ "$USER"$/d" \ - -e "s/,"$USER"//g" \ - -e "s/"$USER",//g" $ALIAS_DATABASE - [ $? = 0 ] && echo "$USER and potential aliases deleted." || errex "Aliases for $USER couldn't be deleted in $ALIAS_DATABASE. $?" - if [ "$MAILDEL" != "y" ]; then - read -p "Do you want to delete the maildir as well(all mails will be removed)?(y/n) " MAILDEL - echo - fi - [ "$MAILDEL" != "y" ] && errex "Leaving the maildir untouched. If you want to delete it at a later point use \"sudo docker exec mail rm -R /var/mail/${MAILARR[1]}/${MAILARR[0]}\"" - rm -r -f /var/mail/${MAILARR[1]}/${MAILARR[0]} - [ $? = 0 ] && echo "Maildir deleted." || errex "Maildir couldn't be deleted: $?" -done +# Protect config file with lock to avoid race conditions +( + flock -e 200 + + for USER in "$@"; do + # very simple plausibility check + [[ "$USER" != *"@"*"."* ]] && errex "No valid address: $USER" + MAILARR=(${USER//@/ }) + # XXX $USER must not contain /s and other syntactic characters + USER=$(escape "$USER") + sed -i "/^"$USER"|/d" $DATABASE + [ $? != 0 ] && errex "$USER couldn't be deleted in $DATABASE. $?" + # Delete all aliases where the user is the only recipient( " $USER$" ) + # Delete user only for all aliases that deliver to multiple recipients ( ",$USER" "$USER," ) + sed -i -e "/ "$USER"$/d" \ + -e "s/,"$USER"//g" \ + -e "s/"$USER",//g" $ALIAS_DATABASE + [ $? = 0 ] && echo "$USER and potential aliases deleted." || errex "Aliases for $USER couldn't be deleted in $ALIAS_DATABASE. $?" + if [ "$MAILDEL" != "y" ]; then + read -p "Do you want to delete the maildir as well(all mails will be removed)?(y/n) " MAILDEL + echo + fi + [ "$MAILDEL" != "y" ] && errex "Leaving the maildir untouched. If you want to delete it at a later point use \"sudo docker exec mail rm -R /var/mail/${MAILARR[1]}/${MAILARR[0]}\"" + rm -r -f /var/mail/${MAILARR[1]}/${MAILARR[0]} + [ $? = 0 ] && echo "Maildir deleted." || errex "Maildir couldn't be deleted: $?" + done + +) 200<$DATABASE diff --git a/target/bin/listmailuser b/target/bin/listmailuser index 04352a5d..658c52eb 100755 --- a/target/bin/listmailuser +++ b/target/bin/listmailuser @@ -10,4 +10,9 @@ errex() { [ -f $DATABASE ] || errex "No postfix-accounts.cf file" [ -s $DATABASE ] || errex "Empty postfix-accounts.cf - no users have been added" -awk -F '|' '{ print $1; }' $DATABASE +# Lock database even though we are only reading +( + flock -e 200 + awk -F '|' '{ print $1; }' $DATABASE +) 200<$DATABASE + diff --git a/target/bin/updatemailuser b/target/bin/updatemailuser index 1d32d0f0..cf9a4a8c 100755 --- a/target/bin/updatemailuser +++ b/target/bin/updatemailuser @@ -27,7 +27,13 @@ if [ -z "$PASSWD" ]; then [ -z "$PASSWD" ] && errex "Password must not be empty" fi HASH="$(doveadm pw -s SHA512-CRYPT -u "$USER" -p "$PASSWD")" -grep -qi "^$(escape "$USER")|" $DATABASE 2>/dev/null || - errex "User \"$USER\" does not exist" -sed -i "s ^"$USER"|.* "$USER"|"$HASH" " $DATABASE +# Protect config file with lock to avoid race conditions +( + flock -e 200 + + grep -qi "^$(escape "$USER")|" $DATABASE 2>/dev/null || + errex "User \"$USER\" does not exist" + + sed -i "s ^"$USER"|.* "$USER"|"$HASH" " $DATABASE +) 200<$DATABASE diff --git a/target/check-for-changes.sh b/target/check-for-changes.sh index 5a5ab494..afcb059b 100755 --- a/target/check-for-changes.sh +++ b/target/check-for-changes.sh @@ -37,8 +37,7 @@ for file in postfix-accounts.cf postfix-virtual.cf postfix-aliases.cf; do done # Wait to make sure server is up before we start -# Plus the files have just been generated, no hurry to process changes -sleep 20 +sleep 10 # Run forever while true; do @@ -46,7 +45,7 @@ while true; do # recreate logdate log_date=$(date +"%Y-%m-%d %H:%M:%S ") -# Get chksum and check it. +# Get chksum and check it, no need to lock config yet chksum=$(sha512sum -c --ignore-missing $CHKSUM_FILE) if [[ $chksum == *"FAIL"* ]]; then @@ -57,6 +56,11 @@ if [[ $chksum == *"FAIL"* ]]; then # Also note that changes are performed in place and are not atomic # We should fix that and write to temporary files, stop, swap and start + # Lock configuration while working + # Not fixing indentation yet to reduce diff (fix later in separate commit) + ( + flock -e 200 + #regen postix aliases. echo "root: ${PM_ADDRESS}" > /etc/aliases if [ -f /tmp/docker-mailserver/postfix-aliases.cf ]; then @@ -195,6 +199,8 @@ if [[ $chksum == *"FAIL"* ]]; then echo "${log_date} Update checksum" sha512sum ${cf_files[@]/#/--tag } >$CHKSUM_FILE + + ) 200