Redesign Cancel/Delete Keys in Partnership Actions

onboard_cancel.sh:
- --direction=h1 (default): remove HOST1's key from HOST2 + delete local pair
- --direction=h2: remove HOST2's key from HOST1's authorized_keys (by hostname match)
- --direction=both: both directions (used by Cancel button at phase 1)

pages/partnership.php:
- Cancel button: phase 1 only, runs --direction=both (full undo)
- Delete Keys (🗑): available at all phases, expands inline panel showing
  HOST1→HOST2 and HOST2→HOST1 as separate removal buttons with descriptions
- _vvDeleteKeys toggle state persists across polls alongside _vvOnboarding
- vvPtShowDeleteKeys / vvPtHideDeleteKeys top-level toggle fns
- vvPtDeleteH1 / vvPtDeleteH2 targeted removal fns
This commit is contained in:
Gmer4Lfe
2026-05-30 21:29:20 -04:00
parent 1956b6b068
commit 2989cefb79
2 changed files with 180 additions and 126 deletions
+98 -87
View File
@@ -1,36 +1,48 @@
#!/bin/bash
# ==============================================================================================
# ============================= Onboard Cancel =================================================
# ============================= Delete Keys ====================================================
# ==============================================================================================
#
# PURPOSE
# ─────────────────────────────────────────────────────────────────────────────
# Undoes Phase 1 of the onboard process:
# 1. Remove HOST1's public key from HOST2's authorized_keys (while key still works)
# 2. Remove phase flags from HOST2's varaverk_setup.db
# 3. Delete local SSH key pair
# 4. Clear phase flags from local varaverk_setup.db
#
# Run on the OWNER. If HOST2 is unreachable the local side is still cleaned up.
# Removes SSH keys between HOST1 and HOST2 in the specified direction.
# Safe to run at any phase. Clears related setup.db flags.
#
# ==============================================================================================
# RUNTIME MODES
# ==============================================================================================
#
# Partnership/onboard_cancel.sh
# Cancel Phase 1 — remove keys and reset state
# Partnership/onboard_cancel.sh --direction=h1 (default)
# HOST1 → HOST2: remove HOST1's public key from HOST2's authorized_keys,
# delete local HOST1 key pair, clear HOST2 phase flags from setup.db.
#
# Partnership/onboard_cancel.sh --direction=h2
# HOST2 → HOST1: remove HOST2's public key from HOST1's authorized_keys.
# Identifies the key by HOST2's hostname in the key comment.
#
# Partnership/onboard_cancel.sh --direction=both
# Both directions.
#
# Partnership/onboard_cancel.sh --dry-run
# Preview all steps without making changes
# Preview without making changes.
#
# ==============================================================================================
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SCRIPTS_ROOT="$SCRIPT_DIR/.."
SSH_TIMEOUT=15
DIRECTION="h1"
FILTERED_ARGS=()
for arg in "$@"; do
case "$arg" in
--direction=*) DIRECTION="${arg#--direction=}" ;;
*) FILTERED_ARGS+=("$arg") ;;
esac
done
source "$SCRIPTS_ROOT/load_config.sh"
parse_args "$@"
parse_args "${FILTERED_ARGS[@]}"
[[ "$EUID" -ne 0 ]] && { error "Must be run as root"; exit 1; }
@@ -43,99 +55,98 @@ MIRROR_ID=$( [[ "$OWNER_ID" == "HOST1" ]] && echo "HOST2" || echo "HOST1" )
MIRROR="${!MIRROR_ID}"
SSH_KEY_PUB="${SSH_KEY}.pub"
STATE_FILE="/boot/config/varaverk_setup.db"
AUTH_KEYS="/root/.ssh/authorized_keys"
MIRROR_SHORT="${MIRROR%%.*}"
START=$(date +%s)
echo ""
echo "━━━ Cancel Phase 1 — $MY_ID$MIRROR_ID ($MIRROR)$(date '+%Y-%m-%d %H:%M:%S') ━━━"
echo ""
echo "━━━ Delete Keys — direction:${DIRECTION}$(date '+%Y-%m-%d %H:%M:%S') ━━━"
[[ "$DRY_RUN" == true ]] && warn "DRY RUN — no changes will be made"
echo ""
REMOTE_CLEANED=false
LOCAL_KEY_GONE=false
STATE_CLEARED=false
H1_DONE=false
H2_DONE=false
# ── Step 1: Remove HOST1's public key from HOST2 ──────────────────────────────
echo "━━━ Step 1 — Remove Public Key from $MIRROR_ID ━━━"
# ── HOST1 → HOST2: remove HOST1's key from HOST2 + delete local pair ──────────
if [[ "$DIRECTION" == "h1" || "$DIRECTION" == "both" ]]; then
echo "━━━ HOST1 → HOST2: Remove HOST1 key from $MIRROR ━━━"
if [[ ! -f "$SSH_KEY_PUB" ]]; then
log "No local public key at $SSH_KEY_PUB — nothing to remove from $MIRROR_ID"
REMOTE_CLEANED=true
else
# Extract the key blob (middle field of pub key) — used as a unique identifier.
# Use | as sed delimiter to avoid clashing with base64 / characters in the blob.
KEY_BLOB=$(awk '{print $2}' "$SSH_KEY_PUB")
MIRROR_IP=$(resolve_tailscale_ip "$MIRROR" 2>/dev/null || true)
if [[ -z "$MIRROR_IP" ]]; then
warn "Cannot resolve $MIRROR Tailscale IP — skipping remote cleanup"
warn "Remove HOST1's public key from $MIRROR:/root/.ssh/authorized_keys manually"
elif [[ "$DRY_RUN" == true ]]; then
warn "DRY RUN — would remove key blob from $MIRROR:/root/.ssh/authorized_keys"
warn "DRY RUN — would clear ${MIRROR_ID}_PHASE* from $MIRROR:/boot/config/varaverk_setup.db"
REMOTE_CLEANED=true
if [[ ! -f "$SSH_KEY_PUB" ]]; then
log "No local public key — nothing to remove from $MIRROR"
H1_DONE=true
else
timeout "$SSH_TIMEOUT" ssh -i "$SSH_KEY" \
-o ConnectTimeout="$SSH_TIMEOUT" -o BatchMode=yes root@"$MIRROR_IP" \
"sed -i \"|${KEY_BLOB}|d\" /root/.ssh/authorized_keys 2>/dev/null
sed -i \"/^${MIRROR_ID}_PHASE/d\" /boot/config/varaverk_setup.db 2>/dev/null
echo ok" 2>/dev/null | grep -q ok && {
log "HOST1 key removed from $MIRROR authorized_keys ✅"
log "Phase flags cleared on $MIRROR"
REMOTE_CLEANED=true
} || warn "Could not SSH to $MIRROR — remove HOST1 key and phase flags there manually"
KEY_BLOB=$(awk '{print $2}' "$SSH_KEY_PUB")
MIRROR_IP=$(resolve_tailscale_ip "$MIRROR" 2>/dev/null || true)
if [[ -z "$MIRROR_IP" ]]; then
warn "Cannot resolve $MIRROR Tailscale IP — remove HOST1 key from $MIRROR manually"
elif [[ "$DRY_RUN" == true ]]; then
warn "DRY RUN — would remove HOST1 key from $MIRROR:/root/.ssh/authorized_keys"
H1_DONE=true
else
timeout "$SSH_TIMEOUT" ssh -i "$SSH_KEY" \
-o ConnectTimeout="$SSH_TIMEOUT" -o BatchMode=yes root@"$MIRROR_IP" \
"sed -i \"|${KEY_BLOB}|d\" /root/.ssh/authorized_keys 2>/dev/null
sed -i \"/^${MIRROR_ID}_PHASE\|^${MIRROR_ID}_KEY_READY/d\" /boot/config/varaverk_setup.db 2>/dev/null
echo ok" 2>/dev/null | grep -q ok && {
log "HOST1 key removed from $MIRROR authorized_keys ✅"
H1_DONE=true
} || warn "Could not SSH to $MIRROR — remove HOST1 key there manually"
fi
fi
# Delete local key pair
if [[ ! -f "$SSH_KEY" && ! -f "$SSH_KEY_PUB" ]]; then
log "Local key already gone"
elif [[ "$DRY_RUN" == true ]]; then
warn "DRY RUN — would delete: $SSH_KEY and ${SSH_KEY}.pub"
else
rm -f "$SSH_KEY" "$SSH_KEY_PUB" && log "Local key pair deleted ✅" || \
warn "Failed to delete local key — check permissions"
fi
# Clear HOST2 phase flags from local setup.db
if [[ -f "$STATE_FILE" ]]; then
if [[ "$DRY_RUN" == false ]]; then
sed -i "/^${MIRROR_ID}_PHASE/d; /^${MIRROR_ID}_KEY_READY/d" "$STATE_FILE"
log "Phase flags cleared from local setup.db ✅"
else
warn "DRY RUN — would clear ${MIRROR_ID}_PHASE* from setup.db"
fi
fi
echo ""
fi
# ── Step 2: Delete local SSH key pair ─────────────────────────────────────────
echo ""
echo "━━━ Step 2 — Delete Local SSH Key ━━━"
# ── HOST2 → HOST1: remove HOST2's key from HOST1's authorized_keys ────────────
if [[ "$DIRECTION" == "h2" || "$DIRECTION" == "both" ]]; then
echo "━━━ HOST2 → HOST1: Remove $MIRROR key from HOST1 ━━━"
if [[ ! -f "$SSH_KEY" && ! -f "$SSH_KEY_PUB" ]]; then
log "Local key already gone"
LOCAL_KEY_GONE=true
elif [[ "$DRY_RUN" == true ]]; then
warn "DRY RUN — would delete: $SSH_KEY"
warn "DRY RUN — would delete: $SSH_KEY_PUB"
LOCAL_KEY_GONE=true
else
rm -f "$SSH_KEY" "$SSH_KEY_PUB" && {
log "Local key pair deleted ✅"
LOCAL_KEY_GONE=true
} || warn "Failed to delete $SSH_KEY — check permissions"
fi
# ── Step 3: Clear phase flags from local setup.db ─────────────────────────────
echo ""
echo "━━━ Step 3 — Clear Phase State ━━━"
if [[ ! -f "$STATE_FILE" ]]; then
log "No varaverk_setup.db — nothing to clear"
STATE_CLEARED=true
elif [[ "$DRY_RUN" == true ]]; then
warn "DRY RUN — would remove ${MIRROR_ID}_PHASE* from $STATE_FILE"
STATE_CLEARED=true
else
sed -i "/^${MIRROR_ID}_PHASE/d" "$STATE_FILE" && {
log "Phase flags cleared from local setup.db ✅"
STATE_CLEARED=true
}
if [[ ! -f "$AUTH_KEYS" ]]; then
log "No authorized_keys on HOST1 — nothing to remove"
H2_DONE=true
elif ! grep -qi "$MIRROR_SHORT" "$AUTH_KEYS" 2>/dev/null; then
log "$MIRROR key not found in HOST1 authorized_keys (already removed or never added)"
H2_DONE=true
elif [[ "$DRY_RUN" == true ]]; then
warn "DRY RUN — would remove $MIRROR_SHORT key from $AUTH_KEYS"
H2_DONE=true
else
sed -i "/${MIRROR_SHORT}/Id" "$AUTH_KEYS" && {
log "$MIRROR key removed from HOST1 authorized_keys ✅"
H2_DONE=true
} || warn "Failed to remove $MIRROR key from HOST1 authorized_keys"
fi
echo ""
fi
# ── Summary ───────────────────────────────────────────────────────────────────
END=$(date +%s)
echo ""
echo "━━━━━ CANCEL SUMMARY ━━━━━"
echo " $MIRROR_ID key removed: $( [[ "$REMOTE_CLEANED" == true ]] && echo "✅" || echo "⚠ manual cleanup needed" )"
echo " Local key deleted: $( [[ "$LOCAL_KEY_GONE" == true ]] && echo "✅" || echo "⚠ still present" )"
echo " Phase state cleared: $( [[ "$STATE_CLEARED" == true ]] && echo "✅" || echo "⚠" )"
echo "━━━━━ DONE ━━━━━"
[[ "$DIRECTION" == "h1" || "$DIRECTION" == "both" ]] && \
echo " HOST1 → HOST2: $( [[ "$H1_DONE" == true ]] && echo "✅" || echo "⚠ manual step may be needed" )"
[[ "$DIRECTION" == "h2" || "$DIRECTION" == "both" ]] && \
echo " HOST2 → HOST1: $( [[ "$H2_DONE" == true ]] && echo "✅" || echo "⚠" )"
echo " Duration: $(format_duration $(( END - START )))"
echo ""
if [[ "$REMOTE_CLEANED" == false ]]; then
echo " Manual cleanup on $MIRROR:"
echo " sed -i '/$(awk "{print \$3}" "$SSH_KEY_PUB" 2>/dev/null || echo "HOST1_key_comment")//d' /root/.ssh/authorized_keys"
fi
echo " Run Phase 1 again to restart the onboard process."
echo "━━━━━━━━━━━━━━━━━━━━━━━"
exit 0