Files
Varaverk/Plugin/unraid/System_Essentials/unraid_api_key_renew.sh
T

167 lines
7.0 KiB
Bash
Executable File

#!/bin/bash
# ==============================================================================================
# ================================= Unraid API Key Renewal ====================================
# ==============================================================================================
#
# PURPOSE
# ─────────────────────────────────────────────────────────────────────────────
# Creates/overwrites the Varaverk API key in the unraid-api service registry at
# array start. The registry is ephemeral — OS updates and service restarts clear
# it. This script re-registers the key every boot so Varaverk's enhanced
# monitoring self-heals without manual intervention.
#
# Also updates HOST*_UNRAID_API_KEY in the local host conf so the partnership
# page always reflects the live key value.
#
# ==============================================================================================
# RUNTIME MODES
# ==============================================================================================
#
# unraid_api_key_renew.sh
# Renew the key. Silent on success.
#
# unraid_api_key_renew.sh --dry-run
# Show what would happen — no changes made.
#
# unraid_api_key_renew.sh --log
# Verbose output.
#
# ==============================================================================================
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/../../../load_config.sh"
parse_args "$@"
acquire_lock
detect_hosts
# ──────────────────────────────────────────────────────────────────────────────
CONF_FILE="$SCRIPT_DIR/../../../Configurations/${MY_ID,,}.conf"
VAR_NAME="${MY_ID}_UNRAID_API_KEY"
# Key name: "Varaverk <hostname>" stripping any unraid- prefix
# Space separator — unRAID API only allows letters, numbers, and spaces
HOSTNAME_SUFFIX=$(hostname -s 2>/dev/null | sed 's/^[Uu][Nn][Rr][Aa][Ii][Dd]-//' || hostname -s)
KEY_NAME="Varaverk ${HOSTNAME_SUFFIX}"
log "$ICON_GEAR Conf file: $CONF_FILE"
log "$ICON_GEAR Key var: $VAR_NAME"
log "$ICON_GEAR Key name: $KEY_NAME"
if [[ ! -f "$CONF_FILE" ]]; then
error "Conf file not found: $CONF_FILE"
exit 1
fi
if [[ "$DRY_RUN" == true ]]; then
warn "DRY RUN — would check registry for $KEY_NAME, renew only if missing"
exit 0
fi
# ──────────────────────────────────────────────────────────────────────────────
# Check if key already exists in the unraid-api registry before creating.
# --overwrite generates a new key value every time, invalidating the old one.
# Only renew if the registry has lost it.
log "Checking unraid-api registry for $KEY_NAME..."
EXISTING=$(timeout 5 /usr/local/sbin/unraid-api apikey --name "$KEY_NAME" --json </dev/null 2>/dev/null)
KEY=$(echo "$EXISTING" | jq -r '.key // empty' 2>/dev/null)
if [[ -n "$KEY" ]]; then
PREVIEW="${KEY:0:8}...${KEY: -4}"
# Always sync registry key → conf, even if the key was already there.
# Conf gets wiped on git pull / conf regeneration without touching the registry.
CONF_HAS_KEY=$(grep -oP "(?<=^\s*${VAR_NAME}=\")[^\"]*" "$CONF_FILE" 2>/dev/null || true)
if [[ "$CONF_HAS_KEY" == "$KEY" ]]; then
echo "API key valid ✅ — $VAR_NAME = $PREVIEW"
log "Key in registry and conf — no action needed"
exit 0
fi
log "Key in registry but conf is stale — syncing..."
if grep -q "^\s*${VAR_NAME}\s*=" "$CONF_FILE"; then
sed -i "s|^\(\s*${VAR_NAME}\s*=\s*\)\"[^\"]*\"|\1\"${KEY}\"|" "$CONF_FILE"
else
echo " ${VAR_NAME}=\"${KEY}\"" >> "$CONF_FILE"
fi
echo "API key synced to conf ✅ — $VAR_NAME = $PREVIEW"
exit 0
fi
log "Key not found in registry — creating new key..."
RAW=$(timeout 10 /usr/local/sbin/unraid-api apikey \
--name "$KEY_NAME" --create --overwrite \
--description "Varaverk plugin" --roles ADMIN --json </dev/null 2>&1)
if [[ -z "$RAW" ]]; then
error "unraid-api returned no output"
exit 1
fi
KEY=$(echo "$RAW" | jq -r '.key // empty' 2>/dev/null)
if [[ -z "$KEY" ]]; then
error "No key in unraid-api response: ${RAW:0:200}"
exit 1
fi
# ──────────────────────────────────────────────────────────────────────────────
if grep -q "^\s*${VAR_NAME}\s*=" "$CONF_FILE"; then
sed -i "s|^\(\s*${VAR_NAME}\s*=\s*\)\"[^\"]*\"|\1\"${KEY}\"|" "$CONF_FILE"
else
echo " ${VAR_NAME}=\"${KEY}\"" >> "$CONF_FILE"
fi
PREVIEW="${KEY:0:8}...${KEY: -4}"
log "Writing new key to: $CONF_FILE"
warn "API key renewed ✅ — $VAR_NAME = $PREVIEW (registry had lost it)"
# ── Push renewed key into each partner's OWN conf ─────────────────────────────
# Each host's conf is its complete keychest — no cross-host conf files needed.
# SSH_KEY is set by detect_hosts() — this server's outbound private key.
if [[ -z "$SSH_KEY" ]]; then
log "No SSH key configured — skipping partner push"
exit 0
fi
for host_var in $(compgen -v | grep -E '^HOST[0-9]+$'); do
partner_host="${!host_var}"
[[ -z "$partner_host" ]] && continue
[[ "${host_var,,}" == "${MY_ID,,}" ]] && continue
partner_slot="${host_var,,}" # e.g. host2
partner_ip=$(resolve_tailscale_ip "$partner_host" 2>/dev/null || true)
[[ -z "$partner_ip" ]] && { log "Cannot resolve IP for $partner_host — skipping"; continue; }
# Target is the partner's OWN conf on their machine
partner_conf="/boot/config/plugins/varaverk/Configurations/${partner_slot}.conf"
tmp=$(mktemp /tmp/vv_kp_XXXXXX.sh)
remote="/tmp/vv_kp_${RANDOM}.sh"
chmod 700 "$tmp"
# Key stays in the temp file — never appears in SSH command args
cat > "$tmp" <<PUSHSCRIPT
#!/bin/sh
target='${partner_conf}'
if grep -q "\b${VAR_NAME}\b" "\$target" 2>/dev/null; then
sed -i 's|^\(\\s*${VAR_NAME}\\s*=\\s*\)"[^"]*"|\1"${KEY}"|' "\$target"
else
printf ' ${VAR_NAME}="%s"\n' '${KEY}' >> "\$target"
fi
echo ok
PUSHSCRIPT
if timeout 10 scp -i "$SSH_KEY" -o ConnectTimeout=10 -o BatchMode=yes \
-o StrictHostKeyChecking=no "$tmp" "root@${partner_ip}:${remote}" 2>/dev/null; then
if timeout 10 ssh -i "$SSH_KEY" -o ConnectTimeout=10 -o BatchMode=yes \
-o StrictHostKeyChecking=no "root@${partner_ip}" \
"bash '${remote}'; rc=\$?; rm -f '${remote}'; exit \$rc" 2>/dev/null | grep -q ok; then
echo "Key pushed to $partner_host ✅"
else
warn "Key push to $partner_host failed — they can create their own copy"
fi
else
warn "SCP to $partner_host failed — skipping"
fi
rm -f "$tmp"
done