mirror of
https://github.com/mail-in-a-box/mailinabox.git
synced 2025-04-01 23:57:05 +00:00
# Conflicts: # management/daemon.py # management/mailconfig.py # management/templates/users.html # setup/bootstrap.sh # setup/mail-dovecot.sh # setup/mail-postfix.sh # setup/mail-users.sh
277 lines
8.5 KiB
Bash
277 lines
8.5 KiB
Bash
#####
|
|
##### This file is part of Mail-in-a-Box-LDAP which is released under the
|
|
##### terms of the GNU Affero General Public License as published by the
|
|
##### Free Software Foundation, either version 3 of the License, or (at
|
|
##### your option) any later version. See file LICENSE or go to
|
|
##### https://github.com/downtownallday/mailinabox-ldap for full license
|
|
##### details.
|
|
#####
|
|
|
|
#
|
|
# requires:
|
|
# scripts: [ colored-output.sh, rest.sh ]
|
|
#
|
|
# these functions are meant for comparing upstream (non-LDAP)
|
|
# installations to a subsequent MiaB-LDAP upgrade
|
|
#
|
|
|
|
parse_miab_version_string() {
|
|
local tmpfile
|
|
tmpfile=$(mktemp)
|
|
awk -F- '
|
|
/^v[0-9]+\./ { split($1,a,"."); print "MAJOR="substr(a[1],2); print "MINOR="a[2]; print "RELEASE="$2; next }
|
|
|
|
$1 ~ /^v[0-9]+[a-z]$/ { print "MAJOR="substr($1,2,length($1)-2); print "MINOR="substr($1,length($1))-"a"+1; print "RELEASE="; next }
|
|
|
|
$1 ~ /^v[0-9]+[A-Z]$/ { print "MAJOR="substr($1,2,length($1)-2); print "MINOR="substr($1,length($1))-"A"+1; print "RELEASE="; next }
|
|
|
|
$1 ~ /^v[0-9]+$/ { print "MAJOR="substr($1,2); print "MINOR="; print "RELEASE="; next }
|
|
|
|
{ exit 1 }' >> "$tmpfile" <<< "$1"
|
|
|
|
if [ $? -ne 0 ]; then
|
|
rm -f "$tmpfile"
|
|
return 1
|
|
fi
|
|
source "$tmpfile"
|
|
rm -f "$tmpfile"
|
|
return 0
|
|
}
|
|
|
|
|
|
installed_state_capture() {
|
|
# users and aliases
|
|
# dns zone files
|
|
# TOOD: tls certificates: expected CN's
|
|
|
|
local state_dir="$1"
|
|
local install_dir="${2:-.}"
|
|
local info="$state_dir/info.txt"
|
|
|
|
H1 "Capture installed state to $state_dir"
|
|
|
|
# nuke saved state, if any
|
|
rm -rf "$state_dir"
|
|
mkdir -p "$state_dir"
|
|
|
|
# create info.json
|
|
if ! pushd "$install_dir" >/dev/null; then
|
|
echo "Directory '$install_dir' no accessible"
|
|
return 1
|
|
fi
|
|
H2 "create info.txt"
|
|
echo "STATE_VERSION=1" > "$info"
|
|
local gitver=$(git describe)
|
|
echo "GIT_VERSION='$gitver'" >>"$info"
|
|
|
|
if [ -z "$gitver" ]; then
|
|
# git: "No names found, cannot describe anything"
|
|
MAJOR=999
|
|
MINOR=
|
|
RELEASE=
|
|
else
|
|
parse_miab_version_string "$gitver"
|
|
if [ $? -ne 0 ]; then
|
|
echo "Unable to parse version string: '$gitver'"
|
|
return 1
|
|
fi
|
|
fi
|
|
echo "MAJOR=$MAJOR" >>"$info"
|
|
echo "MINOR=$MINOR" >>"$info"
|
|
echo "RELEASE=$RELEASE" >>"$info"
|
|
|
|
echo "GIT_ORIGIN='$(git remote -v | grep ^origin | grep 'fetch)$' | awk '{print $2}')'" >>"$info"
|
|
echo "MIGRATION_VERSION=$([ -e "$STORAGE_ROOT/mailinabox.version" ] && cat "$STORAGE_ROOT/mailinabox.version")" >>"$info"
|
|
echo "MIGRATION_ML_VERSION=$([ -e "$STORAGE_ROOT/mailinabox-ldap.version" ] && cat "$STORAGE_ROOT/mailinabox-ldap.version")" >>"$info"
|
|
popd >/dev/null
|
|
|
|
# record users
|
|
H2 "record users"
|
|
if ! rest_urlencoded GET "/admin/mail/users?format=json" "$EMAIL_ADDR" "$EMAIL_PW" --insecure 2>/dev/null
|
|
then
|
|
echo "Unable to get users: rc=$? err=$REST_ERROR" 1>&2
|
|
return 1
|
|
fi
|
|
echo "$REST_OUTPUT" > "$state_dir/users.json"
|
|
|
|
# record aliases
|
|
H2 "record aliases"
|
|
if ! rest_urlencoded GET "/admin/mail/aliases?format=json" "$EMAIL_ADDR" "$EMAIL_PW" --insecure 2>/dev/null
|
|
then
|
|
echo "Unable to get aliases: rc=$? err=$REST_ERROR" 1>&2
|
|
return 2
|
|
fi
|
|
echo "$REST_OUTPUT" > "$state_dir/aliases.json"
|
|
|
|
# record dns config
|
|
H2 "record dns details"
|
|
local file
|
|
mkdir -p "$state_dir/zones"
|
|
for file in /etc/nsd/zones/*.signed; do
|
|
if ! cp "$file" "$state_dir/zones"
|
|
then
|
|
echo "Copy $file -> $state_dir/zones failed" 1>&2
|
|
return 3
|
|
fi
|
|
done
|
|
|
|
return 0
|
|
}
|
|
|
|
|
|
|
|
installed_state_compare() {
|
|
local s1="$1"
|
|
local s2="$2"
|
|
|
|
local output
|
|
local changed="false"
|
|
|
|
H1 "COMPARE STATES: $(basename "$s1") VS $(basename "$2")"
|
|
|
|
#
|
|
# determine compare type id (incorporating repo, branch, version, etc)
|
|
#
|
|
source "$s1/info.txt"
|
|
MAJOR_A="$MAJOR"
|
|
MINOR_A="${MINOR:-0}"
|
|
RELEASE_A="${RELEASE:-0}"
|
|
PROD_A="miab"
|
|
grep "mailinabox-ldap" <<<"$GIT_ORIGIN" >/dev/null && PROD_A="miabldap"
|
|
MIGRATION_ML_VERSION_A="${MIGRATION_ML_VERSION:-0}"
|
|
|
|
source "$s2/info.txt"
|
|
MAJOR_B="$MAJOR"
|
|
MINOR_B="${MINOR:-0}"
|
|
RELEASE_B="${RELEASE:-0}"
|
|
PROD_B="miab"
|
|
grep "mailinabox-ldap" <<<"$GIT_ORIGIN" >/dev/null && PROD_B="miabldap"
|
|
MIGRATION_ML_VERSION_B="${MIGRATION_ML_VERSION:-0}"
|
|
|
|
cmptype="${PROD_A}2${PROD_B}"
|
|
|
|
#
|
|
# filter data for compare type
|
|
#
|
|
cp "$s1/users.json" "$s1/users-cmp.json" || changed="true"
|
|
cp "$s1/aliases.json" "$s1/aliases-cmp.json" || changed="true"
|
|
cp "$s2/users.json" "$s2/users-cmp.json" || changed="true"
|
|
cp "$s2/aliases.json" "$s2/aliases-cmp.json" || changed="true"
|
|
|
|
if [ "$cmptype" = "miab2miabldap" ]
|
|
then
|
|
# user display names is a feature added to MiaB-LDAP that is
|
|
# not in MiaB
|
|
grep -v '"display_name":' "$s2/users.json" > "$s2/users-cmp.json" || changed="true"
|
|
|
|
# alias descriptions is a feature added to MiaB-LDAP that is
|
|
# not in MiaB
|
|
grep -v '"description":' "$s2/aliases.json" > "$s2/aliases-cmp.json" || changed="true"
|
|
fi
|
|
|
|
# cmp: v0.54 to current
|
|
if [ "$cmptype" = "miabldap2miabldap" -a $MAJOR_A -eq 0 -a $MINOR_A -le 54 -a $RELEASE_A -eq 0 ]
|
|
then
|
|
# s1: convert aliases 'required' to 'auto' and resort
|
|
jq -c ".[] | .aliases | sort_by(.address) | .[] | {address:.address, forwards_to:.forwards_to, permitted_senders:.permitted_senders, auto:.required, description:.description}" "$s1/aliases.json" > "$s1/aliases-cmp.json"
|
|
sed -i 's/\("address":"administrator@.*"auto":\)true/\1false/' "$s1/aliases-cmp.json"
|
|
|
|
# s2: re-sort aliases
|
|
jq -c ".[] | .aliases | sort_by(.address) | .[] | {address:.address, forwards_to:.forwards_to, permitted_senders:.permitted_senders, auto:.auto, description:.description}" "$s2/aliases.json" > "$s2/aliases-cmp.json"
|
|
|
|
if [ $MIGRATION_ML_VERSION_A -le 2 -a $MIGRATION_ML_VERSION_B -ge 3 ]; then
|
|
# miabldap migration level <=2 does not have quota fields, so
|
|
# remove them from the comparison
|
|
grep -vE '"(quota|box_quota|box_size|percent)":' "$s2/users-cmp.json" > "$s2/users-cmp2.json" || changed="true"
|
|
cp "$s2/users-cmp2.json" "$s2/users-cmp.json" && rm -f "$s2/users-cmp2.json"
|
|
fi
|
|
fi
|
|
|
|
|
|
#
|
|
# users
|
|
#
|
|
H2 "Users"
|
|
output="$(diff "$s1/users-cmp.json" "$s2/users-cmp.json" 2>&1)"
|
|
if [ $? -ne 0 ]; then
|
|
changed="true"
|
|
echo "USERS ARE DIFFERENT!"
|
|
echo "$output"
|
|
else
|
|
echo "No change"
|
|
fi
|
|
|
|
#
|
|
# aliases
|
|
#
|
|
|
|
H2 "Aliases"
|
|
output="$(diff "$s1/aliases-cmp.json" "$s2/aliases-cmp.json" 2>&1)"
|
|
if [ $? -ne 0 ]; then
|
|
changed="true"
|
|
echo "ALIASES ARE DIFFERENT!"
|
|
echo "$output"
|
|
else
|
|
echo "No change"
|
|
fi
|
|
|
|
H2 "DNS - zones missing"
|
|
local zone count=0
|
|
for zone in $(cd "$s1/zones"; ls *.signed); do
|
|
if [ ! -e "$s2/zones/$zone" ]; then
|
|
echo "MISSING zone: $zone"
|
|
changed="true"
|
|
let count+=1
|
|
fi
|
|
done
|
|
echo "$count missing"
|
|
|
|
H2 "DNS - zones added"
|
|
count=0
|
|
for zone in $(cd "$s2/zones"; ls *.signed); do
|
|
if [ ! -e "$s2/zones/$zone" ]; then
|
|
echo "ADDED zone: $zone"
|
|
changed="true"
|
|
let count+=1
|
|
fi
|
|
done
|
|
echo "$count added"
|
|
|
|
# H2 "DNS - zones changed"
|
|
# count=0
|
|
# for zone in $(cd "$s1/zones"; ls *.signed); do
|
|
# if [ -e "$s2/zones/$zone" ]; then
|
|
# # all the signatures change if we're using self-signed certs
|
|
# # ignore ttl changes
|
|
# local t1="/tmp/s1.$$.txt"
|
|
# local t2="/tmp/s2.$$.txt"
|
|
# awk '\
|
|
# $4 == "RRSIG" || $4 == "NSEC3" { next; } \
|
|
# $4 == "SOA" { print $1" "$3" "$4" "$5" "$6" "$8" "$10" "$12; next } \
|
|
# { for(i=1;i<=NF;i++) if (i!=2) printf("%s ",$i); print ""; }' \
|
|
# "$s1/zones/$zone" > "$t1"
|
|
|
|
# awk '\
|
|
# $4 == "RRSIG" || $4 == "NSEC3" { next; } \
|
|
# $4 == "SOA" { print $1" "$3" "$4" "$5" "$6" "$8" "$10" "$12; next } \
|
|
# { for(i=1;i<=NF;i++) if (i!=2) printf("%s ",$i); print ""; }' \
|
|
# "$s2/zones/$zone" > "$t2"
|
|
|
|
# output="$(diff "$t1" "$t2" 2>&1)"
|
|
# if [ $? -ne 0 ]; then
|
|
# echo "CHANGED zone: $zone"
|
|
# echo "$output"
|
|
# changed="true"
|
|
# let count+=1
|
|
# fi
|
|
# fi
|
|
# done
|
|
# echo "$count zone files had differences"
|
|
|
|
if $changed; then
|
|
return 1
|
|
else
|
|
return 0
|
|
fi
|
|
}
|