Harden admin authentication behind trusted proxy
This commit is contained in:
@@ -4,7 +4,6 @@ from datetime import datetime, timezone
|
||||
import html
|
||||
import json
|
||||
from uuid import UUID
|
||||
from hmac import compare_digest
|
||||
from typing import Optional
|
||||
from sqlalchemy import text
|
||||
from fastapi import APIRouter, Request, Depends, HTTPException
|
||||
@@ -12,7 +11,8 @@ from fastapi.responses import HTMLResponse, RedirectResponse, PlainTextResponse,
|
||||
from starlette.concurrency import run_in_threadpool
|
||||
from app.admin_queries import list_action_runs, list_business_events
|
||||
from app.integration_outbox_service import get_outbox_item, list_outbox, set_outbox_status
|
||||
from app.config import is_production_like_env, settings
|
||||
from app.admin_auth import require_admin_auth
|
||||
from app.config import settings
|
||||
from app.preparation_service import prepare_task as run_task_preparation
|
||||
from app.preparation_view_model import build_preparation_view_model
|
||||
from app.workflow_guard import OperationActionBlocked, get_workflow_action_plan
|
||||
@@ -63,24 +63,8 @@ from app.admin_ui.layout import layout
|
||||
from app.admin_ui.styles import ADMIN_UI_V451_CSS
|
||||
# Route handlers moved to app.admin_ui.pages.* in v4.7.2. ADMIN_UI_CSS moved to app.admin_ui.styles. Já existe documento atual. A associação direta fica bloqueada
|
||||
def require_admin_access(request: Request) -> None:
|
||||
"""Proteção opcional da UI admin.
|
||||
Se CLIENTFLOW_ADMIN_TOKEN estiver vazio, mantém compatibilidade local.
|
||||
Em produção deve ser definido e enviado em X-ClientFlow-Admin-Token,
|
||||
cookie clientflow_admin_token, ou query param admin_token atrás de HTTPS/proxy.
|
||||
"""
|
||||
expected = (settings.clientflow_admin_token or "").strip()
|
||||
if not expected:
|
||||
if is_production_like_env():
|
||||
raise HTTPException(status_code=503, detail="admin auth not configured")
|
||||
return
|
||||
received = (
|
||||
request.headers.get("X-ClientFlow-Admin-Token")
|
||||
or request.cookies.get("clientflow_admin_token")
|
||||
or (request.query_params.get("admin_token") if not is_production_like_env() else None)
|
||||
or ""
|
||||
).strip()
|
||||
if not received or not compare_digest(received, expected):
|
||||
raise HTTPException(status_code=401, detail="admin auth required")
|
||||
"""Apply UI auth (including X-ClientFlow-Admin-Token in token mode)."""
|
||||
require_admin_auth(request, area="admin_ui")
|
||||
router = APIRouter(prefix="", tags=["admin"], dependencies=[Depends(require_admin_access)])
|
||||
def esc(value) -> str:
|
||||
return html.escape(str(value or ""))
|
||||
|
||||
Reference in New Issue
Block a user