Fix checksum race condition in check-for-changes.sh

If a change to one of the tracked files happened soon after (<1 second?)
a previously detected change, it could end up going undetected. In
particular, this could cause integration tests to fail (see next
commits).

Fixed by computing the new checksum file _before_ checking for changes.
This commit is contained in:
mwnx 2020-08-24 20:46:50 +02:00
parent f225e14a21
commit 2a70f33a4b
5 changed files with 39 additions and 32 deletions

View file

@ -16,7 +16,6 @@ if [ ! -f postfix-accounts.cf ]; then
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
@ -32,12 +31,6 @@ fi
PM_ADDRESS="${POSTMASTER_ADDRESS:=postmaster@${DOMAINNAME}}"
echo "${log_date} Using postmaster address ${PM_ADDRESS}"
# 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 dovecot-quotas.cf /etc/letsencrypt/acme.json "/etc/letsencrypt/live/$HOSTNAME/key.pem" "/etc/letsencrypt/live/$HOSTNAME/fullchain.pem"; do
[ -f "$file" ] && cf_files+=("$file")
done
# Wait to make sure server is up before we start
sleep 10
@ -48,10 +41,12 @@ while true; do
log_date=$(date +"%Y-%m-%d %H:%M:%S ")
# Get chksum and check it, no need to lock config yet
chksum=$(sha512sum -c --ignore-missing $CHKSUM_FILE)
monitored_files_checksums >"$CHKSUM_FILE.new"
if [[ $chksum == *"FAIL"* ]]; then
if ! cmp --silent -- "$CHKSUM_FILE" "$CHKSUM_FILE.new"; then
echo "${log_date} Change detected"
changed=$(grep -Fxvf "$CHKSUM_FILE" "$CHKSUM_FILE.new" | sed 's/^[^ ]\+ //')
mv "$CHKSUM_FILE.new" "$CHKSUM_FILE"
# Bug alert! This overwrites the alias set by start-mailserver.sh
# Take care that changes in one script are propagated to the other
@ -63,13 +58,18 @@ if [[ $chksum == *"FAIL"* ]]; then
(
flock -e 200
if [[ $chksum == *"/etc/letsencrypt/acme.json: FAILED"* ]]; then
for certdomain in $SSL_DOMAIN $HOSTNAME $DOMAINNAME; do
if extractCertsFromAcmeJson "$certdomain"; then
break
fi
done
fi
for file in $changed; do
case $file in
/etc/letsencrypt/acme.json)
for certdomain in $SSL_DOMAIN $HOSTNAME $DOMAINNAME; do
if extractCertsFromAcmeJson "$certdomain"; then
break
fi
done
;;
#TODO: Perform updates below conditionally as well.
esac
done
#regen postix aliases.
echo "root: ${PM_ADDRESS}" > /etc/aliases
@ -211,9 +211,6 @@ if [[ $chksum == *"FAIL"* ]]; then
supervisorctl restart dovecot
fi
echo "${log_date} Update checksum"
sha512sum ${cf_files[@]/#/--tag } >$CHKSUM_FILE
) 200<postfix-accounts.cf # end lock
fi