- Organized 252 files across project - Root directory: 187 → 2 files (98.9% reduction) - Moved configuration guides to docs/04-configuration/ - Moved troubleshooting guides to docs/09-troubleshooting/ - Moved quick start guides to docs/01-getting-started/ - Moved reports to reports/ directory - Archived temporary files - Generated comprehensive reports and documentation - Created maintenance scripts and guides All files organized according to established standards.
151 lines
4.6 KiB
Bash
Executable File
151 lines
4.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Fix JWT validation by using a simple HTTP service instead of FastCGI
|
|
|
|
set -euo pipefail
|
|
|
|
PROXMOX_HOST="${PROXMOX_HOST:-192.168.11.10}"
|
|
VMID=2501
|
|
|
|
# Create a simple HTTP validation service
|
|
ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@${PROXMOX_HOST} \
|
|
"pct exec $VMID -- bash" <<'FIX_EOF'
|
|
# Create systemd service for JWT validation
|
|
cat > /etc/systemd/system/jwt-validator.service <<'SERVICE_EOF'
|
|
[Unit]
|
|
Description=JWT Validation Service
|
|
After=network.target
|
|
|
|
[Service]
|
|
Type=simple
|
|
User=www-data
|
|
ExecStart=/usr/bin/python3 /usr/local/bin/jwt-validator-http.py
|
|
Restart=always
|
|
RestartSec=5
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
SERVICE_EOF
|
|
|
|
# Create HTTP-based JWT validator
|
|
cat > /usr/local/bin/jwt-validator-http.py <<'PYTHON_EOF'
|
|
#!/usr/bin/env python3
|
|
import http.server
|
|
import socketserver
|
|
import sys
|
|
import os
|
|
import hmac
|
|
import hashlib
|
|
import base64
|
|
import json
|
|
import time
|
|
import urllib.parse
|
|
|
|
def base64url_decode(data):
|
|
padding = 4 - len(data) % 4
|
|
if padding != 4:
|
|
data += '=' * padding
|
|
return base64.urlsafe_b64decode(data)
|
|
|
|
def verify_jwt(token, secret):
|
|
try:
|
|
parts = token.split('.')
|
|
if len(parts) != 3:
|
|
return False, "Invalid token format"
|
|
|
|
header_data = base64url_decode(parts[0])
|
|
payload_data = base64url_decode(parts[1])
|
|
signature = parts[2]
|
|
|
|
message = f"{parts[0]}.{parts[1]}"
|
|
expected_sig = hmac.new(
|
|
secret.encode('utf-8'),
|
|
message.encode('utf-8'),
|
|
hashlib.sha256
|
|
).digest()
|
|
expected_sig_b64 = base64.urlsafe_b64encode(expected_sig).decode('utf-8').rstrip('=')
|
|
|
|
if signature != expected_sig_b64:
|
|
return False, "Invalid signature"
|
|
|
|
payload = json.loads(payload_data)
|
|
if 'exp' in payload:
|
|
if time.time() > payload['exp']:
|
|
return False, "Token expired"
|
|
|
|
return True, payload
|
|
except Exception as e:
|
|
return False, str(e)
|
|
|
|
class JWTValidatorHandler(http.server.BaseHTTPRequestHandler):
|
|
def do_GET(self):
|
|
auth_header = self.headers.get('Authorization', '')
|
|
if not auth_header.startswith('Bearer '):
|
|
self.send_response(401)
|
|
self.send_header('Content-Type', 'application/json')
|
|
self.end_headers()
|
|
self.wfile.write(b'{"error": "Missing or invalid Authorization header"}')
|
|
return
|
|
|
|
token = auth_header[7:]
|
|
|
|
# Read secret
|
|
try:
|
|
with open('/etc/nginx/jwt_secret', 'r') as f:
|
|
secret = f.read().strip()
|
|
except Exception as e:
|
|
self.send_response(500)
|
|
self.send_header('Content-Type', 'application/json')
|
|
self.end_headers()
|
|
self.wfile.write(f'{{"error": "Server error: {str(e)}"}}'.encode())
|
|
return
|
|
|
|
valid, result = verify_jwt(token, secret)
|
|
|
|
if valid:
|
|
self.send_response(200)
|
|
self.send_header('Content-Type', 'application/json')
|
|
self.end_headers()
|
|
self.wfile.write(b'{"valid": true}')
|
|
else:
|
|
self.send_response(401)
|
|
self.send_header('Content-Type', 'application/json')
|
|
self.end_headers()
|
|
self.wfile.write(f'{{"error": "Invalid token", "reason": "{result}"}}'.encode())
|
|
|
|
def log_message(self, format, *args):
|
|
# Suppress default logging
|
|
pass
|
|
|
|
if __name__ == '__main__':
|
|
PORT = 8888
|
|
with socketserver.TCPServer(("127.0.0.1", PORT), JWTValidatorHandler) as httpd:
|
|
httpd.serve_forever()
|
|
PYTHON_EOF
|
|
|
|
chmod +x /usr/local/bin/jwt-validator-http.py
|
|
|
|
# Update nginx config to use HTTP instead of FastCGI
|
|
sed -i 's|proxy_pass http://127.0.0.1:8888/validate;|proxy_pass http://127.0.0.1:8888/;|' /etc/nginx/sites-available/rpc-perm
|
|
sed -i 's|fastcgi_pass unix:/var/run/fcgiwrap.socket;|# Removed FastCGI|' /etc/nginx/sites-available/rpc-perm
|
|
sed -i 's|include fastcgi_params;|# Removed FastCGI|' /etc/nginx/sites-available/rpc-perm
|
|
sed -i 's|fastcgi_param SCRIPT_FILENAME /usr/local/bin/jwt-validate.py;|# Removed FastCGI|' /etc/nginx/sites-available/rpc-perm
|
|
sed -i 's|fastcgi_param HTTP_AUTHORIZATION \$http_authorization;|# Removed FastCGI|' /etc/nginx/sites-available/rpc-perm
|
|
|
|
# Remove the internal FastCGI server block
|
|
sed -i '/# Internal server for JWT validation/,/^}$/d' /etc/nginx/sites-available/rpc-perm
|
|
|
|
# Enable and start the service
|
|
systemctl daemon-reload
|
|
systemctl enable jwt-validator.service
|
|
systemctl restart jwt-validator.service
|
|
|
|
# Test nginx config
|
|
nginx -t
|
|
|
|
# Reload nginx
|
|
systemctl restart nginx
|
|
FIX_EOF
|
|
|
|
echo "JWT validation service updated!"
|
|
|