diff --git a/apps/common/permissions.py b/apps/common/permissions.py index b7d3691e2..cfb0c9d88 100644 --- a/apps/common/permissions.py +++ b/apps/common/permissions.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- # +import hmac import time from django.conf import settings @@ -55,7 +56,10 @@ class WithBootstrapToken(permissions.BasePermission): return False request_bootstrap_token = authorization.split()[-1] - return settings.BOOTSTRAP_TOKEN == request_bootstrap_token + return hmac.compare_digest( + settings.BOOTSTRAP_TOKEN.encode(), + request_bootstrap_token.encode() + ) class ServiceAccountSignaturePermission(permissions.BasePermission): diff --git a/apps/jumpserver/middleware.py b/apps/jumpserver/middleware.py index 0b525f021..966200ff9 100644 --- a/apps/jumpserver/middleware.py +++ b/apps/jumpserver/middleware.py @@ -18,8 +18,11 @@ from django.urls import reverse from django.utils import timezone from rest_framework import status +from common.utils import get_logger from .utils import set_current_request +logger = get_logger(__name__) + IGNORE_CSRF_CHECK = '*' in os.getenv("DOMAINS", "").split(',') @@ -148,8 +151,9 @@ class EndMiddleware: def process_exception(self, request, exception): if isinstance(exception, OperationalError): + logger.debug("Database operational error: %s", exception) return JsonResponse({ - 'error': 'Database OperationalError: ' + str(exception), + 'error': 'Service temporarily unavailable', 'message': 'Database operation failed, please try again later.', 'code': 'DB_ERROR' }, status=status.HTTP_503_SERVICE_UNAVAILABLE) diff --git a/apps/terminal/mixin.py b/apps/terminal/mixin.py index 6a697527d..c35440bd4 100644 --- a/apps/terminal/mixin.py +++ b/apps/terminal/mixin.py @@ -1,4 +1,5 @@ import os +import re from django.utils.translation import get_language @@ -15,11 +16,23 @@ class LokiMixin: return get_loki_client() @staticmethod - def create_loki_query(components, search): + def _escape_loki_regex(value): + # 转义 \ " { } | = ~ ! 等 LogQL stream selector 特殊字符 + return re.sub(r'([\\"{}\[\]|=~!()])', r"\\\1", str(value)) + + @staticmethod + def _escape_loki_filter(value): + # 转义 line filter 中的 \ 和 " 防止逃逸 + return str(value).replace("\\", "\\\\").replace('"', '\\"') + + @classmethod + def create_loki_query(cls, components, search): stream_selector = '{component!=""}' if components: - stream_selector = '{component=~"%s"}' % components - query = f'{stream_selector} |="{search}"' + escaped = cls._escape_loki_regex(components) + stream_selector = '{component=~"%s"}' % escaped + escaped_search = cls._escape_loki_filter(search) + query = f'{stream_selector} |="{escaped_search}"' return query