Complete markdown files cleanup and organization
- 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.
This commit is contained in:
150
scripts/fix-jwt-validation.sh
Executable file
150
scripts/fix-jwt-validation.sh
Executable file
@@ -0,0 +1,150 @@
|
||||
#!/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!"
|
||||
|
||||
Reference in New Issue
Block a user