update security
This commit is contained in:
@@ -0,0 +1,128 @@
|
||||
#!/usr/bin/env bash
|
||||
# Cluster discovery and remote update helpers for TA-ProxMenu.
|
||||
|
||||
TAPM_COROSYNC_CONFIG="${TAPM_COROSYNC_CONFIG:-/etc/pve/corosync.conf}"
|
||||
|
||||
TAPM_CLUSTER_NODES_FROM_JSON() {
|
||||
python3 -c '
|
||||
import json, re, sys
|
||||
try:
|
||||
payload = json.load(sys.stdin)
|
||||
except (json.JSONDecodeError, OSError):
|
||||
raise SystemExit(1)
|
||||
if isinstance(payload, dict):
|
||||
payload = payload.get("data", [])
|
||||
if not isinstance(payload, list):
|
||||
raise SystemExit(1)
|
||||
valid_name = re.compile(r"^[A-Za-z0-9][A-Za-z0-9.-]{0,62}$")
|
||||
rows = []
|
||||
for item in payload:
|
||||
if not isinstance(item, dict):
|
||||
continue
|
||||
name = str(item.get("node", "")).strip()
|
||||
status = str(item.get("status", "unknown")).strip().lower()
|
||||
if valid_name.fullmatch(name):
|
||||
rows.append((name, status))
|
||||
for name, status in sorted(rows):
|
||||
print(f"{name}\t{status}")
|
||||
'
|
||||
}
|
||||
|
||||
TAPM_CLUSTER_NODE_ROWS() {
|
||||
local node_json
|
||||
|
||||
node_json="$(timeout 10 pvesh get /nodes --output-format json 2>/dev/null)" ||
|
||||
return 1
|
||||
printf '%s' "$node_json" | TAPM_CLUSTER_NODES_FROM_JSON
|
||||
}
|
||||
|
||||
TAPM_LOCAL_CLUSTER_NODE() {
|
||||
local local_link=''
|
||||
|
||||
local_link="$(readlink /etc/pve/local 2>/dev/null || true)"
|
||||
if [[ -n "$local_link" ]]; then
|
||||
basename "$local_link"
|
||||
else
|
||||
hostname -s
|
||||
fi
|
||||
}
|
||||
|
||||
TAPM_UPDATE_REMOTE_NODE() {
|
||||
local node="$1"
|
||||
|
||||
[[ "$node" =~ ^[A-Za-z0-9][A-Za-z0-9.-]{0,62}$ ]] || return 1
|
||||
timeout 240 ssh \
|
||||
-o BatchMode=yes \
|
||||
-o ConnectTimeout=10 \
|
||||
-o ServerAliveInterval=15 \
|
||||
-o ServerAliveCountMax=2 \
|
||||
"root@${node}" \
|
||||
'/opt/idssys/ta-proxmenu/run.sh update --local-only'
|
||||
}
|
||||
|
||||
INSTALL_CLUSTER_UPDATES() {
|
||||
local index
|
||||
local local_node
|
||||
local node
|
||||
local required_command
|
||||
local status
|
||||
local node_rows=''
|
||||
local cluster_failed=0
|
||||
local -a cluster_nodes=()
|
||||
local -a cluster_statuses=()
|
||||
|
||||
if [[ ! -s "$TAPM_COROSYNC_CONFIG" ]]; then
|
||||
INSTALL_LOCAL_UPDATES
|
||||
return $?
|
||||
fi
|
||||
for required_command in pvesh python3 ssh timeout; do
|
||||
if ! command -v "$required_command" >/dev/null 2>&1; then
|
||||
echo -e "${idsCL[Red]}Cluster update requires ${required_command}; no nodes were updated.${idsCL[Default]}"
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
node_rows="$(TAPM_CLUSTER_NODE_ROWS)" || {
|
||||
echo -e "${idsCL[Red]}Could not retrieve the Proxmox cluster node list; no nodes were updated.${idsCL[Default]}"
|
||||
return 1
|
||||
}
|
||||
while IFS=$'\t' read -r node status; do
|
||||
[[ -n "$node" ]] || continue
|
||||
cluster_nodes+=("$node")
|
||||
cluster_statuses+=("$status")
|
||||
done <<<"$node_rows"
|
||||
if (( ${#cluster_nodes[@]} == 0 )); then
|
||||
echo -e "${idsCL[Red]}The Proxmox API returned no cluster nodes; no nodes were updated.${idsCL[Default]}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local_node="$(TAPM_LOCAL_CLUSTER_NODE)"
|
||||
echo -e "${idsCL[LightCyan]}Updating TA-ProxMenu across ${#cluster_nodes[@]} cluster node(s)...${idsCL[Default]}"
|
||||
for index in "${!cluster_nodes[@]}"; do
|
||||
node="${cluster_nodes[$index]}"
|
||||
status="${cluster_statuses[$index]}"
|
||||
if [[ "$node" == "$local_node" ]]; then
|
||||
continue
|
||||
fi
|
||||
if [[ "$status" != "online" ]]; then
|
||||
echo -e "${idsCL[LightYellow]}Skipping ${node}: node status is ${status}.${idsCL[Default]}"
|
||||
cluster_failed=1
|
||||
continue
|
||||
fi
|
||||
echo -e "${idsCL[LightCyan]}Updating remote node ${node}...${idsCL[Default]}"
|
||||
if TAPM_UPDATE_REMOTE_NODE "$node"; then
|
||||
echo -e "${idsCL[Green]}Remote node ${node} is updated.${idsCL[Default]}"
|
||||
else
|
||||
echo -e "${idsCL[Red]}Remote node ${node} failed to update.${idsCL[Default]}"
|
||||
cluster_failed=1
|
||||
fi
|
||||
done
|
||||
|
||||
echo -e "${idsCL[LightCyan]}Updating local node ${local_node}...${idsCL[Default]}"
|
||||
INSTALL_LOCAL_UPDATES || cluster_failed=1
|
||||
if (( cluster_failed == 0 )); then
|
||||
echo -e "${idsCL[Green]}TA-ProxMenu is updated on all ${#cluster_nodes[@]} cluster node(s).${idsCL[Default]}"
|
||||
return 0
|
||||
fi
|
||||
echo -e "${idsCL[LightYellow]}Cluster update completed with failures; review the node messages above.${idsCL[Default]}"
|
||||
return 1
|
||||
}
|
||||
Reference in New Issue
Block a user