From b76b6613bf8b8a529189d84d574fafc1364cee59 Mon Sep 17 00:00:00 2001 From: Matteo Date: Tue, 17 Mar 2026 15:14:52 +0100 Subject: [PATCH] feat : sudoers bug (WIP) --- RebuildBdd/Checkup/check-postgresql.sh | 19 +++---- RebuildBdd/Checkup/check-target-readiness.sh | 42 +++++++------- RebuildBdd/bootstrap-target-host.sh | 58 ++++++-------------- 3 files changed, 49 insertions(+), 70 deletions(-) diff --git a/RebuildBdd/Checkup/check-postgresql.sh b/RebuildBdd/Checkup/check-postgresql.sh index 5c8562f..2d9feee 100755 --- a/RebuildBdd/Checkup/check-postgresql.sh +++ b/RebuildBdd/Checkup/check-postgresql.sh @@ -70,7 +70,7 @@ if ! require_cmd "$SUDO_BIN"; then fail "sudo absent sur la cible" fi -if ! "$SUDO_BIN" -n true >/dev/null 2>&1; then +if ! "$SUDO_BIN" -n /usr/bin/true >/dev/null 2>&1; then fail "sudo non interactif indisponible pour l'utilisateur courant" fi @@ -78,12 +78,15 @@ if [[ ! "$PGPORT" =~ ^[0-9]+$ ]]; then fail "PGPORT invalide : $PGPORT" fi +POSTGRES_INSTALLED="no" + if ! require_cmd psql || ! require_cmd pg_restore || ! require_cmd createdb || ! require_cmd dropdb; then [[ "${AUTO_INSTALL_POSTGRES,,}" == "yes" ]] || fail "PostgreSQL absent et AUTO_INSTALL_POSTGRES=no" log "PostgreSQL absent : installation en cours..." "$SUDO_BIN" -n apt update >/dev/null 2>&1 || fail "échec de apt update" "$SUDO_BIN" -n apt install -y $POSTGRES_PACKAGE_LIST >/dev/null 2>&1 || fail "échec de l'installation PostgreSQL" + POSTGRES_INSTALLED="yes" log "Installation PostgreSQL terminée." else log "PostgreSQL déjà installé." @@ -98,20 +101,20 @@ fi log "Vérification de la disponibilité de PostgreSQL..." for _ in {1..20}; do - if "$SUDO_BIN" -n -u postgres psql -d postgres -c "SELECT 1;" >/dev/null 2>&1; then + if "$SUDO_BIN" -n -u postgres /usr/bin/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 psql -d postgres -c "SELECT 1;" >/dev/null 2>&1; then - fail "PostgreSQL ne répond pas correctement" +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" fi if [[ "${AUTO_CREATE_PGUSER,,}" == "yes" ]]; then ROLE_EXISTS="$( - "$SUDO_BIN" -n -u postgres psql -d postgres -tAc \ + "$SUDO_BIN" -n -u postgres /usr/bin/psql -d postgres -tAc \ "SELECT 1 FROM pg_roles WHERE rolname='${PGUSER//\'/\'\'}'" 2>/dev/null || true )" @@ -123,7 +126,7 @@ if [[ "${AUTO_CREATE_PGUSER,,}" == "yes" ]]; then ROLE_ATTRIBUTES="LOGIN SUPERUSER CREATEDB CREATEROLE" fi - "$SUDO_BIN" -n -u postgres psql -d postgres -c \ + "$SUDO_BIN" -n -u postgres /usr/bin/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}" @@ -133,10 +136,6 @@ if [[ "${AUTO_CREATE_PGUSER,,}" == "yes" ]]; then fi fi -if ! "$SUDO_BIN" -n -u postgres true >/dev/null 2>&1; then - fail "sudo -n -u postgres indisponible" -fi - if ! psql -h "$PGHOST" -p "$PGPORT" -U "$PGUSER" -d postgres -c "SELECT 1;" >/dev/null 2>&1; then fail "connexion PostgreSQL locale impossible avec PGUSER=${PGUSER}" fi diff --git a/RebuildBdd/Checkup/check-target-readiness.sh b/RebuildBdd/Checkup/check-target-readiness.sh index 0bc61e8..e9f0d70 100755 --- a/RebuildBdd/Checkup/check-target-readiness.sh +++ b/RebuildBdd/Checkup/check-target-readiness.sh @@ -3,9 +3,6 @@ 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)" @@ -119,8 +116,6 @@ 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() { @@ -175,26 +170,32 @@ 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" - [[ -f "$SSH_KEY" ]] || fail "clé SSH absente : $SSH_KEY" + 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 + chmod 600 "$SSH_KEY" || fail "impossible de chmod 600 sur la clé privée" - [[ -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" + [[ -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" log "Clé SSH prête." } prepare_known_hosts() { - local ssh_dir known_hosts + local ssh_dir known_hosts ssh_port 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}:${BACKUP_REMOTE_SSH_PORT} à known_hosts" - ssh-keyscan -p "$BACKUP_REMOTE_SSH_PORT" -H "$BACKUP_REMOTE_HOST" >>"$known_hosts" 2>/dev/null || \ + log "Ajout de ${BACKUP_REMOTE_HOST}:${ssh_port} à known_hosts" + ssh-keyscan -p "$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." @@ -202,12 +203,13 @@ prepare_known_hosts() { } test_backup_ssh() { - local ssh_timeout + local ssh_port ssh_timeout + ssh_port="${BACKUP_REMOTE_SSH_PORT:-22}" ssh_timeout="${SSH_CONNECT_TIMEOUT:-8}" ssh \ -i "$SSH_KEY" \ - -p "$BACKUP_REMOTE_SSH_PORT" \ + -p "$ssh_port" \ -o IdentitiesOnly=yes \ -o BatchMode=yes \ -o ConnectTimeout="$ssh_timeout" \ @@ -229,7 +231,7 @@ install_sudoers_if_allowed() { return 0 fi - if ! sudo -n true >/dev/null 2>&1; then + if ! sudo -n /usr/bin/true >/dev/null 2>&1; then fail "AUTO_CONFIGURE_SUDOERS=yes mais sudo -n n'est pas disponible ; configuration initiale manuelle requise" fi @@ -239,8 +241,8 @@ install_sudoers_if_allowed() { tmp_file="$(mktemp)" cat >"$tmp_file" </dev/null 2>&1 || \ - fail "sudo non interactif indisponible pour ${USER}" + sudo -n /usr/bin/true >/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}" log "sudo non interactif validé." } @@ -278,7 +283,6 @@ 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 f6b9243..851d587 100755 --- a/RebuildBdd/bootstrap-target-host.sh +++ b/RebuildBdd/bootstrap-target-host.sh @@ -102,38 +102,6 @@ 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" @@ -231,6 +199,7 @@ 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=( @@ -322,17 +291,24 @@ EXCLUDED_RESTORE_ROLES=$(printf '%s\n' "$TARGET_EXCLUDED_RESTORE_ROLES_VALUE") EOF log "Copie du .env cible" -copy_file_to_remote_via_ssh "$TMP_ENV_FILE" "$TARGET_ENV_FILE_PATH" "600" +scp "${SSH_OPTS[@]}" "$TMP_ENV_FILE" "${REMOTE}:$(printf '%q' "$TARGET_ENV_FILE_PATH")" >/dev/null 2>&1 \ + || fail "échec de copie du .env cible" 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" -copy_file_to_remote_via_ssh "$TARGET_BACKUP_SOURCE_SSH_PRIVATE_KEY_VALUE" "$TARGET_SSH_KEY_VALUE" "600" +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" if [[ -n "$TARGET_BACKUP_SOURCE_SSH_PUBLIC_KEY_VALUE" ]]; then log "Copie de la clé publique backup sur la cible" - copy_file_to_remote_via_ssh "$TARGET_BACKUP_SOURCE_SSH_PUBLIC_KEY_VALUE" "${TARGET_SSH_KEY_VALUE}.pub" "644" + 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" fi REMOTE_SSH_PERMS_CMD=" @@ -421,8 +397,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 true >/dev/null 2>&1 || { - echo 'sudo -n indisponible' >&2 +sudo -n /usr/bin/true >/dev/null 2>&1 || { + echo 'sudo -n root indisponible pour /usr/bin/true' >&2 exit 1 } " @@ -499,8 +475,8 @@ ssh "${SSH_OPTS[@]}" "$REMOTE" "$REMOTE_RUN_CHECK_PG_CMD" \ REMOTE_VALIDATE_SUDO_POSTGRES_CMD=" set -euo pipefail -sudo -n -u postgres true >/dev/null 2>&1 || { - echo 'sudo -n -u postgres indisponible après préparation PostgreSQL' >&2 +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 exit 1 } "