Merge pull request #8076 from jumpserver/dev

v2.21.0-rc3
pull/8133/head
Jiangjie.Bai 2022-04-18 11:43:40 +08:00 committed by GitHub
commit afcbe60531
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 66 additions and 10 deletions

View File

@ -288,15 +288,14 @@ class Application(CommonModelMixin, OrgModelMixin, ApplicationTreeNodeMixin):
raise ValueError("Remote App not has asset attr")
def get_target_ip(self):
target_ip = ''
if self.category_remote_app:
asset = self.get_remote_app_asset()
target_ip = asset.ip
target_ip = asset.ip if asset else target_ip
elif self.category_cloud:
target_ip = self.attrs.get('cluster')
elif self.category_db:
target_ip = self.attrs.get('host')
else:
target_ip = ''
return target_ip

View File

@ -484,7 +484,8 @@ class UserConnectionTokenViewSet(
tp = 'app' if application else 'asset'
data = {
"id": token, 'secret': secret,
'type': tp, 'protocol': system_user.protocol
'type': tp, 'protocol': system_user.protocol,
'expire_time': self.get_token_ttl(token),
}
return Response(data, status=201)

View File

@ -1,5 +1,7 @@
from django.shortcuts import redirect, reverse
from django.utils.deprecation import MiddlewareMixin
from django.http import HttpResponse
from django.conf import settings
class MFAMiddleware:
@ -34,3 +36,15 @@ class MFAMiddleware:
url = reverse('authentication:login-mfa') + '?_=middleware'
return redirect(url)
class SessionCookieMiddleware(MiddlewareMixin):
@staticmethod
def process_response(request, response: HttpResponse):
key = settings.SESSION_COOKIE_NAME_PREFIX_KEY
value = settings.SESSION_COOKIE_NAME_PREFIX
if request.COOKIES.get(key) == value:
return response
response.set_cookie(key, value)
return response

View File

@ -1,5 +1,7 @@
import time
from channels_redis.core import RedisChannelLayer as _RedisChannelLayer
from common.utils.lock import DistributedLock
from common.utils.connection import get_redis_client
from common.utils import lazyproperty
@ -216,3 +218,29 @@ class CacheValueDesc:
def to_internal_value(self, value):
return self.field_type.field_type(value)
class RedisChannelLayer(_RedisChannelLayer):
async def _brpop_with_clean(self, index, channel, timeout):
cleanup_script = """
local backed_up = redis.call('ZRANGE', ARGV[2], 0, -1, 'WITHSCORES')
for i = #backed_up, 1, -2 do
redis.call('ZADD', ARGV[1], backed_up[i], backed_up[i - 1])
end
redis.call('DEL', ARGV[2])
"""
backup_queue = self._backup_channel_name(channel)
async with self.connection(index) as connection:
# 部分云厂商的 Redis 此操作会报错(不支持,比如阿里云有限制)
try:
await connection.eval(cleanup_script, keys=[], args=[channel, backup_queue])
except:
pass
result = await connection.bzpopmin(channel, timeout=timeout)
if result is not None:
_, member, timestamp = result
await connection.zadd(backup_queue, float(timestamp), member)
else:
member = None
return member

View File

@ -157,6 +157,7 @@ class Config(dict):
'DEFAULT_EXPIRED_YEARS': 70,
'SESSION_COOKIE_DOMAIN': None,
'CSRF_COOKIE_DOMAIN': None,
'SESSION_COOKIE_NAME_PREFIX': None,
'SESSION_COOKIE_AGE': 3600 * 24,
'SESSION_EXPIRE_AT_BROWSER_CLOSE': False,
'LOGIN_URL': reverse_lazy('authentication:login'),

View File

@ -94,6 +94,7 @@ MIDDLEWARE = [
'authentication.backends.oidc.middleware.OIDCRefreshIDTokenMiddleware',
'authentication.backends.cas.middleware.CASMiddleware',
'authentication.middleware.MFAMiddleware',
'authentication.middleware.SessionCookieMiddleware',
'simple_history.middleware.HistoryRequestMiddleware',
]
@ -128,6 +129,20 @@ LOGIN_URL = reverse_lazy('authentication:login')
SESSION_COOKIE_DOMAIN = CONFIG.SESSION_COOKIE_DOMAIN
CSRF_COOKIE_DOMAIN = CONFIG.SESSION_COOKIE_DOMAIN
# 设置 SESSION_COOKIE_NAME_PREFIX_KEY
# 解决 不同域 session csrf cookie 获取混乱问题
SESSION_COOKIE_NAME_PREFIX_KEY = 'SESSION_COOKIE_NAME_PREFIX'
SESSION_COOKIE_NAME_PREFIX = CONFIG.SESSION_COOKIE_NAME_PREFIX
if SESSION_COOKIE_NAME_PREFIX is not None:
pass
elif SESSION_COOKIE_DOMAIN is not None:
SESSION_COOKIE_NAME_PREFIX = SESSION_COOKIE_DOMAIN.split('.')[0]
else:
SESSION_COOKIE_NAME_PREFIX = 'jms_'
CSRF_COOKIE_NAME = '{}csrftoken'.format(SESSION_COOKIE_NAME_PREFIX)
SESSION_COOKIE_NAME = '{}sessionid'.format(SESSION_COOKIE_NAME_PREFIX)
SESSION_COOKIE_AGE = CONFIG.SESSION_COOKIE_AGE
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
# 自定义的配置SESSION_EXPIRE_AT_BROWSER_CLOSE 始终为 True, 下面这个来控制是否强制关闭后过期 cookie

View File

@ -96,12 +96,12 @@ else:
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'BACKEND': 'common.cache.RedisChannelLayer',
'CONFIG': {
"hosts": [{
'address': (CONFIG.REDIS_HOST, CONFIG.REDIS_PORT),
'db': CONFIG.REDIS_DB_WS,
'password': CONFIG.REDIS_PASSWORD,
'password': CONFIG.REDIS_PASSWORD or None,
'ssl': context
}],
},

View File

@ -8,6 +8,7 @@ from assets.models import Asset
from orgs.utils import tmp_to_root_org
from applications.models import Application
from terminal.models import Session
from common.permissions import IsValidUser
from ..models import Endpoint, EndpointRule
from .. import serializers
@ -20,9 +21,6 @@ class EndpointViewSet(JMSBulkModelViewSet):
search_fields = filterset_fields
serializer_class = serializers.EndpointSerializer
queryset = Endpoint.objects.all()
rbac_perms = {
'smart': 'terminal.view_endpoint'
}
@staticmethod
def get_target_ip(request):
@ -57,7 +55,7 @@ class EndpointViewSet(JMSBulkModelViewSet):
target_ip = instance.get_target_ip()
return target_ip
@action(methods=['get'], detail=False, url_path='smart')
@action(methods=['get'], detail=False, permission_classes=[IsValidUser], url_path='smart')
def smart(self, request, *args, **kwargs):
protocol = request.GET.get('protocol')
if not protocol: