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:
@@ -102,7 +102,6 @@ async def login(creds: LoginRequest, request: Request):
|
||||
async def proxy_auth(request: Request):
|
||||
"""Auto-login when Authelia has already authenticated the user via forward-auth.
|
||||
Caddy sets Remote-User and Remote-Groups headers after successful Authelia verification."""
|
||||
import config
|
||||
from rbac import resolve_role
|
||||
if not config.is_trusted_proxy(request.client.host):
|
||||
logger.warning(f"Rejected proxy auth attempt from unauthorized IP: {request.client.host}")
|
||||
@@ -195,16 +194,18 @@ async def rbac_config(current_user = Depends(auth.get_current_user)):
|
||||
async def rbac_set_override(username: str, request: Request, current_user = Depends(auth.get_current_user)):
|
||||
if current_user.role != "admin":
|
||||
raise HTTPException(status_code=403, detail="Admin only")
|
||||
from rbac import load_rbac, save_rbac
|
||||
from rbac import update_rbac
|
||||
body = await request.json()
|
||||
pages = body.get("pages")
|
||||
if pages is None:
|
||||
raise HTTPException(status_code=400, detail="Missing pages field")
|
||||
rbac = load_rbac()
|
||||
existing = rbac.setdefault("user_overrides", {}).get(username, {})
|
||||
existing["pages"] = pages
|
||||
rbac["user_overrides"][username] = existing
|
||||
save_rbac(rbac)
|
||||
|
||||
def mutator(rbac):
|
||||
existing = rbac.setdefault("user_overrides", {}).get(username, {})
|
||||
existing["pages"] = pages
|
||||
rbac["user_overrides"][username] = existing
|
||||
|
||||
update_rbac(mutator)
|
||||
return {"ok": True}
|
||||
|
||||
@router.get("/preferences")
|
||||
@@ -235,17 +236,19 @@ async def save_preferences(request: Request, current_user = Depends(auth.get_cur
|
||||
async def rbac_delete_override(username: str, current_user = Depends(auth.get_current_user)):
|
||||
if current_user.role != "admin":
|
||||
raise HTTPException(status_code=403, detail="Admin only")
|
||||
from rbac import load_rbac, save_rbac
|
||||
rbac = load_rbac()
|
||||
rbac.get("user_overrides", {}).pop(username, None)
|
||||
save_rbac(rbac)
|
||||
from rbac import update_rbac
|
||||
|
||||
def mutator(rbac):
|
||||
rbac.get("user_overrides", {}).pop(username, None)
|
||||
|
||||
update_rbac(mutator)
|
||||
return {"ok": True}
|
||||
|
||||
@router.put("/rbac/roles/{role}")
|
||||
async def rbac_update_role(role: str, request: Request, current_user = Depends(auth.get_current_user)):
|
||||
if current_user.role != "admin":
|
||||
raise HTTPException(status_code=403, detail="Admin only")
|
||||
from rbac import load_rbac, save_rbac
|
||||
from rbac import update_rbac
|
||||
body = await request.json()
|
||||
pages = body.get("pages")
|
||||
sidebar_links = body.get("sidebar_links")
|
||||
@@ -255,10 +258,12 @@ async def rbac_update_role(role: str, request: Request, current_user = Depends(a
|
||||
raise HTTPException(status_code=400, detail="pages must be '*' or a list")
|
||||
if sidebar_links is not None and sidebar_links != "*" and not isinstance(sidebar_links, list):
|
||||
raise HTTPException(status_code=400, detail="sidebar_links must be '*' or a list")
|
||||
rbac = load_rbac()
|
||||
role_config = {"pages": pages}
|
||||
if sidebar_links is not None:
|
||||
role_config["sidebar_links"] = sidebar_links
|
||||
rbac.setdefault("role_defaults", {})[role] = role_config
|
||||
save_rbac(rbac)
|
||||
|
||||
def mutator(rbac):
|
||||
role_config = {"pages": pages}
|
||||
if sidebar_links is not None:
|
||||
role_config["sidebar_links"] = sidebar_links
|
||||
rbac.setdefault("role_defaults", {})[role] = role_config
|
||||
|
||||
update_rbac(mutator)
|
||||
return {"ok": True}
|
||||
|
||||
Reference in New Issue
Block a user