From 7ba0ff143cfe8bab696674afc3e97dc5919bc768 Mon Sep 17 00:00:00 2001 From: enzo Date: Sat, 21 Mar 2026 01:29:07 +0100 Subject: [PATCH] fix: sudo -n pour pct exec/list (permissions root requises) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tous les appels pct passent par sudo -n pour les sessions SSH non-root. GetPackages est résilient : utilise l'output même si exit code != 0. Co-Authored-By: Claude Sonnet 4.6 --- backend/internal/api/updates.go | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/backend/internal/api/updates.go b/backend/internal/api/updates.go index ba2a28d..054b889 100644 --- a/backend/internal/api/updates.go +++ b/backend/internal/api/updates.go @@ -77,7 +77,7 @@ func (h *UpdatesHandler) GetTargets(w http.ResponseWriter, r *http.Request) { {ID: "host", Name: "Proxmox Host", Status: "running"}, } - output, err := h.sshPool.RunCommand(sshHost, sshUser, sshPass, "/usr/sbin/pct list 2>/dev/null") + output, err := h.sshPool.RunCommand(sshHost, sshUser, sshPass, "sudo -n /usr/sbin/pct list 2>/dev/null") if err == nil { for _, line := range strings.Split(output, "\n") { line = strings.TrimSpace(line) @@ -130,20 +130,21 @@ func (h *UpdatesHandler) GetPackages(w http.ResponseWriter, r *http.Request) { command = "apt list --upgradable 2>/dev/null" case len(target) > 4 && target[:4] == "lxc:": lxcID := target[4:] - command = fmt.Sprintf("/usr/sbin/pct exec %s -- apt list --upgradable 2>/dev/null", lxcID) + command = fmt.Sprintf("sudo -n /usr/sbin/pct exec %s -- apt list --upgradable 2>/dev/null", lxcID) default: JSONError(w, "Cible invalide", http.StatusBadRequest) return } output, err := h.sshPool.RunCommand(sshHost, sshUser, sshPass, command) - if err != nil { + packages := parseAptPackages(output) + if err != nil && len(packages) == 0 { log.Printf("[updates/packages] Erreur SSH pour %s : %v", target, err) JSONError(w, "Erreur SSH : "+err.Error(), http.StatusBadGateway) return } - JSONResponse(w, http.StatusOK, parseAptPackages(output)) + JSONResponse(w, http.StatusOK, packages) } // parseAptPackages analyse la sortie de `apt list --upgradable`. @@ -289,14 +290,14 @@ func (h *UpdatesHandler) executeUpdate(jobID, target, sshHost, sshUser, sshPass case len(target) > 4 && target[:4] == "lxc:": lxcID := target[4:] command = fmt.Sprintf( - "/usr/sbin/pct exec %s -- bash -c 'DEBIAN_FRONTEND=noninteractive apt-get update && DEBIAN_FRONTEND=noninteractive apt-get full-upgrade -y'", + "sudo -n /usr/sbin/pct exec %s -- bash -c 'DEBIAN_FRONTEND=noninteractive apt-get update && DEBIAN_FRONTEND=noninteractive apt-get full-upgrade -y'", lxcID, ) case target == "all": - command = `for ct in $(/usr/sbin/pct list | awk 'NR>1 {print $1}'); do + command = `for ct in $(sudo -n /usr/sbin/pct list | awk 'NR>1 {print $1}'); do echo "=== LXC $ct ===" - /usr/sbin/pct exec $ct -- bash -c 'DEBIAN_FRONTEND=noninteractive apt-get update -qq && DEBIAN_FRONTEND=noninteractive apt-get full-upgrade -y' 2>/dev/null || echo "SKIP LXC $ct" + sudo -n /usr/sbin/pct exec $ct -- bash -c 'DEBIAN_FRONTEND=noninteractive apt-get update -qq && DEBIAN_FRONTEND=noninteractive apt-get full-upgrade -y' 2>/dev/null || echo "SKIP LXC $ct" done` default: