From 7974491e93d1744fcdc277555051b0405fb65617 Mon Sep 17 00:00:00 2001 From: Matteo Date: Tue, 17 Mar 2026 15:18:35 +0100 Subject: [PATCH] feat : sudoers bug (WIP) --- RebuildBdd/Checkup/check-postgresql.sh | 18 ++++--- RebuildBdd/Checkup/check-target-readiness.sh | 42 +++++++-------- RebuildBdd/bootstrap-target-host.sh | 56 ++++++++++++++------ 3 files changed, 70 insertions(+), 46 deletions(-) diff --git a/RebuildBdd/Checkup/check-postgresql.sh b/RebuildBdd/Checkup/check-postgresql.sh index 2d9feee..faac0a0 100755 --- a/RebuildBdd/Checkup/check-postgresql.sh +++ b/RebuildBdd/Checkup/check-postgresql.sh @@ -70,8 +70,12 @@ if ! require_cmd "$SUDO_BIN"; then fail "sudo absent sur la cible" fi -if ! "$SUDO_BIN" -n /usr/bin/true >/dev/null 2>&1; then - fail "sudo non interactif indisponible pour l'utilisateur courant" +if ! "$SUDO_BIN" -n /usr/bin/systemctl --version >/dev/null 2>&1; then + fail "sudo non interactif indisponible pour systemctl" +fi + +if ! "$SUDO_BIN" -n -u postgres /usr/bin/psql -d postgres -c "SELECT 1;" >/dev/null 2>&1; then + fail "sudo -n -u postgres indisponible" fi if [[ ! "$PGPORT" =~ ^[0-9]+$ ]]; then @@ -101,20 +105,20 @@ fi log "Vérification de la disponibilité de PostgreSQL..." for _ in {1..20}; do - if "$SUDO_BIN" -n -u postgres /usr/bin/psql -d postgres -c "SELECT 1;" >/dev/null 2>&1; then + if "$SUDO_BIN" -n -u postgres psql -d postgres -c "SELECT 1;" >/dev/null 2>&1; then log "PostgreSQL répond correctement." break fi sleep 1 done -if ! "$SUDO_BIN" -n -u postgres /usr/bin/psql -d postgres -c "SELECT 1;" >/dev/null 2>&1; then - fail "PostgreSQL ne répond pas correctement ou sudo -u postgres n'autorise pas psql" +if ! "$SUDO_BIN" -n -u postgres psql -d postgres -c "SELECT 1;" >/dev/null 2>&1; then + fail "PostgreSQL ne répond pas correctement" fi if [[ "${AUTO_CREATE_PGUSER,,}" == "yes" ]]; then ROLE_EXISTS="$( - "$SUDO_BIN" -n -u postgres /usr/bin/psql -d postgres -tAc \ + "$SUDO_BIN" -n -u postgres psql -d postgres -tAc \ "SELECT 1 FROM pg_roles WHERE rolname='${PGUSER//\'/\'\'}'" 2>/dev/null || true )" @@ -126,7 +130,7 @@ if [[ "${AUTO_CREATE_PGUSER,,}" == "yes" ]]; then ROLE_ATTRIBUTES="LOGIN SUPERUSER CREATEDB CREATEROLE" fi - "$SUDO_BIN" -n -u postgres /usr/bin/psql -d postgres -c \ + "$SUDO_BIN" -n -u postgres psql -d postgres -c \ "CREATE ROLE \"${PGUSER}\" WITH ${ROLE_ATTRIBUTES} PASSWORD '${PGPASSWORD//\'/\'\'}';" \ >/dev/null 2>&1 || fail "échec de création du rôle ${PGUSER}" diff --git a/RebuildBdd/Checkup/check-target-readiness.sh b/RebuildBdd/Checkup/check-target-readiness.sh index e9f0d70..0bc61e8 100755 --- a/RebuildBdd/Checkup/check-target-readiness.sh +++ b/RebuildBdd/Checkup/check-target-readiness.sh @@ -3,6 +3,9 @@ set -euo pipefail ############################################################################### # check-target-readiness.sh +# +# Prépare la machine cible pour permettre l'exécution non interactive du +# script de rebuild depuis une interface web. ############################################################################### SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" @@ -116,6 +119,8 @@ validate_env_values() { [[ -n "$BACKUP_REMOTE_HOST" ]] || fail "BACKUP_REMOTE_HOST vide" [[ -n "$BACKUP_REMOTE_USER" ]] || fail "BACKUP_REMOTE_USER vide" [[ -n "$BACKUP_REMOTE_DIR" ]] || fail "BACKUP_REMOTE_DIR vide" + BACKUP_REMOTE_SSH_PORT="${BACKUP_REMOTE_SSH_PORT:-22}" + [[ "$BACKUP_REMOTE_SSH_PORT" =~ ^[0-9]+$ ]] || fail "BACKUP_REMOTE_SSH_PORT invalide" } prepare_log_file() { @@ -170,32 +175,26 @@ prepare_ssh_key() { mkdir -p "$key_dir" || fail "impossible de créer le dossier SSH : $key_dir" chmod 700 "$key_dir" || fail "impossible de chmod 700 sur $key_dir" - if [[ ! -f "$SSH_KEY" ]]; then - log "Clé SSH absente : génération de ${SSH_KEY}" - ssh-keygen -t ed25519 -N "" -f "$SSH_KEY" >/dev/null 2>&1 || \ - fail "impossible de générer la clé SSH" - fi - + [[ -f "$SSH_KEY" ]] || fail "clé SSH absente : $SSH_KEY" chmod 600 "$SSH_KEY" || fail "impossible de chmod 600 sur la clé privée" - [[ -f "${SSH_KEY}.pub" ]] || fail "clé publique absente : ${SSH_KEY}.pub" - chmod 644 "${SSH_KEY}.pub" || fail "impossible de chmod 644 sur la clé publique" + [[ -f "${SSH_KEY}.pub" ]] || log "clé publique absente : ${SSH_KEY}.pub" + [[ ! -f "${SSH_KEY}.pub" ]] || chmod 644 "${SSH_KEY}.pub" || fail "impossible de chmod 644 sur la clé publique" log "Clé SSH prête." } prepare_known_hosts() { - local ssh_dir known_hosts ssh_port + local ssh_dir known_hosts ssh_dir="$(dirname "$SSH_KEY")" known_hosts="${ssh_dir}/known_hosts" - ssh_port="${BACKUP_REMOTE_SSH_PORT:-22}" touch "$known_hosts" || fail "impossible de créer known_hosts" chmod 644 "$known_hosts" || fail "impossible de chmod 644 sur known_hosts" if ! ssh-keygen -F "$BACKUP_REMOTE_HOST" -f "$known_hosts" >/dev/null 2>&1; then - log "Ajout de ${BACKUP_REMOTE_HOST}:${ssh_port} à known_hosts" - ssh-keyscan -p "$ssh_port" -H "$BACKUP_REMOTE_HOST" >>"$known_hosts" 2>/dev/null || \ + log "Ajout de ${BACKUP_REMOTE_HOST}:${BACKUP_REMOTE_SSH_PORT} à known_hosts" + ssh-keyscan -p "$BACKUP_REMOTE_SSH_PORT" -H "$BACKUP_REMOTE_HOST" >>"$known_hosts" 2>/dev/null || \ fail "échec de récupération de la clé hôte pour ${BACKUP_REMOTE_HOST}" else log "Host déjà présent dans known_hosts." @@ -203,13 +202,12 @@ prepare_known_hosts() { } test_backup_ssh() { - local ssh_port ssh_timeout - ssh_port="${BACKUP_REMOTE_SSH_PORT:-22}" + local ssh_timeout ssh_timeout="${SSH_CONNECT_TIMEOUT:-8}" ssh \ -i "$SSH_KEY" \ - -p "$ssh_port" \ + -p "$BACKUP_REMOTE_SSH_PORT" \ -o IdentitiesOnly=yes \ -o BatchMode=yes \ -o ConnectTimeout="$ssh_timeout" \ @@ -231,7 +229,7 @@ install_sudoers_if_allowed() { return 0 fi - if ! sudo -n /usr/bin/true >/dev/null 2>&1; then + if ! sudo -n true >/dev/null 2>&1; then fail "AUTO_CONFIGURE_SUDOERS=yes mais sudo -n n'est pas disponible ; configuration initiale manuelle requise" fi @@ -241,8 +239,8 @@ install_sudoers_if_allowed() { tmp_file="$(mktemp)" cat >"$tmp_file" </dev/null 2>&1 || \ - fail "sudo non interactif root indisponible pour ${USER}" - - sudo -n -u postgres /usr/bin/psql -d postgres -c 'SELECT 1;' >/dev/null 2>&1 || \ - fail "sudo -n -u postgres indisponible pour psql pour ${USER}" + sudo -n true >/dev/null 2>&1 || \ + fail "sudo non interactif indisponible pour ${USER}" log "sudo non interactif validé." } @@ -283,6 +278,7 @@ run_postgresql_check() { --non-interactive \ >>"$LOG_FILE" 2>&1 || fail "échec de préparation PostgreSQL" + sudo -n -u postgres true >/dev/null 2>&1 || fail "sudo -n -u postgres indisponible après préparation PostgreSQL" log "Préparation PostgreSQL validée." } diff --git a/RebuildBdd/bootstrap-target-host.sh b/RebuildBdd/bootstrap-target-host.sh index 851d587..4abae51 100755 --- a/RebuildBdd/bootstrap-target-host.sh +++ b/RebuildBdd/bootstrap-target-host.sh @@ -102,6 +102,38 @@ cleanup() { } trap cleanup EXIT +copy_file_to_remote_via_ssh() { + local local_file="$1" + local remote_final_path="$2" + local remote_mode="$3" + local remote_parent + local remote_tmp + + [[ -f "$local_file" ]] || fail "fichier source introuvable : $local_file" + [[ -r "$local_file" ]] || fail "fichier source non lisible : $local_file" + + remote_parent="$(dirname "$remote_final_path")" + remote_tmp="/tmp/bootstrap_copy.$$.$RANDOM.tmp" + + ssh "${SSH_OPTS[@]}" "$REMOTE" " + set -euo pipefail + mkdir -p $(shell_quote "$remote_parent") + test -d $(shell_quote "$remote_parent") + test -w $(shell_quote "$remote_parent") + " >/dev/null 2>&1 || fail "dossier distant absent ou non inscriptible : $remote_parent" + + ssh "${SSH_OPTS[@]}" "$REMOTE" " + set -euo pipefail + cat > $(shell_quote "$remote_tmp") + " < "$local_file" >/dev/null 2>&1 || fail "échec d'écriture temporaire distante : $remote_tmp" + + ssh "${SSH_OPTS[@]}" "$REMOTE" " + set -euo pipefail + install -m $(shell_quote "$remote_mode") $(shell_quote "$remote_tmp") $(shell_quote "$remote_final_path") + rm -f $(shell_quote "$remote_tmp") + " >/dev/null 2>&1 || fail "échec d'installation distante : $remote_final_path" +} + TARGET_NAME="${CLI_TARGET:-${TARGET_NAME:-}}" [[ -n "$TARGET_NAME" ]] || fail "target manquante" @@ -199,7 +231,6 @@ to_bool_yes_no "$TARGET_BOOTSTRAP_ALLOW_PASSWORDLESS_SUDO_VALUE" >/dev/null || f ALLOW_PASSWORDLESS_SUDO="$(to_bool_yes_no "$TARGET_BOOTSTRAP_ALLOW_PASSWORDLESS_SUDO_VALUE")" require_cmd ssh -require_cmd scp require_cmd python3 SSH_OPTS=( @@ -291,24 +322,17 @@ EXCLUDED_RESTORE_ROLES=$(printf '%s\n' "$TARGET_EXCLUDED_RESTORE_ROLES_VALUE") EOF log "Copie du .env cible" -scp "${SSH_OPTS[@]}" "$TMP_ENV_FILE" "${REMOTE}:$(printf '%q' "$TARGET_ENV_FILE_PATH")" >/dev/null 2>&1 \ - || fail "échec de copie du .env cible" +copy_file_to_remote_via_ssh "$TMP_ENV_FILE" "$TARGET_ENV_FILE_PATH" "600" REMOTE_SSH_DIR="$(dirname "$TARGET_SSH_KEY_VALUE")" REMOTE_KNOWN_HOSTS="${REMOTE_SSH_DIR}/known_hosts" log "Copie de la clé privée backup sur la cible" -scp "${SSH_OPTS[@]}" \ - "$TARGET_BACKUP_SOURCE_SSH_PRIVATE_KEY_VALUE" \ - "${REMOTE}:$(printf '%q' "$TARGET_SSH_KEY_VALUE")" >/dev/null 2>&1 \ - || fail "échec de copie de la clé privée backup" +copy_file_to_remote_via_ssh "$TARGET_BACKUP_SOURCE_SSH_PRIVATE_KEY_VALUE" "$TARGET_SSH_KEY_VALUE" "600" if [[ -n "$TARGET_BACKUP_SOURCE_SSH_PUBLIC_KEY_VALUE" ]]; then log "Copie de la clé publique backup sur la cible" - scp "${SSH_OPTS[@]}" \ - "$TARGET_BACKUP_SOURCE_SSH_PUBLIC_KEY_VALUE" \ - "${REMOTE}:$(printf '%q' "${TARGET_SSH_KEY_VALUE}.pub")" >/dev/null 2>&1 \ - || fail "échec de copie de la clé publique backup" + copy_file_to_remote_via_ssh "$TARGET_BACKUP_SOURCE_SSH_PUBLIC_KEY_VALUE" "${TARGET_SSH_KEY_VALUE}.pub" "644" fi REMOTE_SSH_PERMS_CMD=" @@ -397,8 +421,8 @@ fi TMP_SUDOERS_FILE=\$(mktemp) cat >\"\$TMP_SUDOERS_FILE\" </dev/null 2>&1 || { echo 'sudo absent sur la cible' >&2 exit 1 } -sudo -n /usr/bin/true >/dev/null 2>&1 || { - echo 'sudo -n root indisponible pour /usr/bin/true' >&2 +sudo -n /usr/bin/systemctl --version >/dev/null 2>&1 || { + echo 'sudo -n indisponible pour systemctl' >&2 exit 1 } " @@ -476,7 +500,7 @@ ssh "${SSH_OPTS[@]}" "$REMOTE" "$REMOTE_RUN_CHECK_PG_CMD" \ REMOTE_VALIDATE_SUDO_POSTGRES_CMD=" set -euo pipefail sudo -n -u postgres /usr/bin/psql -d postgres -c 'SELECT 1;' >/dev/null 2>&1 || { - echo 'sudo -n -u postgres indisponible pour psql' >&2 + echo 'sudo -n -u postgres indisponible après préparation PostgreSQL' >&2 exit 1 } "