115 lines
3.2 KiB
Bash
115 lines
3.2 KiB
Bash
#!/bin/sh
|
|
# Install as root:root 0755 at /usr/local/sbin/han-message-safety-mode.
|
|
set -eu
|
|
|
|
MODE_FILE=/etc/han-chat/message-safety-mode.env
|
|
COMPOSE=/usr/local/sbin/han-vm2-compose
|
|
LOCK=/run/lock/han-message-safety-mode.lock
|
|
MODE_GROUP=han-message-safety
|
|
|
|
if [ "$#" -eq 1 ] && [ "$1" = standard ]; then
|
|
mock=false
|
|
text=false
|
|
file=false
|
|
elif [ "$#" -eq 5 ] &&
|
|
[ "$1" = mock ] &&
|
|
[ "$2" = --text-free ] &&
|
|
{ [ "$3" = true ] || [ "$3" = false ]; } &&
|
|
[ "$4" = --file-free ] &&
|
|
{ [ "$5" = true ] || [ "$5" = false ]; }; then
|
|
mock=true
|
|
text=$3
|
|
file=$5
|
|
else
|
|
echo "usage: han-message-safety-mode standard | mock --text-free true|false --file-free true|false" >&2
|
|
exit 64
|
|
fi
|
|
|
|
[ "$(id -u)" -eq 0 ] || {
|
|
echo "must run through approved sudo rule" >&2
|
|
exit 77
|
|
}
|
|
[ -x "$COMPOSE" ] || {
|
|
echo "fixed compose launcher is unavailable" >&2
|
|
exit 69
|
|
}
|
|
|
|
exec 9>"$LOCK"
|
|
/usr/bin/flock -n 9 || {
|
|
echo "another mode transition is active" >&2
|
|
exit 75
|
|
}
|
|
|
|
directory=$(dirname "$MODE_FILE")
|
|
/usr/bin/install -d -o root -g root -m 0700 "$directory"
|
|
temporary=$(/usr/bin/mktemp "$directory/.message-safety-mode.XXXXXX")
|
|
backup=$(/usr/bin/mktemp "$directory/.message-safety-mode.backup.XXXXXX")
|
|
cleanup() {
|
|
/usr/bin/rm -f "$temporary" "$backup"
|
|
}
|
|
trap cleanup EXIT HUP INT TERM
|
|
|
|
if [ -f "$MODE_FILE" ]; then
|
|
/usr/bin/cp --preserve=mode,ownership "$MODE_FILE" "$backup"
|
|
else
|
|
: >"$backup"
|
|
/usr/bin/chmod 0600 "$backup"
|
|
fi
|
|
old_mode=$(/usr/bin/awk -F= '
|
|
$1 == "MESSAGE_SAFETY_MOCK_ENABLED" {mock=$2}
|
|
$1 == "MESSAGE_SAFETY_MOCK_TEXT_FREE" {text=$2}
|
|
$1 == "MESSAGE_SAFETY_MOCK_FILE_FREE" {file=$2}
|
|
END {printf "mock=%s,text=%s,file=%s", mock, text, file}
|
|
' "$backup")
|
|
|
|
{
|
|
printf 'MESSAGE_SAFETY_MOCK_ENABLED=%s\n' "$mock"
|
|
printf 'MESSAGE_SAFETY_MOCK_TEXT_FREE=%s\n' "$text"
|
|
printf 'MESSAGE_SAFETY_MOCK_FILE_FREE=%s\n' "$file"
|
|
} >"$temporary"
|
|
/usr/bin/chown root:"$MODE_GROUP" "$temporary"
|
|
/usr/bin/chmod 0640 "$temporary"
|
|
/usr/bin/mv -fT "$temporary" "$MODE_FILE"
|
|
|
|
restart_api() {
|
|
"$COMPOSE" config --quiet &&
|
|
"$COMPOSE" up -d --no-deps --force-recreate message-safety-api
|
|
}
|
|
|
|
healthy=false
|
|
if restart_api; then
|
|
attempt=0
|
|
while [ "$attempt" -lt 30 ]; do
|
|
container=$("$COMPOSE" ps -q message-safety-api)
|
|
if [ -n "$container" ]; then
|
|
status=$(/usr/bin/docker inspect --format '{{if .State.Health}}{{.State.Health.Status}}{{else}}{{.State.Status}}{{end}}' "$container")
|
|
if [ "$status" = healthy ]; then
|
|
healthy=true
|
|
break
|
|
fi
|
|
fi
|
|
attempt=$((attempt + 1))
|
|
/usr/bin/sleep 2
|
|
done
|
|
fi
|
|
|
|
if [ "$healthy" != true ]; then
|
|
if [ -s "$backup" ]; then
|
|
/usr/bin/cp "$backup" "$temporary"
|
|
else
|
|
printf '%s\n' \
|
|
'MESSAGE_SAFETY_MOCK_ENABLED=false' \
|
|
'MESSAGE_SAFETY_MOCK_TEXT_FREE=false' \
|
|
'MESSAGE_SAFETY_MOCK_FILE_FREE=false' >"$temporary"
|
|
fi
|
|
/usr/bin/chown root:"$MODE_GROUP" "$temporary"
|
|
/usr/bin/chmod 0640 "$temporary"
|
|
/usr/bin/mv -fT "$temporary" "$MODE_FILE"
|
|
restart_api || true
|
|
/usr/bin/logger -p authpriv.err -t han-message-safety-mode "transition failed; previous policy restored"
|
|
exit 1
|
|
fi
|
|
|
|
/usr/bin/logger -p authpriv.notice -t han-message-safety-mode \
|
|
"transition succeeded old=$old_mode new=mock=$mock,text=$text,file=$file actor=${SUDO_USER:-root}"
|