瀏覽代碼

Reject Git downgrades and compare commit IDs correctly

Proxmox Router 4 天之前
父節點
當前提交
a031ea82fd
共有 3 個文件被更改,包括 15 次插入 和 3 次删除
  1. 1 0
      install.sh
  2. 1 1
      internal/api/update_handlers.go
  3. 13 2
      scripts/debtik-update

+ 1 - 0
install.sh

@@ -27,6 +27,7 @@ CGO_ENABLED=0 go build -trimpath -ldflags "-X proxmox-router/internal/api.BuildC
 CGO_ENABLED=0 go build -trimpath -o "$build/debtik-cli" ./cmd/debtik-cli
 install -d -m 0700 /etc/proxmox-router
 install -d -m 0700 /var/lib/debtik/update
+if [[ $commit =~ ^[a-f0-9]{40}$ ]]; then printf '%s\n' "$commit" > /var/lib/debtik/update/installed_commit; fi
 install -d -m 0755 /usr/local/libexec
 install -m 0750 scripts/debtik-update /usr/local/libexec/debtik-update
 install -d -m 0755 /etc/network/interfaces.d

+ 1 - 1
internal/api/update_handlers.go

@@ -131,7 +131,7 @@ func (s *Server) handleUpdateCheck(w http.ResponseWriter, r *http.Request) {
 		http.Error(w, "Unexpected Git response", 502)
 		return
 	}
-	writeJSON(w, 200, map[string]any{"installed_commit": BuildCommit, "available_commit": fields[0], "update_available": BuildCommit != fields[0]})
+	writeJSON(w, 200, map[string]any{"installed_commit": BuildCommit, "available_commit": fields[0], "update_available": !strings.HasPrefix(fields[0], BuildCommit)})
 }
 func (s *Server) handleUpdateAction(w http.ResponseWriter, r *http.Request) {
 	if !requireUpdateAdmin(w, r) {

+ 13 - 2
scripts/debtik-update

@@ -28,12 +28,13 @@ PY
 restore() {
   state rolling_back
   systemctl stop proxmox-router.service || true
-  cleanup_veth
+  cleanup_veth || true
   for name in proxmox-router debtik-cli; do
     test -f "$base/previous/$name"
     cp -p "$base/previous/$name" "/usr/local/bin/$name.rollback"
     mv -f "/usr/local/bin/$name.rollback" "/usr/local/bin/$name"
   done
+  if [[ -f "$base/previous_commit" ]]; then cp -p "$base/previous_commit" "$base/installed_commit"; fi
   systemctl start proxmox-router.service
   systemctl is-active --quiet proxmox-router.service
   state rolled_back
@@ -52,9 +53,17 @@ work=$(mktemp -d "$base/work.XXXXXXXX")
 trap 'rm -rf "$work"' EXIT
 trap 'state failed' ERR
 state fetching
-GIT_TERMINAL_PROMPT=0 git -c protocol.file.allow=never "${git_opts[@]}" clone --depth 1 --single-branch --branch "$branch" -- "$repo" "$work/source"
+GIT_TERMINAL_PROMPT=0 git -c protocol.file.allow=never "${git_opts[@]}" clone --single-branch --branch "$branch" -- "$repo" "$work/source"
 cd "$work/source"
 commit=$(git rev-parse HEAD)
+if [[ -f "$base/installed_commit" ]]; then
+  installed=$(cat "$base/installed_commit")
+  if [[ $installed =~ ^[a-f0-9]{40}$ ]] && ! git merge-base --is-ancestor "$installed" "$commit"; then
+    state failed
+    echo "Selected branch does not contain installed commit; refusing downgrade or unrelated history"
+    exit 1
+  fi
+fi
 state building
 go_cmd=$(command -v go || true)
 if [[ -x /opt/debtik/go/bin/go ]]; then go_cmd=/opt/debtik/go/bin/go; fi
@@ -63,6 +72,7 @@ CGO_ENABLED=0 "$go_cmd" build -trimpath -ldflags "-X proxmox-router/internal/api
 CGO_ENABLED=0 "$go_cmd" build -trimpath -o "$work/debtik-cli" ./cmd/debtik-cli
 install -d -m 0700 "$base/previous"
 for name in proxmox-router debtik-cli; do cp -p "/usr/local/bin/$name" "$base/previous/$name"; done
+if [[ -f "$base/installed_commit" ]]; then cp -p "$base/installed_commit" "$base/previous_commit"; fi
 printf '%s\n' "$commit" > "$base/candidate_commit"
 state installing
 rollback_on_error() { trap - ERR; restore || state failed; exit 1; }
@@ -76,4 +86,5 @@ done
 systemctl start proxmox-router.service
 sleep 3
 systemctl is-active --quiet proxmox-router.service
+printf '%s\n' "$commit" > "$base/installed_commit"
 state complete