Files
server/opt/psa/admin/sbin/repair_mysql_perms
cutemeli 0bfc6c8425 Initial
2025-12-22 10:32:59 +00:00

191 lines
4.0 KiB
Bash
Executable File

#!/bin/bash
### Copyright 1999-2025. WebPros International GmbH. All rights reserved.
export LC_ALL="C" PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
unset GREP_OPTIONS
umask 022
prog="`basename $0`"
action="$1"
# Communication protocol with repaird is:
# * emit output to stdout as plaintext;
# * stderr is not shown to user, but may be logged by 'repaird -v 3';
# * last line of output is JSON with any remaining output (see result() below);
# * exit code is 0.
info()
{
echo "INFO: $*"
}
warn()
{
echo "WARNING: $*"
}
err()
{
echo "ERROR: $*"
}
die()
{
err "$@" | result "failed"
exit 0
}
success()
{
echo -n | result "ok"
exit 0
}
usage()
{
echo "Usage: $prog { --check | --repair }" >&2
exit 1
}
result()
{
local status="$1"
python3 -c 'import sys, json
message = sys.stdin.read()
status = sys.argv[1] if message.strip() else "ok"
print(json.dumps({"status": status, "message": message}))
' "$status"
}
is_remote_db_feature_enabled()
{
[ -s "/etc/psa/private/dsn.ini" ]
}
get_mysql_option_value()
{
local section="$1"
local name="$2"
local default="$3"
local value="`/usr/bin/my_print_defaults "$section" | sed -n "s/^--$name=//p" | tail -n 1`"
echo "${value:-$default}"
}
get_mysql_datadir()
{
get_mysql_option_value mysqld datadir "/var/lib/mysql"
}
find_psa_shadow()
{
find /etc/psa/.psa.shadow /etc/psa/private/secret_key "$@"
}
find_mysql_datadir()
{
find "$MYSQL_DATADIR" -maxdepth 0 "$@"
}
find_mysql_dirs()
{
find "$MYSQL_DATADIR" -mindepth 1 -type d ! \( -name 'lost+found' -o -name 'lost@002bfound' \) "$@"
}
find_mysql_files()
{
find "$MYSQL_DATADIR" -mindepth 1 -type f \
! \( -name 'debian-*.flag' -o -name 'mysql_upgrade_info' -o -name 'mariadb_upgrade_info' \) "$@"
}
declare -A PERMS=(
[find_psa_shadow]=" " # Use permissions fsmng knows about
# Ideally permission changes on MySQL files should be done with stopped MySQL, but we don't
# want the procedure to require downtime, so sacrifice some degree of correctness by skipping this.
[find_mysql_dirs]=" --perms 0700 --owner mysql --group mysql --filetype directory"
[find_mysql_files]=" --perms 0660,0600 --owner mysql --group mysql --filetype file"
[find_mysql_datadir]=" --perms 0755 --owner mysql --group mysql --filetype directory"
)
permissions()
{
local operation="$1"
[ "$operation" = "--check-ac" -o "$operation" = "--set-ac" ] || die "Unknown operation: $operation"
local restorecon_opts=(-iv)
[ "$operation" = "--set-ac" ] || restorecon_opts+=(-n)
local rc=0
for finder in "${!PERMS[@]}"; do
local perms="${PERMS[$finder]}"
$finder | "$PRODUCT_ROOT_D/admin/sbin/fsmng" "$operation" - $perms 2>&1 || rc="$?"
done
if command -v restorecon >/dev/null 2>&1 && should_check_selinux "$operation"; then
for finder in "${!PERMS[@]}"; do
$finder
done | restorecon -f - "${restorecon_opts[@]}" || rc="$?"
fi
return "$rc"
}
should_check_selinux()
{
local operation="$1"
local mode="`get_selinux_mode`"
if [ "$operation" = "--check-ac" -a "$mode" = "Enforcing" ]; then
# Check only in Enforcing mode
return 0
elif [ "$operation" = "--set-ac" -a "$mode" != "Disabled" ]; then
# Repair in Enforcing or Permissive mode
return 0
fi
return 1
}
get_selinux_mode()
{
if ! command -v selinuxenabled >/dev/null 2>&1 || ! selinuxenabled; then
echo "Disabled"
elif ! command -v getenforce >/dev/null 2>&1; then
echo "Disabled"
else
getenforce || echo "Disabled"
fi
}
check()
{
! is_remote_db_feature_enabled || die "Cannot check permissions of MySQL-related files with a remote database."
permissions --check-ac | result "corrupted"
exit 0
}
repair()
{
! is_remote_db_feature_enabled || die "Cannot repair permissions of MySQL-related files with a remote database."
permissions --set-ac || die "Failed to repair some permissions of MySQL-related files."
success
}
PRODUCT_ROOT_D="/opt/psa"
MYSQL_DATADIR="`get_mysql_datadir`"
case "$action" in
--check)
check
;;
--repair)
repair
;;
*)
usage
;;
esac
# vim:ft=sh