978 lines
27 KiB
Bash
Executable File
978 lines
27 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_OIDC_RELEASE_BASE="https://github.com/server-camp/mattermost-oidc-plugin/releases/download"
|
|
MM_OIDC_PLUGIN_ID="mattermost-oidc"
|
|
MM_SOURCE_BASE="/usr/local/src/mattermost"
|
|
MM_INSTALL_DIR="/opt/mattermost"
|
|
MM_BIN="${MM_INSTALL_DIR}/bin/mattermost"
|
|
MMCTL="${MM_INSTALL_DIR}/bin/mmctl"
|
|
MM_CONFIG_FILE="${MM_INSTALL_DIR}/config/config.json"
|
|
MM_LOCAL_SOCKET="/var/tmp/mattermost_local.socket"
|
|
MM_SERVICE="mattermost.service"
|
|
MM_USER="mattermost"
|
|
MM_GROUP="mattermost"
|
|
|
|
INSTALLATION_MODE=""
|
|
MM_CURRENT_VERSION=""
|
|
MM_NEW_VERSION=""
|
|
MM_LATEST_VERSION=""
|
|
MM_MIN_SERVER_VERSION=""
|
|
MM_SERVER_VERSION=""
|
|
MM_BUNDLE=""
|
|
MM_BUNDLE_BACKUP=""
|
|
|
|
MM_ROLLBACK_BUNDLE=""
|
|
MM_PREVIOUS_PLUGIN_ENABLED=false
|
|
MM_ROLLBACK_REQUIRED=false
|
|
|
|
|
|
# ----------
|
|
# 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
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
version_ge() {
|
|
[[ "$(printf '%s\n%s\n' "$2" "$1" | sort -V | head -1)" = "$2" ]]
|
|
}
|
|
|
|
plugin_state_json() {
|
|
"$MMCTL" --local --json plugin list 2>> "$log_file"
|
|
}
|
|
|
|
installed_plugin_version() {
|
|
plugin_state_json | python3 -c '
|
|
import json, sys
|
|
plugin_id = sys.argv[1]
|
|
try:
|
|
data = json.load(sys.stdin)
|
|
except Exception:
|
|
raise SystemExit(1)
|
|
if isinstance(data, list) and len(data) == 1 and isinstance(data[0], dict):
|
|
data = data[0]
|
|
|
|
def walk(obj):
|
|
if isinstance(obj, dict):
|
|
if obj.get("id") == plugin_id and obj.get("version"):
|
|
print(obj["version"])
|
|
raise SystemExit(0)
|
|
for value in obj.values():
|
|
walk(value)
|
|
elif isinstance(obj, list):
|
|
for value in obj:
|
|
walk(value)
|
|
|
|
walk(data)
|
|
raise SystemExit(2)
|
|
' "$MM_OIDC_PLUGIN_ID"
|
|
}
|
|
|
|
plugin_is_enabled() {
|
|
plugin_state_json | python3 -c '
|
|
import json, sys
|
|
plugin_id = sys.argv[1]
|
|
try:
|
|
data = json.load(sys.stdin)
|
|
except Exception:
|
|
raise SystemExit(1)
|
|
|
|
if isinstance(data, list) and len(data) == 1 and isinstance(data[0], dict):
|
|
data = data[0]
|
|
|
|
if not isinstance(data, dict):
|
|
raise SystemExit(1)
|
|
|
|
active = data.get("active")
|
|
inactive = data.get("inactive")
|
|
|
|
if not isinstance(active, list) or not isinstance(inactive, list):
|
|
raise SystemExit(1)
|
|
|
|
for plugin in active:
|
|
if isinstance(plugin, dict) and plugin.get("id") == plugin_id:
|
|
raise SystemExit(0)
|
|
|
|
for plugin in inactive:
|
|
if isinstance(plugin, dict) and plugin.get("id") == plugin_id:
|
|
raise SystemExit(2)
|
|
|
|
raise SystemExit(1)
|
|
' "$MM_OIDC_PLUGIN_ID"
|
|
}
|
|
|
|
|
|
restore_release_bundle() {
|
|
if [[ -n "$MM_BUNDLE_BACKUP" && -f "$MM_BUNDLE_BACKUP" ]]; then
|
|
rm -f "$MM_BUNDLE"
|
|
if mv "$MM_BUNDLE_BACKUP" "$MM_BUNDLE" > "$log_file" 2>&1 ; then
|
|
MM_BUNDLE_BACKUP=""
|
|
return 0
|
|
fi
|
|
return 1
|
|
fi
|
|
|
|
rm -f "$MM_BUNDLE"
|
|
return 0
|
|
}
|
|
|
|
|
|
cleanup_prepared_bundles() {
|
|
if [[ -n "$MM_ROLLBACK_BUNDLE" ]]; then
|
|
rm -f "$MM_ROLLBACK_BUNDLE"
|
|
fi
|
|
|
|
restore_release_bundle
|
|
}
|
|
|
|
|
|
rollback_plugin() {
|
|
local rollback_failed=false
|
|
local restore_command_failed=false
|
|
local _rollback_version=""
|
|
local _rollback_rc
|
|
local _plugin_enabled_rc
|
|
|
|
blank_line
|
|
warn "Mattermost OIDC Plugin installation failed. Trying to restore the previous plugin state."
|
|
|
|
if [[ "$INSTALLATION_MODE" = "upgrade" ]]; then
|
|
echononl "Restore Mattermost OIDC Plugin ${MM_CURRENT_VERSION}.."
|
|
if [[ -f "$MM_ROLLBACK_BUNDLE" ]] &&
|
|
"$MMCTL" --local plugin add --force "$MM_ROLLBACK_BUNDLE" > "$log_file" 2>&1 ; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
restore_command_failed=true
|
|
fi
|
|
|
|
if $MM_PREVIOUS_PLUGIN_ENABLED ; then
|
|
echononl "Restore previous plugin state 'enabled'.."
|
|
if "$MMCTL" --local plugin enable "$MM_OIDC_PLUGIN_ID" > "$log_file" 2>&1 ; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
restore_command_failed=true
|
|
fi
|
|
else
|
|
echononl "Restore previous plugin state 'disabled'.."
|
|
if "$MMCTL" --local plugin disable "$MM_OIDC_PLUGIN_ID" > "$log_file" 2>&1 ; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
restore_command_failed=true
|
|
fi
|
|
fi
|
|
|
|
echononl "Verify restored plugin version '${MM_CURRENT_VERSION}'.."
|
|
_rollback_version="$(installed_plugin_version 2>/dev/null)"
|
|
if [[ "$_rollback_version" = "$MM_CURRENT_VERSION" ]]; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
rollback_failed=true
|
|
fi
|
|
|
|
echononl "Verify restored plugin state.."
|
|
plugin_is_enabled
|
|
_plugin_enabled_rc=$?
|
|
if $MM_PREVIOUS_PLUGIN_ENABLED ; then
|
|
if [[ $_plugin_enabled_rc -eq 0 ]]; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
rollback_failed=true
|
|
fi
|
|
else
|
|
if [[ $_plugin_enabled_rc -eq 2 ]]; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
rollback_failed=true
|
|
fi
|
|
fi
|
|
|
|
elif [[ "$INSTALLATION_MODE" = "initial-installation" ]]; then
|
|
installed_plugin_version > /dev/null 2>&1
|
|
_rollback_rc=$?
|
|
|
|
echononl "Remove newly installed Mattermost OIDC Plugin.."
|
|
if [[ $_rollback_rc -eq 2 ]]; then
|
|
echo_ok
|
|
elif [[ $_rollback_rc -eq 0 ]]; then
|
|
if "$MMCTL" --local plugin delete "$MM_OIDC_PLUGIN_ID" > "$log_file" 2>&1 ; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
restore_command_failed=true
|
|
fi
|
|
else
|
|
echo_failed
|
|
restore_command_failed=true
|
|
fi
|
|
|
|
echononl "Verify Mattermost OIDC Plugin was removed.."
|
|
installed_plugin_version > /dev/null 2>&1
|
|
_rollback_rc=$?
|
|
if [[ $_rollback_rc -eq 2 ]]; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
rollback_failed=true
|
|
fi
|
|
else
|
|
rollback_failed=true
|
|
fi
|
|
|
|
if $rollback_failed ; then
|
|
error "Automatic plugin rollback could not fully restore the previous state."
|
|
return 1
|
|
fi
|
|
|
|
if $restore_command_failed ; then
|
|
warn "One or more rollback commands reported an error, but the previous plugin state was successfully verified."
|
|
fi
|
|
|
|
info "Previous Mattermost OIDC Plugin state was successfully restored."
|
|
return 0
|
|
}
|
|
|
|
|
|
fatal_with_plugin_rollback() {
|
|
local failure_message="$1"
|
|
|
|
if $MM_ROLLBACK_REQUIRED ; then
|
|
if rollback_plugin ; then
|
|
MM_ROLLBACK_REQUIRED=false
|
|
|
|
if [[ -n "$MM_ROLLBACK_BUNDLE" && -f "$MM_ROLLBACK_BUNDLE" ]]; then
|
|
echononl "Remove temporary rollback bundle.."
|
|
if rm -f "$MM_ROLLBACK_BUNDLE" > "$log_file" 2>&1 ; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
warn "Plugin rollback was successful, but temporary rollback bundle '${MM_ROLLBACK_BUNDLE}' could not be removed."
|
|
fi
|
|
fi
|
|
|
|
if [[ -n "$MM_BUNDLE_BACKUP" && -f "$MM_BUNDLE_BACKUP" ]]; then
|
|
echononl "Remove previous release bundle backup.."
|
|
if rm -f "$MM_BUNDLE_BACKUP" > "$log_file" 2>&1 ; then
|
|
MM_BUNDLE_BACKUP=""
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
warn "Plugin rollback was successful, but previous release bundle backup '${MM_BUNDLE_BACKUP}' could not be removed."
|
|
fi
|
|
fi
|
|
|
|
fatal "${failure_message} The previous plugin state was successfully restored."
|
|
else
|
|
fatal "${failure_message} Automatic rollback could not fully restore the previous state. Manual intervention is required."
|
|
fi
|
|
fi
|
|
|
|
fatal "$failure_message"
|
|
}
|
|
|
|
|
|
handle_signal() {
|
|
trap - SIGHUP SIGINT SIGTERM
|
|
|
|
blank_line
|
|
warn "Installation interrupted by signal."
|
|
|
|
if $MM_ROLLBACK_REQUIRED ; then
|
|
if rollback_plugin ; then
|
|
MM_ROLLBACK_REQUIRED=false
|
|
|
|
cleanup_prepared_bundles ||
|
|
warn "Plugin rollback was successful, but previous release bundle state could not be fully restored."
|
|
else
|
|
error "Automatic rollback could not fully restore the previous plugin state. Manual intervention is required."
|
|
fi
|
|
else
|
|
cleanup_prepared_bundles ||
|
|
warn "Could not fully restore previous release bundle state."
|
|
fi
|
|
|
|
clean_up 1
|
|
}
|
|
|
|
|
|
# ----------
|
|
# Jobhandling
|
|
# ----------
|
|
|
|
trap 'handle_signal' 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 curl tar awk grep sed sort python3 systemctl stat uname mv cp mkdir ; 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 binary.."
|
|
if [[ -x "$MM_BIN" ]]; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
fatal "Mattermost binary '${MM_BIN}' was not found."
|
|
fi
|
|
|
|
echononl "Check mmctl binary.."
|
|
if [[ -x "$MMCTL" ]]; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
fatal "mmctl binary '${MMCTL}' was not found."
|
|
fi
|
|
|
|
echononl "Check Mattermost service '${MM_SERVICE}'.."
|
|
if systemctl is-active --quiet "$MM_SERVICE" ; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
fatal "Mattermost service '${MM_SERVICE}' is not active."
|
|
fi
|
|
|
|
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 configuration '${MM_CONFIG_FILE}'.."
|
|
if [[ -r "$MM_CONFIG_FILE" ]]; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
fatal "Mattermost configuration '${MM_CONFIG_FILE}' is not readable."
|
|
fi
|
|
|
|
echononl "Check Mattermost Local Mode configuration.."
|
|
_local_data="$(python3 - "$MM_CONFIG_FILE" <<'PY_EOF'
|
|
import json, sys
|
|
with open(sys.argv[1], encoding="utf-8") as f:
|
|
data = json.load(f)
|
|
s = data.get("ServiceSettings", {})
|
|
print("true" if s.get("EnableLocalMode") is True else "false")
|
|
print(s.get("LocalModeSocketLocation") or "/var/tmp/mattermost_local.socket")
|
|
PY_EOF
|
|
)" || {
|
|
echo_failed
|
|
fatal "Could not parse '${MM_CONFIG_FILE}'."
|
|
}
|
|
_local_enabled="$(printf '%s\n' "$_local_data" | sed -n '1p')"
|
|
_local_socket="$(printf '%s\n' "$_local_data" | sed -n '2p')"
|
|
if [[ "$_local_enabled" = "true" ]]; then
|
|
MM_LOCAL_SOCKET="$_local_socket"
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
fatal "Mattermost Local Mode is disabled. Set ServiceSettings.EnableLocalMode to true and restart Mattermost first."
|
|
fi
|
|
|
|
echononl "Check Mattermost Local Mode socket '${MM_LOCAL_SOCKET}'.."
|
|
if [[ -S "$MM_LOCAL_SOCKET" ]]; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
fatal "Mattermost Local Mode socket '${MM_LOCAL_SOCKET}' does not exist."
|
|
fi
|
|
|
|
echononl "Test mmctl Local Mode connection.."
|
|
if "$MMCTL" --local plugin list > "$log_file" 2>&1 ; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
fatal "mmctl Local Mode connection failed. $(cat "$log_file")"
|
|
fi
|
|
|
|
echononl "Check Mattermost plugin configuration.."
|
|
_plugin_settings="$(python3 - "$MM_CONFIG_FILE" <<'PY_EOF'
|
|
import json, sys
|
|
with open(sys.argv[1], encoding="utf-8") as f:
|
|
data = json.load(f)
|
|
s = data.get("PluginSettings", {})
|
|
print("true" if s.get("Enable") is True else "false")
|
|
print("true" if s.get("EnableUploads") is True else "false")
|
|
PY_EOF
|
|
)" || {
|
|
echo_failed
|
|
fatal "Could not parse Mattermost plugin settings in '${MM_CONFIG_FILE}'."
|
|
}
|
|
|
|
_plugins_enabled="$(printf '%s\n' "$_plugin_settings" | sed -n '1p')"
|
|
_plugin_uploads_enabled="$(printf '%s\n' "$_plugin_settings" | sed -n '2p')"
|
|
|
|
if [[ "$_plugins_enabled" != "true" ]]; then
|
|
echo_failed
|
|
fatal "Mattermost plugins are disabled. Set PluginSettings.Enable to true and restart Mattermost first."
|
|
elif [[ "$_plugin_uploads_enabled" != "true" ]]; then
|
|
echo_failed
|
|
fatal "Mattermost plugin uploads are disabled. Set PluginSettings.EnableUploads to true and restart Mattermost first."
|
|
else
|
|
echo_ok
|
|
fi
|
|
|
|
MM_SERVER_VERSION="$("$MM_BIN" version 2>/dev/null | awk -F': ' '$1 == "Version" {print $2; exit}')"
|
|
[[ -n "$MM_SERVER_VERSION" ]] || fatal "Could not determine installed Mattermost version."
|
|
|
|
|
|
# ----------
|
|
# Detect installation mode
|
|
# ----------
|
|
|
|
echononl "Detect existing Mattermost OIDC plugin installation.."
|
|
MM_CURRENT_VERSION="$(installed_plugin_version 2>/dev/null)"
|
|
_plugin_version_rc=$?
|
|
if [[ $_plugin_version_rc -eq 0 && -n "$MM_CURRENT_VERSION" ]]; then
|
|
INSTALLATION_MODE="upgrade"
|
|
plugin_is_enabled
|
|
_plugin_enabled_rc=$?
|
|
if [[ $_plugin_enabled_rc -eq 0 ]]; then
|
|
MM_PREVIOUS_PLUGIN_ENABLED=true
|
|
elif [[ $_plugin_enabled_rc -eq 2 ]]; then
|
|
MM_PREVIOUS_PLUGIN_ENABLED=false
|
|
else
|
|
echo_failed
|
|
fatal "Could not determine whether Mattermost OIDC Plugin '${MM_OIDC_PLUGIN_ID}' is enabled or disabled."
|
|
fi
|
|
echo_ok
|
|
elif [[ $_plugin_version_rc -eq 2 ]]; then
|
|
INSTALLATION_MODE="initial-installation"
|
|
MM_CURRENT_VERSION=""
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
fatal "Could not determine current Mattermost OIDC plugin state."
|
|
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"
|
|
else
|
|
echo " Installation mode....................: Upgrade"
|
|
echo " Currently installed version.........: ${MM_CURRENT_VERSION}"
|
|
fi
|
|
echo " Installed Mattermost version........: ${MM_SERVER_VERSION}"
|
|
echo " Latest stable OIDC version..........: ${MM_LATEST_VERSION}"
|
|
blank_line
|
|
|
|
while true ; do
|
|
echononl "New Mattermost OIDC Plugin 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 Plugin ${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_BUNDLE="${MM_SOURCE_BASE}/mattermost-oidc-${MM_NEW_VERSION}.tar.gz"
|
|
|
|
|
|
# ----------
|
|
# Summary
|
|
# ----------
|
|
|
|
blank_line
|
|
echo -e "\033[37m\033[1mMattermost OIDC Plugin installation settings:\033[m"
|
|
blank_line
|
|
echo " Installation mode....................: ${INSTALLATION_MODE}"
|
|
[[ -n "$MM_CURRENT_VERSION" ]] && echo " Current plugin version...............: ${MM_CURRENT_VERSION}"
|
|
echo " New plugin version...................: ${MM_NEW_VERSION}"
|
|
echo " Latest stable version...............: ${MM_LATEST_VERSION}"
|
|
echo " Installed Mattermost version........: ${MM_SERVER_VERSION}"
|
|
echo " Repository...........................: ${MM_OIDC_REPOSITORY}"
|
|
echo " Release bundle.......................: ${MM_BUNDLE}"
|
|
echo " Plugin ID............................: ${MM_OIDC_PLUGIN_ID}"
|
|
echo " Local Mode socket....................: ${MM_LOCAL_SOCKET}"
|
|
blank_line
|
|
|
|
if ! ask_yes_no "einverstanden" "no" ; then
|
|
fatal "Stopped by user"
|
|
fi
|
|
|
|
|
|
# ----------
|
|
# Prepare source directory
|
|
# ----------
|
|
|
|
blank_line
|
|
|
|
# ----------
|
|
# Download release bundle
|
|
# ----------
|
|
|
|
blank_line
|
|
echo -e "\033[37m\033[1mPrepare Mattermost OIDC Plugin release bundle..\033[m"
|
|
blank_line
|
|
|
|
echononl "Create source directory '${MM_SOURCE_BASE}'.."
|
|
if mkdir -p "$MM_SOURCE_BASE" > "$log_file" 2>&1 ; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
fatal "$(cat "$log_file")"
|
|
fi
|
|
|
|
if [[ -e "$MM_BUNDLE" ]]; then
|
|
MM_BUNDLE_BACKUP="${MM_BUNDLE}.${backup_date}"
|
|
echononl "Backup existing release bundle.."
|
|
if mv "$MM_BUNDLE" "$MM_BUNDLE_BACKUP" > "$log_file" 2>&1 ; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
fatal "$(cat "$log_file")"
|
|
fi
|
|
else
|
|
echononl "Backup existing release bundle.."
|
|
echo_skipped
|
|
fi
|
|
|
|
echononl "Download Mattermost OIDC Plugin ${MM_NEW_VERSION}.."
|
|
_release_url="${MM_OIDC_RELEASE_BASE}/v${MM_NEW_VERSION}/mattermost-oidc-${MM_NEW_VERSION}.tar.gz"
|
|
if curl -fL --retry 2 --connect-timeout 15 -o "$MM_BUNDLE" "$_release_url" > "$log_file" 2>&1 ; then
|
|
echo_ok
|
|
else
|
|
_download_error="$(cat "$log_file")"
|
|
echo_failed
|
|
restore_release_bundle || warn "Could not restore previous release bundle."
|
|
fatal "Could not download '${_release_url}'. ${_download_error}"
|
|
fi
|
|
|
|
echononl "Check release bundle archive.."
|
|
if tar tzf "$MM_BUNDLE" > "$log_file" 2>&1 ; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
restore_release_bundle || warn "Could not restore previous release bundle."
|
|
fatal "Downloaded release bundle is not a valid gzip-compressed tar archive."
|
|
fi
|
|
|
|
echononl "Read and verify plugin metadata.."
|
|
_plugin_json="$(tar xOf "$MM_BUNDLE" mattermost-oidc/plugin.json 2> "$log_file")" || {
|
|
echo_failed
|
|
restore_release_bundle || warn "Could not restore previous release bundle."
|
|
fatal "Could not read mattermost-oidc/plugin.json from release bundle."
|
|
}
|
|
_metadata="$(printf '%s' "$_plugin_json" | python3 -c '
|
|
import json, sys
|
|
expected_id, expected_version = sys.argv[1:3]
|
|
try:
|
|
data = json.load(sys.stdin)
|
|
except Exception:
|
|
raise SystemExit(1)
|
|
if data.get("id") != expected_id:
|
|
raise SystemExit(2)
|
|
if data.get("version") != expected_version:
|
|
raise SystemExit(3)
|
|
print(data.get("min_server_version", ""))
|
|
' "$MM_OIDC_PLUGIN_ID" "$MM_NEW_VERSION")"
|
|
_metadata_rc=$?
|
|
if [[ $_metadata_rc -eq 0 ]]; then
|
|
MM_MIN_SERVER_VERSION="$_metadata"
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
restore_release_bundle || warn "Could not restore previous release bundle."
|
|
fatal "Plugin metadata does not match expected ID '${MM_OIDC_PLUGIN_ID}' and version '${MM_NEW_VERSION}'."
|
|
fi
|
|
|
|
if [[ -n "$MM_MIN_SERVER_VERSION" ]]; then
|
|
echononl "Check Mattermost version (installed: ${MM_SERVER_VERSION}, required: ${MM_MIN_SERVER_VERSION}).."
|
|
if version_ge "$MM_SERVER_VERSION" "$MM_MIN_SERVER_VERSION" ; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
restore_release_bundle || warn "Could not restore previous release bundle."
|
|
fatal "Mattermost ${MM_NEW_VERSION} requires Mattermost ${MM_MIN_SERVER_VERSION} or newer. Installed version is ${MM_SERVER_VERSION}."
|
|
fi
|
|
fi
|
|
|
|
_arch="$(uname -m)"
|
|
case "$_arch" in
|
|
x86_64|amd64) _bundle_arch="amd64" ;;
|
|
aarch64|arm64) _bundle_arch="arm64" ;;
|
|
*)
|
|
restore_release_bundle || warn "Could not restore previous release bundle."
|
|
fatal "Unsupported system architecture '${_arch}'."
|
|
;;
|
|
esac
|
|
|
|
echononl "Check Linux server binary for architecture '${_bundle_arch}'.."
|
|
if tar tzf "$MM_BUNDLE" | grep -qx "mattermost-oidc/server/dist/plugin-linux-${_bundle_arch}" ; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
restore_release_bundle || warn "Could not restore previous release bundle."
|
|
fatal "Release bundle does not contain plugin-linux-${_bundle_arch}."
|
|
fi
|
|
|
|
|
|
# ----------
|
|
# Prepare rollback bundle
|
|
# ----------
|
|
|
|
if [[ "$INSTALLATION_MODE" = "upgrade" ]]; then
|
|
MM_ROLLBACK_BUNDLE="${MM_SOURCE_BASE}/mattermost-oidc-${MM_CURRENT_VERSION}.rollback-${backup_date}.tar.gz"
|
|
|
|
blank_line
|
|
echo -e "\033[37m\033[1mPrepare Mattermost OIDC Plugin rollback bundle..\033[m"
|
|
blank_line
|
|
|
|
echononl "Download rollback bundle for Mattermost OIDC Plugin ${MM_CURRENT_VERSION}.."
|
|
_rollback_url="${MM_OIDC_RELEASE_BASE}/v${MM_CURRENT_VERSION}/mattermost-oidc-${MM_CURRENT_VERSION}.tar.gz"
|
|
if curl -fL --retry 2 --connect-timeout 15 -o "$MM_ROLLBACK_BUNDLE" "$_rollback_url" > "$log_file" 2>&1 ; then
|
|
echo_ok
|
|
else
|
|
_rollback_download_error="$(cat "$log_file")"
|
|
echo_failed
|
|
cleanup_prepared_bundles || warn "Could not fully restore previous release bundle state."
|
|
fatal "Could not prepare rollback bundle '${_rollback_url}'. No changes were made to the installed plugin. ${_rollback_download_error}"
|
|
fi
|
|
|
|
echononl "Check rollback bundle archive.."
|
|
if tar tzf "$MM_ROLLBACK_BUNDLE" > "$log_file" 2>&1 ; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
cleanup_prepared_bundles || warn "Could not fully restore previous release bundle state."
|
|
fatal "Rollback bundle for version '${MM_CURRENT_VERSION}' is not a valid gzip-compressed tar archive."
|
|
fi
|
|
|
|
echononl "Verify rollback bundle metadata.."
|
|
_rollback_plugin_json="$(tar xOf "$MM_ROLLBACK_BUNDLE" mattermost-oidc/plugin.json 2> "$log_file")" || {
|
|
echo_failed
|
|
cleanup_prepared_bundles || warn "Could not fully restore previous release bundle state."
|
|
fatal "Could not read plugin metadata from rollback bundle."
|
|
}
|
|
|
|
if printf '%s' "$_rollback_plugin_json" | python3 -c '
|
|
import json, sys
|
|
expected_id, expected_version = sys.argv[1:3]
|
|
try:
|
|
data = json.load(sys.stdin)
|
|
except Exception:
|
|
raise SystemExit(1)
|
|
if data.get("id") != expected_id or data.get("version") != expected_version:
|
|
raise SystemExit(1)
|
|
' "$MM_OIDC_PLUGIN_ID" "$MM_CURRENT_VERSION" ; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
cleanup_prepared_bundles || warn "Could not fully restore previous release bundle state."
|
|
fatal "Rollback bundle metadata does not match plugin '${MM_OIDC_PLUGIN_ID}' version '${MM_CURRENT_VERSION}'."
|
|
fi
|
|
fi
|
|
|
|
|
|
|
|
# ----------
|
|
# Install/upgrade plugin
|
|
# ----------
|
|
|
|
blank_line
|
|
echo -e "\033[37m\033[1mInstall Mattermost OIDC Plugin..\033[m"
|
|
blank_line
|
|
|
|
echononl "Install Mattermost OIDC Plugin ${MM_NEW_VERSION}.."
|
|
MM_ROLLBACK_REQUIRED=true
|
|
if "$MMCTL" --local plugin add --force "$MM_BUNDLE" > "$log_file" 2>&1 ; then
|
|
echo_ok
|
|
else
|
|
_install_error="$(cat "$log_file")"
|
|
echo_failed
|
|
fatal_with_plugin_rollback "Plugin installation failed. ${_install_error}"
|
|
fi
|
|
|
|
echononl "Enable Mattermost OIDC Plugin '${MM_OIDC_PLUGIN_ID}'.."
|
|
if "$MMCTL" --local plugin enable "$MM_OIDC_PLUGIN_ID" > "$log_file" 2>&1 ; then
|
|
echo_ok
|
|
else
|
|
_enable_error="$(cat "$log_file")"
|
|
echo_failed
|
|
fatal_with_plugin_rollback "Plugin was installed but could not be enabled. ${_enable_error}"
|
|
fi
|
|
|
|
|
|
# ----------
|
|
# Verify installation
|
|
# ----------
|
|
|
|
blank_line
|
|
echo -e "\033[37m\033[1mVerify Mattermost OIDC Plugin installation..\033[m"
|
|
blank_line
|
|
|
|
sleep 1
|
|
|
|
echononl "Verify installed plugin version '${MM_NEW_VERSION}'.."
|
|
_verified_version="$(installed_plugin_version 2>/dev/null)"
|
|
if [[ "$_verified_version" = "$MM_NEW_VERSION" ]]; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
fatal_with_plugin_rollback "Installed plugin version is '${_verified_version:-unknown}', expected '${MM_NEW_VERSION}'."
|
|
fi
|
|
|
|
echononl "Verify plugin is enabled.."
|
|
plugin_is_enabled
|
|
_plugin_enabled_rc=$?
|
|
if [[ $_plugin_enabled_rc -eq 0 ]]; then
|
|
echo_ok
|
|
MM_ROLLBACK_REQUIRED=false
|
|
elif [[ $_plugin_enabled_rc -eq 2 ]]; then
|
|
echo_failed
|
|
fatal_with_plugin_rollback "Plugin '${MM_OIDC_PLUGIN_ID}' is installed but not enabled."
|
|
else
|
|
echo_failed
|
|
fatal_with_plugin_rollback "Could not determine whether Mattermost OIDC Plugin '${MM_OIDC_PLUGIN_ID}' is enabled."
|
|
fi
|
|
|
|
|
|
if [[ -n "$MM_ROLLBACK_BUNDLE" && -f "$MM_ROLLBACK_BUNDLE" ]]; then
|
|
echononl "Remove temporary rollback bundle.."
|
|
if rm -f "$MM_ROLLBACK_BUNDLE" > "$log_file" 2>&1 ; then
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
warn "Mattermost OIDC Plugin was successfully installed, but temporary rollback bundle '${MM_ROLLBACK_BUNDLE}' could not be removed."
|
|
fi
|
|
fi
|
|
|
|
|
|
if [[ -n "$MM_BUNDLE_BACKUP" && -f "$MM_BUNDLE_BACKUP" ]]; then
|
|
echononl "Remove previous release bundle backup.."
|
|
if rm -f "$MM_BUNDLE_BACKUP" > "$log_file" 2>&1 ; then
|
|
MM_BUNDLE_BACKUP=""
|
|
echo_ok
|
|
else
|
|
echo_failed
|
|
warn "Mattermost OIDC Plugin was successfully installed, but previous release bundle backup '${MM_BUNDLE_BACKUP}' could not be removed."
|
|
fi
|
|
fi
|
|
|
|
|
|
# ----------
|
|
# Final information
|
|
# ----------
|
|
|
|
blank_line
|
|
echo -e "\033[37m\033[1mMattermost OIDC Plugin successfully installed.\033[m"
|
|
blank_line
|
|
echo " Installed version.....................: ${MM_NEW_VERSION}"
|
|
echo " Plugin ID.............................: ${MM_OIDC_PLUGIN_ID}"
|
|
echo " Release bundle........................: ${MM_BUNDLE}"
|
|
echo " Mattermost version....................: ${MM_SERVER_VERSION}"
|
|
echo " Minimum Mattermost version............: ${MM_MIN_SERVER_VERSION:-not specified}"
|
|
echo " Status................................: enabled"
|
|
blank_line
|
|
|
|
clean_up 0
|