From b55000663e3579a263cd3496d438aff4892af34c Mon Sep 17 00:00:00 2001 From: ibuler Date: Thu, 27 Mar 2025 16:07:57 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E6=8F=90=E5=8D=87=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E6=B3=A8=E5=86=8C=E5=AE=89=E5=85=A8=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/authentication/backends/test/test_drf.py | 30 +++++++++++++++++++ apps/common/permissions.py | 13 ++++++++ apps/jumpserver/conf.py | 2 +- apps/jumpserver/settings/libs.py | 4 ++- apps/settings/serializers/terminal.py | 6 +++- apps/terminal/api/component/terminal.py | 6 ---- 6 files changed, 52 insertions(+), 9 deletions(-) create mode 100644 apps/authentication/backends/test/test_drf.py diff --git a/apps/authentication/backends/test/test_drf.py b/apps/authentication/backends/test/test_drf.py new file mode 100644 index 000000000..4e55b846d --- /dev/null +++ b/apps/authentication/backends/test/test_drf.py @@ -0,0 +1,30 @@ +import os +import requests +from httpsig.requests_auth import HTTPSignatureAuth +import datetime + + +def test_drf_ak(): + KEY_ID = os.environ.get('KEY_ID') or '' + SECRET = os.environ.get('KEY_SECRET') or '' + + signature_headers = ['(request-target)', 'date'] + now = datetime.datetime.now() + headers = { + 'Host': 'localhost:8000', + 'Accept': 'application/json', + 'Date': now.strftime('%a, %d %b %Y %H:%M:%S GMT'), + } + + # url = 'http://localhost:8080/api/v1/assets/assets/?limit=100' + url = 'http://localhost:8080/api/v1/users/users/?limit=100' + + auth = HTTPSignatureAuth(key_id=KEY_ID, secret=SECRET, + algorithm='hmac-sha256', + headers=signature_headers) + req = requests.get(url, auth=auth, headers=headers) + print(req.content) + + +if __name__ == '__main__': + test_drf_ak() diff --git a/apps/common/permissions.py b/apps/common/permissions.py index fd3e984e3..898308d03 100644 --- a/apps/common/permissions.py +++ b/apps/common/permissions.py @@ -27,10 +27,23 @@ class IsServiceAccount(IsValidUser): class WithBootstrapToken(permissions.BasePermission): + def check_can_register(self): + enabled = settings.SECURITY_SERVICE_ACCOUNT_REGISTRATION + if enabled == 'auto': + return time.time() - settings.JUMPSERVER_UPTIME < 300 + elif enabled: + return True + else: + return False + def has_permission(self, request, view): authorization = request.META.get('HTTP_AUTHORIZATION', '') if not authorization: return False + + if not self.check_can_register(): + return False + request_bootstrap_token = authorization.split()[-1] return settings.BOOTSTRAP_TOKEN == request_bootstrap_token diff --git a/apps/jumpserver/conf.py b/apps/jumpserver/conf.py index 0471bcd9d..4da1bb28a 100644 --- a/apps/jumpserver/conf.py +++ b/apps/jumpserver/conf.py @@ -568,7 +568,7 @@ class Config(dict): 'SECURITY_COMMAND_BLACKLIST': [ 'reboot', 'shutdown', 'poweroff', 'halt', 'dd', 'half', 'top' ], - 'SECURITY_SERVICE_ACCOUNT_REGISTRATION': True, + 'SECURITY_SERVICE_ACCOUNT_REGISTRATION': 'auto', 'SECURITY_VIEW_AUTH_NEED_MFA': True, 'SECURITY_MAX_IDLE_TIME': 30, 'SECURITY_MAX_SESSION_TIME': 24, diff --git a/apps/jumpserver/settings/libs.py b/apps/jumpserver/settings/libs.py index d705939e6..70eee17e6 100644 --- a/apps/jumpserver/settings/libs.py +++ b/apps/jumpserver/settings/libs.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # import os - +import time from .base import ( REDIS_SSL_CA, REDIS_SSL_CERT, REDIS_SSL_KEY, REDIS_SSL_REQUIRED, REDIS_USE_SSL, REDIS_PROTOCOL, REDIS_SENTINEL_SERVICE_NAME, REDIS_SENTINELS, REDIS_SENTINEL_PASSWORD, @@ -197,3 +197,5 @@ PIICO_DEVICE_ENABLE = CONFIG.PIICO_DEVICE_ENABLE PIICO_DRIVER_PATH = CONFIG.PIICO_DRIVER_PATH LEAK_PASSWORD_DB_PATH = CONFIG.LEAK_PASSWORD_DB_PATH + +JUMPSERVER_UPTIME = int(time.time()) diff --git a/apps/settings/serializers/terminal.py b/apps/settings/serializers/terminal.py index c9172b228..8e484e5ad 100644 --- a/apps/settings/serializers/terminal.py +++ b/apps/settings/serializers/terminal.py @@ -18,7 +18,11 @@ class TerminalSettingSerializer(serializers.Serializer): ('25', '25'), ('50', '50'), ) - SECURITY_SERVICE_ACCOUNT_REGISTRATION = serializers.BooleanField( + SECURITY_SERVICE_ACCOUNT_REGISTRATION = serializers.ChoiceField( + choices=[ + ('auto', _('Auto(Enabled for the first 5 minutes after startup, then disabled.)')), + (True, _('Enable')), (False, _('Disable')) + ], required=True, label=_('Registration'), help_text=_( "Allow component register, after all component setup, you should disable this for security" diff --git a/apps/terminal/api/component/terminal.py b/apps/terminal/api/component/terminal.py index defe33773..6c1f0f0c7 100644 --- a/apps/terminal/api/component/terminal.py +++ b/apps/terminal/api/component/terminal.py @@ -85,12 +85,6 @@ class TerminalRegistrationApi(generics.CreateAPIView): permission_classes = [WithBootstrapToken] http_method_names = ['post'] - def create(self, request, *args, **kwargs): - if not settings.SECURITY_SERVICE_ACCOUNT_REGISTRATION: - data = {"error": "service account registration disabled"} - return Response(data=data, status=status.HTTP_400_BAD_REQUEST) - return super().create(request, *args, **kwargs) - class EncryptedTerminalConfig(generics.CreateAPIView): serializer_class = serializers.EncryptedConfigSerializer