This commit is contained in:
Timothy Jaeryang Baek
2026-04-12 16:25:01 -05:00
parent fb5ef978bf
commit 5ee791d5d2
3 changed files with 15 additions and 3 deletions
+3
View File
@@ -909,6 +909,9 @@ AUDIT_INCLUDED_PATHS = os.getenv('AUDIT_INCLUDED_PATHS', '').split(',')
AUDIT_INCLUDED_PATHS = [path.strip() for path in AUDIT_INCLUDED_PATHS] AUDIT_INCLUDED_PATHS = [path.strip() for path in AUDIT_INCLUDED_PATHS]
AUDIT_INCLUDED_PATHS = [path.lstrip('/') for path in AUDIT_INCLUDED_PATHS if path] AUDIT_INCLUDED_PATHS = [path.lstrip('/') for path in AUDIT_INCLUDED_PATHS if path]
# When enabled, GET requests are also audited (disabled by default to avoid log noise)
ENABLE_AUDIT_GET_REQUESTS = os.getenv('ENABLE_AUDIT_GET_REQUESTS', 'False').lower() == 'true'
#################################### ####################################
# OPENTELEMETRY # OPENTELEMETRY
+2
View File
@@ -475,6 +475,7 @@ from open_webui.env import (
LICENSE_KEY, LICENSE_KEY,
AUDIT_EXCLUDED_PATHS, AUDIT_EXCLUDED_PATHS,
AUDIT_INCLUDED_PATHS, AUDIT_INCLUDED_PATHS,
ENABLE_AUDIT_GET_REQUESTS,
AUDIT_LOG_LEVEL, AUDIT_LOG_LEVEL,
CHANGELOG, CHANGELOG,
REDIS_URL, REDIS_URL,
@@ -1560,6 +1561,7 @@ if audit_level != AuditLevel.NONE:
audit_level=audit_level, audit_level=audit_level,
excluded_paths=AUDIT_EXCLUDED_PATHS, excluded_paths=AUDIT_EXCLUDED_PATHS,
included_paths=AUDIT_INCLUDED_PATHS, included_paths=AUDIT_INCLUDED_PATHS,
audit_get_requests=ENABLE_AUDIT_GET_REQUESTS,
max_body_size=MAX_BODY_LOG_SIZE, max_body_size=MAX_BODY_LOG_SIZE,
) )
################################## ##################################
+10 -3
View File
@@ -24,7 +24,7 @@ from asgiref.typing import (
from loguru import logger from loguru import logger
from starlette.requests import Request from starlette.requests import Request
from open_webui.env import AUDIT_LOG_LEVEL, AUDIT_INCLUDED_PATHS, MAX_BODY_LOG_SIZE from open_webui.env import AUDIT_LOG_LEVEL, ENABLE_AUDIT_GET_REQUESTS, AUDIT_INCLUDED_PATHS, MAX_BODY_LOG_SIZE
from open_webui.utils.auth import get_current_user, get_http_authorization_cred from open_webui.utils.auth import get_current_user, get_http_authorization_cred
from open_webui.models.users import UserModel from open_webui.models.users import UserModel
@@ -117,7 +117,7 @@ class AuditLoggingMiddleware:
ASGI middleware that intercepts HTTP requests and responses to perform audit logging. It captures request/response bodies (depending on audit level), headers, HTTP methods, and user information, then logs a structured audit entry at the end of the request cycle. ASGI middleware that intercepts HTTP requests and responses to perform audit logging. It captures request/response bodies (depending on audit level), headers, HTTP methods, and user information, then logs a structured audit entry at the end of the request cycle.
""" """
AUDITED_METHODS = {'PUT', 'PATCH', 'DELETE', 'POST'} DEFAULT_AUDITED_METHODS = {'PUT', 'PATCH', 'DELETE', 'POST'}
def __init__( def __init__(
self, self,
@@ -127,12 +127,16 @@ class AuditLoggingMiddleware:
included_paths: Optional[list[str]] = None, included_paths: Optional[list[str]] = None,
max_body_size: int = MAX_BODY_LOG_SIZE, max_body_size: int = MAX_BODY_LOG_SIZE,
audit_level: AuditLevel = AuditLevel.NONE, audit_level: AuditLevel = AuditLevel.NONE,
audit_get_requests: bool = False,
) -> None: ) -> None:
self.app = app self.app = app
self.audit_logger = AuditLogger(logger) self.audit_logger = AuditLogger(logger)
self.excluded_paths = excluded_paths or [] self.excluded_paths = excluded_paths or []
self.included_paths = included_paths or [] self.included_paths = included_paths or []
self.max_body_size = max_body_size self.max_body_size = max_body_size
self.audited_methods = set(self.DEFAULT_AUDITED_METHODS)
if audit_get_requests:
self.audited_methods.add('GET')
self.audit_level = audit_level self.audit_level = audit_level
if self.included_paths and self.excluded_paths: if self.included_paths and self.excluded_paths:
@@ -202,7 +206,10 @@ class AuditLoggingMiddleware:
return None return None
def _should_skip_auditing(self, request: Request) -> bool: def _should_skip_auditing(self, request: Request) -> bool:
if request.method not in {'POST', 'PUT', 'PATCH', 'DELETE'} or AUDIT_LOG_LEVEL == 'NONE': if AUDIT_LOG_LEVEL == 'NONE':
return True
if request.method not in self.audited_methods:
return True return True
ALWAYS_LOG_ENDPOINTS = { ALWAYS_LOG_ENDPOINTS = {