242 lines
8.3 KiB
Bash
242 lines
8.3 KiB
Bash
|
|
#!/bin/bash
|
||
|
|
|
||
|
|
# Configure Let's Encrypt SSL Certificate for explorer.d-bis.org in NPMplus
|
||
|
|
# Uses credentials from .env file
|
||
|
|
|
||
|
|
set -euo pipefail
|
||
|
|
|
||
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||
|
|
ROOT_ENV="$(cd "$PROJECT_ROOT/.." && pwd)/.env"
|
||
|
|
|
||
|
|
# Source .env files (try root first, then project)
|
||
|
|
if [ -f "$ROOT_ENV" ]; then
|
||
|
|
set +euo pipefail
|
||
|
|
source "$ROOT_ENV" 2>/dev/null || true
|
||
|
|
set -euo pipefail
|
||
|
|
fi
|
||
|
|
|
||
|
|
if [ -f "$PROJECT_ROOT/.env" ]; then
|
||
|
|
set +euo pipefail
|
||
|
|
source "$PROJECT_ROOT/.env" 2>/dev/null || true
|
||
|
|
set -euo pipefail
|
||
|
|
fi
|
||
|
|
|
||
|
|
# NPMplus configuration
|
||
|
|
NPM_URL="${NPM_URL:-https://192.168.11.167:81}"
|
||
|
|
NPM_EMAIL="${NPM_EMAIL:-nsatoshi2007@hotmail.com}"
|
||
|
|
# NPMplus uses hashed passwords - try hash from script if plain password doesn't work
|
||
|
|
NPM_PASSWORD="${NPM_PASSWORD:-}"
|
||
|
|
NPM_PASSWORD_HASH="${NPM_PASSWORD_HASH:-ce8219e321e1cd97bd590fb792d3caeb7e2e3b94ca7e20124acaf253f911ff72}"
|
||
|
|
|
||
|
|
# Domain to configure
|
||
|
|
DOMAIN="explorer.d-bis.org"
|
||
|
|
EMAIL="${NPM_EMAIL}"
|
||
|
|
|
||
|
|
# Colors
|
||
|
|
RED='\033[0;31m'
|
||
|
|
GREEN='\033[0;32m'
|
||
|
|
YELLOW='\033[1;33m'
|
||
|
|
BLUE='\033[0;34m'
|
||
|
|
NC='\033[0m'
|
||
|
|
|
||
|
|
echo "=========================================="
|
||
|
|
echo "Configure Let's Encrypt Certificate"
|
||
|
|
echo "=========================================="
|
||
|
|
echo ""
|
||
|
|
echo "Domain: $DOMAIN"
|
||
|
|
echo "Email: $EMAIL"
|
||
|
|
echo "NPMplus URL: $NPM_URL"
|
||
|
|
echo ""
|
||
|
|
|
||
|
|
# Check if password is set
|
||
|
|
if [ -z "$NPM_PASSWORD" ]; then
|
||
|
|
echo -e "${RED}❌ NPM_PASSWORD not found in .env${NC}"
|
||
|
|
echo ""
|
||
|
|
echo "Please set NPM_PASSWORD in $PROJECT_ROOT/.env"
|
||
|
|
echo "Example: NPM_PASSWORD=your-password-hash"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
# Step 1: Authenticate to NPMplus
|
||
|
|
echo -e "${BLUE}Step 1: Authenticating to NPMplus...${NC}"
|
||
|
|
|
||
|
|
# Try plain password first, then hash if that fails
|
||
|
|
AUTH_SECRET="$NPM_PASSWORD"
|
||
|
|
if [ -z "$AUTH_SECRET" ]; then
|
||
|
|
AUTH_SECRET="$NPM_PASSWORD_HASH"
|
||
|
|
fi
|
||
|
|
|
||
|
|
# Get token from cookie header (NPMplus returns token in Set-Cookie header)
|
||
|
|
TOKEN_RESPONSE=$(curl -s -k -i -X POST "$NPM_URL/api/tokens" \
|
||
|
|
-H "Content-Type: application/json" \
|
||
|
|
-d "{\"identity\":\"$NPM_EMAIL\",\"secret\":\"$AUTH_SECRET\"}" 2>/dev/null || echo "")
|
||
|
|
|
||
|
|
TOKEN=$(echo "$TOKEN_RESPONSE" | grep -i "set-cookie:" | grep -o "token=[^;]*" | cut -d'=' -f2 || echo "")
|
||
|
|
|
||
|
|
# If plain password failed, try hash
|
||
|
|
if [ -z "$TOKEN" ]; then
|
||
|
|
if [ "$AUTH_SECRET" != "$NPM_PASSWORD_HASH" ] && [ -n "$NPM_PASSWORD_HASH" ]; then
|
||
|
|
echo -e "${YELLOW}Plain password failed, trying hash...${NC}"
|
||
|
|
TOKEN_RESPONSE=$(curl -s -k -i -X POST "$NPM_URL/api/tokens" \
|
||
|
|
-H "Content-Type: application/json" \
|
||
|
|
-d "{\"identity\":\"$NPM_EMAIL\",\"secret\":\"$NPM_PASSWORD_HASH\"}" 2>/dev/null || echo "")
|
||
|
|
TOKEN=$(echo "$TOKEN_RESPONSE" | grep -i "set-cookie:" | grep -o "token=[^;]*" | cut -d'=' -f2 || echo "")
|
||
|
|
fi
|
||
|
|
fi
|
||
|
|
|
||
|
|
if [ -z "$TOKEN" ] || [ "$TOKEN" = "null" ]; then
|
||
|
|
ERROR_MSG=$(echo "$TOKEN_RESPONSE" | jq -r '.error.message // "Unknown error"' 2>/dev/null || echo "$TOKEN_RESPONSE")
|
||
|
|
echo -e "${RED}❌ Failed to authenticate: $ERROR_MSG${NC}"
|
||
|
|
echo ""
|
||
|
|
echo "Please verify:"
|
||
|
|
echo " - NPM_EMAIL is correct: $NPM_EMAIL"
|
||
|
|
echo " - NPM_PASSWORD is correct (tried both plain and hash)"
|
||
|
|
echo " - NPMplus is accessible at: $NPM_URL"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo -e "${GREEN}✅ Authenticated successfully${NC}"
|
||
|
|
echo ""
|
||
|
|
|
||
|
|
# Step 2: Get proxy host ID for explorer.d-bis.org
|
||
|
|
echo -e "${BLUE}Step 2: Finding proxy host for $DOMAIN...${NC}"
|
||
|
|
PROXY_HOSTS=$(curl -s -k -X GET "$NPM_URL/api/nginx/proxy-hosts" \
|
||
|
|
-H "Cookie: token=$TOKEN" 2>/dev/null || echo "[]")
|
||
|
|
|
||
|
|
PROXY_HOST_ID=$(echo "$PROXY_HOSTS" | jq -r ".[] | select(.domain_names[]? == \"$DOMAIN\") | .id" 2>/dev/null | head -1)
|
||
|
|
|
||
|
|
if [ -z "$PROXY_HOST_ID" ]; then
|
||
|
|
echo -e "${RED}❌ Proxy host for $DOMAIN not found${NC}"
|
||
|
|
echo ""
|
||
|
|
echo "Available proxy hosts:"
|
||
|
|
echo "$PROXY_HOSTS" | jq -r '.[] | " - \(.domain_names | join(", ")) (ID: \(.id))"' 2>/dev/null || echo " (none found)"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo -e "${GREEN}✅ Found proxy host ID: $PROXY_HOST_ID${NC}"
|
||
|
|
echo ""
|
||
|
|
|
||
|
|
# Step 3: Check if certificate already exists
|
||
|
|
echo -e "${BLUE}Step 3: Checking for existing certificate...${NC}"
|
||
|
|
CERTIFICATES=$(curl -s -k -X GET "$NPM_URL/api/nginx/certificates" \
|
||
|
|
-H "Authorization: Bearer $TOKEN" 2>/dev/null || echo "[]")
|
||
|
|
|
||
|
|
EXISTING_CERT=$(echo "$CERTIFICATES" | jq -r ".[] | select(.friendly_name == \"$DOMAIN\" or (.domains[]? == \"$DOMAIN\")) | .id" 2>/dev/null | head -1)
|
||
|
|
|
||
|
|
if [ -n "$EXISTING_CERT" ]; then
|
||
|
|
echo -e "${YELLOW}⚠️ Certificate already exists (ID: $EXISTING_CERT)${NC}"
|
||
|
|
echo "Using existing certificate..."
|
||
|
|
CERT_ID="$EXISTING_CERT"
|
||
|
|
else
|
||
|
|
# Step 4: Create Let's Encrypt certificate
|
||
|
|
echo -e "${BLUE}Step 4: Creating Let's Encrypt certificate...${NC}"
|
||
|
|
|
||
|
|
CERT_DATA=$(jq -n \
|
||
|
|
--arg domain "$DOMAIN" \
|
||
|
|
--arg email "$EMAIL" \
|
||
|
|
'{
|
||
|
|
"provider": "letsencrypt",
|
||
|
|
"domain_names": [$domain],
|
||
|
|
"meta": {
|
||
|
|
"letsencrypt_agree": true,
|
||
|
|
"letsencrypt_email": $email
|
||
|
|
},
|
||
|
|
"friendly_name": $domain
|
||
|
|
}')
|
||
|
|
|
||
|
|
CERT_RESPONSE=$(curl -s -k -X POST "$NPM_URL/api/nginx/certificates" \
|
||
|
|
-H "Cookie: token=$TOKEN" \
|
||
|
|
-H "Content-Type: application/json" \
|
||
|
|
-d "$CERT_DATA" 2>/dev/null || echo "{}")
|
||
|
|
|
||
|
|
CERT_ID=$(echo "$CERT_RESPONSE" | jq -r '.id // empty' 2>/dev/null || echo "")
|
||
|
|
|
||
|
|
if [ -z "$CERT_ID" ] || [ "$CERT_ID" = "null" ]; then
|
||
|
|
ERROR_MSG=$(echo "$CERT_RESPONSE" | jq -r '.error.message // "Unknown error"' 2>/dev/null || echo "$CERT_RESPONSE")
|
||
|
|
echo -e "${RED}❌ Failed to create certificate: $ERROR_MSG${NC}"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo -e "${GREEN}✅ Certificate created (ID: $CERT_ID)${NC}"
|
||
|
|
echo "Waiting for certificate issuance (this may take 1-2 minutes)..."
|
||
|
|
|
||
|
|
# Wait for certificate to be issued
|
||
|
|
MAX_WAIT=120
|
||
|
|
WAITED=0
|
||
|
|
while [ $WAITED -lt $MAX_WAIT ]; do
|
||
|
|
sleep 5
|
||
|
|
WAITED=$((WAITED + 5))
|
||
|
|
CERT_STATUS=$(curl -s -k -X GET "$NPM_URL/api/nginx/certificates/$CERT_ID" \
|
||
|
|
-H "Authorization: Bearer $TOKEN" 2>/dev/null | jq -r '.meta.letsencrypt_email // empty' 2>/dev/null || echo "")
|
||
|
|
|
||
|
|
if [ -n "$CERT_STATUS" ]; then
|
||
|
|
echo -e "${GREEN}✅ Certificate issued successfully${NC}"
|
||
|
|
break
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo -n "."
|
||
|
|
done
|
||
|
|
echo ""
|
||
|
|
fi
|
||
|
|
|
||
|
|
# Step 5: Assign certificate to proxy host
|
||
|
|
echo -e "${BLUE}Step 5: Assigning certificate to proxy host...${NC}"
|
||
|
|
|
||
|
|
# Get current proxy host configuration
|
||
|
|
PROXY_HOST=$(curl -s -k -X GET "$NPM_URL/api/nginx/proxy-hosts/$PROXY_HOST_ID" \
|
||
|
|
-H "Cookie: token=$TOKEN" 2>/dev/null || echo "{}")
|
||
|
|
|
||
|
|
# Update proxy host with certificate
|
||
|
|
UPDATE_DATA=$(echo "$PROXY_HOST" | jq \
|
||
|
|
--arg cert_id "$CERT_ID" \
|
||
|
|
'{
|
||
|
|
"domain_names": .domain_names,
|
||
|
|
"forward_scheme": .forward_scheme,
|
||
|
|
"forward_host": .forward_host,
|
||
|
|
"forward_port": .forward_port,
|
||
|
|
"forward_path": .forward_path,
|
||
|
|
"ssl_certificate_id": ($cert_id | tonumber),
|
||
|
|
"ssl_forced": true,
|
||
|
|
"http2_support": true,
|
||
|
|
"hsts_enabled": true,
|
||
|
|
"hsts_subdomains": false,
|
||
|
|
"access_list_id": .access_list_id,
|
||
|
|
"block_exploits": .block_exploits,
|
||
|
|
"caching_enabled": .caching_enabled,
|
||
|
|
"websockets_support": .websockets_support
|
||
|
|
}')
|
||
|
|
|
||
|
|
UPDATE_RESPONSE=$(curl -s -k -X PUT "$NPM_URL/api/nginx/proxy-hosts/$PROXY_HOST_ID" \
|
||
|
|
-H "Cookie: token=$TOKEN" \
|
||
|
|
-H "Content-Type: application/json" \
|
||
|
|
-d "$UPDATE_DATA" 2>/dev/null || echo "{}")
|
||
|
|
|
||
|
|
if echo "$UPDATE_RESPONSE" | jq -e '.id' >/dev/null 2>&1; then
|
||
|
|
echo -e "${GREEN}✅ Certificate assigned to proxy host${NC}"
|
||
|
|
echo -e "${GREEN}✅ SSL forced enabled${NC}"
|
||
|
|
echo -e "${GREEN}✅ HTTP/2 support enabled${NC}"
|
||
|
|
echo -e "${GREEN}✅ HSTS enabled${NC}"
|
||
|
|
else
|
||
|
|
ERROR_MSG=$(echo "$UPDATE_RESPONSE" | jq -r '.error.message // "Unknown error"' 2>/dev/null || echo "$UPDATE_RESPONSE")
|
||
|
|
echo -e "${RED}❌ Failed to assign certificate: $ERROR_MSG${NC}"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo ""
|
||
|
|
echo "=========================================="
|
||
|
|
echo "Configuration Complete!"
|
||
|
|
echo "=========================================="
|
||
|
|
echo ""
|
||
|
|
echo "Summary:"
|
||
|
|
echo " - Domain: $DOMAIN"
|
||
|
|
echo " - Certificate ID: $CERT_ID"
|
||
|
|
echo " - Proxy Host ID: $PROXY_HOST_ID"
|
||
|
|
echo " - SSL Forced: Enabled"
|
||
|
|
echo " - HTTP/2: Enabled"
|
||
|
|
echo " - HSTS: Enabled"
|
||
|
|
echo ""
|
||
|
|
echo "Test the configuration:"
|
||
|
|
echo " curl -I https://$DOMAIN"
|
||
|
|
echo ""
|