Compare commits

...

5 Commits

Author SHA1 Message Date
github-actions[bot]
254d0fc2b2 perf: Update Dockerfile with new base image tag 2025-12-26 09:58:35 +00:00
wangruidong
d229a809b0 fix: api docs access error 2025-12-26 17:52:08 +08:00
wangruidong
c39ef027f1 perf: Implement AsyncLocal for asynchronous context storage and update signal handler 2025-12-26 15:28:02 +08:00
wangruidong
6dfddf9d2a fix: Update aliyun-python-sdk-core-v3 to version 2.13.36 and remove telnetlib3 dependency 2025-12-26 15:20:50 +08:00
wangruidong
916dc5578a perf: Upgrade python version and dependency libraries 2025-12-25 17:25:12 +08:00
10 changed files with 2483 additions and 2093 deletions

View File

@@ -1,4 +1,4 @@
FROM jumpserver/core-base:20251128_025056 AS stage-build
FROM jumpserver/core-base:20251226_095252 AS stage-build
ARG VERSION

View File

@@ -12,7 +12,7 @@ from urllib.parse import urlparse
from django.conf import settings
from django.core.exceptions import SuspiciousOperation
from django.utils.encoding import force_bytes, smart_bytes
from django.utils.encoding import force_bytes
from jwkest import JWKESTException
from jwkest.jwk import KEYS
from jwkest.jws import JWS
@@ -58,7 +58,7 @@ def _get_jwks_keys(shared_key):
# Adds the shared key (which can correspond to the client_secret) as an oct key so it can be
# used for HMAC signatures.
logger.debug(log_prompt.format('Add key'))
jwks_keys.add({'key': smart_bytes(shared_key), 'kty': 'oct'})
jwks_keys.add({'key': force_bytes(shared_key), 'kty': 'oct'})
logger.debug(log_prompt.format('End'))
return jwks_keys

View File

@@ -1,9 +1,39 @@
import contextvars
import re
from werkzeug.local import Local
from typing import Any, Dict
thread_local = Local()
class AsyncLocal:
"""
一个异步环境下安全的上下文存储对象,用于替代 werkzeug.local.Local。
内部使用一个 ContextVar 来存储一个字典。
"""
def __init__(self, context_var_name: str = "_async_local_storage"):
self._storage: contextvars.ContextVar[Dict[str, Any]] = contextvars.ContextVar(
context_var_name,
default={}
)
def set(self, key: str, value: Any) -> None:
current_data = self._storage.get().copy()
current_data[key] = value
self._storage.set(current_data)
def get(self, key: str, default: Any = None) -> Any:
return self._storage.get().get(key, default)
def delete(self, key: str) -> None:
current_data = self._storage.get().copy()
if key in current_data:
del current_data[key]
self._storage.set(current_data)
def clear(self) -> None:
self._storage.set({})
thread_local = AsyncLocal()
exclude_encrypted_fields = ('secret_type', 'secret_strategy', 'password_rules')
similar_encrypted_pattern = re.compile(
'password|secret|token|passphrase|private|key|cert', re.IGNORECASE

View File

@@ -92,7 +92,7 @@ def on_request_finished_logging_db_query(sender, **kwargs):
def on_request_finished_release_local(sender, **kwargs):
thread_local.__release_local__()
thread_local.clear()
def _get_request_user_name():

View File

@@ -2,6 +2,7 @@
#
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,
@@ -87,6 +88,7 @@ SPECTACULAR_SETTINGS = {
'jumpserver.views.schema.LabelRelatedFieldExtension',
],
'SECURITY': [{'Bearer': []}],
'DISABLE_ERRORS_AND_WARNINGS': True
}
# Captcha settings, more see https://django-simple-captcha.readthedocs.io/en/latest/advanced.html
CAPTCHA_IMAGE_SIZE = (180, 38)

View File

@@ -28,7 +28,7 @@ is_available:
sample: true
'''
import telnetlib
import telnetlib3
from ansible.module_utils.basic import AnsibleModule
@@ -57,9 +57,9 @@ def main():
port = module.params['login_port']
timeout = module.params['timeout']
try:
client = telnetlib.Telnet(host, port, timeout=timeout)
client = telnetlib3.Telnet(host, port, timeout=timeout)
client.close()
except Exception as err: # noqa
except Exception as err: # noqa
result['is_available'] = False
module.fail_json(msg='Unable to connect to asset: %s' % err)

View File

@@ -2,7 +2,8 @@
#
import asyncio
import socket
import telnetlib
import telnetlib3
from settings.utils import generate_ips
@@ -12,7 +13,7 @@ PROMPT_REGEX = r'[\<|\[](.*)[\>|\]]'
async def telnet(dest_addr, port_number=23, timeout=10):
loop = asyncio.get_running_loop()
try:
connection = await loop.run_in_executor(None, telnetlib.Telnet, dest_addr, port_number, timeout)
connection = await loop.run_in_executor(None, telnetlib3.Telnet, dest_addr, port_number, timeout)
except asyncio.TimeoutError:
return False, 'Timeout'
except (ConnectionRefusedError, socket.timeout, socket.gaierror) as e:

View File

@@ -60,10 +60,6 @@ class TerminalSerializer(BulkModelSerializer):
fields_fk = ['load', 'stat']
fields = fields_small + fields_fk
read_only_fields = ['type', 'date_created']
extra_kwargs = {
'command_storage': {'required': True, },
'replay_storage': {'required': True, },
}
@staticmethod
def get_kwargs_may_be_uuid(value):

View File

@@ -40,11 +40,11 @@ dependencies = [
'pyyaml==6.0.1',
'requests==2.32.4',
'simplejson==3.19.1',
'six==1.16.0',
'six==1.17.0',
'sshtunnel==0.4.0',
'sshpubkeys==3.3.1',
'uritemplate==4.1.1',
'vine==5.0.0',
'vine==5.1.0',
'werkzeug==3.0.6',
'unicodecsv==0.14.1',
'httpsig==1.3.0',
@@ -68,32 +68,32 @@ dependencies = [
'ipip-ipdb==1.6.1',
'pywinrm==0.4.3',
'python-nmap==0.7.1',
'django==4.1.13',
'django==5.2.9',
'django-bootstrap3==23.4',
'django-filter==23.2',
'django-filter==24.3',
'django-formtools==2.5.1',
'django-ranged-response==0.2.0',
'django-simple-captcha==0.5.18',
'django-timezone-field==5.1',
'djangorestframework==3.14.0',
'django-timezone-field==7.1',
'djangorestframework==3.15.0',
'djangorestframework-bulk==0.2.1',
'django-simple-history==3.6.0',
'django-private-storage==3.1',
'django-private-storage==3.1.3',
'drf-nested-routers==0.93.4',
'drf-writable-nested==0.7.0',
'rest-condition==1.0.3',
'drf-spectacular==0.28.0',
'pillow==10.2.0',
'drf-spectacular==0.29.0',
'pillow==12.0.0',
'pytz==2025.2',
'django-proxy==1.2.2',
'python-daemon==3.0.1',
'eventlet==0.40.3',
'greenlet==3.2.4',
'gunicorn==23.0.0',
'celery==5.3.1',
'celery==5.6.0',
'flower==2.0.1',
'django-celery-beat==2.6.0',
'kombu==5.3.5',
'django-celery-beat==2.8.1',
'kombu==5.6.0',
'uvicorn==0.22.0',
'websockets==11.0.3',
'python-ldap==3.4.5',
@@ -103,10 +103,10 @@ dependencies = [
'python-cas==1.6.0',
'django-auth-ldap==4.4.0',
'mysqlclient==2.2.4',
'pymssql==2.3.4',
'django-redis==5.3.0',
'pymssql==2.3.10',
'django-redis==5.4.0',
'python-redis-lock==4.0.0',
'pyopenssl==23.2.0',
'pyopenssl==24.0.0',
'redis',
'pymongo==4.6.3',
'pyfreerdp==0.0.2',
@@ -177,7 +177,7 @@ xpack = [
'python-keystoneclient==5.1.0',
'bce-python-sdk==0.8.87',
'tencentcloud-sdk-python==3.0.941',
'aliyun-python-sdk-core-v3==2.13.33',
'aliyun-python-sdk-core-v3==2.13.36',
'aliyun-python-sdk-ecs==4.24.64',
'keystoneauth1==5.2.1',
'oracledb==1.4.0',

4483
uv.lock generated

File diff suppressed because it is too large Load Diff