update pulse installer

This commit is contained in:
David Schroeder
2026-07-25 22:02:07 -05:00
parent d8d27e5966
commit 854309c3a1
3 changed files with 116 additions and 2 deletions
+1 -1
View File
@@ -3,7 +3,7 @@
action="${1:-}" action="${1:-}"
FOLDER='/opt/idssys/ta-proxmenu' FOLDER='/opt/idssys/ta-proxmenu'
VERS='2026.7.25-53' VERS='2026.7.25-54'
noupdate=' ' noupdate=' '
+76 -1
View File
@@ -491,6 +491,76 @@ raise SystemExit(0 if success is True else 1)
unset generated_password generated_api_token unset generated_password generated_api_token
} }
TAPM_PULSE_NORMALIZE_V611_SETUP_ARTIFACT() {
local response="$1"
local pulse_url="$2"
local expected_host="${3:-}"
PULSE_SETUP_RESPONSE="$response" \
PULSE_SETUP_URL="$pulse_url" \
PULSE_SETUP_HOST="$expected_host" \
python3 -c '
import json
import os
import re
import sys
import time
from urllib.parse import quote
try:
data = json.loads(os.environ["PULSE_SETUP_RESPONSE"])
except (TypeError, ValueError):
raise SystemExit("Pulse returned invalid setup-token JSON")
token = str(data.get("setupToken", "")).strip()
returned_host = str(data.get("host", "")).strip()
host = os.environ["PULSE_SETUP_HOST"].strip() or returned_host
expires = data.get("expires", 0)
if not re.fullmatch(r"[0-9a-fA-F]{32,128}", token):
raise SystemExit("Pulse returned no valid setup token")
if data.get("type") != "pve" or not returned_host or not host:
raise SystemExit("Pulse returned an invalid PVE setup artifact")
try:
if int(expires) <= int(time.time()):
raise SystemExit("Pulse returned an expired setup token")
except (TypeError, ValueError):
raise SystemExit("Pulse returned an invalid setup-token expiry")
pulse_url = os.environ["PULSE_SETUP_URL"].rstrip("/")
empty = ""
expected_url = (
f"{pulse_url}/api/setup-script?"
f"host={quote(host, safe=empty)}&"
f"pulse_url={quote(pulse_url, safe=empty)}&type=pve"
)
expected_download_url = (
f"{pulse_url}/api/setup-script?"
f"host={quote(host, safe=empty)}&"
f"pulse_url={quote(pulse_url, safe=empty)}&"
f"setup_token={quote(token, safe=empty)}&type=pve"
)
# Pulse v6.1.1 rejects its own valid artifact if the server selected a
# different public base URL or included an optional query parameter. These
# presentation fields are not executed by auto_register_pve_node; align them
# with the helper contract while preserving the server-issued token.
old_url = str(data.get("url", ""))
if not old_url:
raise SystemExit("Pulse returned no setup-script URL")
for field in ("command", "commandWithEnv", "commandWithoutEnv"):
value = str(data.get(field, ""))
if not value or old_url not in value:
raise SystemExit(f"Pulse returned an invalid {field} field")
data[field] = value.replace(old_url, expected_url)
data["url"] = expected_url
data["downloadURL"] = expected_download_url
data["host"] = host
data["scriptFileName"] = "pulse-setup-pve.sh"
json.dump(data, sys.stdout, separators=(",", ":"))
'
}
TAPM_PULSE_REGISTER_CLUSTER() { TAPM_PULSE_REGISTER_CLUSTER() {
local ctid="$1" local ctid="$1"
local container_ip="$2" local container_ip="$2"
@@ -523,10 +593,15 @@ TAPM_PULSE_REGISTER_CLUSTER() {
# the primary token only to that request; never send it to Proxmox. # the primary token only to that request; never send it to Proxmox.
curl() { curl() {
local curl_argument local curl_argument
local setup_response
for curl_argument in "$@"; do for curl_argument in "$@"; do
if [[ "$curl_argument" == "${pulse_url}/api/setup-script-url" ]]; then if [[ "$curl_argument" == "${pulse_url}/api/setup-script-url" ]]; then
command curl --config "$curl_config" "$@" setup_response="$(command curl --config "$curl_config" "$@")" ||
return 1
TAPM_PULSE_NORMALIZE_V611_SETUP_ARTIFACT \
"$setup_response" "$pulse_url" \
"${normalized_host_url:-}"
return return
fi fi
done done
+39
View File
@@ -53,6 +53,45 @@ assert_equal '{"type":"pve","enableCommands":false}' \
"$(TAPM_PULSE_AGENT_TOKEN_REQUEST_JSON)" \ "$(TAPM_PULSE_AGENT_TOKEN_REQUEST_JSON)" \
"Proxmox-specific agent enrollment requested with commands disabled" "Proxmox-specific agent enrollment requested with commands disabled"
setup_token='0123456789abcdef0123456789abcdef'
setup_host='https://pve1.example.test:8006'
setup_old_url='https://pulse.example.test/api/setup-script?backup_perms=true'
setup_response="$(
SETUP_TOKEN="$setup_token" SETUP_HOST="$setup_host" SETUP_OLD_URL="$setup_old_url" \
python3 -c '
import json, os, sys, time
old_url = os.environ["SETUP_OLD_URL"]
token = os.environ["SETUP_TOKEN"]
json.dump({
"type": "pve",
"host": os.environ["SETUP_HOST"],
"url": old_url,
"downloadURL": old_url + "&setup_token=" + token,
"scriptFileName": "pulse-setup-pve.sh",
"command": old_url + " PULSE_SETUP_TOKEN=" + token + " if",
"commandWithEnv": old_url + " PULSE_SETUP_TOKEN=" + token + " if",
"commandWithoutEnv": old_url + " if",
"expires": int(time.time()) + 300,
"setupToken": token,
"tokenHint": token[:3] + "..." + token[-3:],
}, sys.stdout)
'
)"
normalized_setup="$(
TAPM_PULSE_NORMALIZE_V611_SETUP_ARTIFACT \
"$setup_response" 'http://10.10.2.30:7655'
)"
assert_equal "$setup_token" \
"$(SETUP_RESPONSE="$normalized_setup" python3 -c 'import json, os; print(json.loads(os.environ["SETUP_RESPONSE"])["setupToken"])')" \
"Pulse v6.1.1 compatibility preserves server-issued setup token"
assert_equal \
'http://10.10.2.30:7655/api/setup-script?host=https%3A%2F%2Fpve1.example.test%3A8006&pulse_url=http%3A%2F%2F10.10.2.30%3A7655&type=pve' \
"$(SETUP_RESPONSE="$normalized_setup" python3 -c 'import json, os; print(json.loads(os.environ["SETUP_RESPONSE"])["url"])')" \
"Pulse v6.1.1 compatibility normalizes setup artifact URL"
assert_failure "Pulse v6.1.1 compatibility rejects missing setup token" \
TAPM_PULSE_NORMALIZE_V611_SETUP_ARTIFACT \
'{"type":"pve","host":"https://pve1:8006"}' 'http://10.10.2.30:7655'
nodes_json='[ nodes_json='[
{"node":"pve3","status":"offline"}, {"node":"pve3","status":"offline"},
{"node":"pve2","status":"online"}, {"node":"pve2","status":"online"},