134 lines
4.9 KiB
Bash
134 lines
4.9 KiB
Bash
|
|
#!/usr/bin/env bash
|
|||
|
|
# Remove NPMplus certificates that are NOT assigned to any proxy host (inactive/duplicate).
|
|||
|
|
# Uses NPM API only (no SSH). Safe: only deletes certs that no proxy host references.
|
|||
|
|
# Uses .env for NPM_URL, NPM_EMAIL, NPM_PASSWORD. See docs/04-configuration/NPMPLUS_TLS_CLEANUP.md
|
|||
|
|
|
|||
|
|
set -euo pipefail
|
|||
|
|
|
|||
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|||
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|||
|
|
|
|||
|
|
# Load .env
|
|||
|
|
if [ -f "$PROJECT_ROOT/.env" ]; then
|
|||
|
|
set +u
|
|||
|
|
set -a
|
|||
|
|
# shellcheck source=/dev/null
|
|||
|
|
source "$PROJECT_ROOT/.env" 2>/dev/null || true
|
|||
|
|
set +a
|
|||
|
|
set -u
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
RED='\033[0;31m'
|
|||
|
|
GREEN='\033[0;32m'
|
|||
|
|
YELLOW='\033[1;33m'
|
|||
|
|
BLUE='\033[0;34m'
|
|||
|
|
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"; }
|
|||
|
|
|
|||
|
|
DRY_RUN="${1:-false}"
|
|||
|
|
NPM_URL="${NPM_URL:-https://192.168.11.167:81}"
|
|||
|
|
NPM_EMAIL="${NPM_EMAIL:-admin@example.org}"
|
|||
|
|
NPM_PASSWORD="${NPM_PASSWORD:-}"
|
|||
|
|
|
|||
|
|
if [ -z "$NPM_PASSWORD" ]; then
|
|||
|
|
log_error "NPM_PASSWORD is required. Set it in .env or export NPM_PASSWORD=..."
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
echo ""
|
|||
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|||
|
|
echo "🧹 NPMplus – Remove inactive (unused) certificates"
|
|||
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|||
|
|
echo ""
|
|||
|
|
|
|||
|
|
if [ "$DRY_RUN" = "true" ] || [ "$DRY_RUN" = "1" ]; then
|
|||
|
|
log_warn "DRY RUN – no certificates will be deleted"
|
|||
|
|
echo ""
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# Authenticate
|
|||
|
|
log_info "Authenticating to NPMplus..."
|
|||
|
|
AUTH_JSON=$(jq -n --arg identity "$NPM_EMAIL" --arg secret "$NPM_PASSWORD" '{identity:$identity,secret:$secret}')
|
|||
|
|
TOKEN_RESPONSE=$(curl -s -k -X POST "$NPM_URL/api/tokens" -H "Content-Type: application/json" -d "$AUTH_JSON")
|
|||
|
|
TOKEN=$(echo "$TOKEN_RESPONSE" | jq -r '.token // empty' 2>/dev/null || echo "")
|
|||
|
|
|
|||
|
|
if [ -z "$TOKEN" ] || [ "$TOKEN" = "null" ]; then
|
|||
|
|
log_error "Authentication failed. Check NPM_URL, NPM_EMAIL, NPM_PASSWORD."
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
log_success "Authenticated"
|
|||
|
|
echo ""
|
|||
|
|
|
|||
|
|
# Get proxy hosts – collect certificate_id in use
|
|||
|
|
log_info "Fetching proxy hosts..."
|
|||
|
|
PROXY_JSON=$(curl -s -k -X GET "$NPM_URL/api/nginx/proxy-hosts" -H "Authorization: Bearer $TOKEN")
|
|||
|
|
IN_USE_IDS=$(echo "$PROXY_JSON" | jq -r '[.[] | select(.certificate_id != null and .certificate_id > 0) | .certificate_id] | unique[]' 2>/dev/null || true)
|
|||
|
|
echo "$IN_USE_IDS" | grep -q . || IN_USE_IDS=""
|
|||
|
|
log_info "Certificate IDs in use (assigned to proxy hosts): $(echo $IN_USE_IDS | tr '\n' ' ')"
|
|||
|
|
echo ""
|
|||
|
|
|
|||
|
|
# Get all certificates
|
|||
|
|
log_info "Fetching certificates..."
|
|||
|
|
CERTS_JSON=$(curl -s -k -X GET "$NPM_URL/api/nginx/certificates" -H "Authorization: Bearer $TOKEN")
|
|||
|
|
CERT_COUNT=$(echo "$CERTS_JSON" | jq 'length' 2>/dev/null || echo "0")
|
|||
|
|
log_info "Total certificates: $CERT_COUNT"
|
|||
|
|
echo ""
|
|||
|
|
|
|||
|
|
# Find certs not in use
|
|||
|
|
TO_DELETE=""
|
|||
|
|
while IFS= read -r cert; do
|
|||
|
|
[ -z "$cert" ] && continue
|
|||
|
|
cid=$(echo "$cert" | jq -r '.id' 2>/dev/null)
|
|||
|
|
[ -z "$cid" ] || [ "$cid" = "null" ] && continue
|
|||
|
|
if echo "$IN_USE_IDS" | grep -q "^${cid}$"; then
|
|||
|
|
continue
|
|||
|
|
fi
|
|||
|
|
TO_DELETE="$TO_DELETE $cid"
|
|||
|
|
done < <(echo "$CERTS_JSON" | jq -c '.[]' 2>/dev/null)
|
|||
|
|
|
|||
|
|
TO_DELETE=$(echo "$TO_DELETE" | xargs)
|
|||
|
|
DELETE_COUNT=0
|
|||
|
|
if [ -z "$TO_DELETE" ]; then
|
|||
|
|
log_success "No inactive certificates to remove (all certs are in use)."
|
|||
|
|
echo ""
|
|||
|
|
exit 0
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
DELETE_NUM=$(echo "$TO_DELETE" | wc -w)
|
|||
|
|
log_warn "Found $DELETE_NUM certificate(s) not assigned to any proxy host (will remove): $TO_DELETE"
|
|||
|
|
echo ""
|
|||
|
|
|
|||
|
|
if [ "$DRY_RUN" = "true" ] || [ "$DRY_RUN" = "1" ]; then
|
|||
|
|
log_info "[DRY RUN] Would delete certificate IDs: $TO_DELETE"
|
|||
|
|
echo ""
|
|||
|
|
exit 0
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# Delete each unused cert via API
|
|||
|
|
for cid in $TO_DELETE; do
|
|||
|
|
log_info "Deleting certificate ID: $cid"
|
|||
|
|
DEL_RESP=$(curl -s -k -w "\n%{http_code}" -X DELETE "$NPM_URL/api/nginx/certificates/$cid" -H "Authorization: Bearer $TOKEN")
|
|||
|
|
HTTP_CODE=$(echo "$DEL_RESP" | tail -n1)
|
|||
|
|
BODY=$(echo "$DEL_RESP" | sed '$d')
|
|||
|
|
|
|||
|
|
if [ "$HTTP_CODE" = "200" ] || [ "$HTTP_CODE" = "204" ]; then
|
|||
|
|
log_success " ✓ Deleted certificate ID: $cid"
|
|||
|
|
DELETE_COUNT=$((DELETE_COUNT + 1))
|
|||
|
|
else
|
|||
|
|
log_error " ✗ Failed to delete certificate ID: $cid (HTTP $HTTP_CODE)"
|
|||
|
|
echo "$BODY" | jq -r '.message // .error // .' 2>/dev/null || echo "$BODY"
|
|||
|
|
fi
|
|||
|
|
sleep 1
|
|||
|
|
done
|
|||
|
|
|
|||
|
|
echo ""
|
|||
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|||
|
|
log_success "Removed $DELETE_COUNT inactive certificate(s)."
|
|||
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|||
|
|
echo ""
|
|||
|
|
log_info "Refresh NPMplus TLS Certificates page to see the cleanup."
|
|||
|
|
echo ""
|