Skip to content

Commit afa0609

Browse files
committed
feat: support whitelist filtering in AuditLoggingMiddleware (open-webui#22515)
Add AUDIT_INCLUDED_PATHS env var for whitelist-based audit filtering. When set, only matching paths are audited and AUDIT_EXCLUDED_PATHS is ignored. Auth endpoints (signin/signout/signup) are always logged regardless of filtering mode.
1 parent 1b1abdd commit afa0609

3 files changed

Lines changed: 27 additions & 2 deletions

File tree

backend/open_webui/env.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -964,6 +964,12 @@ def parse_section(section):
964964
AUDIT_EXCLUDED_PATHS = [path.strip() for path in AUDIT_EXCLUDED_PATHS]
965965
AUDIT_EXCLUDED_PATHS = [path.lstrip("/") for path in AUDIT_EXCLUDED_PATHS]
966966

967+
# Comma separated list of urls to include in audit (whitelist mode)
968+
# When set, only these paths are audited and AUDIT_EXCLUDED_PATHS is ignored
969+
AUDIT_INCLUDED_PATHS = os.getenv("AUDIT_INCLUDED_PATHS", "").split(",")
970+
AUDIT_INCLUDED_PATHS = [path.strip() for path in AUDIT_INCLUDED_PATHS]
971+
AUDIT_INCLUDED_PATHS = [path.lstrip("/") for path in AUDIT_INCLUDED_PATHS if path]
972+
967973

968974
####################################
969975
# OPENTELEMETRY

backend/open_webui/main.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,7 @@
467467
ENABLE_CUSTOM_MODEL_FALLBACK,
468468
LICENSE_KEY,
469469
AUDIT_EXCLUDED_PATHS,
470+
AUDIT_INCLUDED_PATHS,
470471
AUDIT_LOG_LEVEL,
471472
CHANGELOG,
472473
REDIS_URL,
@@ -1581,6 +1582,7 @@ async def inspect_websocket(request: Request, call_next):
15811582
AuditLoggingMiddleware,
15821583
audit_level=audit_level,
15831584
excluded_paths=AUDIT_EXCLUDED_PATHS,
1585+
included_paths=AUDIT_INCLUDED_PATHS,
15841586
max_body_size=MAX_BODY_LOG_SIZE,
15851587
)
15861588
##################################

backend/open_webui/utils/audit.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
from loguru import logger
2525
from starlette.requests import Request
2626

27-
from open_webui.env import AUDIT_LOG_LEVEL, MAX_BODY_LOG_SIZE
27+
from open_webui.env import AUDIT_LOG_LEVEL, AUDIT_INCLUDED_PATHS, MAX_BODY_LOG_SIZE
2828
from open_webui.utils.auth import get_current_user, get_http_authorization_cred
2929
from open_webui.models.users import UserModel
3030

@@ -129,15 +129,23 @@ def __init__(
129129
app: ASGI3Application,
130130
*,
131131
excluded_paths: Optional[list[str]] = None,
132+
included_paths: Optional[list[str]] = None,
132133
max_body_size: int = MAX_BODY_LOG_SIZE,
133134
audit_level: AuditLevel = AuditLevel.NONE,
134135
) -> None:
135136
self.app = app
136137
self.audit_logger = AuditLogger(logger)
137138
self.excluded_paths = excluded_paths or []
139+
self.included_paths = included_paths or []
138140
self.max_body_size = max_body_size
139141
self.audit_level = audit_level
140142

143+
if self.included_paths and self.excluded_paths:
144+
logger.warning(
145+
"Both AUDIT_INCLUDED_PATHS and AUDIT_EXCLUDED_PATHS are set. "
146+
"AUDIT_INCLUDED_PATHS (whitelist) takes precedence."
147+
)
148+
141149
async def __call__(
142150
self,
143151
scope: ASGIScope,
@@ -226,7 +234,16 @@ def _should_skip_auditing(self, request: Request) -> bool:
226234
):
227235
return True
228236

229-
# match either /api/<resource>/...(for the endpoint /api/chat case) or /api/v1/<resource>/...
237+
# Whitelist mode: only log paths that match included_paths
238+
if self.included_paths:
239+
pattern = re.compile(
240+
r"^/api(?:/v1)?/(" + "|".join(self.included_paths) + r")\b"
241+
)
242+
if not pattern.match(request.url.path):
243+
return True # Skip: path not in whitelist
244+
return False # Do NOT skip: path is in whitelist
245+
246+
# Blacklist mode: skip paths that match excluded_paths
230247
pattern = re.compile(
231248
r"^/api(?:/v1)?/(" + "|".join(self.excluded_paths) + r")\b"
232249
)

0 commit comments

Comments
 (0)