mirror of
https://github.com/jumpserver/jumpserver.git
synced 2026-01-17 07:58:52 +00:00
* [Update] 暂存,优化解决不了问题 * [Update] 待续(小白) * [Update] 修改asset user * [Update] 计划再次更改 * [Update] 修改asset user * [Update] 暂存与喜爱 * [Update] Add id in * [Update] 阶段性完成ops task该做 * [Update] 修改asset user api * [Update] 修改asset user 任务,查看认证等 * [Update] 基本完成asset user改造 * [Update] dynamic user only allow 1 * [Update] 修改asset user task * [Update] 修改node admin user task api * [Update] remove file header license * [Update] 添加sftp root * [Update] 暂存 * [Update] 暂存 * [Update] 修改翻译 * [Update] 修改系统用户改为同名后,用户名改为空 * [Update] 基本完成CAS调研 * [Update] 支持cas server * [Update] 支持cas server * [Update] 添加requirements * [Update] 为方便调试添加mysql ipython到包中 * [Update] 添加huaweiyun翻译 * [Update] 增加下载session 录像 * [Update] 只有第一次通知replay离线的使用方法 * [Update] 暂存一下 * [Bugfix] 获取系统用户信息报错 * [Bugfix] 修改system user info * [Update] 改成清理10天git status * [Update] 修改celery日志保留时间 * [Update]修复部分pip包依赖的版本不兼容问题 (#3672) * [Update] 修复用户更新页面会清空用户public_key的问题 * Fix broken dependencies Co-authored-by: BaiJiangJie <32935519+BaiJiangJie@users.noreply.github.com> * [Update] 修改获取系统用户auth info * [Update] Remove log * [Bugfix] 修复sftp home设置的bug * [Update] 授权的系统用户添加sftp root * [Update] 修改系统用户关联的用户 * [Update] 修改placeholder * [Update] 优化获取授权的系统用户 * [Update] 修改tasks * [Update] tree service update * [Update] 暂存 * [Update] 基本完成用户授权树和资产树改造 * [Update] Dashbaord perf * [update] Add huawei cloud sdk requirements * [Updte] 优化dashboard页面 * [Update] system user auth info 添加id * [Update] 修改系统用户serializer * [Update] 优化api * [Update] LDAP Test Util (#3720) * [Update] LDAPTestUtil 1 * [Update] LDAPTestUtil 2 * [Update] LDAPTestUtil 3 * [Update] LDAPTestUtil 4 * [Update] LDAPTestUtil 5 * [Update] LDAPTestUtil 6 * [Update] LDAPTestUtil 7 * [Update] session 已添加is success,并且添加display serializer * [Bugfix] 修复无法删除空节点的bug * [Update] 命令记录分组织显示 * [Update] Session is_success 添加迁移文件 * [Update] 批量命令添加org_id * [Update] 修复一些文案,修改不绑定MFA,不能ssh登录 * [Update] 修改replay api, 返回session信息 * [Update] 解决无效es导致访问命令记录页面失败的问题 * [Update] 拆分profile view * [Update] 修改一个翻译 * [Update] 修改aysnc api框架 * [Update] 命令列表添加risk level * [Update] 完成录像打包下载 * [Update] 更改登陆otp页面 * [Update] 修改command 存储redis_level * [Update] 修改翻译 * [Update] 修改系统用户的用户列表字段 * [Update] 使用新logo和统一Jumpserver为JumpServer * [Update] 优化cloud task * [Update] 统一period task * [Update] 统一period form serializer字段 * [Update] 修改period task * [Update] 修改资产网关信息 * [Update] 用户授权资产树资产信息添加domain * [Update] 修改翻译 * [Update] 测试可连接性 * 1.5.7 bai (#3764) * [Update] 修复index页面Bug;修复测试资产用户可连接性问题; * [Update] 修改测试资产用户可连接 * [Bugfix] 修复backends问题 * [Update] 修改marksafe依赖版本 * [Update] 修改测试资产用户可连接性 * [Update] 修改检测服务器性能时获取percent值 * [Update] 更新依赖boto3=1.12.14 Co-authored-by: Yanzhe Lee <lee.yanzhe@yanzhe.org> Co-authored-by: BaiJiangJie <32935519+BaiJiangJie@users.noreply.github.com> Co-authored-by: Bai <bugatti_it@163.com>
263 lines
9.4 KiB
Python
263 lines
9.4 KiB
Python
# -*- coding: utf-8 -*-
|
|
#
|
|
|
|
import json
|
|
|
|
from smtplib import SMTPSenderRefused
|
|
from rest_framework import generics
|
|
from rest_framework.views import Response, APIView
|
|
from django.conf import settings
|
|
from django.core.mail import send_mail
|
|
from django.utils.translation import ugettext_lazy as _
|
|
|
|
from .utils import (
|
|
LDAPServerUtil, LDAPCacheUtil, LDAPImportUtil, LDAPSyncUtil,
|
|
LDAP_USE_CACHE_FLAGS, LDAPTestUtil,
|
|
)
|
|
from .tasks import sync_ldap_user_task
|
|
from common.permissions import IsOrgAdmin, IsSuperUser
|
|
from common.utils import get_logger
|
|
from .serializers import (
|
|
MailTestSerializer, LDAPTestConfigSerializer, LDAPUserSerializer,
|
|
PublicSettingSerializer, LDAPTestLoginSerializer,
|
|
)
|
|
from users.models import User
|
|
|
|
|
|
logger = get_logger(__file__)
|
|
|
|
|
|
class MailTestingAPI(APIView):
|
|
permission_classes = (IsSuperUser,)
|
|
serializer_class = MailTestSerializer
|
|
success_message = _("Test mail sent to {}, please check")
|
|
|
|
def post(self, request):
|
|
serializer = self.serializer_class(data=request.data)
|
|
if serializer.is_valid():
|
|
email_from = serializer.validated_data["EMAIL_FROM"]
|
|
email_recipient = serializer.validated_data["EMAIL_RECIPIENT"]
|
|
email_host_user = serializer.validated_data["EMAIL_HOST_USER"]
|
|
for k, v in serializer.validated_data.items():
|
|
if k.startswith('EMAIL'):
|
|
setattr(settings, k, v)
|
|
try:
|
|
subject = "Test"
|
|
message = "Test smtp setting"
|
|
email_from = email_from or email_host_user
|
|
email_recipient = email_recipient or email_from
|
|
send_mail(subject, message, email_from, [email_recipient])
|
|
except SMTPSenderRefused as e:
|
|
resp = e.smtp_error
|
|
if isinstance(resp, bytes):
|
|
for coding in ('gbk', 'utf8'):
|
|
try:
|
|
resp = resp.decode(coding)
|
|
except UnicodeDecodeError:
|
|
continue
|
|
else:
|
|
break
|
|
return Response({"error": str(resp)}, status=401)
|
|
except Exception as e:
|
|
print(e)
|
|
return Response({"error": str(e)}, status=401)
|
|
return Response({"msg": self.success_message.format(email_recipient)})
|
|
else:
|
|
return Response({"error": str(serializer.errors)}, status=401)
|
|
|
|
|
|
class LDAPTestingConfigAPI(APIView):
|
|
permission_classes = (IsSuperUser,)
|
|
serializer_class = LDAPTestConfigSerializer
|
|
|
|
def post(self, request):
|
|
serializer = self.serializer_class(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response({"error": str(serializer.errors)}, status=401)
|
|
config = self.get_ldap_config(serializer)
|
|
ok, msg = LDAPTestUtil(config).test_config()
|
|
status = 200 if ok else 401
|
|
return Response(msg, status=status)
|
|
|
|
@staticmethod
|
|
def get_ldap_config(serializer):
|
|
server_uri = serializer.validated_data["AUTH_LDAP_SERVER_URI"]
|
|
bind_dn = serializer.validated_data["AUTH_LDAP_BIND_DN"]
|
|
password = serializer.validated_data["AUTH_LDAP_BIND_PASSWORD"]
|
|
use_ssl = serializer.validated_data.get("AUTH_LDAP_START_TLS", False)
|
|
search_ou = serializer.validated_data["AUTH_LDAP_SEARCH_OU"]
|
|
search_filter = serializer.validated_data["AUTH_LDAP_SEARCH_FILTER"]
|
|
attr_map = serializer.validated_data["AUTH_LDAP_USER_ATTR_MAP"]
|
|
auth_ldap = serializer.validated_data.get('AUTH_LDAP', False)
|
|
config = {
|
|
'server_uri': server_uri,
|
|
'bind_dn': bind_dn,
|
|
'password': password,
|
|
'use_ssl': use_ssl,
|
|
'search_ou': search_ou,
|
|
'search_filter': search_filter,
|
|
'attr_map': attr_map,
|
|
'auth_ldap': auth_ldap
|
|
}
|
|
return config
|
|
|
|
|
|
class LDAPTestingLoginAPI(APIView):
|
|
permission_classes = (IsSuperUser,)
|
|
serializer_class = LDAPTestLoginSerializer
|
|
|
|
def post(self, request):
|
|
serializer = self.serializer_class(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response({"error": str(serializer.errors)}, status=401)
|
|
username = serializer.validated_data['username']
|
|
password = serializer.validated_data['password']
|
|
ok, msg = LDAPTestUtil().test_login(username, password)
|
|
status = 200 if ok else 401
|
|
return Response(msg, status=status)
|
|
|
|
|
|
class LDAPUserListApi(generics.ListAPIView):
|
|
permission_classes = (IsSuperUser,)
|
|
serializer_class = LDAPUserSerializer
|
|
|
|
def get_queryset_from_cache(self):
|
|
search_value = self.request.query_params.get('search')
|
|
users = LDAPCacheUtil().search(search_value=search_value)
|
|
return users
|
|
|
|
def get_queryset_from_server(self):
|
|
search_value = self.request.query_params.get('search')
|
|
users = LDAPServerUtil().search(search_value=search_value)
|
|
return users
|
|
|
|
def get_queryset(self):
|
|
if hasattr(self, 'swagger_fake_view'):
|
|
return []
|
|
cache_police = self.request.query_params.get('cache_police', True)
|
|
if cache_police in LDAP_USE_CACHE_FLAGS:
|
|
users = self.get_queryset_from_cache()
|
|
else:
|
|
users = self.get_queryset_from_server()
|
|
return users
|
|
|
|
@staticmethod
|
|
def processing_queryset(queryset):
|
|
db_username_list = User.objects.all().values_list('username', flat=True)
|
|
for q in queryset:
|
|
q['id'] = q['username']
|
|
q['existing'] = q['username'] in db_username_list
|
|
return queryset
|
|
|
|
def sort_queryset(self, queryset):
|
|
order_by = self.request.query_params.get('order')
|
|
if not order_by:
|
|
order_by = 'existing'
|
|
if order_by.startswith('-'):
|
|
order_by = order_by.lstrip('-')
|
|
reverse = True
|
|
else:
|
|
reverse = False
|
|
queryset = sorted(queryset, key=lambda x: x[order_by], reverse=reverse)
|
|
return queryset
|
|
|
|
def filter_queryset(self, queryset):
|
|
if queryset is None:
|
|
return queryset
|
|
queryset = self.processing_queryset(queryset)
|
|
queryset = self.sort_queryset(queryset)
|
|
return queryset
|
|
|
|
def list(self, request, *args, **kwargs):
|
|
cache_police = self.request.query_params.get('cache_police', True)
|
|
# 不是用缓存
|
|
if cache_police not in LDAP_USE_CACHE_FLAGS:
|
|
return super().list(request, *args, **kwargs)
|
|
|
|
try:
|
|
queryset = self.get_queryset()
|
|
except Exception as e:
|
|
data = {'error': str(e)}
|
|
return Response(data=data, status=400)
|
|
|
|
# 缓存有数据
|
|
if queryset is not None:
|
|
return super().list(request, *args, **kwargs)
|
|
|
|
sync_util = LDAPSyncUtil()
|
|
# 还没有同步任务
|
|
if sync_util.task_no_start:
|
|
# 任务外部设置 task running 状态
|
|
sync_util.set_task_status(sync_util.TASK_STATUS_IS_RUNNING)
|
|
task = sync_ldap_user_task.delay()
|
|
data = {'msg': 'Cache no data, sync task {} started.'.format(task.id)}
|
|
return Response(data=data, status=409)
|
|
# 同步任务正在执行
|
|
if sync_util.task_is_running:
|
|
data = {'msg': 'synchronization is running.'}
|
|
return Response(data=data, status=409)
|
|
# 同步任务执行结束
|
|
if sync_util.task_is_over:
|
|
msg = sync_util.get_task_error_msg()
|
|
data = {'error': 'Synchronization task report error: {}'.format(msg)}
|
|
return Response(data=data, status=400)
|
|
|
|
return super().list(request, *args, **kwargs)
|
|
|
|
|
|
class LDAPUserImportAPI(APIView):
|
|
permission_classes = (IsSuperUser,)
|
|
|
|
def get_ldap_users(self):
|
|
username_list = self.request.data.get('username_list', [])
|
|
cache_police = self.request.query_params.get('cache_police', True)
|
|
if cache_police in LDAP_USE_CACHE_FLAGS:
|
|
users = LDAPCacheUtil().search(search_users=username_list)
|
|
else:
|
|
users = LDAPServerUtil().search(search_users=username_list)
|
|
return users
|
|
|
|
def post(self, request):
|
|
try:
|
|
users = self.get_ldap_users()
|
|
except Exception as e:
|
|
return Response({'error': str(e)}, status=401)
|
|
|
|
if users is None:
|
|
return Response({'msg': _('Get ldap users is None')}, status=401)
|
|
|
|
errors = LDAPImportUtil().perform_import(users)
|
|
if errors:
|
|
return Response({'errors': errors}, status=401)
|
|
|
|
count = users if users is None else len(users)
|
|
return Response({'msg': _('Imported {} users successfully').format(count)})
|
|
|
|
|
|
class LDAPCacheRefreshAPI(generics.RetrieveAPIView):
|
|
permission_classes = (IsSuperUser,)
|
|
|
|
def retrieve(self, request, *args, **kwargs):
|
|
try:
|
|
LDAPSyncUtil().clear_cache()
|
|
except Exception as e:
|
|
logger.error(str(e))
|
|
return Response(data={'msg': str(e)}, status=400)
|
|
return Response(data={'msg': 'success'})
|
|
|
|
|
|
class PublicSettingApi(generics.RetrieveAPIView):
|
|
permission_classes = ()
|
|
serializer_class = PublicSettingSerializer
|
|
|
|
def get_object(self):
|
|
instance = {
|
|
"data": {
|
|
"WINDOWS_SKIP_ALL_MANUAL_PASSWORD": settings.WINDOWS_SKIP_ALL_MANUAL_PASSWORD,
|
|
"SECURITY_MAX_IDLE_TIME": settings.SECURITY_MAX_IDLE_TIME,
|
|
}
|
|
}
|
|
return instance
|
|
|
|
|