Some checks failed
Deploy to Phoenix / deploy (push) Has been cancelled
- ADD_CHAIN138_TO_LEDGER_LIVE: Ledger form done; public code review repo bis-innovations/LedgerLive; init/push commands - CONTRACT_DEPLOYMENT_RUNBOOK: Chain 138 gas price 1 gwei, 36-addr check, TransactionMirror workaround - CONTRACT_*: AddressMapper, MirrorManager deployed 2026-02-12; 36-address on-chain check - NEXT_STEPS_FOR_YOU: Ledger done; steps completable now (no LAN); run-completable-tasks-from-anywhere - MASTER_INDEX, OPERATOR_OPTIONAL, SMART_CONTRACTS_INVENTORY_SIMPLE: updates - LEDGER_BLOCKCHAIN_INTEGRATION_COMPLETE: bis-innovations/LedgerLive reference Co-authored-by: Cursor <cursoragent@cursor.com>
233 lines
8.4 KiB
Bash
Executable File
233 lines
8.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Comprehensive audit of NPMplus proxy host mappings against all Proxmox VMs
|
|
# Identifies inconsistencies, missing mappings, and incorrect routes
|
|
|
|
set -euo pipefail
|
|
|
|
# Load IP configuration
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
source "${PROJECT_ROOT}/config/ip-addresses.conf" 2>/dev/null || true
|
|
|
|
|
|
PROXMOX_HOST="${1:-192.168.11.11}"
|
|
CONTAINER_ID="${2:-10233}"
|
|
|
|
# Colors
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
CYAN='\033[0;36m'
|
|
NC='\033[0m'
|
|
|
|
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
|
log_success() { echo -e "${GREEN}[✓]${NC} $1"; }
|
|
log_warn() { echo -e "${YELLOW}[⚠]${NC} $1"; }
|
|
log_error() { echo -e "${RED}[✗]${NC} $1"; }
|
|
log_section() { echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"; }
|
|
|
|
echo ""
|
|
log_section
|
|
echo "🔍 NPMplus VM Mapping Audit"
|
|
log_section
|
|
echo ""
|
|
|
|
# Step 1: Get all VMs from Proxmox
|
|
log_info "Step 1: Collecting all VMs from Proxmox..."
|
|
VM_LIST=$(ssh -o StrictHostKeyChecking=no root@"$PROXMOX_HOST" "
|
|
for vmid in \$(pct list 2>/dev/null | awk 'NR>1 {print \$1}' | grep -E '^[0-9]+$'); do
|
|
status=\$(pct status \$vmid 2>&1 | head -1)
|
|
if echo \"\$status\" | grep -q 'running\|stopped'; then
|
|
hostname=\$(pct config \$vmid 2>/dev/null | grep '^hostname:' | awk '{print \$2}' || echo 'unknown')
|
|
# Extract IP, removing CIDR notation
|
|
ip=\$(pct config \$vmid 2>/dev/null | grep -E '^ip[0-9]+' | head -1 | awk -F'=' '{print \$2}' | awk '{print \$1}' | sed 's|/.*||' || echo '')
|
|
if [ -n \"\$ip\" ] && [ \"\$ip\" != \"\" ]; then
|
|
echo \"\$vmid|\$hostname|\$ip|\$status\"
|
|
fi
|
|
fi
|
|
done
|
|
" 2>&1)
|
|
|
|
# Step 2: Get all NPMplus proxy hosts
|
|
log_info "Step 2: Collecting NPMplus proxy host configurations..."
|
|
NPMPLUS_HOSTS=$(ssh -o StrictHostKeyChecking=no root@"$PROXMOX_HOST" "pct exec $CONTAINER_ID -- docker exec npmplus node -e \"
|
|
const Database = require('better-sqlite3');
|
|
const db = new Database('/data/npmplus/database.sqlite', { readonly: true });
|
|
const hosts = db.prepare('SELECT id, domain_names, forward_scheme, forward_host, forward_port, ssl_forced FROM proxy_host ORDER BY id').all();
|
|
console.log(JSON.stringify(hosts));
|
|
db.close();
|
|
\" 2>&1" || echo "[]")
|
|
|
|
# Step 3: Build VM IP to VMID mapping
|
|
log_info "Step 3: Building VM inventory..."
|
|
declare -A IP_TO_VMID
|
|
declare -A IP_TO_HOSTNAME
|
|
declare -A IP_TO_STATUS
|
|
|
|
while IFS='|' read -r vmid hostname ip status; do
|
|
if [ -n "$ip" ] && [ "$ip" != "" ]; then
|
|
IP_TO_VMID["$ip"]="$vmid"
|
|
IP_TO_HOSTNAME["$ip"]="$hostname"
|
|
IP_TO_STATUS["$ip"]="$status"
|
|
fi
|
|
done <<< "$VM_LIST"
|
|
|
|
# Step 4: Analyze NPMplus mappings
|
|
log_info "Step 4: Analyzing NPMplus mappings..."
|
|
echo ""
|
|
|
|
# Use temp files for arrays (bash limitation with subshells)
|
|
TMPDIR=$(mktemp -d)
|
|
INCONSISTENCIES_FILE="$TMPDIR/inconsistencies.txt"
|
|
MISSING_VMS_FILE="$TMPDIR/missing_vms.txt"
|
|
CORRECT_MAPPINGS_FILE="$TMPDIR/correct_mappings.txt"
|
|
IP_CONFLICTS_FILE="$TMPDIR/ip_conflicts.txt"
|
|
|
|
touch "$INCONSISTENCIES_FILE" "$MISSING_VMS_FILE" "$CORRECT_MAPPINGS_FILE" "$IP_CONFLICTS_FILE"
|
|
|
|
# Parse NPMplus hosts
|
|
echo "$NPMPLUS_HOSTS" | jq -r '.[] | "\(.id)|\(.domain_names)|\(.forward_host)|\(.forward_port)"' 2>/dev/null | while IFS='|' read -r host_id domains_json forward_host forward_port; do
|
|
domain=$(echo "$domains_json" | jq -r '.[0] // empty' 2>/dev/null || echo "$domains_json")
|
|
|
|
if [ -z "$forward_host" ] || [ "$forward_host" = "null" ]; then
|
|
continue
|
|
fi
|
|
|
|
# Check if IP maps to a VM - use associative array lookup
|
|
# Export the arrays by checking the VM_LIST directly
|
|
vmid=""
|
|
expected_hostname=""
|
|
status=""
|
|
|
|
# Search VM_LIST for matching IP
|
|
vm_match=$(echo "$VM_LIST" | grep "|$forward_host|" | head -1)
|
|
if [ -n "$vm_match" ]; then
|
|
IFS='|' read -r vmid expected_hostname ip_match status <<< "$vm_match"
|
|
fi
|
|
|
|
if [ -z "$vmid" ]; then
|
|
# IP not found in VM list - might be external or missing
|
|
echo "$domain|$forward_host|$forward_port|External or missing VM" >> "$MISSING_VMS_FILE"
|
|
else
|
|
# Check for IP conflicts (multiple VMs with same IP)
|
|
conflict_count=$(echo "$VM_LIST" | grep -c "|$forward_host|" || echo "0")
|
|
if [ "$conflict_count" -gt 1 ]; then
|
|
echo "$domain|$forward_host|Multiple VMs share this IP" >> "$IP_CONFLICTS_FILE"
|
|
fi
|
|
|
|
# Check if service is running
|
|
if echo "$status" | grep -q "stopped"; then
|
|
echo "$domain|$forward_host:$forward_port|VMID $vmid ($expected_hostname) is STOPPED" >> "$INCONSISTENCIES_FILE"
|
|
else
|
|
echo "$domain|$forward_host:$forward_port|VMID $vmid ($expected_hostname)" >> "$CORRECT_MAPPINGS_FILE"
|
|
fi
|
|
fi
|
|
done
|
|
|
|
# Step 5: Find VMs that might need NPMplus mappings
|
|
log_info "Step 5: Identifying VMs that might need NPMplus mappings..."
|
|
POTENTIAL_SERVICES_FILE="$TMPDIR/potential_services.txt"
|
|
touch "$POTENTIAL_SERVICES_FILE"
|
|
|
|
while IFS='|' read -r vmid hostname ip status; do
|
|
if [ -z "$ip" ] || [ "$ip" = "" ]; then
|
|
continue
|
|
fi
|
|
|
|
# Check if this VM is already in NPMplus
|
|
in_npmplus=$(echo "$NPMPLUS_HOSTS" | jq -r ".[] | select(.forward_host == \"$ip\") | .domain_names[0]" 2>/dev/null | head -1)
|
|
|
|
if [ -z "$in_npmplus" ] && echo "$status" | grep -q "running"; then
|
|
# Check if it's a web service (has ports 80, 443, 3000, 4000, 8080, etc.)
|
|
# This is a heuristic - you may need to adjust
|
|
if [[ "$hostname" =~ (portal|web|api|frontend|admin|dashboard|explorer|gitea|firefly) ]]; then
|
|
echo "$vmid|$hostname|$ip|Potential web service" >> "$POTENTIAL_SERVICES_FILE"
|
|
fi
|
|
fi
|
|
done <<< "$VM_LIST"
|
|
|
|
# Step 6: Generate report
|
|
log_section
|
|
echo "📊 Audit Report"
|
|
log_section
|
|
echo ""
|
|
|
|
CORRECT_COUNT=$(wc -l < "$CORRECT_MAPPINGS_FILE" | tr -d ' ')
|
|
INCONSISTENCY_COUNT=$(wc -l < "$INCONSISTENCIES_FILE" | tr -d ' ')
|
|
CONFLICT_COUNT=$(wc -l < "$IP_CONFLICTS_FILE" | tr -d ' ')
|
|
MISSING_COUNT=$(wc -l < "$MISSING_VMS_FILE" | tr -d ' ')
|
|
POTENTIAL_COUNT=$(wc -l < "$POTENTIAL_SERVICES_FILE" | tr -d ' ')
|
|
|
|
echo "✅ Correct Mappings ($CORRECT_COUNT):"
|
|
if [ "$CORRECT_COUNT" -eq 0 ]; then
|
|
log_warn " No correct mappings found (check script logic)"
|
|
else
|
|
while IFS='|' read -r domain target vm_info; do
|
|
printf " %-50s → %-25s (%s)\n" "$domain" "$target" "$vm_info"
|
|
done < "$CORRECT_MAPPINGS_FILE" | head -20
|
|
fi
|
|
|
|
echo ""
|
|
echo "⚠️ Inconsistencies ($INCONSISTENCY_COUNT):"
|
|
if [ "$INCONSISTENCY_COUNT" -eq 0 ]; then
|
|
log_success " No inconsistencies found"
|
|
else
|
|
while IFS='|' read -r domain target issue_desc; do
|
|
log_warn " $domain → $target: $issue_desc"
|
|
done < "$INCONSISTENCIES_FILE"
|
|
fi
|
|
|
|
echo ""
|
|
echo "🔴 IP Conflicts ($CONFLICT_COUNT):"
|
|
if [ "$CONFLICT_COUNT" -eq 0 ]; then
|
|
log_success " No IP conflicts found"
|
|
else
|
|
while IFS='|' read -r domain ip issue_desc; do
|
|
log_error " $domain → $ip: $issue_desc"
|
|
# Show which VMs share this IP
|
|
echo "$VM_LIST" | grep "|$ip|" | while IFS='|' read -r vmid hostname ip2 status; do
|
|
echo " - VMID $vmid: $hostname ($status)"
|
|
done
|
|
done < "$IP_CONFLICTS_FILE"
|
|
fi
|
|
|
|
echo ""
|
|
echo "❓ Missing/External IPs ($MISSING_COUNT):"
|
|
if [ "$MISSING_COUNT" -eq 0 ]; then
|
|
log_success " All IPs map to known VMs"
|
|
else
|
|
while IFS='|' read -r domain ip port reason; do
|
|
log_warn " $domain → $ip:$port ($reason)"
|
|
done < "$MISSING_VMS_FILE"
|
|
fi
|
|
|
|
echo ""
|
|
echo "💡 Potential Services Not in NPMplus ($POTENTIAL_COUNT):"
|
|
if [ "$POTENTIAL_COUNT" -eq 0 ]; then
|
|
log_info " No obvious missing services"
|
|
else
|
|
while IFS='|' read -r vmid hostname ip reason; do
|
|
log_info " VMID $vmid: $hostname ($ip) - $reason"
|
|
done < "$POTENTIAL_SERVICES_FILE"
|
|
fi
|
|
|
|
echo ""
|
|
log_section
|
|
echo "📋 Summary"
|
|
log_section
|
|
echo "Total VMs found: $(echo "$VM_LIST" | wc -l)"
|
|
echo "NPMplus proxy hosts: $(echo "$NPMPLUS_HOSTS" | jq '. | length' 2>/dev/null || echo "0")"
|
|
echo "Correct mappings: $CORRECT_COUNT"
|
|
echo "Issues found: $((INCONSISTENCY_COUNT + CONFLICT_COUNT + MISSING_COUNT))"
|
|
echo ""
|
|
|
|
# Cleanup
|
|
rm -rf "$TMPDIR"
|
|
|
|
if [ $((INCONSISTENCY_COUNT + CONFLICT_COUNT)) -gt 0 ]; then
|
|
log_warn "⚠️ Action required: Review inconsistencies and IP conflicts above"
|
|
else
|
|
log_success "✅ No critical issues found"
|
|
fi
|