fix: harden dashboard auth and terminal flows
Deploy Dashboard (Dev) / deploy-dev (push) Successful in 3m29s
Deploy Dashboard (Dev) / deploy-dev (push) Successful in 3m29s
Tighten terminal websocket auth and proxy trust handling while making file-backed auth/RBAC writes atomic to reduce high-impact security and persistence risks. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,7 @@ from slowapi.util import get_remote_address
|
||||
from slowapi.errors import RateLimitExceeded
|
||||
from routers import docker_router, gitea, files, terminal, system, auth, chat_summary, security, passkey, totp, litellm, cc_connect, info_engine
|
||||
import auth as auth_module
|
||||
import config
|
||||
from rbac import require_page, require_write
|
||||
|
||||
import asyncio
|
||||
@@ -16,7 +17,7 @@ import logging
|
||||
import time
|
||||
import jwt
|
||||
from datetime import datetime, timezone, timedelta
|
||||
from config import TELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_ID, CORS_ORIGINS, SECRET_KEY, ALGORITHM, VOLUME_ROOT
|
||||
from config import TELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_ID, CORS_ORIGINS, SECRET_KEY, ALGORITHM, VOLUME_ROOT, get_client_ip
|
||||
|
||||
_tz_cst = timezone(timedelta(hours=8))
|
||||
|
||||
@@ -70,19 +71,11 @@ async def audit_log(request: Request, call_next):
|
||||
start = time.time()
|
||||
response = await call_next(request)
|
||||
duration = int((time.time() - start) * 1000)
|
||||
user = "-"
|
||||
try:
|
||||
auth_header = request.headers.get("authorization", "")
|
||||
if auth_header.startswith("Bearer "):
|
||||
payload = jwt.decode(auth_header[7:], SECRET_KEY, algorithms=[ALGORITHM])
|
||||
user = payload.get("sub", "-")
|
||||
except jwt.PyJWTError:
|
||||
user = "Invalid/Malformed Token"
|
||||
except Exception:
|
||||
pass
|
||||
user = getattr(request.state, "user", None)
|
||||
username = user.username if user else "-"
|
||||
_audit_logger.info(
|
||||
"%s %s %s %s %s %d %dms",
|
||||
datetime.now(_tz_cst).strftime("%Y-%m-%dT%H:%M:%S"), request.client.host, user,
|
||||
datetime.now(_tz_cst).strftime("%Y-%m-%dT%H:%M:%S"), get_client_ip(request), username,
|
||||
request.method, request.url.path, response.status_code, duration,
|
||||
)
|
||||
return response
|
||||
@@ -128,12 +121,7 @@ async def health():
|
||||
|
||||
@app.get("/api/client-ip")
|
||||
async def client_ip(request: Request):
|
||||
ip = request.client.host
|
||||
import config
|
||||
if config.is_trusted_proxy(ip):
|
||||
forwarded = request.headers.get("x-forwarded-for", "").split(",")[0].strip()
|
||||
if forwarded:
|
||||
ip = forwarded
|
||||
ip = get_client_ip(request)
|
||||
|
||||
# LAN detection logic:
|
||||
# - True LAN IP (192.168.31.x) → lan=True
|
||||
|
||||
Reference in New Issue
Block a user