1167 lines
35 KiB
Bash
Executable File
1167 lines
35 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
script_name="$(basename $(realpath $0))"
|
|
working_dir="$(dirname $(realpath $0))"
|
|
|
|
LOCK_DIR="/tmp/$(basename $0).$$.LOCK"
|
|
log_file="${LOCK_DIR}/${script_name%%.*}.log"
|
|
|
|
backup_date="$(date +%Y-%m-%d-%H%M%S)"
|
|
|
|
MM_OIDC_REPOSITORY="https://github.com/server-camp/mattermost-oidc-plugin.git"
|
|
MM_BRIDGE_SOURCE_BASE="/usr/local/src/mattermost-oidc/mobile-bridge"
|
|
MM_BRIDGE_INSTALL_DIR="/usr/local/sbin"
|
|
MM_BRIDGE_NAME="mattermost-oidc-mobile-bridge"
|
|
MM_BRIDGE_LINK="${MM_BRIDGE_INSTALL_DIR}/${MM_BRIDGE_NAME}"
|
|
MM_BRIDGE_SERVICE="mattermost-oidc-mobile-bridge.service"
|
|
MM_SERVICE="mattermost.service"
|
|
MM_USER="mattermost"
|
|
MM_GROUP="mattermost"
|
|
MM_BRIDGE_LISTEN="127.0.0.1:8066"
|
|
MM_BRIDGE_UPSTREAM="http://127.0.0.1:8065"
|
|
MM_CONFIG_FILE="/opt/mattermost/config/config.json"
|
|
MM_SITE_URL=""
|
|
|
|
INSTALLATION_MODE=""
|
|
MM_CURRENT_VERSION=""
|
|
MM_CURRENT_TARGET=""
|
|
MM_NEW_VERSION=""
|
|
MM_LATEST_VERSION=""
|
|
MM_SOURCE_DIR=""
|
|
MM_BRIDGE_BIN=""
|
|
NGINX_CONFIG_FILE=""
|
|
NGINX_CHANGED=false
|
|
SYMLINK_CHANGED=false
|
|
UNIT_CREATED=false
|
|
ROLLBACK_TARGET=""
|
|
LEGACY_BRIDGE_BACKUP=""
|
|
|
|
|
|
# ----------
|
|
# Base Function(s)
|
|
# ----------
|
|
|
|
clean_up() {
|
|
rm -rf "$LOCK_DIR"
|
|
blank_line
|
|
exit $1
|
|
}
|
|
|
|
echononl(){
|
|
if $terminal ; then
|
|
echo X\\c > /tmp/shprompt$$
|
|
if [ `wc -c /tmp/shprompt$$ | awk '{print $1}'` -eq 1 ]; then
|
|
echo -e -n " $*\\c" 1>&2
|
|
else
|
|
echo -e -n " $*" 1>&2
|
|
fi
|
|
rm /tmp/shprompt$$
|
|
fi
|
|
}
|
|
|
|
fatal(){
|
|
echo ""
|
|
if $terminal ; then
|
|
echo -e " [ \033[31m\033[1mFatal\033[m ] $*"
|
|
else
|
|
echo -e " [ Fatal ] $*"
|
|
fi
|
|
echo ""
|
|
if $terminal ; then
|
|
echo -e " \033[1mScript terminated\033[m.."
|
|
else
|
|
echo -e " Script terminated.."
|
|
fi
|
|
echo ""
|
|
clean_up 1
|
|
}
|
|
|
|
error (){
|
|
echo ""
|
|
if $terminal ; then
|
|
echo -e " [ \033[31m\033[1mError\033[m ] $*"
|
|
else
|
|
echo " [ Error ] $*"
|
|
fi
|
|
echo ""
|
|
}
|
|
|
|
warn (){
|
|
echo ""
|
|
if $terminal ; then
|
|
echo -e " [ \033[33m\033[1mWarning\033[m ] $*"
|
|
else
|
|
echo " [ Warning ] $*"
|
|
fi
|
|
echo ""
|
|
}
|
|
|
|
info (){
|
|
if $terminal ; then
|
|
echo ""
|
|
echo -e " [ \033[32m\033[1mInfo\033[m ] $*"
|
|
echo ""
|
|
fi
|
|
}
|
|
|
|
echo_ok() {
|
|
if $terminal ; then
|
|
echo -e "\033[85G[ \033[32mok\033[m ]"
|
|
fi
|
|
}
|
|
|
|
echo_failed(){
|
|
if $terminal ; then
|
|
echo -e "\033[85G[ \033[1;31mfailed\033[m ]"
|
|
fi
|
|
}
|
|
|
|
echo_skipped() {
|
|
if $terminal ; then
|
|
echo -e "\033[85G[ \033[33m\033[1mskipped\033[m ]"
|
|
fi
|
|
}
|
|
|
|
echo_wait(){
|
|
if $terminal ; then
|
|
echo -en "\033[85G[ \033[5m\033[1m..\033[m ]"
|
|
fi
|
|
}
|
|
|
|
blank_line() {
|
|
if $terminal ; then
|
|
echo ""
|
|
fi
|
|
}
|
|
|
|
ask_yes_no() {
|
|
local question="$1"
|
|
local default_answer="${2:-no}"
|
|
local answer=""
|
|
local prompt="[yes/no]"
|
|
|
|
if [[ "$default_answer" = "yes" ]]; then
|
|
prompt="[yes/no, default: yes]"
|
|
elif [[ "$default_answer" = "no" ]]; then
|
|
prompt="[yes/no, default: no]"
|
|
fi
|
|
|
|
while true ; do
|
|
echononl "$question $prompt: "
|
|
read answer
|
|
answer="${answer,,}"
|
|
[[ -z "$answer" ]] && answer="$default_answer"
|
|
case "$answer" in
|
|
yes) return 0 ;;
|
|
no) return 1 ;;
|
|
*) warn "Wrong entry! Please enter 'yes' or 'no'." ;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
rollback_bridge() {
|
|
local rollback_failed=false
|
|
local rollback_path=""
|
|
|
|
[[ "$SYMLINK_CHANGED" = true ]] || return 0
|
|
|
|
if [[ "$INSTALLATION_MODE" = "initial-installation" ]]; then
|
|
warn "The new bridge did not pass all checks. Cleaning up the initial activation."
|
|
systemctl stop "$MM_BRIDGE_SERVICE" >> "$log_file" 2>&1 || true
|
|
|
|
if [[ "$UNIT_CREATED" = true ]]; then
|
|
systemctl disable "$MM_BRIDGE_SERVICE" >> "$log_file" 2>&1 || rollback_failed=true
|
|
fi
|
|
|
|
rm -f "$MM_BRIDGE_LINK" >> "$log_file" 2>&1 || rollback_failed=true
|
|
|
|
if [[ "$NGINX_CHANGED" = true && -n "$NGINX_BACKUP" && -f "$NGINX_BACKUP" ]]; then
|
|
warn "Restoring the nginx configuration from before the initial bridge installation."
|
|
if cp -a "$NGINX_BACKUP" "$NGINX_CONFIG_FILE" >> "$log_file" 2>&1 \
|
|
&& nginx -t >> "$log_file" 2>&1 \
|
|
&& systemctl reload nginx.service >> "$log_file" 2>&1 ; then
|
|
info "Previous nginx configuration was restored and reloaded."
|
|
else
|
|
rollback_failed=true
|
|
error "Could not fully restore/reload the previous nginx configuration. Check nginx manually."
|
|
fi
|
|
fi
|
|
|
|
if [[ "$rollback_failed" = true ]]; then
|
|
error "Initial-install cleanup was not fully successful. Please check '${MM_BRIDGE_LINK}', '${MM_BRIDGE_SERVICE}' and nginx manually."
|
|
else
|
|
info "Initial activation was removed. The new binary, source directory and unit file were kept for analysis."
|
|
fi
|
|
return 0
|
|
fi
|
|
|
|
warn "The new bridge did not pass all checks. Trying to restore the previous installation."
|
|
|
|
if [[ -n "$ROLLBACK_TARGET" ]]; then
|
|
if [[ "$ROLLBACK_TARGET" = /* ]]; then
|
|
rollback_path="$ROLLBACK_TARGET"
|
|
else
|
|
rollback_path="${MM_BRIDGE_INSTALL_DIR}/${ROLLBACK_TARGET}"
|
|
fi
|
|
fi
|
|
|
|
if [[ -n "$ROLLBACK_TARGET" && -e "$rollback_path" ]]; then
|
|
ln -s "$ROLLBACK_TARGET" "${MM_BRIDGE_LINK}.rollback.$$" >> "$log_file" 2>&1 \
|
|
&& mv -Tf "${MM_BRIDGE_LINK}.rollback.$$" "$MM_BRIDGE_LINK" >> "$log_file" 2>&1 \
|
|
|| rollback_failed=true
|
|
elif [[ -n "$LEGACY_BRIDGE_BACKUP" && -f "$LEGACY_BRIDGE_BACKUP" ]]; then
|
|
rm -f "$MM_BRIDGE_LINK" >> "$log_file" 2>&1
|
|
cp -a "$LEGACY_BRIDGE_BACKUP" "$MM_BRIDGE_LINK" >> "$log_file" 2>&1 || rollback_failed=true
|
|
else
|
|
rollback_failed=true
|
|
fi
|
|
|
|
if [[ "$rollback_failed" = false ]]; then
|
|
systemctl restart "$MM_BRIDGE_SERVICE" >> "$log_file" 2>&1 || rollback_failed=true
|
|
fi
|
|
|
|
if [[ "$rollback_failed" = true ]]; then
|
|
error "Automatic rollback failed. Please check '${MM_BRIDGE_LINK}' and '${MM_BRIDGE_SERVICE}' manually."
|
|
else
|
|
info "Previous bridge installation was restored and restarted."
|
|
fi
|
|
}
|
|
|
|
bridge_test() {
|
|
local response=""
|
|
local location=""
|
|
local http_code=""
|
|
local headers_file="${LOCK_DIR}/bridge-redirect-headers"
|
|
|
|
echononl "Check bridge service status.."
|
|
if systemctl is-active --quiet "$MM_BRIDGE_SERVICE" ; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
return 1
|
|
fi
|
|
|
|
echononl "Check bridge listener '${MM_BRIDGE_LISTEN}'.."
|
|
_listener_ready=false
|
|
for _listener_try in {1..10}; do
|
|
if ss -lnt | awk -v listen="$MM_BRIDGE_LISTEN" '$4 == listen {found=1} END {exit !found}' ; then
|
|
_listener_ready=true
|
|
break
|
|
fi
|
|
sleep 1
|
|
done
|
|
if [[ "$_listener_ready" = true ]]; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
return 1
|
|
fi
|
|
|
|
echononl "Test mobile client configuration endpoint.."
|
|
if response="$(curl -fsS --max-time 10 \
|
|
-A 'Mattermost Mobile/2.0' \
|
|
"http://${MM_BRIDGE_LISTEN}/api/v4/config/client" 2>> "$log_file")" \
|
|
&& printf '%s' "$response" | python3 -c '
|
|
import json, sys
|
|
try:
|
|
value = json.load(sys.stdin).get("EnableSignUpWithOpenId")
|
|
except Exception:
|
|
raise SystemExit(1)
|
|
raise SystemExit(0 if value in (True, "true") else 1)
|
|
' ; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
return 1
|
|
fi
|
|
|
|
echononl "Test browser client configuration endpoint.."
|
|
if response="$(curl -fsS --max-time 10 \
|
|
-A 'Mozilla/5.0' \
|
|
"http://${MM_BRIDGE_LISTEN}/api/v4/config/client" 2>> "$log_file")" \
|
|
&& printf '%s' "$response" | python3 -c '
|
|
import json, sys
|
|
try:
|
|
value = json.load(sys.stdin).get("EnableSignUpWithOpenId")
|
|
except Exception:
|
|
raise SystemExit(1)
|
|
raise SystemExit(0 if value in (False, "false") else 1)
|
|
' ; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
return 1
|
|
fi
|
|
|
|
echononl "Test mobile OIDC redirect endpoint.."
|
|
: > "$headers_file"
|
|
http_code="$(curl -sS --max-time 10 \
|
|
-o /dev/null -D "$headers_file" -w '%{http_code}' \
|
|
"http://${MM_BRIDGE_LISTEN}/oauth/openid/mobile_login?redirect_to=mmauth%3A%2F%2Fcallback" \
|
|
2>> "$log_file")"
|
|
location="$(awk 'BEGIN{IGNORECASE=1} /^Location:/ {sub(/^[^:]*:[[:space:]]*/,""); sub(/\r$/,""); print; exit}' "$headers_file")"
|
|
if [[ "$http_code" = "302" ]] \
|
|
&& [[ "$location" == /plugins/mattermost-oidc/oauth2/connect* ]] \
|
|
&& [[ "$location" == *"mobile_redirect="* ]]; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
|
|
nginx_e2e_test() {
|
|
local response=""
|
|
local location=""
|
|
local http_code=""
|
|
local headers_file="${LOCK_DIR}/nginx-redirect-headers"
|
|
|
|
[[ -n "$MM_SITE_URL" ]] || return 0
|
|
|
|
echononl "Test mobile client configuration endpoint through nginx.."
|
|
if response="$(curl -fsS --max-time 10 \
|
|
-A 'Mattermost Mobile/2.0' \
|
|
"${MM_SITE_URL%/}/api/v4/config/client" 2>> "$log_file")" \
|
|
&& printf '%s' "$response" | python3 -c '
|
|
import json, sys
|
|
try:
|
|
value = json.load(sys.stdin).get("EnableSignUpWithOpenId")
|
|
except Exception:
|
|
raise SystemExit(1)
|
|
raise SystemExit(0 if value in (True, "true") else 1)
|
|
' ; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
return 1
|
|
fi
|
|
|
|
echononl "Test browser client configuration endpoint through nginx.."
|
|
if response="$(curl -fsS --max-time 10 \
|
|
-A 'Mozilla/5.0' \
|
|
"${MM_SITE_URL%/}/api/v4/config/client" 2>> "$log_file")" \
|
|
&& printf '%s' "$response" | python3 -c '
|
|
import json, sys
|
|
try:
|
|
value = json.load(sys.stdin).get("EnableSignUpWithOpenId")
|
|
except Exception:
|
|
raise SystemExit(1)
|
|
raise SystemExit(0 if value in (False, "false") else 1)
|
|
' ; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
return 1
|
|
fi
|
|
|
|
echononl "Test mobile OIDC redirect endpoint through nginx.."
|
|
: > "$headers_file"
|
|
http_code="$(curl -sS --max-time 10 \
|
|
-o /dev/null -D "$headers_file" -w '%{http_code}' \
|
|
"${MM_SITE_URL%/}/oauth/openid/mobile_login?redirect_to=mmauth%3A%2F%2Fcallback" \
|
|
2>> "$log_file")"
|
|
location="$(awk 'BEGIN{IGNORECASE=1} /^Location:/ {sub(/^[^:]*:[[:space:]]*/,""); sub(/\r$/,""); print; exit}' "$headers_file")"
|
|
if [[ "$http_code" = "302" ]] \
|
|
&& [[ "$location" == /plugins/mattermost-oidc/oauth2/connect* ]] \
|
|
&& [[ "$location" == *"mobile_redirect="* ]]; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
# ----------
|
|
# Jobhandling
|
|
# ----------
|
|
|
|
trap 'clean_up 1' SIGHUP SIGINT SIGTERM
|
|
|
|
if ! mkdir "$LOCK_DIR" 2>/dev/null ; then
|
|
echo "Cannot create lock directory '$LOCK_DIR'."
|
|
exit 1
|
|
fi
|
|
|
|
if [[ -t 1 ]] ; then
|
|
terminal=true
|
|
else
|
|
fatal "Script must run in a terminal."
|
|
fi
|
|
|
|
|
|
# ==========
|
|
# Begin Main Script
|
|
# ==========
|
|
|
|
if $terminal ; then
|
|
echo ""
|
|
echo -e "\033[1m----------\033[m"
|
|
echo -e "\033[32m\033[1mRunning script \033[m\033[1m$script_name\033[32m .. \033[m"
|
|
echo -e "\033[1m----------\033[m"
|
|
fi
|
|
|
|
blank_line
|
|
|
|
# ----------
|
|
# Some checks
|
|
# ----------
|
|
|
|
echononl "Check if script is running as root.."
|
|
if [[ "$(id -u)" -eq 0 ]]; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
fatal "This script must be run as root."
|
|
fi
|
|
|
|
for _cmd in git systemctl systemd-analyze curl ss awk grep sed sort file install readlink ln mv cp mkdir python3 ; do
|
|
echononl "Check for command '${_cmd}'.."
|
|
if command -v "$_cmd" > /dev/null 2>&1 ; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
fatal "Required command '${_cmd}' was not found."
|
|
fi
|
|
done
|
|
|
|
|
|
echononl "Check Mattermost user '${MM_USER}'.."
|
|
if id "$MM_USER" > /dev/null 2>&1 ; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
fatal "Mattermost user '${MM_USER}' does not exist."
|
|
fi
|
|
|
|
echononl "Check Mattermost group '${MM_GROUP}'.."
|
|
if getent group "$MM_GROUP" > /dev/null 2>&1 ; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
fatal "Mattermost group '${MM_GROUP}' does not exist."
|
|
fi
|
|
|
|
echononl "Check Mattermost service '${MM_SERVICE}'.."
|
|
if systemctl cat "$MM_SERVICE" > /dev/null 2>&1 ; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
fatal "Mattermost service '${MM_SERVICE}' was not found."
|
|
fi
|
|
|
|
|
|
# ----------
|
|
# Detect installation mode
|
|
# ----------
|
|
|
|
echononl "Detect existing Mattermost OIDC Mobile Bridge installation.."
|
|
if [[ -L "$MM_BRIDGE_LINK" ]]; then
|
|
MM_CURRENT_TARGET="$(readlink "$MM_BRIDGE_LINK")"
|
|
if [[ ! -e "$MM_BRIDGE_LINK" ]]; then
|
|
echo_failed
|
|
fatal "Broken symlink '${MM_BRIDGE_LINK}' -> '${MM_CURRENT_TARGET}'."
|
|
fi
|
|
|
|
if [[ "$MM_CURRENT_TARGET" =~ ^${MM_BRIDGE_NAME}-([0-9]+\.[0-9]+\.[0-9]+.*)$ ]]; then
|
|
MM_CURRENT_VERSION="${BASH_REMATCH[1]}"
|
|
else
|
|
echo_failed
|
|
fatal "Cannot determine installed bridge version from symlink target '${MM_CURRENT_TARGET}'."
|
|
fi
|
|
INSTALLATION_MODE="upgrade"
|
|
ROLLBACK_TARGET="$MM_CURRENT_TARGET"
|
|
echo_ok
|
|
elif [[ -e "$MM_BRIDGE_LINK" ]]; then
|
|
INSTALLATION_MODE="legacy-upgrade"
|
|
echo_ok
|
|
else
|
|
INSTALLATION_MODE="initial-installation"
|
|
echo_ok
|
|
fi
|
|
|
|
|
|
# ----------
|
|
# Determine latest stable release
|
|
# ----------
|
|
|
|
echononl "Determine latest stable Mattermost OIDC release.."
|
|
MM_LATEST_VERSION="$(git ls-remote --tags --refs "$MM_OIDC_REPOSITORY" 2> "$log_file" \
|
|
| awk '{print $2}' \
|
|
| sed -nE 's#refs/tags/v([0-9]+\.[0-9]+\.[0-9]+)$#\1#p' \
|
|
| sort -V \
|
|
| tail -1)"
|
|
if [[ -n "$MM_LATEST_VERSION" ]]; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
fatal "Could not determine latest stable release from '${MM_OIDC_REPOSITORY}'. $(cat "$log_file")"
|
|
fi
|
|
|
|
blank_line
|
|
if [[ "$INSTALLATION_MODE" = "initial-installation" ]]; then
|
|
echo " Installation mode....................: Initial installation"
|
|
elif [[ "$INSTALLATION_MODE" = "legacy-upgrade" ]]; then
|
|
echo " Installation mode....................: Upgrade of legacy/unversioned installation"
|
|
echo " Currently installed version.........: unknown"
|
|
else
|
|
echo " Installation mode....................: Upgrade"
|
|
echo " Currently installed version.........: ${MM_CURRENT_VERSION}"
|
|
fi
|
|
echo " Latest stable version...............: ${MM_LATEST_VERSION}"
|
|
blank_line
|
|
|
|
while true ; do
|
|
echononl "New Mattermost OIDC Mobile Bridge Version [${MM_LATEST_VERSION}]: "
|
|
read MM_NEW_VERSION
|
|
MM_NEW_VERSION="${MM_NEW_VERSION#v}"
|
|
[[ -z "$MM_NEW_VERSION" ]] && MM_NEW_VERSION="$MM_LATEST_VERSION"
|
|
|
|
echononl "Check release tag 'v${MM_NEW_VERSION}'.."
|
|
if git ls-remote --exit-code --tags "$MM_OIDC_REPOSITORY" \
|
|
"refs/tags/v${MM_NEW_VERSION}" "refs/tags/v${MM_NEW_VERSION}^{}" \
|
|
> /dev/null 2> "$log_file" ; then
|
|
echo_ok
|
|
break
|
|
else
|
|
echo_failed
|
|
warn "Tag 'v${MM_NEW_VERSION}' does not exist in the upstream repository."
|
|
fi
|
|
done
|
|
|
|
if [[ "$INSTALLATION_MODE" = "upgrade" && "$MM_NEW_VERSION" = "$MM_CURRENT_VERSION" ]]; then
|
|
blank_line
|
|
warn "Mattermost OIDC Mobile Bridge ${MM_CURRENT_VERSION} is already installed."
|
|
if ! ask_yes_no "Reinstall version ${MM_NEW_VERSION}" "no" ; then
|
|
info "Version ${MM_CURRENT_VERSION} is already installed. Nothing to do."
|
|
clean_up 0
|
|
fi
|
|
fi
|
|
|
|
MM_SOURCE_DIR="${MM_BRIDGE_SOURCE_BASE}/mattermost-oidc-plugin-${MM_NEW_VERSION}"
|
|
MM_BRIDGE_BIN="${MM_BRIDGE_INSTALL_DIR}/${MM_BRIDGE_NAME}-${MM_NEW_VERSION}"
|
|
|
|
if [[ -r "$MM_CONFIG_FILE" ]]; then
|
|
MM_SITE_URL="$(python3 - "$MM_CONFIG_FILE" 2>> "$log_file" <<'PY_EOF'
|
|
import json, sys
|
|
try:
|
|
with open(sys.argv[1], encoding="utf-8") as f:
|
|
data = json.load(f)
|
|
print(data.get("ServiceSettings", {}).get("SiteURL", ""))
|
|
except Exception:
|
|
pass
|
|
PY_EOF
|
|
)"
|
|
fi
|
|
|
|
|
|
# ----------
|
|
# Check systemd and nginx state
|
|
# ----------
|
|
|
|
UNIT_EXISTS=false
|
|
if systemctl cat "$MM_BRIDGE_SERVICE" > /dev/null 2>&1 ; then
|
|
UNIT_EXISTS=true
|
|
fi
|
|
|
|
NGINX_AVAILABLE=false
|
|
if command -v nginx > /dev/null 2>&1 ; then
|
|
NGINX_AVAILABLE=true
|
|
fi
|
|
|
|
if [[ "$NGINX_AVAILABLE" = true ]]; then
|
|
echononl "Try to detect active Mattermost nginx configuration.."
|
|
_nginx_candidates=()
|
|
_mm_site_host=""
|
|
|
|
if [[ -n "$MM_SITE_URL" ]]; then
|
|
_mm_site_host="$(python3 - "$MM_SITE_URL" <<'PY_EOF'
|
|
from urllib.parse import urlparse
|
|
import sys
|
|
try:
|
|
print(urlparse(sys.argv[1]).hostname or "")
|
|
except Exception:
|
|
pass
|
|
PY_EOF
|
|
)"
|
|
fi
|
|
|
|
if [[ -n "$_mm_site_host" ]]; then
|
|
mapfile -t _nginx_candidates < <(nginx -T 2>/dev/null \
|
|
| awk -v host="$_mm_site_host" '
|
|
/^# configuration file \/.*:$/ {f=$0; sub(/^# configuration file /,"",f); sub(/:$/,"",f)}
|
|
/^[[:space:]]*server_name[[:space:]]+/ {
|
|
line=$0; sub(/#.*/,"",line); gsub(/;/,"",line)
|
|
n=split(line,a,/[[:space:]]+/)
|
|
for (i=2; i<=n; i++) if (a[i] == host && f != "") print f
|
|
}
|
|
' | sort -u)
|
|
fi
|
|
|
|
if [[ ${#_nginx_candidates[@]} -eq 0 ]]; then
|
|
mapfile -t _nginx_candidates < <(nginx -T 2>/dev/null \
|
|
| awk -v upstream="$MM_BRIDGE_UPSTREAM" '
|
|
/^# configuration file \/.*:$/ {f=$0; sub(/^# configuration file /,"",f); sub(/:$/,"",f)}
|
|
index($0, "proxy_pass " upstream) {if (f != "") print f}
|
|
' | sort -u)
|
|
fi
|
|
|
|
if [[ ${#_nginx_candidates[@]} -eq 1 && -f "${_nginx_candidates[0]}" ]]; then
|
|
NGINX_CONFIG_FILE="${_nginx_candidates[0]}"
|
|
echo_ok
|
|
else
|
|
echo_skipped
|
|
fi
|
|
fi
|
|
|
|
if [[ -n "$NGINX_CONFIG_FILE" ]]; then
|
|
echo
|
|
echo " Detected Mattermost nginx vHost configuration:"
|
|
echo " ${NGINX_CONFIG_FILE}"
|
|
echononl "Configuration file [RETURN = use detected file]: "
|
|
read _nginx_input
|
|
[[ -n "$_nginx_input" ]] && NGINX_CONFIG_FILE="$_nginx_input"
|
|
elif [[ "$NGINX_AVAILABLE" = true ]]; then
|
|
echo
|
|
echo " Mattermost nginx vHost configuration could not be detected automatically."
|
|
echo " Enter the full path to the nginx vHost configuration file."
|
|
echo " Press RETURN without entering a path to skip nginx setup."
|
|
echononl "Configuration file: "
|
|
read NGINX_CONFIG_FILE
|
|
fi
|
|
|
|
if [[ -n "$NGINX_CONFIG_FILE" && ! -f "$NGINX_CONFIG_FILE" ]]; then
|
|
fatal "nginx configuration file '${NGINX_CONFIG_FILE}' does not exist."
|
|
fi
|
|
|
|
# Work on the real file, not on a sites-enabled symlink. This also makes
|
|
# timestamped backups independent from the live symlink.
|
|
if [[ -n "$NGINX_CONFIG_FILE" ]]; then
|
|
NGINX_CONFIG_FILE="$(readlink -f "$NGINX_CONFIG_FILE")"
|
|
[[ -f "$NGINX_CONFIG_FILE" ]] || fatal "Could not resolve nginx configuration file."
|
|
fi
|
|
|
|
|
|
# ----------
|
|
# Summary
|
|
# ----------
|
|
|
|
blank_line
|
|
echo -e "\033[37m\033[1mMattermost OIDC Mobile Bridge installation settings:\033[m"
|
|
blank_line
|
|
echo " Installation mode....................: ${INSTALLATION_MODE}"
|
|
[[ -n "$MM_CURRENT_VERSION" ]] && echo " Current bridge version...............: ${MM_CURRENT_VERSION}"
|
|
echo " New bridge version...................: ${MM_NEW_VERSION}"
|
|
echo " Latest stable version................: ${MM_LATEST_VERSION}"
|
|
echo " Repository...........................: ${MM_OIDC_REPOSITORY}"
|
|
echo " Source directory.....................: ${MM_SOURCE_DIR}"
|
|
echo " Versioned binary.....................: ${MM_BRIDGE_BIN}"
|
|
echo " Stable symlink.......................: ${MM_BRIDGE_LINK}"
|
|
echo " Bridge service.......................: ${MM_BRIDGE_SERVICE}"
|
|
echo " Bridge listen address................: ${MM_BRIDGE_LISTEN}"
|
|
echo " Mattermost upstream..................: ${MM_BRIDGE_UPSTREAM}"
|
|
if [[ -n "$NGINX_CONFIG_FILE" ]]; then
|
|
echo " nginx configuration..................: ${NGINX_CONFIG_FILE}"
|
|
else
|
|
echo " nginx configuration..................: not selected"
|
|
fi
|
|
blank_line
|
|
|
|
if ! ask_yes_no "einverstanden" "no" ; then
|
|
fatal "Stopped by user"
|
|
fi
|
|
|
|
|
|
# ----------
|
|
# Prepare source tree
|
|
# ----------
|
|
|
|
blank_line
|
|
echo -e "\033[37m\033[1mBuild Mattermost OIDC Mobile Bridge..\033[m"
|
|
blank_line
|
|
|
|
echononl "Create source base directory.."
|
|
if mkdir -p "$MM_BRIDGE_SOURCE_BASE" > "$log_file" 2>&1 ; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
fatal "$(cat "$log_file")"
|
|
fi
|
|
|
|
if [[ -e "$MM_SOURCE_DIR" ]]; then
|
|
echononl "Backup existing source directory.."
|
|
if mv "$MM_SOURCE_DIR" "${MM_SOURCE_DIR}.${backup_date}" > "$log_file" 2>&1 ; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
fatal "$(cat "$log_file")"
|
|
fi
|
|
else
|
|
echononl "Backup existing source directory.."
|
|
echo_skipped
|
|
fi
|
|
|
|
echononl "Clone release 'v${MM_NEW_VERSION}'.."
|
|
if git clone --depth 1 --branch "v${MM_NEW_VERSION}" "$MM_OIDC_REPOSITORY" "$MM_SOURCE_DIR" \
|
|
> "$log_file" 2>&1 ; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
fatal "$(cat "$log_file")"
|
|
fi
|
|
|
|
echononl "Verify checked out release tag.."
|
|
if [[ "$(git -C "$MM_SOURCE_DIR" describe --tags --exact-match 2> "$log_file")" = "v${MM_NEW_VERSION}" ]]; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
fatal "Source tree does not match expected tag 'v${MM_NEW_VERSION}'."
|
|
fi
|
|
|
|
if [[ ! -f "${MM_SOURCE_DIR}/mobile-bridge/go.mod" || ! -f "${MM_SOURCE_DIR}/mobile-bridge/main.go" ]]; then
|
|
fatal "Expected mobile-bridge source files were not found in '${MM_SOURCE_DIR}/mobile-bridge'."
|
|
fi
|
|
|
|
GO_REQUIRED_VERSION="$(awk '$1 == "go" {print $2; exit}' "${MM_SOURCE_DIR}/mobile-bridge/go.mod")"
|
|
[[ -n "$GO_REQUIRED_VERSION" ]] || fatal "Could not determine required Go version from mobile-bridge/go.mod."
|
|
|
|
echononl "Check if Go is installed.."
|
|
if command -v go > /dev/null 2>&1 ; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
fatal "Go is not installed. Mattermost OIDC Mobile Bridge ${MM_NEW_VERSION} requires Go ${GO_REQUIRED_VERSION} or newer."
|
|
fi
|
|
|
|
GO_INSTALLED_VERSION="$(go version 2>/dev/null | awk '{sub(/^go/,"",$3); print $3}')"
|
|
[[ -n "$GO_INSTALLED_VERSION" ]] || fatal "Could not determine installed Go version."
|
|
|
|
echononl "Check Go version (installed: ${GO_INSTALLED_VERSION}, required: ${GO_REQUIRED_VERSION}).."
|
|
if [[ "$(printf '%s\n%s\n' "$GO_REQUIRED_VERSION" "$GO_INSTALLED_VERSION" | sort -V | head -1)" = "$GO_REQUIRED_VERSION" ]]; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
fatal "Installed Go version '${GO_INSTALLED_VERSION}' is too old. Version '${GO_REQUIRED_VERSION}' or newer is required."
|
|
fi
|
|
|
|
echononl "Build Mattermost OIDC Mobile Bridge ${MM_NEW_VERSION}.."
|
|
if ( cd "${MM_SOURCE_DIR}/mobile-bridge" && CGO_ENABLED=0 go build -trimpath -o "${LOCK_DIR}/${MM_BRIDGE_NAME}" . ) \
|
|
> "$log_file" 2>&1 ; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
fatal "$(cat "$log_file")"
|
|
fi
|
|
|
|
echononl "Verify built bridge binary.."
|
|
if [[ -x "${LOCK_DIR}/${MM_BRIDGE_NAME}" ]] \
|
|
&& file "${LOCK_DIR}/${MM_BRIDGE_NAME}" | grep -q 'ELF' ; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
fatal "Built bridge binary is missing, not executable or not an ELF binary."
|
|
fi
|
|
|
|
|
|
# ----------
|
|
# Install versioned binary
|
|
# ----------
|
|
|
|
blank_line
|
|
echo -e "\033[37m\033[1mInstall Mattermost OIDC Mobile Bridge..\033[m"
|
|
blank_line
|
|
|
|
if [[ -e "$MM_BRIDGE_BIN" ]]; then
|
|
echononl "Backup existing bridge binary.."
|
|
if mv "$MM_BRIDGE_BIN" "${MM_BRIDGE_BIN}.${backup_date}" > "$log_file" 2>&1 ; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
fatal "$(cat "$log_file")"
|
|
fi
|
|
else
|
|
echononl "Backup existing bridge binary.."
|
|
echo_skipped
|
|
fi
|
|
|
|
echononl "Install versioned bridge binary.."
|
|
if install -o root -g root -m 0755 "${LOCK_DIR}/${MM_BRIDGE_NAME}" "$MM_BRIDGE_BIN" \
|
|
> "$log_file" 2>&1 ; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
fatal "$(cat "$log_file")"
|
|
fi
|
|
|
|
# Preserve an old unversioned installation before replacing it with a symlink.
|
|
if [[ "$INSTALLATION_MODE" = "legacy-upgrade" ]]; then
|
|
LEGACY_BRIDGE_BACKUP="${MM_BRIDGE_LINK}.${backup_date}"
|
|
echononl "Backup legacy bridge binary.."
|
|
if mv "$MM_BRIDGE_LINK" "$LEGACY_BRIDGE_BACKUP" > "$log_file" 2>&1 ; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
fatal "$(cat "$log_file")"
|
|
fi
|
|
fi
|
|
|
|
|
|
# ----------
|
|
# Install/check systemd unit
|
|
# ----------
|
|
|
|
UNIT_FILE="/etc/systemd/system/${MM_BRIDGE_SERVICE}"
|
|
|
|
if [[ "$UNIT_EXISTS" = false ]]; then
|
|
echononl "Create systemd service '${MM_BRIDGE_SERVICE}'.."
|
|
cat > "$UNIT_FILE" <<SYSTEMD_EOF
|
|
[Unit]
|
|
Description=Mattermost OIDC Mobile Bridge
|
|
After=network.target mattermost.service
|
|
Requires=mattermost.service
|
|
|
|
[Service]
|
|
Type=simple
|
|
User=${MM_USER}
|
|
Group=${MM_GROUP}
|
|
Environment=LISTEN=${MM_BRIDGE_LISTEN}
|
|
Environment=UPSTREAM=${MM_BRIDGE_UPSTREAM}
|
|
ExecStart=${MM_BRIDGE_LINK}
|
|
Restart=on-failure
|
|
RestartSec=5s
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
SYSTEMD_EOF
|
|
if [[ $? -eq 0 ]]; then
|
|
UNIT_CREATED=true
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
fatal "Failed to create '${UNIT_FILE}'."
|
|
fi
|
|
|
|
echononl "Verify systemd service '${MM_BRIDGE_SERVICE}'.."
|
|
if systemd-analyze verify "$UNIT_FILE" > "$log_file" 2>&1 ; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
fatal "$(cat "$log_file")"
|
|
fi
|
|
|
|
echononl "Reload systemd configuration.."
|
|
if systemctl daemon-reload > "$log_file" 2>&1 ; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
fatal "$(cat "$log_file")"
|
|
fi
|
|
|
|
echononl "Enable '${MM_BRIDGE_SERVICE}'.."
|
|
if systemctl enable "$MM_BRIDGE_SERVICE" > "$log_file" 2>&1 ; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
fatal "$(cat "$log_file")"
|
|
fi
|
|
else
|
|
echononl "Keep existing systemd service '${MM_BRIDGE_SERVICE}'.."
|
|
echo_ok
|
|
|
|
_unit_text="$(systemctl cat "$MM_BRIDGE_SERVICE" 2>/dev/null)"
|
|
|
|
UNIT_EXECSTART_OK=true
|
|
if [[ "$_unit_text" != *"ExecStart=${MM_BRIDGE_LINK}"* ]]; then
|
|
UNIT_EXECSTART_OK=false
|
|
warn "Existing systemd unit does not contain expected ExecStart=${MM_BRIDGE_LINK}. It will not be changed automatically."
|
|
fi
|
|
|
|
[[ "$_unit_text" == *"LISTEN=${MM_BRIDGE_LISTEN}"* ]] \
|
|
|| warn "Existing systemd unit does not contain expected LISTEN=${MM_BRIDGE_LISTEN}. It will not be changed automatically."
|
|
[[ "$_unit_text" == *"UPSTREAM=${MM_BRIDGE_UPSTREAM}"* ]] \
|
|
|| warn "Existing systemd unit does not contain expected UPSTREAM=${MM_BRIDGE_UPSTREAM}. It will not be changed automatically."
|
|
[[ "$_unit_text" == *"User=${MM_USER}"* ]] \
|
|
|| warn "Existing systemd unit does not contain expected User=${MM_USER}. It will not be changed automatically."
|
|
[[ "$_unit_text" == *"Group=${MM_GROUP}"* ]] \
|
|
|| warn "Existing systemd unit does not contain expected Group=${MM_GROUP}. It will not be changed automatically."
|
|
|
|
if [[ "$UNIT_EXECSTART_OK" = false ]]; then
|
|
blank_line
|
|
if ! ask_yes_no "Continue although ExecStart differs from the expected stable bridge symlink" "no" ; then
|
|
fatal "Stopped by user because existing systemd ExecStart differs."
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
|
|
# ----------
|
|
# Configure nginx if requested
|
|
# ----------
|
|
|
|
if [[ -n "$NGINX_CONFIG_FILE" ]]; then
|
|
blank_line
|
|
echo -e "\033[37m\033[1mCheck nginx configuration..\033[m"
|
|
blank_line
|
|
|
|
API_LOCATION_STATE="missing"
|
|
MOBILE_LOCATION_STATE="missing"
|
|
|
|
_bridge_proxy_pass="proxy_passhttp://${MM_BRIDGE_LISTEN};"
|
|
|
|
if grep -Eq '^[[:space:]]*location[[:space:]]*=[[:space:]]*/api/v4/config/client[[:space:]]*\{' "$NGINX_CONFIG_FILE" ; then
|
|
if awk -v expected="$_bridge_proxy_pass" '
|
|
/^[[:space:]]*location[[:space:]]*=[[:space:]]*\/api\/v4\/config\/client[[:space:]]*\{/ {inloc=1; depth=1; next}
|
|
inloc {depth += gsub(/\{/ ,"{"); depth -= gsub(/\}/,"}"); line=$0; gsub(/[[:space:]]/,"",line); if (line == expected) ok=1; if (depth<=0) exit}
|
|
END {exit !ok}
|
|
' "$NGINX_CONFIG_FILE" ; then
|
|
API_LOCATION_STATE="ok"
|
|
else
|
|
API_LOCATION_STATE="different"
|
|
fi
|
|
fi
|
|
|
|
if grep -Eq '^[[:space:]]*location[[:space:]]*=[[:space:]]*/oauth/openid/mobile_login[[:space:]]*\{' "$NGINX_CONFIG_FILE" ; then
|
|
if awk -v expected="$_bridge_proxy_pass" '
|
|
/^[[:space:]]*location[[:space:]]*=[[:space:]]*\/oauth\/openid\/mobile_login[[:space:]]*\{/ {inloc=1; depth=1; next}
|
|
inloc {depth += gsub(/\{/ ,"{"); depth -= gsub(/\}/,"}"); line=$0; gsub(/[[:space:]]/,"",line); if (line == expected) ok=1; if (depth<=0) exit}
|
|
END {exit !ok}
|
|
' "$NGINX_CONFIG_FILE" ; then
|
|
MOBILE_LOCATION_STATE="ok"
|
|
else
|
|
MOBILE_LOCATION_STATE="different"
|
|
fi
|
|
fi
|
|
|
|
echo " /api/v4/config/client.................: ${API_LOCATION_STATE}"
|
|
echo " /oauth/openid/mobile_login............: ${MOBILE_LOCATION_STATE}"
|
|
blank_line
|
|
|
|
if [[ "$API_LOCATION_STATE" = "different" || "$MOBILE_LOCATION_STATE" = "different" ]]; then
|
|
warn "At least one required location already exists with a different configuration. Existing location blocks will not be modified automatically."
|
|
fi
|
|
|
|
MISSING_LOCATIONS=false
|
|
[[ "$API_LOCATION_STATE" = "missing" ]] && MISSING_LOCATIONS=true
|
|
[[ "$MOBILE_LOCATION_STATE" = "missing" ]] && MISSING_LOCATIONS=true
|
|
|
|
if [[ "$MISSING_LOCATIONS" = true ]]; then
|
|
if ask_yes_no "Add missing Mattermost OIDC Mobile Bridge locations to nginx configuration" "yes" ; then
|
|
NGINX_BACKUP="${NGINX_CONFIG_FILE}.${backup_date}"
|
|
echononl "Backup nginx configuration.."
|
|
if cp -a "$NGINX_CONFIG_FILE" "$NGINX_BACKUP" > "$log_file" 2>&1 ; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
fatal "$(cat "$log_file")"
|
|
fi
|
|
|
|
NGINX_INSERT_FILE="${LOCK_DIR}/nginx-locations.conf"
|
|
: > "$NGINX_INSERT_FILE"
|
|
|
|
if [[ "$API_LOCATION_STATE" = "missing" ]]; then
|
|
cat >> "$NGINX_INSERT_FILE" <<NGINX_API_EOF
|
|
location = /api/v4/config/client {
|
|
proxy_set_header Host \$host;
|
|
proxy_set_header X-Real-IP \$remote_addr;
|
|
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto \$scheme;
|
|
|
|
proxy_pass http://${MM_BRIDGE_LISTEN};
|
|
}
|
|
|
|
NGINX_API_EOF
|
|
fi
|
|
|
|
if [[ "$MOBILE_LOCATION_STATE" = "missing" ]]; then
|
|
cat >> "$NGINX_INSERT_FILE" <<NGINX_MOBILE_EOF
|
|
location = /oauth/openid/mobile_login {
|
|
proxy_set_header Host \$host;
|
|
proxy_set_header X-Real-IP \$remote_addr;
|
|
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto \$scheme;
|
|
|
|
proxy_pass http://${MM_BRIDGE_LISTEN};
|
|
}
|
|
|
|
NGINX_MOBILE_EOF
|
|
fi
|
|
|
|
echononl "Insert missing bridge locations before Mattermost 'location /'.."
|
|
python3 - "$NGINX_CONFIG_FILE" "$NGINX_INSERT_FILE" "$MM_BRIDGE_UPSTREAM" <<'PY_EOF' > "$log_file" 2>&1
|
|
import re
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
config = Path(sys.argv[1])
|
|
insert = Path(sys.argv[2]).read_text()
|
|
upstream = sys.argv[3].rstrip("/")
|
|
text = config.read_text()
|
|
|
|
def matching_brace(data, open_pos):
|
|
depth = 0
|
|
quote = None
|
|
escaped = False
|
|
comment = False
|
|
for pos in range(open_pos, len(data)):
|
|
ch = data[pos]
|
|
if comment:
|
|
if ch == "\n":
|
|
comment = False
|
|
continue
|
|
if quote:
|
|
if escaped:
|
|
escaped = False
|
|
elif ch == "\\":
|
|
escaped = True
|
|
elif ch == quote:
|
|
quote = None
|
|
continue
|
|
if ch == "#":
|
|
comment = True
|
|
elif ch in ("\"", "'"):
|
|
quote = ch
|
|
elif ch == "{":
|
|
depth += 1
|
|
elif ch == "}":
|
|
depth -= 1
|
|
if depth == 0:
|
|
return pos
|
|
return None
|
|
|
|
servers = []
|
|
for match in re.finditer(r'(?m)^[ \t]*server[ \t]*\{', text):
|
|
open_pos = text.find("{", match.start(), match.end())
|
|
close_pos = matching_brace(text, open_pos)
|
|
if close_pos is None:
|
|
raise SystemExit("Could not parse nginx server block")
|
|
body = text[open_pos + 1:close_pos]
|
|
proxy_re = re.compile(r'proxy_pass\s+' + re.escape(upstream) + r'/?\s*;')
|
|
if proxy_re.search(body):
|
|
servers.append((open_pos + 1, close_pos, body))
|
|
|
|
if len(servers) != 1:
|
|
raise SystemExit(f"Expected exactly one server block proxying to {upstream}, found {len(servers)}")
|
|
|
|
body_start, body_end, body = servers[0]
|
|
locations = list(re.finditer(r'(?m)^[ \t]*location[ \t]+/[ \t]*\{', body))
|
|
if len(locations) != 1:
|
|
raise SystemExit(f"Expected exactly one general 'location /' in Mattermost server block, found {len(locations)}")
|
|
|
|
insert_pos = body_start + locations[0].start()
|
|
text = text[:insert_pos] + insert + text[insert_pos:]
|
|
config.write_text(text)
|
|
PY_EOF
|
|
if [[ $? -eq 0 ]]; then
|
|
echo_ok
|
|
NGINX_CHANGED=true
|
|
else
|
|
echo_failed
|
|
cp -a "$NGINX_BACKUP" "$NGINX_CONFIG_FILE"
|
|
fatal "Could not insert nginx location blocks. Original configuration was restored. $(cat "$log_file")"
|
|
fi
|
|
|
|
echononl "Test nginx configuration.."
|
|
if nginx -t > "$log_file" 2>&1 ; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
cp -a "$NGINX_CONFIG_FILE" "${NGINX_CONFIG_FILE}.failed-${backup_date}" 2>/dev/null
|
|
cp -a "$NGINX_BACKUP" "$NGINX_CONFIG_FILE"
|
|
nginx -t >> "$log_file" 2>&1
|
|
fatal "nginx configuration test failed. Original configuration was restored. See '${NGINX_CONFIG_FILE}.failed-${backup_date}' and '${log_file}' while this script is running."
|
|
fi
|
|
else
|
|
warn "Missing nginx location blocks were not added."
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
|
|
# ----------
|
|
# Switch stable symlink and start bridge
|
|
# ----------
|
|
|
|
blank_line
|
|
echo -e "\033[37m\033[1mActivate Mattermost OIDC Mobile Bridge..\033[m"
|
|
blank_line
|
|
|
|
echononl "Switch stable bridge symlink to '${MM_BRIDGE_NAME}-${MM_NEW_VERSION}'.."
|
|
_tmp_link="${MM_BRIDGE_LINK}.new.$$"
|
|
rm -f "$_tmp_link"
|
|
if ln -s "${MM_BRIDGE_NAME}-${MM_NEW_VERSION}" "$_tmp_link" > "$log_file" 2>&1 \
|
|
&& mv -Tf "$_tmp_link" "$MM_BRIDGE_LINK" >> "$log_file" 2>&1 ; then
|
|
SYMLINK_CHANGED=true
|
|
echo_ok
|
|
else
|
|
rm -f "$_tmp_link"
|
|
echo_failed
|
|
fatal "$(cat "$log_file")"
|
|
fi
|
|
|
|
if [[ "$NGINX_CHANGED" = true ]]; then
|
|
echononl "Reload nginx service.."
|
|
if systemctl reload nginx.service > "$log_file" 2>&1 ; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
error "nginx reload failed. Restoring the previous nginx configuration."
|
|
cp -a "$NGINX_CONFIG_FILE" "${NGINX_CONFIG_FILE}.failed-${backup_date}" 2>/dev/null || true
|
|
if cp -a "$NGINX_BACKUP" "$NGINX_CONFIG_FILE" >> "$log_file" 2>&1 && nginx -t >> "$log_file" 2>&1 && systemctl reload nginx.service >> "$log_file" 2>&1 ; then
|
|
info "Previous nginx configuration was restored and reloaded."
|
|
else
|
|
error "Could not fully restore/reload the previous nginx configuration. Check nginx manually."
|
|
fi
|
|
rollback_bridge
|
|
fatal "nginx reload failed after adding the Mattermost OIDC Mobile Bridge locations."
|
|
fi
|
|
fi
|
|
|
|
echononl "Restart Mattermost OIDC Mobile Bridge service.."
|
|
if systemctl restart "$MM_BRIDGE_SERVICE" > "$log_file" 2>&1 ; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
rollback_bridge
|
|
fatal "Failed to restart '${MM_BRIDGE_SERVICE}'."
|
|
fi
|
|
|
|
if ! bridge_test ; then
|
|
rollback_bridge
|
|
fatal "Mattermost OIDC Mobile Bridge functional test failed."
|
|
fi
|
|
|
|
if [[ -n "$NGINX_CONFIG_FILE" ]]; then
|
|
if [[ -n "$MM_SITE_URL" ]]; then
|
|
if ! nginx_e2e_test ; then
|
|
rollback_bridge
|
|
fatal "Mattermost OIDC Mobile Bridge end-to-end test through nginx failed."
|
|
fi
|
|
else
|
|
warn "Mattermost SiteURL could not be read from '${MM_CONFIG_FILE}'. End-to-end nginx tests were skipped."
|
|
fi
|
|
fi
|
|
|
|
|
|
# ----------
|
|
# Final information
|
|
# ----------
|
|
|
|
blank_line
|
|
echo -e "\033[37m\033[1mMattermost OIDC Mobile Bridge successfully installed.\033[m"
|
|
blank_line
|
|
echo " Installed version.....................: ${MM_NEW_VERSION}"
|
|
echo " Binary................................: ${MM_BRIDGE_BIN}"
|
|
echo " Symlink...............................: ${MM_BRIDGE_LINK} -> $(readlink "$MM_BRIDGE_LINK")"
|
|
echo " Source directory......................: ${MM_SOURCE_DIR}"
|
|
echo " Service...............................: ${MM_BRIDGE_SERVICE}"
|
|
if [[ -n "$NGINX_CONFIG_FILE" ]]; then
|
|
echo " nginx configuration...................: ${NGINX_CONFIG_FILE}"
|
|
fi
|
|
blank_line
|
|
|
|
clean_up 0
|