mirror of https://github.com/jumpserver/jumpserver
feat: 页面配置serializer版 (#6750)
* feat: 页面配置serializer版 * perf: 优化配置 * perf: 优化设置 * perf: 优化设置 * perf: 优化配置页面 * perf: 基本完成设置优化 Co-authored-by: feng626 <1304903146@qq.com> Co-authored-by: ibuler <ibuler@qq.com>pull/6783/head
parent
7a2e93c087
commit
07179a4d22
|
@ -131,8 +131,8 @@ def on_system_user_groups_change(instance, action, pk_set, reverse, **kwargs):
|
|||
@on_transaction_commit
|
||||
def on_system_user_update(instance: SystemUser, created, **kwargs):
|
||||
"""
|
||||
当系统用户更新时,可能更新了秘钥,用户名等,这时要自动推送系统用户到资产上,
|
||||
其实应该当 用户名,密码,秘钥 sudo等更新时再推送,这里偷个懒,
|
||||
当系统用户更新时,可能更新了密钥,用户名等,这时要自动推送系统用户到资产上,
|
||||
其实应该当 用户名,密码,密钥 sudo等更新时再推送,这里偷个懒,
|
||||
这里直接取了 instance.assets 因为nodes和系统用户发生变化时,会自动将nodes下的资产
|
||||
关联到上面
|
||||
"""
|
||||
|
|
|
@ -5,14 +5,12 @@ from django.utils import timezone
|
|||
from celery import shared_task
|
||||
|
||||
from ops.celery.decorator import (
|
||||
register_as_period_task, after_app_shutdown_clean_periodic
|
||||
register_as_period_task
|
||||
)
|
||||
from .models import UserLoginLog, OperateLog
|
||||
from common.utils import get_log_keep_day
|
||||
|
||||
|
||||
@shared_task
|
||||
@after_app_shutdown_clean_periodic
|
||||
def clean_login_log_period():
|
||||
now = timezone.now()
|
||||
days = get_log_keep_day('LOGIN_LOG_KEEP_DAYS')
|
||||
|
@ -20,8 +18,6 @@ def clean_login_log_period():
|
|||
UserLoginLog.objects.filter(datetime__lt=expired_day).delete()
|
||||
|
||||
|
||||
@shared_task
|
||||
@after_app_shutdown_clean_periodic
|
||||
def clean_operation_log_period():
|
||||
now = timezone.now()
|
||||
days = get_log_keep_day('OPERATE_LOG_KEEP_DAYS')
|
||||
|
@ -29,7 +25,6 @@ def clean_operation_log_period():
|
|||
OperateLog.objects.filter(datetime__lt=expired_day).delete()
|
||||
|
||||
|
||||
@shared_task
|
||||
def clean_ftp_log_period():
|
||||
now = timezone.now()
|
||||
days = get_log_keep_day('FTP_LOG_KEEP_DAYS')
|
||||
|
|
|
@ -51,7 +51,8 @@ class UserLoginView(mixins.AuthMixin, FormView):
|
|||
|
||||
if settings.AUTH_OPENID:
|
||||
auth_type = 'OIDC'
|
||||
openid_auth_url = reverse(settings.AUTH_OPENID_AUTH_LOGIN_URL_NAME) + f'?next={next_url}'
|
||||
openid_auth_url = reverse(settings.AUTH_OPENID_AUTH_LOGIN_URL_NAME)
|
||||
openid_auth_url = openid_auth_url + f'?next={next_url}'
|
||||
else:
|
||||
openid_auth_url = None
|
||||
|
||||
|
@ -64,16 +65,13 @@ class UserLoginView(mixins.AuthMixin, FormView):
|
|||
if not any([openid_auth_url, cas_auth_url]):
|
||||
return None
|
||||
|
||||
if settings.LOGIN_REDIRECT_TO_BACKEND == 'OPENID' and openid_auth_url:
|
||||
login_redirect = settings.LOGIN_REDIRECT_TO_BACKEND.lower()
|
||||
if login_redirect == ['CAS', 'cas'] and cas_auth_url:
|
||||
auth_url = cas_auth_url
|
||||
else:
|
||||
auth_url = openid_auth_url
|
||||
|
||||
elif settings.LOGIN_REDIRECT_TO_BACKEND == 'CAS' and cas_auth_url:
|
||||
auth_url = cas_auth_url
|
||||
|
||||
else:
|
||||
auth_url = openid_auth_url or cas_auth_url
|
||||
|
||||
if settings.LOGIN_REDIRECT_TO_BACKEND:
|
||||
if settings.LOGIN_REDIRECT_TO_BACKEND or not settings.LOGIN_REDIRECT_MSG_ENABLED:
|
||||
redirect_url = auth_url
|
||||
else:
|
||||
message_data = {
|
||||
|
|
|
@ -179,13 +179,14 @@ class Config(dict):
|
|||
'AUTH_OPENID_CLIENT_SECRET': 'client-secret',
|
||||
'AUTH_OPENID_SHARE_SESSION': True,
|
||||
'AUTH_OPENID_IGNORE_SSL_VERIFICATION': True,
|
||||
|
||||
# OpenID 新配置参数 (version >= 1.5.9)
|
||||
'AUTH_OPENID_PROVIDER_ENDPOINT': 'https://op-example.com/',
|
||||
'AUTH_OPENID_PROVIDER_AUTHORIZATION_ENDPOINT': 'https://op-example.com/authorize',
|
||||
'AUTH_OPENID_PROVIDER_TOKEN_ENDPOINT': 'https://op-example.com/token',
|
||||
'AUTH_OPENID_PROVIDER_JWKS_ENDPOINT': 'https://op-example.com/jwks',
|
||||
'AUTH_OPENID_PROVIDER_USERINFO_ENDPOINT': 'https://op-example.com/userinfo',
|
||||
'AUTH_OPENID_PROVIDER_END_SESSION_ENDPOINT': 'https://op-example.com/logout',
|
||||
'AUTH_OPENID_PROVIDER_ENDPOINT': 'https://oidc.example.com/',
|
||||
'AUTH_OPENID_PROVIDER_AUTHORIZATION_ENDPOINT': 'https://oidc.example.com/authorize',
|
||||
'AUTH_OPENID_PROVIDER_TOKEN_ENDPOINT': 'https://oidc.example.com/token',
|
||||
'AUTH_OPENID_PROVIDER_JWKS_ENDPOINT': 'https://oidc.example.com/jwks',
|
||||
'AUTH_OPENID_PROVIDER_USERINFO_ENDPOINT': 'https://oidc.example.com/userinfo',
|
||||
'AUTH_OPENID_PROVIDER_END_SESSION_ENDPOINT': 'https://oidc.example.com/logout',
|
||||
'AUTH_OPENID_PROVIDER_SIGNATURE_ALG': 'HS256',
|
||||
'AUTH_OPENID_PROVIDER_SIGNATURE_KEY': None,
|
||||
'AUTH_OPENID_SCOPES': 'openid profile email',
|
||||
|
@ -194,10 +195,13 @@ class Config(dict):
|
|||
'AUTH_OPENID_USE_STATE': True,
|
||||
'AUTH_OPENID_USE_NONCE': True,
|
||||
'AUTH_OPENID_ALWAYS_UPDATE_USER': True,
|
||||
# OpenID 旧配置参数 (version <= 1.5.8 (discarded))
|
||||
'AUTH_OPENID_SERVER_URL': 'http://openid',
|
||||
|
||||
# Keycloak 旧配置参数 (version <= 1.5.8 (discarded))
|
||||
'AUTH_OPENID_KEYCLOAK': True,
|
||||
'AUTH_OPENID_SERVER_URL': 'https://keycloak.example.com',
|
||||
'AUTH_OPENID_REALM_NAME': None,
|
||||
|
||||
# Raidus 认证
|
||||
'AUTH_RADIUS': False,
|
||||
'RADIUS_SERVER': 'localhost',
|
||||
'RADIUS_PORT': 1812,
|
||||
|
@ -205,8 +209,9 @@ class Config(dict):
|
|||
'RADIUS_ENCRYPT_PASSWORD': True,
|
||||
'OTP_IN_RADIUS': False,
|
||||
|
||||
# Cas 认证
|
||||
'AUTH_CAS': False,
|
||||
'CAS_SERVER_URL': "http://host/cas/",
|
||||
'CAS_SERVER_URL': "https://example.com/cas/",
|
||||
'CAS_ROOT_PROXIED_AS': '',
|
||||
'CAS_LOGOUT_COMPLETELY': True,
|
||||
'CAS_VERSION': 3,
|
||||
|
@ -218,24 +223,31 @@ class Config(dict):
|
|||
'AUTH_SSO': False,
|
||||
'AUTH_SSO_AUTHKEY_TTL': 60 * 15,
|
||||
|
||||
# 企业微信
|
||||
'AUTH_WECOM': False,
|
||||
'WECOM_CORPID': '',
|
||||
'WECOM_AGENTID': '',
|
||||
'WECOM_SECRET': '',
|
||||
|
||||
# 钉钉
|
||||
'AUTH_DINGTALK': False,
|
||||
'DINGTALK_AGENTID': '',
|
||||
'DINGTALK_APPKEY': '',
|
||||
'DINGTALK_APPSECRET': '',
|
||||
|
||||
# 飞书
|
||||
'AUTH_FEISHU': False,
|
||||
'FEISHU_APP_ID': '',
|
||||
'FEISHU_APP_SECRET': '',
|
||||
|
||||
'LOGIN_REDIRECT_TO_BACKEND': '', # 'OPENID / CAS
|
||||
'LOGIN_REDIRECT_MSG_ENABLED': True,
|
||||
|
||||
'OTP_VALID_WINDOW': 2,
|
||||
'OTP_ISSUER_NAME': 'JumpServer',
|
||||
'EMAIL_SUFFIX': 'jumpserver.org',
|
||||
'EMAIL_SUFFIX': 'example.com',
|
||||
|
||||
# Terminal配置
|
||||
'TERMINAL_PASSWORD_AUTH': True,
|
||||
'TERMINAL_PUBLIC_KEY_AUTH': True,
|
||||
'TERMINAL_HEARTBEAT_INTERVAL': 20,
|
||||
|
@ -245,7 +257,9 @@ class Config(dict):
|
|||
'TERMINAL_HOST_KEY': '',
|
||||
'TERMINAL_TELNET_REGEX': '',
|
||||
'TERMINAL_COMMAND_STORAGE': {},
|
||||
'TERMINAL_RDP_ADDR': '',
|
||||
|
||||
# 安全配置
|
||||
'SECURITY_MFA_AUTH': 0, # 0 不开启 1 全局开启 2 管理员开启
|
||||
'SECURITY_COMMAND_EXECUTION': True,
|
||||
'SECURITY_SERVICE_ACCOUNT_REGISTRATION': True,
|
||||
|
@ -262,58 +276,60 @@ class Config(dict):
|
|||
'SECURITY_PASSWORD_SPECIAL_CHAR': False,
|
||||
'SECURITY_LOGIN_CHALLENGE_ENABLED': False,
|
||||
'SECURITY_LOGIN_CAPTCHA_ENABLED': True,
|
||||
'SECURITY_DATA_CRYPTO_ALGO': 'aes',
|
||||
'SECURITY_INSECURE_COMMAND': False,
|
||||
'SECURITY_INSECURE_COMMAND_LEVEL': 5,
|
||||
'SECURITY_INSECURE_COMMAND_EMAIL_RECEIVER': '',
|
||||
'SECURITY_LUNA_REMEMBER_AUTH': True,
|
||||
'SECURITY_WATERMARK_ENABLED': True,
|
||||
'SECURITY_MFA_VERIFY_TTL': 3600,
|
||||
'SECURITY_SESSION_SHARE': True,
|
||||
'OLD_PASSWORD_HISTORY_LIMIT_COUNT': 5,
|
||||
'LOGIN_CONFIRM_ENABLE': False, # 准备废弃,放到 acl 中
|
||||
'CHANGE_AUTH_PLAN_SECURE_MODE_ENABLED': True,
|
||||
'USER_LOGIN_SINGLE_MACHINE_ENABLED': False,
|
||||
'ONLY_ALLOW_EXIST_USER_AUTH': False,
|
||||
'ONLY_ALLOW_AUTH_FROM_SOURCE': False,
|
||||
|
||||
# 启动前
|
||||
'HTTP_BIND_HOST': '0.0.0.0',
|
||||
'HTTP_LISTEN_PORT': 8080,
|
||||
'WS_LISTEN_PORT': 8070,
|
||||
'SYSLOG_ADDR': '', # '192.168.0.1:514'
|
||||
'SYSLOG_FACILITY': 'user',
|
||||
'SYSLOG_SOCKTYPE': 2,
|
||||
'PERM_EXPIRED_CHECK_PERIODIC': 60 * 60,
|
||||
'FLOWER_URL': "127.0.0.1:5555",
|
||||
'LANGUAGE_CODE': 'zh',
|
||||
'TIME_ZONE': 'Asia/Shanghai',
|
||||
'FORCE_SCRIPT_NAME': '',
|
||||
'SESSION_COOKIE_SECURE': False,
|
||||
'CSRF_COOKIE_SECURE': False,
|
||||
'REFERER_CHECK_ENABLED': False,
|
||||
'SESSION_SAVE_EVERY_REQUEST': True,
|
||||
'SESSION_EXPIRE_AT_BROWSER_CLOSE_FORCE': False,
|
||||
'SERVER_REPLAY_STORAGE': {},
|
||||
'SECURITY_DATA_CRYPTO_ALGO': 'aes',
|
||||
|
||||
# 记录清理清理
|
||||
'LOGIN_LOG_KEEP_DAYS': 200,
|
||||
'TASK_LOG_KEEP_DAYS': 90,
|
||||
'OPERATE_LOG_KEEP_DAYS': 200,
|
||||
'FTP_LOG_KEEP_DAYS': 200,
|
||||
'ASSETS_PERM_CACHE_TIME': 3600 * 24,
|
||||
'SECURITY_MFA_VERIFY_TTL': 3600,
|
||||
'OLD_PASSWORD_HISTORY_LIMIT_COUNT': 5,
|
||||
'ASSETS_PERM_CACHE_ENABLE': HAS_XPACK,
|
||||
'SYSLOG_ADDR': '', # '192.168.0.1:514'
|
||||
'SYSLOG_FACILITY': 'user',
|
||||
'SYSLOG_SOCKTYPE': 2,
|
||||
'PERM_SINGLE_ASSET_TO_UNGROUP_NODE': False,
|
||||
'PERM_EXPIRED_CHECK_PERIODIC': 60 * 60,
|
||||
'WINDOWS_SSH_DEFAULT_SHELL': 'cmd',
|
||||
'FLOWER_URL': "127.0.0.1:5555",
|
||||
'DEFAULT_ORG_SHOW_ALL_USERS': True,
|
||||
'PERIOD_TASK_ENABLED': True,
|
||||
'FORCE_SCRIPT_NAME': '',
|
||||
'LOGIN_CONFIRM_ENABLE': False,
|
||||
'WINDOWS_SKIP_ALL_MANUAL_PASSWORD': False,
|
||||
'ORG_CHANGE_TO_URL': '',
|
||||
'LANGUAGE_CODE': 'zh',
|
||||
'TIME_ZONE': 'Asia/Shanghai',
|
||||
'CHANGE_AUTH_PLAN_SECURE_MODE_ENABLED': True,
|
||||
'USER_LOGIN_SINGLE_MACHINE_ENABLED': False,
|
||||
'TICKETS_ENABLED': True,
|
||||
'SESSION_COOKIE_SECURE': False,
|
||||
'CSRF_COOKIE_SECURE': False,
|
||||
'REFERER_CHECK_ENABLED': False,
|
||||
'SERVER_REPLAY_STORAGE': {},
|
||||
'CONNECTION_TOKEN_ENABLED': False,
|
||||
'ONLY_ALLOW_EXIST_USER_AUTH': False,
|
||||
'ONLY_ALLOW_AUTH_FROM_SOURCE': False,
|
||||
'SESSION_SAVE_EVERY_REQUEST': True,
|
||||
'SESSION_EXPIRE_AT_BROWSER_CLOSE_FORCE': False,
|
||||
'FORGOT_PASSWORD_URL': '',
|
||||
'HEALTH_CHECK_TOKEN': '',
|
||||
'LOGIN_REDIRECT_TO_BACKEND': None, # 'OPENID / CAS
|
||||
'CLOUD_SYNC_TASK_EXECUTION_KEEP_DAYS': 30,
|
||||
|
||||
'TERMINAL_RDP_ADDR': ''
|
||||
# 废弃的
|
||||
'DEFAULT_ORG_SHOW_ALL_USERS': True,
|
||||
'ORG_CHANGE_TO_URL': '',
|
||||
'WINDOWS_SKIP_ALL_MANUAL_PASSWORD': False,
|
||||
'CONNECTION_TOKEN_ENABLED': False,
|
||||
|
||||
'PERM_SINGLE_ASSET_TO_UNGROUP_NODE': False,
|
||||
'WINDOWS_SSH_DEFAULT_SHELL': 'cmd',
|
||||
'PERIOD_TASK_ENABLED': True,
|
||||
|
||||
'TICKETS_ENABLED': True,
|
||||
'FORGOT_PASSWORD_URL': '',
|
||||
'HEALTH_CHECK_TOKEN': '',
|
||||
}
|
||||
|
||||
def compatible_auth_openid_of_key(self):
|
||||
|
@ -324,6 +340,9 @@ class Config(dict):
|
|||
构造出新配置中标准OpenID协议中所需的Endpoint即可
|
||||
(Keycloak说明文档参考: https://www.keycloak.org/docs/latest/securing_apps/)
|
||||
"""
|
||||
if self.AUTH_OPENID and not self.AUTH_OPENID_REALM_NAME:
|
||||
self['AUTH_OPENID_KEYCLOAK'] = False
|
||||
|
||||
if not self.AUTH_OPENID:
|
||||
return
|
||||
|
||||
|
|
|
@ -72,14 +72,9 @@ TERMINAL_HOST_KEY = CONFIG.TERMINAL_HOST_KEY
|
|||
TERMINAL_HEADER_TITLE = CONFIG.TERMINAL_HEADER_TITLE
|
||||
TERMINAL_TELNET_REGEX = CONFIG.TERMINAL_TELNET_REGEX
|
||||
|
||||
# User or user group permission cache time, default 3600 seconds
|
||||
ASSETS_PERM_CACHE_ENABLE = CONFIG.ASSETS_PERM_CACHE_ENABLE
|
||||
ASSETS_PERM_CACHE_TIME = CONFIG.ASSETS_PERM_CACHE_TIME
|
||||
|
||||
# Asset user auth external backend, default AuthBook backend
|
||||
BACKEND_ASSET_USER_AUTH_VAULT = False
|
||||
|
||||
DEFAULT_ORG_SHOW_ALL_USERS = CONFIG.DEFAULT_ORG_SHOW_ALL_USERS
|
||||
PERM_SINGLE_ASSET_TO_UNGROUP_NODE = CONFIG.PERM_SINGLE_ASSET_TO_UNGROUP_NODE
|
||||
PERM_EXPIRED_CHECK_PERIODIC = CONFIG.PERM_EXPIRED_CHECK_PERIODIC
|
||||
WINDOWS_SSH_DEFAULT_SHELL = CONFIG.WINDOWS_SSH_DEFAULT_SHELL
|
||||
|
@ -132,5 +127,6 @@ SECURITY_WATERMARK_ENABLED = CONFIG.SECURITY_WATERMARK_ENABLED
|
|||
SECURITY_SESSION_SHARE = CONFIG.SECURITY_SESSION_SHARE
|
||||
|
||||
LOGIN_REDIRECT_TO_BACKEND = CONFIG.LOGIN_REDIRECT_TO_BACKEND
|
||||
LOGIN_REDIRECT_MSG_ENABLED = CONFIG.LOGIN_REDIRECT_MSG_ENABLED
|
||||
|
||||
CLOUD_SYNC_TASK_EXECUTION_KEEP_DAYS = CONFIG.CLOUD_SYNC_TASK_EXECUTION_KEEP_DAYS
|
||||
|
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
@ -4,7 +4,6 @@ from redis.exceptions import ConnectionError
|
|||
from channels.generic.websocket import JsonWebsocketConsumer
|
||||
|
||||
from common.utils import get_logger
|
||||
from .models import SiteMessage
|
||||
from .site_msg import SiteMessageUtil
|
||||
from .signals_handler import new_site_msg_chan
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ class BaseHost(Host):
|
|||
if host_data.get('username'):
|
||||
self.set_variable('ansible_user', host_data['username'])
|
||||
|
||||
# 添加密码和秘钥
|
||||
# 添加密码和密钥
|
||||
if host_data.get('password'):
|
||||
self.set_variable('ansible_ssh_pass', host_data['password'])
|
||||
if host_data.get('private_key'):
|
||||
|
|
|
@ -159,7 +159,7 @@ class PeriodTaskFormMixin(forms.Form):
|
|||
)
|
||||
interval = forms.IntegerField(
|
||||
required=False, initial=24,
|
||||
help_text=_('Tips: (Units: hour)'), label=_("Cycle perform"),
|
||||
help_text=_('Unit: hour'), label=_("Cycle perform"),
|
||||
)
|
||||
|
||||
def get_initial_for_field(self, field, field_name):
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
from .common import *
|
||||
from .settings import *
|
||||
from .ldap import *
|
||||
from .wecom import *
|
||||
from .dingtalk import *
|
||||
from .feishu import *
|
||||
from .public import *
|
||||
from .email import *
|
||||
|
|
|
@ -1,193 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
from smtplib import SMTPSenderRefused
|
||||
from rest_framework import generics
|
||||
from rest_framework.views import Response, APIView
|
||||
from rest_framework.permissions import AllowAny
|
||||
from django.conf import settings
|
||||
from django.core.mail import send_mail, get_connection
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.templatetags.static import static
|
||||
|
||||
from jumpserver.utils import has_valid_xpack_license
|
||||
from common.permissions import IsSuperUser
|
||||
from common.utils import get_logger
|
||||
from .. import serializers
|
||||
from ..models import Setting
|
||||
|
||||
logger = get_logger(__file__)
|
||||
|
||||
|
||||
class MailTestingAPI(APIView):
|
||||
permission_classes = (IsSuperUser,)
|
||||
serializer_class = serializers.MailTestSerializer
|
||||
success_message = _("Test mail sent to {}, please check")
|
||||
|
||||
def post(self, request):
|
||||
serializer = self.serializer_class(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
email_host = serializer.validated_data['EMAIL_HOST']
|
||||
email_port = serializer.validated_data['EMAIL_PORT']
|
||||
email_host_user = serializer.validated_data["EMAIL_HOST_USER"]
|
||||
email_host_password = serializer.validated_data['EMAIL_HOST_PASSWORD']
|
||||
email_from = serializer.validated_data["EMAIL_FROM"]
|
||||
email_recipient = serializer.validated_data["EMAIL_RECIPIENT"]
|
||||
email_use_ssl = serializer.validated_data['EMAIL_USE_SSL']
|
||||
email_use_tls = serializer.validated_data['EMAIL_USE_TLS']
|
||||
|
||||
# 设置 settings 的值,会导致动态配置在当前进程失效
|
||||
# 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
|
||||
connection = get_connection(
|
||||
host=email_host, port=email_port,
|
||||
username=email_host_user, password=email_host_password,
|
||||
use_tls=email_use_tls, use_ssl=email_use_ssl,
|
||||
)
|
||||
send_mail(
|
||||
subject, message, email_from, [email_recipient],
|
||||
connection=connection
|
||||
)
|
||||
except SMTPSenderRefused as e:
|
||||
error = e.smtp_error
|
||||
if isinstance(error, bytes):
|
||||
for coding in ('gbk', 'utf8'):
|
||||
try:
|
||||
error = error.decode(coding)
|
||||
except UnicodeDecodeError:
|
||||
continue
|
||||
else:
|
||||
break
|
||||
return Response({"error": str(error)}, status=400)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
return Response({"error": str(e)}, status=400)
|
||||
return Response({"msg": self.success_message.format(email_recipient)})
|
||||
|
||||
|
||||
class PublicSettingApi(generics.RetrieveAPIView):
|
||||
permission_classes = (AllowAny,)
|
||||
serializer_class = serializers.PublicSettingSerializer
|
||||
|
||||
@staticmethod
|
||||
def get_logo_urls():
|
||||
logo_urls = {
|
||||
'logo_logout': static('img/logo.png'),
|
||||
'logo_index': static('img/logo_text.png'),
|
||||
'login_image': static('img/login_image.jpg'),
|
||||
'favicon': static('img/facio.ico')
|
||||
}
|
||||
if not settings.XPACK_ENABLED:
|
||||
return logo_urls
|
||||
from xpack.plugins.interface.models import Interface
|
||||
obj = Interface.interface()
|
||||
if not obj:
|
||||
return logo_urls
|
||||
for attr in ['logo_logout', 'logo_index', 'login_image', 'favicon']:
|
||||
if getattr(obj, attr, '') and getattr(obj, attr).url:
|
||||
logo_urls.update({attr: getattr(obj, attr).url})
|
||||
return logo_urls
|
||||
|
||||
@staticmethod
|
||||
def get_login_title():
|
||||
default_title = _('Welcome to the JumpServer open source Bastion Host')
|
||||
if not settings.XPACK_ENABLED:
|
||||
return default_title
|
||||
from xpack.plugins.interface.models import Interface
|
||||
return Interface.get_login_title()
|
||||
|
||||
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,
|
||||
"XPACK_ENABLED": settings.XPACK_ENABLED,
|
||||
"LOGIN_CONFIRM_ENABLE": settings.LOGIN_CONFIRM_ENABLE,
|
||||
"SECURITY_VIEW_AUTH_NEED_MFA": settings.SECURITY_VIEW_AUTH_NEED_MFA,
|
||||
"SECURITY_MFA_VERIFY_TTL": settings.SECURITY_MFA_VERIFY_TTL,
|
||||
"OLD_PASSWORD_HISTORY_LIMIT_COUNT": settings.OLD_PASSWORD_HISTORY_LIMIT_COUNT,
|
||||
"SECURITY_COMMAND_EXECUTION": settings.SECURITY_COMMAND_EXECUTION,
|
||||
"SECURITY_PASSWORD_EXPIRATION_TIME": settings.SECURITY_PASSWORD_EXPIRATION_TIME,
|
||||
"SECURITY_LUNA_REMEMBER_AUTH": settings.SECURITY_LUNA_REMEMBER_AUTH,
|
||||
"XPACK_LICENSE_IS_VALID": has_valid_xpack_license(),
|
||||
"LOGIN_TITLE": self.get_login_title(),
|
||||
"LOGO_URLS": self.get_logo_urls(),
|
||||
"TICKETS_ENABLED": settings.TICKETS_ENABLED,
|
||||
"PASSWORD_RULE": {
|
||||
'SECURITY_PASSWORD_MIN_LENGTH': settings.SECURITY_PASSWORD_MIN_LENGTH,
|
||||
'SECURITY_ADMIN_USER_PASSWORD_MIN_LENGTH': settings.SECURITY_ADMIN_USER_PASSWORD_MIN_LENGTH,
|
||||
'SECURITY_PASSWORD_UPPER_CASE': settings.SECURITY_PASSWORD_UPPER_CASE,
|
||||
'SECURITY_PASSWORD_LOWER_CASE': settings.SECURITY_PASSWORD_LOWER_CASE,
|
||||
'SECURITY_PASSWORD_NUMBER': settings.SECURITY_PASSWORD_NUMBER,
|
||||
'SECURITY_PASSWORD_SPECIAL_CHAR': settings.SECURITY_PASSWORD_SPECIAL_CHAR,
|
||||
},
|
||||
"AUTH_WECOM": settings.AUTH_WECOM,
|
||||
"AUTH_DINGTALK": settings.AUTH_DINGTALK,
|
||||
"AUTH_FEISHU": settings.AUTH_FEISHU,
|
||||
'SECURITY_WATERMARK_ENABLED': settings.SECURITY_WATERMARK_ENABLED,
|
||||
'SECURITY_SESSION_SHARE': settings.SECURITY_SESSION_SHARE
|
||||
}
|
||||
}
|
||||
return instance
|
||||
|
||||
|
||||
class SettingsApi(generics.RetrieveUpdateAPIView):
|
||||
permission_classes = (IsSuperUser,)
|
||||
serializer_class_mapper = {
|
||||
'all': serializers.SettingsSerializer,
|
||||
'basic': serializers.BasicSettingSerializer,
|
||||
'terminal': serializers.TerminalSettingSerializer,
|
||||
'security': serializers.SecuritySettingSerializer,
|
||||
'ldap': serializers.LDAPSettingSerializer,
|
||||
'email': serializers.EmailSettingSerializer,
|
||||
'email_content': serializers.EmailContentSettingSerializer,
|
||||
'wecom': serializers.WeComSettingSerializer,
|
||||
'dingtalk': serializers.DingTalkSettingSerializer,
|
||||
'feishu': serializers.FeiShuSettingSerializer,
|
||||
}
|
||||
|
||||
def get_serializer_class(self):
|
||||
category = self.request.query_params.get('category', serializers.BasicSettingSerializer)
|
||||
return self.serializer_class_mapper.get(category, serializers.BasicSettingSerializer)
|
||||
|
||||
def get_fields(self):
|
||||
serializer = self.get_serializer_class()()
|
||||
fields = serializer.get_fields()
|
||||
return fields
|
||||
|
||||
def get_object(self):
|
||||
items = self.get_fields().keys()
|
||||
obj = {item: getattr(settings, item) for item in items}
|
||||
return obj
|
||||
|
||||
def parse_serializer_data(self, serializer):
|
||||
data = []
|
||||
fields = self.get_fields()
|
||||
encrypted_items = [name for name, field in fields.items() if field.write_only]
|
||||
category = self.request.query_params.get('category', '')
|
||||
for name, value in serializer.validated_data.items():
|
||||
encrypted = name in encrypted_items
|
||||
if encrypted and value in ['', None]:
|
||||
continue
|
||||
data.append({
|
||||
'name': name, 'value': value,
|
||||
'encrypted': encrypted, 'category': category
|
||||
})
|
||||
return data
|
||||
|
||||
def perform_update(self, serializer):
|
||||
settings_items = self.parse_serializer_data(serializer)
|
||||
serializer_data = getattr(serializer, 'data', {})
|
||||
for item in settings_items:
|
||||
changed, setting = Setting.update_or_create(**item)
|
||||
if not changed:
|
||||
continue
|
||||
serializer_data[setting.name] = setting.cleaned_value
|
||||
setattr(serializer, '_data', serializer_data)
|
|
@ -0,0 +1,68 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
from smtplib import SMTPSenderRefused
|
||||
from rest_framework.views import Response, APIView
|
||||
from django.core.mail import send_mail, get_connection
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from common.permissions import IsSuperUser
|
||||
from common.utils import get_logger
|
||||
from .. import serializers
|
||||
|
||||
logger = get_logger(__file__)
|
||||
|
||||
__all__ = ['MailTestingAPI']
|
||||
|
||||
|
||||
class MailTestingAPI(APIView):
|
||||
permission_classes = (IsSuperUser,)
|
||||
serializer_class = serializers.MailTestSerializer
|
||||
success_message = _("Test mail sent to {}, please check")
|
||||
|
||||
def post(self, request):
|
||||
serializer = self.serializer_class(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
email_host = serializer.validated_data['EMAIL_HOST']
|
||||
email_port = serializer.validated_data['EMAIL_PORT']
|
||||
email_host_user = serializer.validated_data["EMAIL_HOST_USER"]
|
||||
email_host_password = serializer.validated_data['EMAIL_HOST_PASSWORD']
|
||||
email_from = serializer.validated_data["EMAIL_FROM"]
|
||||
email_recipient = serializer.validated_data["EMAIL_RECIPIENT"]
|
||||
email_use_ssl = serializer.validated_data['EMAIL_USE_SSL']
|
||||
email_use_tls = serializer.validated_data['EMAIL_USE_TLS']
|
||||
|
||||
# 设置 settings 的值,会导致动态配置在当前进程失效
|
||||
# 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
|
||||
connection = get_connection(
|
||||
host=email_host, port=email_port,
|
||||
username=email_host_user, password=email_host_password,
|
||||
use_tls=email_use_tls, use_ssl=email_use_ssl,
|
||||
)
|
||||
send_mail(
|
||||
subject, message, email_from, [email_recipient],
|
||||
connection=connection
|
||||
)
|
||||
except SMTPSenderRefused as e:
|
||||
error = e.smtp_error
|
||||
if isinstance(error, bytes):
|
||||
for coding in ('gbk', 'utf8'):
|
||||
try:
|
||||
error = error.decode(coding)
|
||||
except UnicodeDecodeError:
|
||||
continue
|
||||
else:
|
||||
break
|
||||
return Response({"error": str(error)}, status=400)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
return Response({"error": str(e)}, status=400)
|
||||
return Response({"msg": self.success_message.format(email_recipient)})
|
|
@ -0,0 +1,79 @@
|
|||
from rest_framework import generics
|
||||
from rest_framework.permissions import AllowAny
|
||||
from django.conf import settings
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.templatetags.static import static
|
||||
|
||||
from jumpserver.utils import has_valid_xpack_license
|
||||
from common.utils import get_logger
|
||||
from .. import serializers
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
__all__ = ['PublicSettingApi']
|
||||
|
||||
|
||||
class PublicSettingApi(generics.RetrieveAPIView):
|
||||
permission_classes = (AllowAny,)
|
||||
serializer_class = serializers.PublicSettingSerializer
|
||||
|
||||
@staticmethod
|
||||
def get_logo_urls():
|
||||
logo_urls = {
|
||||
'logo_logout': static('img/logo.png'),
|
||||
'logo_index': static('img/logo_text.png'),
|
||||
'login_image': static('img/login_image.jpg'),
|
||||
'favicon': static('img/facio.ico')
|
||||
}
|
||||
if not settings.XPACK_ENABLED:
|
||||
return logo_urls
|
||||
from xpack.plugins.interface.models import Interface
|
||||
obj = Interface.interface()
|
||||
if not obj:
|
||||
return logo_urls
|
||||
for attr in ['logo_logout', 'logo_index', 'login_image', 'favicon']:
|
||||
if getattr(obj, attr, '') and getattr(obj, attr).url:
|
||||
logo_urls.update({attr: getattr(obj, attr).url})
|
||||
return logo_urls
|
||||
|
||||
@staticmethod
|
||||
def get_login_title():
|
||||
default_title = _('Welcome to the JumpServer open source Bastion Host')
|
||||
if not settings.XPACK_ENABLED:
|
||||
return default_title
|
||||
from xpack.plugins.interface.models import Interface
|
||||
return Interface.get_login_title()
|
||||
|
||||
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,
|
||||
"XPACK_ENABLED": settings.XPACK_ENABLED,
|
||||
"LOGIN_CONFIRM_ENABLE": settings.LOGIN_CONFIRM_ENABLE,
|
||||
"SECURITY_VIEW_AUTH_NEED_MFA": settings.SECURITY_VIEW_AUTH_NEED_MFA,
|
||||
"SECURITY_MFA_VERIFY_TTL": settings.SECURITY_MFA_VERIFY_TTL,
|
||||
"OLD_PASSWORD_HISTORY_LIMIT_COUNT": settings.OLD_PASSWORD_HISTORY_LIMIT_COUNT,
|
||||
"SECURITY_COMMAND_EXECUTION": settings.SECURITY_COMMAND_EXECUTION,
|
||||
"SECURITY_PASSWORD_EXPIRATION_TIME": settings.SECURITY_PASSWORD_EXPIRATION_TIME,
|
||||
"SECURITY_LUNA_REMEMBER_AUTH": settings.SECURITY_LUNA_REMEMBER_AUTH,
|
||||
"XPACK_LICENSE_IS_VALID": has_valid_xpack_license(),
|
||||
"LOGIN_TITLE": self.get_login_title(),
|
||||
"LOGO_URLS": self.get_logo_urls(),
|
||||
"TICKETS_ENABLED": settings.TICKETS_ENABLED,
|
||||
"PASSWORD_RULE": {
|
||||
'SECURITY_PASSWORD_MIN_LENGTH': settings.SECURITY_PASSWORD_MIN_LENGTH,
|
||||
'SECURITY_ADMIN_USER_PASSWORD_MIN_LENGTH': settings.SECURITY_ADMIN_USER_PASSWORD_MIN_LENGTH,
|
||||
'SECURITY_PASSWORD_UPPER_CASE': settings.SECURITY_PASSWORD_UPPER_CASE,
|
||||
'SECURITY_PASSWORD_LOWER_CASE': settings.SECURITY_PASSWORD_LOWER_CASE,
|
||||
'SECURITY_PASSWORD_NUMBER': settings.SECURITY_PASSWORD_NUMBER,
|
||||
'SECURITY_PASSWORD_SPECIAL_CHAR': settings.SECURITY_PASSWORD_SPECIAL_CHAR,
|
||||
},
|
||||
"AUTH_WECOM": settings.AUTH_WECOM,
|
||||
"AUTH_DINGTALK": settings.AUTH_DINGTALK,
|
||||
"AUTH_FEISHU": settings.AUTH_FEISHU,
|
||||
'SECURITY_WATERMARK_ENABLED': settings.SECURITY_WATERMARK_ENABLED,
|
||||
'SECURITY_SESSION_SHARE': settings.SECURITY_SESSION_SHARE,
|
||||
}
|
||||
}
|
||||
return instance
|
|
@ -0,0 +1,85 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
from rest_framework import generics
|
||||
from django.conf import settings
|
||||
|
||||
from jumpserver.conf import Config
|
||||
from common.permissions import IsSuperUser
|
||||
from common.utils import get_logger
|
||||
from .. import serializers
|
||||
from ..models import Setting
|
||||
|
||||
logger = get_logger(__file__)
|
||||
|
||||
|
||||
class SettingsApi(generics.RetrieveUpdateAPIView):
|
||||
permission_classes = (IsSuperUser,)
|
||||
serializer_class_mapper = {
|
||||
'all': serializers.SettingsSerializer,
|
||||
'basic': serializers.BasicSettingSerializer,
|
||||
'terminal': serializers.TerminalSettingSerializer,
|
||||
'security': serializers.SecuritySettingSerializer,
|
||||
'ldap': serializers.LDAPSettingSerializer,
|
||||
'email': serializers.EmailSettingSerializer,
|
||||
'email_content': serializers.EmailContentSettingSerializer,
|
||||
'wecom': serializers.WeComSettingSerializer,
|
||||
'dingtalk': serializers.DingTalkSettingSerializer,
|
||||
'feishu': serializers.FeiShuSettingSerializer,
|
||||
'auth': serializers.AuthSettingSerializer,
|
||||
'oidc': serializers.OIDCSettingSerializer,
|
||||
'keycloak': serializers.KeycloakSettingSerializer,
|
||||
'radius': serializers.RadiusSettingSerializer,
|
||||
'cas': serializers.CASSettingSerializer,
|
||||
'sso': serializers.SSOSettingSerializer,
|
||||
'clean': serializers.CleaningSerializer,
|
||||
'other': serializers.OtherSettingSerializer,
|
||||
}
|
||||
|
||||
def get_serializer_class(self):
|
||||
category = self.request.query_params.get('category', 'basic')
|
||||
default = serializers.BasicSettingSerializer
|
||||
cls = self.serializer_class_mapper.get(category, default)
|
||||
return cls
|
||||
|
||||
def get_fields(self):
|
||||
serializer = self.get_serializer_class()()
|
||||
fields = serializer.get_fields()
|
||||
return fields
|
||||
|
||||
def get_object(self):
|
||||
items = self.get_fields().keys()
|
||||
obj = {}
|
||||
for item in items:
|
||||
if hasattr(settings, item):
|
||||
obj[item] = getattr(settings, item)
|
||||
else:
|
||||
obj[item] = Config.defaults[item]
|
||||
return obj
|
||||
|
||||
def parse_serializer_data(self, serializer):
|
||||
data = []
|
||||
fields = self.get_fields()
|
||||
encrypted_items = [name for name, field in fields.items() if field.write_only]
|
||||
category = self.request.query_params.get('category', '')
|
||||
for name, value in serializer.validated_data.items():
|
||||
encrypted = name in encrypted_items
|
||||
if encrypted and value in ['', None]:
|
||||
continue
|
||||
data.append({
|
||||
'name': name, 'value': value,
|
||||
'encrypted': encrypted, 'category': category
|
||||
})
|
||||
return data
|
||||
|
||||
def perform_update(self, serializer):
|
||||
settings_items = self.parse_serializer_data(serializer)
|
||||
serializer_data = getattr(serializer, 'data', {})
|
||||
for item in settings_items:
|
||||
changed, setting = Setting.update_or_create(**item)
|
||||
if not changed:
|
||||
continue
|
||||
serializer_data[setting.name] = setting.cleaned_value
|
||||
setattr(serializer, '_data', serializer_data)
|
||||
if hasattr(serializer, 'post_save'):
|
||||
serializer.post_save()
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 3.1.12 on 2021-09-01 02:35
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('settings', '0002_auto_20210729_1546'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='setting',
|
||||
name='value',
|
||||
field=models.TextField(blank=True, null=True, verbose_name='Value'),
|
||||
),
|
||||
]
|
|
@ -27,7 +27,7 @@ class SettingManager(models.Manager):
|
|||
|
||||
class Setting(models.Model):
|
||||
name = models.CharField(max_length=128, unique=True, verbose_name=_("Name"))
|
||||
value = models.TextField(verbose_name=_("Value"))
|
||||
value = models.TextField(verbose_name=_("Value"), null=True, blank=True)
|
||||
category = models.CharField(max_length=128, default="default")
|
||||
encrypted = models.BooleanField(default=False)
|
||||
enabled = models.BooleanField(verbose_name=_("Enabled"), default=True)
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
from .basic import *
|
||||
from .auth import *
|
||||
from .email import *
|
||||
from .ldap import *
|
||||
from .public import *
|
||||
from .settings import *
|
||||
from .security import *
|
||||
from .terminal import *
|
||||
from .cleaning import *
|
||||
from .other import *
|
||||
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
from .cas import *
|
||||
from .ldap import *
|
||||
from .oidc import *
|
||||
from .radius import *
|
||||
from .dingtalk import *
|
||||
from .feishu import *
|
||||
from .wecom import *
|
||||
from .sso import *
|
||||
from .base import *
|
|
@ -0,0 +1,25 @@
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
__all__ = [
|
||||
'AuthSettingSerializer',
|
||||
]
|
||||
|
||||
|
||||
class AuthSettingSerializer(serializers.Serializer):
|
||||
AUTH_CAS = serializers.BooleanField(required=False, label=_('CAS Auth'))
|
||||
AUTH_OPENID = serializers.BooleanField(required=False, label=_('OPENID Auth'))
|
||||
AUTH_RADIUS = serializers.BooleanField(required=False, label=_('RADIUS Auth'))
|
||||
AUTH_DINGTALK = serializers.BooleanField(default=False, label=_('DingTalk Auth'))
|
||||
AUTH_FEISHU = serializers.BooleanField(default=False, label=_('FeiShu Auth'))
|
||||
AUTH_WECOM = serializers.BooleanField(default=False, label=_('WeCom Auth'))
|
||||
AUTH_SSO = serializers.BooleanField(default=False, label=_("SSO Auth"))
|
||||
FORGOT_PASSWORD_URL = serializers.CharField(
|
||||
required=False, max_length=1024, label=_("Forgot password url")
|
||||
)
|
||||
HEALTH_CHECK_TOKEN = serializers.CharField(
|
||||
required=False, max_length=1024, label=_("Health check token")
|
||||
)
|
||||
LOGIN_REDIRECT_MSG_ENABLED = serializers.BooleanField(
|
||||
required=False, label=_("Enable login redirect msg")
|
||||
)
|
|
@ -0,0 +1,18 @@
|
|||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
__all__ = [
|
||||
'CASSettingSerializer',
|
||||
]
|
||||
|
||||
|
||||
class CASSettingSerializer(serializers.Serializer):
|
||||
AUTH_CAS = serializers.BooleanField(required=False, label=_('Enable CAS Auth'))
|
||||
CAS_SERVER_URL = serializers.CharField(required=False, max_length=1024, label=_('Server url'))
|
||||
CAS_LOGOUT_COMPLETELY = serializers.BooleanField(required=False, label=_('Logout completely'))
|
||||
CAS_VERSION = serializers.IntegerField(required=False, label=_('Version'))
|
||||
CAS_USERNAME_ATTRIBUTE = serializers.CharField(required=False, max_length=1024, label=_('Username attr'))
|
||||
CAS_APPLY_ATTRIBUTES_TO_USER = serializers.BooleanField(required=False, label=_('Enable attributes map'))
|
||||
CAS_RENAME_ATTRIBUTES = serializers.DictField(required=False, label=_('Rename attr'))
|
||||
CAS_CREATE_USER = serializers.BooleanField(required=False, label=_('Create user if not'))
|
|
@ -0,0 +1,11 @@
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
__all__ = ['DingTalkSettingSerializer']
|
||||
|
||||
|
||||
class DingTalkSettingSerializer(serializers.Serializer):
|
||||
DINGTALK_AGENTID = serializers.CharField(max_length=256, required=True, label='AgentId')
|
||||
DINGTALK_APPKEY = serializers.CharField(max_length=256, required=True, label='AppKey')
|
||||
DINGTALK_APPSECRET = serializers.CharField(max_length=256, required=False, label='AppSecret', write_only=True)
|
||||
AUTH_DINGTALK = serializers.BooleanField(default=False, label=_('Enable DingTalk Auth'))
|
|
@ -0,0 +1,11 @@
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
__all__ = ['FeiShuSettingSerializer']
|
||||
|
||||
|
||||
class FeiShuSettingSerializer(serializers.Serializer):
|
||||
FEISHU_APP_ID = serializers.CharField(max_length=256, required=True, label='App ID')
|
||||
FEISHU_APP_SECRET = serializers.CharField(max_length=256, required=False, label='App Secret', write_only=True)
|
||||
AUTH_FEISHU = serializers.BooleanField(default=False, label=_('Enable FeiShu Auth'))
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
__all__ = [
|
||||
'LDAPTestConfigSerializer', 'LDAPUserSerializer', 'LDAPTestLoginSerializer',
|
||||
'LDAPSettingSerializer',
|
||||
]
|
||||
|
||||
|
||||
class LDAPTestConfigSerializer(serializers.Serializer):
|
||||
AUTH_LDAP_SERVER_URI = serializers.CharField(max_length=1024)
|
||||
AUTH_LDAP_BIND_DN = serializers.CharField(max_length=1024, required=False, allow_blank=True)
|
||||
AUTH_LDAP_BIND_PASSWORD = serializers.CharField(required=False, allow_blank=True)
|
||||
AUTH_LDAP_SEARCH_OU = serializers.CharField()
|
||||
AUTH_LDAP_SEARCH_FILTER = serializers.CharField()
|
||||
AUTH_LDAP_USER_ATTR_MAP = serializers.CharField()
|
||||
AUTH_LDAP_START_TLS = serializers.BooleanField(required=False)
|
||||
AUTH_LDAP = serializers.BooleanField(required=False)
|
||||
|
||||
|
||||
class LDAPTestLoginSerializer(serializers.Serializer):
|
||||
username = serializers.CharField(max_length=1024, required=True)
|
||||
password = serializers.CharField(max_length=2014, required=True)
|
||||
|
||||
|
||||
class LDAPUserSerializer(serializers.Serializer):
|
||||
id = serializers.CharField()
|
||||
username = serializers.CharField()
|
||||
name = serializers.CharField()
|
||||
email = serializers.CharField()
|
||||
existing = serializers.BooleanField(read_only=True)
|
||||
|
||||
|
||||
class LDAPSettingSerializer(serializers.Serializer):
|
||||
# encrypt_fields 现在使用 write_only 来判断了
|
||||
|
||||
AUTH_LDAP_SERVER_URI = serializers.CharField(
|
||||
required=True, max_length=1024, label=_('LDAP server'),
|
||||
help_text=_('eg: ldap://localhost:389')
|
||||
)
|
||||
AUTH_LDAP_BIND_DN = serializers.CharField(required=False, max_length=1024, label=_('Bind DN'))
|
||||
AUTH_LDAP_BIND_PASSWORD = serializers.CharField(max_length=1024, write_only=True, required=False,
|
||||
label=_('Password'))
|
||||
AUTH_LDAP_SEARCH_OU = serializers.CharField(
|
||||
max_length=1024, allow_blank=True, required=False, label=_('User OU'),
|
||||
help_text=_('Use | split multi OUs')
|
||||
)
|
||||
AUTH_LDAP_SEARCH_FILTER = serializers.CharField(
|
||||
max_length=1024, required=True, label=_('User search filter'),
|
||||
help_text=_('Choice may be (cn|uid|sAMAccountName)=%(user)s)')
|
||||
)
|
||||
AUTH_LDAP_USER_ATTR_MAP = serializers.DictField(
|
||||
required=True, label=_('User attr map'),
|
||||
help_text=_('User attr map present how to map LDAP user attr to '
|
||||
'jumpserver, username,name,email is jumpserver attr')
|
||||
)
|
||||
AUTH_LDAP_SYNC_IS_PERIODIC = serializers.BooleanField(required=False, label=_('Periodic display'))
|
||||
AUTH_LDAP_SYNC_INTERVAL = serializers.CharField(
|
||||
required=False, max_length=1024, allow_null=True,
|
||||
label=_('Interval'), help_text=_('Unit: hour')
|
||||
)
|
||||
AUTH_LDAP_SYNC_CRONTAB = serializers.CharField(
|
||||
required=False, max_length=1024, allow_null=True, label=_('Regularly perform')
|
||||
)
|
||||
AUTH_LDAP_CONNECT_TIMEOUT = serializers.IntegerField(required=False, label=_('Connect timeout'))
|
||||
AUTH_LDAP_SEARCH_PAGED_SIZE = serializers.IntegerField(required=False, label=_('Search paged size'))
|
||||
|
||||
AUTH_LDAP = serializers.BooleanField(required=False, label=_('Enable LDAP auth'))
|
||||
|
||||
@staticmethod
|
||||
def post_save():
|
||||
from users.tasks import import_ldap_user_periodic
|
||||
import_ldap_user_periodic()
|
|
@ -0,0 +1,78 @@
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
__all__ = [
|
||||
'OIDCSettingSerializer', 'KeycloakSettingSerializer',
|
||||
]
|
||||
|
||||
|
||||
class CommonSettingSerializer(serializers.Serializer):
|
||||
# OpenID 公有配置参数 (version <= 1.5.8 或 version >= 1.5.8)
|
||||
BASE_SITE_URL = serializers.CharField(
|
||||
required=False, allow_null=True, max_length=1024, label=_('Base site url')
|
||||
)
|
||||
AUTH_OPENID_CLIENT_ID = serializers.CharField(
|
||||
required=False, max_length=1024, label=_('Client Id')
|
||||
)
|
||||
AUTH_OPENID_CLIENT_SECRET = serializers.CharField(
|
||||
required=False, max_length=1024, write_only=True, label=_('Client Secret')
|
||||
)
|
||||
AUTH_OPENID_SHARE_SESSION = serializers.BooleanField(required=False, label=_('Share session'))
|
||||
AUTH_OPENID_IGNORE_SSL_VERIFICATION = serializers.BooleanField(
|
||||
required=False, label=_('Ignore ssl verification')
|
||||
)
|
||||
|
||||
|
||||
class KeycloakSettingSerializer(CommonSettingSerializer):
|
||||
# OpenID 旧配置参数 (version <= 1.5.8 (discarded))
|
||||
AUTH_OPENID_KEYCLOAK = serializers.BooleanField(
|
||||
label=_("Use Keycloak"), required=False, default=False
|
||||
)
|
||||
AUTH_OPENID_SERVER_URL = serializers.CharField(
|
||||
required=False, max_length=1024, label=_('Server url')
|
||||
)
|
||||
AUTH_OPENID_REALM_NAME = serializers.CharField(
|
||||
required=False, max_length=1024, allow_null=True, label=_('Realm name')
|
||||
)
|
||||
|
||||
|
||||
class OIDCSettingSerializer(KeycloakSettingSerializer):
|
||||
# OpenID 新配置参数 (version >= 1.5.9)
|
||||
AUTH_OPENID = serializers.BooleanField(required=False, label=_('Enable OPENID Auth'))
|
||||
AUTH_OPENID_PROVIDER_ENDPOINT = serializers.CharField(
|
||||
required=False, max_length=1024, label=_('Provider endpoint')
|
||||
)
|
||||
AUTH_OPENID_PROVIDER_AUTHORIZATION_ENDPOINT = serializers.CharField(
|
||||
required=False, max_length=1024, label=_('Provider auth endpoint')
|
||||
)
|
||||
AUTH_OPENID_PROVIDER_TOKEN_ENDPOINT = serializers.CharField(
|
||||
required=False, max_length=1024, label=_('Provider token endpoint')
|
||||
)
|
||||
AUTH_OPENID_PROVIDER_JWKS_ENDPOINT = serializers.CharField(
|
||||
required=False, max_length=1024, label=_('Provider jwks endpoint')
|
||||
)
|
||||
AUTH_OPENID_PROVIDER_USERINFO_ENDPOINT = serializers.CharField(
|
||||
required=False, max_length=1024, label=_('Provider userinfo endpoint')
|
||||
)
|
||||
AUTH_OPENID_PROVIDER_END_SESSION_ENDPOINT = serializers.CharField(
|
||||
required=False, max_length=1024, label=_('Provider end session endpoint')
|
||||
)
|
||||
AUTH_OPENID_PROVIDER_SIGNATURE_ALG = serializers.CharField(
|
||||
required=False, max_length=1024, label=_('Provider sign alg')
|
||||
)
|
||||
AUTH_OPENID_PROVIDER_SIGNATURE_KEY = serializers.CharField(
|
||||
required=False, max_length=1024, allow_null=True, label=_('Provider sign key')
|
||||
)
|
||||
AUTH_OPENID_SCOPES = serializers.CharField(required=False, max_length=1024, label=_('Scopes'))
|
||||
AUTH_OPENID_ID_TOKEN_MAX_AGE = serializers.IntegerField(
|
||||
required=False, label=_('Id token max age')
|
||||
)
|
||||
AUTH_OPENID_ID_TOKEN_INCLUDE_CLAIMS = serializers.BooleanField(
|
||||
required=False, label=_('Id token include claims')
|
||||
)
|
||||
AUTH_OPENID_USE_STATE = serializers.BooleanField(required=False, label=_('Use state'))
|
||||
AUTH_OPENID_USE_NONCE = serializers.BooleanField(required=False, label=_('Use nonce'))
|
||||
AUTH_OPENID_ALWAYS_UPDATE_USER = serializers.BooleanField(
|
||||
required=False, label=_('Always update user')
|
||||
)
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
__all__ = [
|
||||
'RadiusSettingSerializer',
|
||||
]
|
||||
|
||||
|
||||
class RadiusSettingSerializer(serializers.Serializer):
|
||||
AUTH_RADIUS = serializers.BooleanField(required=False, label=_('Enable RADIUS Auth'))
|
||||
RADIUS_SERVER = serializers.CharField(required=False, max_length=1024, label=_('Host'))
|
||||
RADIUS_PORT = serializers.IntegerField(required=False, label=_('Port'))
|
||||
RADIUS_SECRET = serializers.CharField(
|
||||
required=False, max_length=1024, allow_null=True, label=_('Secret'), write_only=True
|
||||
)
|
||||
OTP_IN_RADIUS = serializers.BooleanField(required=False, label=_('OTP in radius'))
|
|
@ -0,0 +1,17 @@
|
|||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
__all__ = [
|
||||
'SSOSettingSerializer',
|
||||
]
|
||||
|
||||
|
||||
class SSOSettingSerializer(serializers.Serializer):
|
||||
AUTH_SSO = serializers.BooleanField(
|
||||
required=False, label=_('Enable SSO auth'),
|
||||
help_text=_("Other service can using SSO token login to JumpServer without password")
|
||||
)
|
||||
AUTH_SSO_AUTHKEY_TTL = serializers.IntegerField(
|
||||
required=False, label=_('SSO auth key TTL'), help_text=_("Unit: second")
|
||||
)
|
|
@ -0,0 +1,11 @@
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
__all__ = ['WeComSettingSerializer']
|
||||
|
||||
|
||||
class WeComSettingSerializer(serializers.Serializer):
|
||||
WECOM_CORPID = serializers.CharField(max_length=256, required=True, label='corpid')
|
||||
WECOM_AGENTID = serializers.CharField(max_length=256, required=True, label='agentid')
|
||||
WECOM_SECRET = serializers.CharField(max_length=256, required=False, label='secret', write_only=True)
|
||||
AUTH_WECOM = serializers.BooleanField(default=False, label=_('Enable WeCom Auth'))
|
|
@ -0,0 +1,22 @@
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
|
||||
class BasicSettingSerializer(serializers.Serializer):
|
||||
SITE_URL = serializers.URLField(
|
||||
required=True, label=_("Site url"),
|
||||
help_text=_('eg: http://dev.jumpserver.org:8080')
|
||||
)
|
||||
USER_GUIDE_URL = serializers.URLField(
|
||||
required=False, allow_blank=True, allow_null=True, label=_("User guide url"),
|
||||
help_text=_('User first login update profile done redirect to it')
|
||||
)
|
||||
FORGOT_PASSWORD_URL = serializers.URLField(
|
||||
required=False, allow_blank=True, allow_null=True, label=_("Forgot password url"),
|
||||
help_text=_('The forgot password url on login page, If you use '
|
||||
'ldap or cas external authentication, you can set it')
|
||||
)
|
||||
GLOBAL_ORG_DISPLAY_NAME = serializers.CharField(
|
||||
required=False, max_length=1024, allow_blank=True, allow_null=True, label=_("Global organization name"),
|
||||
help_text=_('The name of global organization to display')
|
||||
)
|
|
@ -0,0 +1,22 @@
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
__all__ = ['CleaningSerializer']
|
||||
|
||||
|
||||
class CleaningSerializer(serializers.Serializer):
|
||||
LOGIN_LOG_KEEP_DAYS = serializers.IntegerField(
|
||||
label=_("Login log keep days"), help_text=_("Unit: day")
|
||||
)
|
||||
TASK_LOG_KEEP_DAYS = serializers.IntegerField(
|
||||
label=_("Task log keep days"), help_text=_("Unit: day")
|
||||
)
|
||||
OPERATE_LOG_KEEP_DAYS = serializers.IntegerField(
|
||||
label=_("Operate log keep days"), help_text=_("Unit: day")
|
||||
)
|
||||
FTP_LOG_KEEP_DAYS = serializers.IntegerField(
|
||||
label=_("FTP log keep days"), help_text=_("Unit: day")
|
||||
)
|
||||
CLOUD_SYNC_TASK_EXECUTION_KEEP_DAYS = serializers.IntegerField(
|
||||
label=_("Cloud sync record keep days"), help_text=_("Unit: day")
|
||||
)
|
|
@ -1,9 +1,10 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
__all__ = ['MailTestSerializer']
|
||||
__all__ = ['MailTestSerializer', 'EmailSettingSerializer', 'EmailContentSettingSerializer']
|
||||
|
||||
|
||||
class MailTestSerializer(serializers.Serializer):
|
||||
|
@ -15,3 +16,56 @@ class MailTestSerializer(serializers.Serializer):
|
|||
EMAIL_RECIPIENT = serializers.CharField(required=False, allow_blank=True)
|
||||
EMAIL_USE_SSL = serializers.BooleanField(default=False)
|
||||
EMAIL_USE_TLS = serializers.BooleanField(default=False)
|
||||
|
||||
|
||||
class EmailSettingSerializer(serializers.Serializer):
|
||||
# encrypt_fields 现在使用 write_only 来判断了
|
||||
|
||||
EMAIL_HOST = serializers.CharField(max_length=1024, required=True, label=_("SMTP host"))
|
||||
EMAIL_PORT = serializers.CharField(max_length=5, required=True, label=_("SMTP port"))
|
||||
EMAIL_HOST_USER = serializers.CharField(max_length=128, required=True, label=_("SMTP account"))
|
||||
EMAIL_HOST_PASSWORD = serializers.CharField(
|
||||
max_length=1024, write_only=True, required=False, label=_("SMTP password"),
|
||||
help_text=_("Tips: Some provider use token except password")
|
||||
)
|
||||
EMAIL_FROM = serializers.CharField(
|
||||
max_length=128, allow_blank=True, required=False, label=_('Send user'),
|
||||
help_text=_('Tips: Send mail account, default SMTP account as the send account')
|
||||
)
|
||||
EMAIL_RECIPIENT = serializers.CharField(
|
||||
max_length=128, allow_blank=True, required=False, label=_('Test recipient'),
|
||||
help_text=_('Tips: Used only as a test mail recipient')
|
||||
)
|
||||
EMAIL_USE_SSL = serializers.BooleanField(
|
||||
required=False, label=_('Use SSL'),
|
||||
help_text=_('If SMTP port is 465, may be select')
|
||||
)
|
||||
EMAIL_USE_TLS = serializers.BooleanField(
|
||||
required=False, label=_("Use TLS"),
|
||||
help_text=_('If SMTP port is 587, may be select')
|
||||
)
|
||||
EMAIL_SUBJECT_PREFIX = serializers.CharField(
|
||||
max_length=1024, required=True, label=_('Subject prefix')
|
||||
)
|
||||
|
||||
|
||||
class EmailContentSettingSerializer(serializers.Serializer):
|
||||
EMAIL_CUSTOM_USER_CREATED_SUBJECT = serializers.CharField(
|
||||
max_length=1024, allow_blank=True, required=False,
|
||||
label=_('Create user email subject'),
|
||||
help_text=_('Tips: When creating a user, send the subject of the email (eg:Create account successfully)')
|
||||
)
|
||||
EMAIL_CUSTOM_USER_CREATED_HONORIFIC = serializers.CharField(
|
||||
max_length=1024, allow_blank=True, required=False,
|
||||
label=_('Create user honorific'),
|
||||
help_text=_('Tips: When creating a user, send the honorific of the email (eg:Hello)')
|
||||
)
|
||||
EMAIL_CUSTOM_USER_CREATED_BODY = serializers.CharField(
|
||||
max_length=4096, allow_blank=True, required=False,
|
||||
label=_('Create user email content'),
|
||||
help_text=_('Tips:When creating a user, send the content of the email')
|
||||
)
|
||||
EMAIL_CUSTOM_USER_CREATED_SIGNATURE = serializers.CharField(
|
||||
max_length=512, allow_blank=True, required=False, label=_('Signature'),
|
||||
help_text=_('Tips: Email signature (eg:jumpserver)')
|
||||
)
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
__all__ = [
|
||||
'LDAPTestConfigSerializer', 'LDAPUserSerializer', 'LDAPTestLoginSerializer'
|
||||
]
|
||||
|
||||
|
||||
class LDAPTestConfigSerializer(serializers.Serializer):
|
||||
AUTH_LDAP_SERVER_URI = serializers.CharField(max_length=1024)
|
||||
AUTH_LDAP_BIND_DN = serializers.CharField(max_length=1024, required=False, allow_blank=True)
|
||||
AUTH_LDAP_BIND_PASSWORD = serializers.CharField(required=False, allow_blank=True)
|
||||
AUTH_LDAP_SEARCH_OU = serializers.CharField()
|
||||
AUTH_LDAP_SEARCH_FILTER = serializers.CharField()
|
||||
AUTH_LDAP_USER_ATTR_MAP = serializers.CharField()
|
||||
AUTH_LDAP_START_TLS = serializers.BooleanField(required=False)
|
||||
AUTH_LDAP = serializers.BooleanField(required=False)
|
||||
|
||||
|
||||
class LDAPTestLoginSerializer(serializers.Serializer):
|
||||
username = serializers.CharField(max_length=1024, required=True)
|
||||
password = serializers.CharField(max_length=2014, required=True)
|
||||
|
||||
|
||||
class LDAPUserSerializer(serializers.Serializer):
|
||||
id = serializers.CharField()
|
||||
username = serializers.CharField()
|
||||
name = serializers.CharField()
|
||||
email = serializers.CharField()
|
||||
existing = serializers.BooleanField(read_only=True)
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
from abc import ABCMeta
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
|
||||
class OtherSettingSerializer(serializers.Serializer):
|
||||
EMAIL_SUFFIX = serializers.CharField(
|
||||
required=False, max_length=1024, label=_("Email suffix"),
|
||||
help_text=_('This is used by default if no email is returned during SSO authentication')
|
||||
)
|
||||
TICKETS_ENABLED = serializers.BooleanField(required=False, default=True, label=_("Enable tickets"))
|
||||
|
||||
OTP_ISSUER_NAME = serializers.CharField(
|
||||
required=False, max_length=1024, label=_('OTP issuer name'),
|
||||
)
|
||||
OTP_VALID_WINDOW = serializers.IntegerField(label=_("OTP valid window"))
|
||||
|
||||
PERIOD_TASK_ENABLED = serializers.BooleanField(required=False, label=_("Enable period task"))
|
||||
WINDOWS_SSH_DEFAULT_SHELL = serializers.CharField(
|
||||
required=False, max_length=1024, label=_('Ansible windows default shell')
|
||||
)
|
||||
|
||||
PERM_SINGLE_ASSET_TO_UNGROUP_NODE = serializers.BooleanField(
|
||||
required=False, label=_("Perm single to ungroup node")
|
||||
)
|
||||
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
|
||||
class SecurityPasswordRuleSerializer(serializers.Serializer):
|
||||
SECURITY_PASSWORD_MIN_LENGTH = serializers.IntegerField(
|
||||
min_value=6, max_value=30, required=True,
|
||||
label=_('Password minimum length')
|
||||
)
|
||||
SECURITY_ADMIN_USER_PASSWORD_MIN_LENGTH = serializers.IntegerField(
|
||||
min_value=6, max_value=30, required=True,
|
||||
label=_('Admin user password minimum length')
|
||||
)
|
||||
SECURITY_PASSWORD_UPPER_CASE = serializers.BooleanField(
|
||||
required=False, label=_('Must contain capital')
|
||||
)
|
||||
SECURITY_PASSWORD_LOWER_CASE = serializers.BooleanField(required=False, label=_('Must contain lowercase'))
|
||||
SECURITY_PASSWORD_NUMBER = serializers.BooleanField(required=False, label=_('Must contain numeric'))
|
||||
SECURITY_PASSWORD_SPECIAL_CHAR = serializers.BooleanField(required=False, label=_('Must contain special'))
|
||||
|
||||
|
||||
class SecurityAuthSerializer(serializers.Serializer):
|
||||
SECURITY_MFA_AUTH = serializers.ChoiceField(
|
||||
choices=(
|
||||
[0, _('Disable')],
|
||||
[1, _('All users')],
|
||||
[2, _('Only admin users')],
|
||||
),
|
||||
required=False, label=_("Global MFA auth")
|
||||
)
|
||||
SECURITY_LOGIN_LIMIT_COUNT = serializers.IntegerField(
|
||||
min_value=3, max_value=99999,
|
||||
label=_('Limit the number of login failures')
|
||||
)
|
||||
SECURITY_LOGIN_LIMIT_TIME = serializers.IntegerField(
|
||||
min_value=5, max_value=99999, required=True,
|
||||
label=_('Block logon interval'),
|
||||
help_text=_(
|
||||
'Unit: minute, If the user has failed to log in for a limited number of times, '
|
||||
'no login is allowed during this time interval.'
|
||||
)
|
||||
)
|
||||
SECURITY_PASSWORD_EXPIRATION_TIME = serializers.IntegerField(
|
||||
min_value=1, max_value=99999, required=True,
|
||||
label=_('User password expiration'),
|
||||
help_text=_(
|
||||
'Unit: day, If the user does not update the password during the time, '
|
||||
'the user password will expire failure;The password expiration reminder mail will be '
|
||||
'automatic sent to the user by system within 5 days (daily) before the password expires'
|
||||
)
|
||||
)
|
||||
OLD_PASSWORD_HISTORY_LIMIT_COUNT = serializers.IntegerField(
|
||||
min_value=0, max_value=99999, required=True,
|
||||
label=_('Number of repeated historical passwords'),
|
||||
help_text=_(
|
||||
'Tip: When the user resets the password, it cannot be '
|
||||
'the previous n historical passwords of the user'
|
||||
)
|
||||
)
|
||||
USER_LOGIN_SINGLE_MACHINE_ENABLED = serializers.BooleanField(
|
||||
required=False, default=False, label=_("Only single device login"),
|
||||
help_text=_("Next device login, pre login will be logout")
|
||||
)
|
||||
ONLY_ALLOW_EXIST_USER_AUTH = serializers.BooleanField(
|
||||
required=False, default=False, label=_("Only exist user login"),
|
||||
help_text=_("If enable, CAS、OIDC auth will be failed, if user not exist yet")
|
||||
)
|
||||
ONLY_ALLOW_AUTH_FROM_SOURCE = serializers.BooleanField(
|
||||
required=False, default=False, label=_("Only from source login"),
|
||||
help_text=_("If enable, CAS、OIDC auth will be failed, if user not exist yet")
|
||||
)
|
||||
SECURITY_MFA_VERIFY_TTL = serializers.IntegerField(label=_("MFA verify TTL"), help_text=_("Unit: second"))
|
||||
SECURITY_LOGIN_CAPTCHA_ENABLED = serializers.BooleanField(
|
||||
required=False, default=True,
|
||||
label=_("Enable Login captcha")
|
||||
)
|
||||
|
||||
|
||||
class SecuritySettingSerializer(SecurityPasswordRuleSerializer, SecurityAuthSerializer):
|
||||
SECURITY_SERVICE_ACCOUNT_REGISTRATION = serializers.BooleanField(
|
||||
required=True, label=_('Enable terminal register'),
|
||||
help_text=_("Allow terminal register, after all terminal setup, you should disable this for security")
|
||||
)
|
||||
SECURITY_WATERMARK_ENABLED = serializers.BooleanField(
|
||||
required=True, label=_('Replay watermark'),
|
||||
help_text=_('Enabled, the session replay contains watermark information')
|
||||
)
|
||||
SECURITY_MAX_IDLE_TIME = serializers.IntegerField(
|
||||
min_value=1, max_value=99999, required=False,
|
||||
label=_('Connection max idle time'),
|
||||
help_text=_('If idle time more than it, disconnect connection Unit: minute')
|
||||
)
|
||||
SECURITY_LUNA_REMEMBER_AUTH = serializers.BooleanField(
|
||||
label=_("Remember manual auth")
|
||||
)
|
||||
CHANGE_AUTH_PLAN_SECURE_MODE_ENABLED = serializers.BooleanField(
|
||||
label=_("Enable change auth secure mode")
|
||||
)
|
||||
SECURITY_INSECURE_COMMAND = serializers.BooleanField(
|
||||
required=False, label=_('Insecure command alert')
|
||||
)
|
||||
SECURITY_INSECURE_COMMAND_EMAIL_RECEIVER = serializers.CharField(
|
||||
max_length=8192, required=False, allow_blank=True, label=_('Email recipient'),
|
||||
help_text=_('Multiple user using , split')
|
||||
)
|
||||
SECURITY_COMMAND_EXECUTION = serializers.BooleanField(
|
||||
required=False, label=_('Batch command execution'),
|
||||
help_text=_('Allow user run batch command or not using ansible')
|
||||
)
|
||||
SECURITY_SESSION_SHARE = serializers.BooleanField(
|
||||
required=True, label=_('Session share'),
|
||||
help_text=_("Enabled, Allows user active session to be shared with other users")
|
||||
)
|
||||
|
||||
|
|
@ -1,250 +1,38 @@
|
|||
# coding: utf-8
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
from .basic import BasicSettingSerializer
|
||||
from .other import OtherSettingSerializer
|
||||
from .email import EmailSettingSerializer, EmailContentSettingSerializer
|
||||
from .auth import (
|
||||
LDAPSettingSerializer, OIDCSettingSerializer, KeycloakSettingSerializer,
|
||||
CASSettingSerializer, RadiusSettingSerializer, FeiShuSettingSerializer,
|
||||
WeComSettingSerializer, DingTalkSettingSerializer
|
||||
)
|
||||
from .terminal import TerminalSettingSerializer
|
||||
from .security import SecuritySettingSerializer
|
||||
from .cleaning import CleaningSerializer
|
||||
|
||||
__all__ = [
|
||||
'BasicSettingSerializer', 'EmailSettingSerializer', 'EmailContentSettingSerializer',
|
||||
'LDAPSettingSerializer', 'TerminalSettingSerializer', 'SecuritySettingSerializer',
|
||||
'SettingsSerializer', 'WeComSettingSerializer', 'DingTalkSettingSerializer',
|
||||
'FeiShuSettingSerializer',
|
||||
'SettingsSerializer',
|
||||
]
|
||||
|
||||
|
||||
class BasicSettingSerializer(serializers.Serializer):
|
||||
SITE_URL = serializers.URLField(
|
||||
required=True, label=_("Site url"),
|
||||
help_text=_('eg: http://dev.jumpserver.org:8080')
|
||||
)
|
||||
|
||||
USER_GUIDE_URL = serializers.URLField(
|
||||
required=False, allow_blank=True, allow_null=True, label=_("User guide url"),
|
||||
help_text=_('User first login update profile done redirect to it')
|
||||
)
|
||||
FORGOT_PASSWORD_URL = serializers.URLField(
|
||||
required=False, allow_blank=True, allow_null=True, label=_("Forgot password url"),
|
||||
help_text=_('The forgot password url on login page, If you use '
|
||||
'ldap or cas external authentication, you can set it')
|
||||
)
|
||||
GLOBAL_ORG_DISPLAY_NAME = serializers.CharField(
|
||||
required=False, max_length=1024, allow_blank=True, allow_null=True, label=_("Global organization name"),
|
||||
help_text=_('The name of global organization to display')
|
||||
)
|
||||
|
||||
|
||||
class EmailSettingSerializer(serializers.Serializer):
|
||||
# encrypt_fields 现在使用 write_only 来判断了
|
||||
|
||||
EMAIL_HOST = serializers.CharField(max_length=1024, required=True, label=_("SMTP host"))
|
||||
EMAIL_PORT = serializers.CharField(max_length=5, required=True, label=_("SMTP port"))
|
||||
EMAIL_HOST_USER = serializers.CharField(max_length=128, required=True, label=_("SMTP account"))
|
||||
EMAIL_HOST_PASSWORD = serializers.CharField(
|
||||
max_length=1024, write_only=True, required=False, label=_("SMTP password"),
|
||||
help_text=_("Tips: Some provider use token except password")
|
||||
)
|
||||
EMAIL_FROM = serializers.CharField(
|
||||
max_length=128, allow_blank=True, required=False, label=_('Send user'),
|
||||
help_text=_('Tips: Send mail account, default SMTP account as the send account')
|
||||
)
|
||||
EMAIL_RECIPIENT = serializers.CharField(
|
||||
max_length=128, allow_blank=True, required=False, label=_('Test recipient'),
|
||||
help_text=_('Tips: Used only as a test mail recipient')
|
||||
)
|
||||
EMAIL_USE_SSL = serializers.BooleanField(
|
||||
required=False, label=_('Use SSL'),
|
||||
help_text=_('If SMTP port is 465, may be select')
|
||||
)
|
||||
EMAIL_USE_TLS = serializers.BooleanField(
|
||||
required=False, label=_("Use TLS"),
|
||||
help_text=_('If SMTP port is 587, may be select')
|
||||
)
|
||||
EMAIL_SUBJECT_PREFIX = serializers.CharField(
|
||||
max_length=1024, required=True, label=_('Subject prefix')
|
||||
)
|
||||
|
||||
|
||||
class EmailContentSettingSerializer(serializers.Serializer):
|
||||
EMAIL_CUSTOM_USER_CREATED_SUBJECT = serializers.CharField(
|
||||
max_length=1024, allow_blank=True, required=False,
|
||||
label=_('Create user email subject'),
|
||||
help_text=_('Tips: When creating a user, send the subject of the email (eg:Create account successfully)')
|
||||
)
|
||||
EMAIL_CUSTOM_USER_CREATED_HONORIFIC = serializers.CharField(
|
||||
max_length=1024, allow_blank=True, required=False,
|
||||
label=_('Create user honorific'),
|
||||
help_text=_('Tips: When creating a user, send the honorific of the email (eg:Hello)')
|
||||
)
|
||||
EMAIL_CUSTOM_USER_CREATED_BODY = serializers.CharField(
|
||||
max_length=4096, allow_blank=True, required=False,
|
||||
label=_('Create user email content'),
|
||||
help_text=_('Tips:When creating a user, send the content of the email')
|
||||
)
|
||||
EMAIL_CUSTOM_USER_CREATED_SIGNATURE = serializers.CharField(
|
||||
max_length=512, allow_blank=True, required=False, label=_('Signature'),
|
||||
help_text=_('Tips: Email signature (eg:jumpserver)')
|
||||
)
|
||||
|
||||
|
||||
class LDAPSettingSerializer(serializers.Serializer):
|
||||
# encrypt_fields 现在使用 write_only 来判断了
|
||||
|
||||
AUTH_LDAP_SERVER_URI = serializers.CharField(
|
||||
required=True, max_length=1024, label=_('LDAP server'), help_text=_('eg: ldap://localhost:389')
|
||||
)
|
||||
AUTH_LDAP_BIND_DN = serializers.CharField(required=False, max_length=1024, label=_('Bind DN'))
|
||||
AUTH_LDAP_BIND_PASSWORD = serializers.CharField(max_length=1024, write_only=True, required=False, label=_('Password'))
|
||||
AUTH_LDAP_SEARCH_OU = serializers.CharField(
|
||||
max_length=1024, allow_blank=True, required=False, label=_('User OU'),
|
||||
help_text=_('Use | split multi OUs')
|
||||
)
|
||||
AUTH_LDAP_SEARCH_FILTER = serializers.CharField(
|
||||
max_length=1024, required=True, label=_('User search filter'),
|
||||
help_text=_('Choice may be (cn|uid|sAMAccountName)=%(user)s)')
|
||||
)
|
||||
AUTH_LDAP_USER_ATTR_MAP = serializers.DictField(
|
||||
required=True, label=_('User attr map'),
|
||||
help_text=_('User attr map present how to map LDAP user attr to jumpserver, username,name,email is jumpserver attr')
|
||||
)
|
||||
AUTH_LDAP = serializers.BooleanField(required=False, label=_('Enable LDAP auth'))
|
||||
|
||||
|
||||
class TerminalSettingSerializer(serializers.Serializer):
|
||||
SORT_BY_CHOICES = (
|
||||
('hostname', _('Hostname')),
|
||||
('ip', _('IP'))
|
||||
)
|
||||
|
||||
PAGE_SIZE_CHOICES = (
|
||||
('all', _('All')),
|
||||
('auto', _('Auto')),
|
||||
('10', '10'),
|
||||
('15', '15'),
|
||||
('25', '25'),
|
||||
('50', '50'),
|
||||
)
|
||||
TERMINAL_PASSWORD_AUTH = serializers.BooleanField(required=False, label=_('Password auth'))
|
||||
TERMINAL_PUBLIC_KEY_AUTH = serializers.BooleanField(
|
||||
required=False, label=_('Public key auth'),
|
||||
help_text=_('Tips: If use other auth method, like AD/LDAP, you should disable this to '
|
||||
'avoid being able to log in after deleting')
|
||||
)
|
||||
TERMINAL_ASSET_LIST_SORT_BY = serializers.ChoiceField(SORT_BY_CHOICES, required=False, label=_('List sort by'))
|
||||
TERMINAL_ASSET_LIST_PAGE_SIZE = serializers.ChoiceField(PAGE_SIZE_CHOICES, required=False, label=_('List page size'))
|
||||
TERMINAL_SESSION_KEEP_DURATION = serializers.IntegerField(
|
||||
min_value=1, max_value=99999, required=True, label=_('Session keep duration'),
|
||||
help_text=_('Units: days, Session, record, command will be delete if more than duration, only in database')
|
||||
)
|
||||
TERMINAL_TELNET_REGEX = serializers.CharField(allow_blank=True, max_length=1024, required=False, label=_('Telnet login regex'))
|
||||
TERMINAL_RDP_ADDR = serializers.CharField(
|
||||
required=False, label=_("RDP address"),
|
||||
max_length=1024,
|
||||
allow_blank=True,
|
||||
help_text=_('RDP visit address, eg: dev.jumpserver.org:3389')
|
||||
)
|
||||
|
||||
|
||||
class SecuritySettingSerializer(serializers.Serializer):
|
||||
SECURITY_MFA_AUTH = serializers.ChoiceField(
|
||||
choices=(
|
||||
[0, _('Disable')],
|
||||
[1, _('All users')],
|
||||
[2, _('Only admin users')],
|
||||
),
|
||||
required=False, label=_("Global MFA auth")
|
||||
)
|
||||
SECURITY_COMMAND_EXECUTION = serializers.BooleanField(
|
||||
required=False, label=_('Batch command execution'),
|
||||
help_text=_('Allow user run batch command or not using ansible')
|
||||
)
|
||||
SECURITY_SERVICE_ACCOUNT_REGISTRATION = serializers.BooleanField(
|
||||
required=True, label=_('Enable terminal register'),
|
||||
help_text=_("Allow terminal register, after all terminal setup, you should disable this for security")
|
||||
)
|
||||
SECURITY_WATERMARK_ENABLED = serializers.BooleanField(
|
||||
required=True, label=_('Replay watermark'),
|
||||
help_text=_('Enabled, the session replay contains watermark information')
|
||||
)
|
||||
SECURITY_SESSION_SHARE = serializers.BooleanField(
|
||||
required=True, label=_('Session share'),
|
||||
help_text=_("Enabled, Allows user active session to be shared with other users")
|
||||
)
|
||||
SECURITY_LOGIN_LIMIT_COUNT = serializers.IntegerField(
|
||||
min_value=3, max_value=99999,
|
||||
label=_('Limit the number of login failures')
|
||||
)
|
||||
SECURITY_LOGIN_LIMIT_TIME = serializers.IntegerField(
|
||||
min_value=5, max_value=99999, required=True,
|
||||
label=_('Block logon interval'),
|
||||
help_text=_('Tip: (unit/minute) if the user has failed to log in for a limited number of times, no login is allowed during this time interval.')
|
||||
)
|
||||
SECURITY_MAX_IDLE_TIME = serializers.IntegerField(
|
||||
min_value=1, max_value=99999, required=False,
|
||||
label=_('Connection max idle time'),
|
||||
help_text=_('If idle time more than it, disconnect connection Unit: minute')
|
||||
)
|
||||
SECURITY_PASSWORD_EXPIRATION_TIME = serializers.IntegerField(
|
||||
min_value=1, max_value=99999, required=True,
|
||||
label=_('User password expiration'),
|
||||
help_text=_('Tip: (unit: day) If the user does not update the password during the time, the user password will expire failure;The password expiration reminder mail will be automatic sent to the user by system within 5 days (daily) before the password expires')
|
||||
)
|
||||
OLD_PASSWORD_HISTORY_LIMIT_COUNT = serializers.IntegerField(
|
||||
min_value=0, max_value=99999, required=True,
|
||||
label=_('Number of repeated historical passwords'),
|
||||
help_text=_('Tip: When the user resets the password, it cannot be the previous n historical passwords of the user')
|
||||
)
|
||||
SECURITY_PASSWORD_MIN_LENGTH = serializers.IntegerField(
|
||||
min_value=6, max_value=30, required=True,
|
||||
label=_('Password minimum length')
|
||||
)
|
||||
SECURITY_ADMIN_USER_PASSWORD_MIN_LENGTH = serializers.IntegerField(
|
||||
min_value=6, max_value=30, required=True,
|
||||
label=_('Admin user password minimum length')
|
||||
)
|
||||
SECURITY_PASSWORD_UPPER_CASE = serializers.BooleanField(
|
||||
required=False, label=_('Must contain capital')
|
||||
)
|
||||
SECURITY_PASSWORD_LOWER_CASE = serializers.BooleanField(required=False, label=_('Must contain lowercase'))
|
||||
SECURITY_PASSWORD_NUMBER = serializers.BooleanField(required=False, label=_('Must contain numeric'))
|
||||
SECURITY_PASSWORD_SPECIAL_CHAR = serializers.BooleanField(required=False, label=_('Must contain special'))
|
||||
SECURITY_INSECURE_COMMAND = serializers.BooleanField(required=False, label=_('Insecure command alert'))
|
||||
SECURITY_INSECURE_COMMAND_EMAIL_RECEIVER = serializers.CharField(
|
||||
max_length=8192, required=False, allow_blank=True, label=_('Email recipient'),
|
||||
help_text=_('Multiple user using , split')
|
||||
)
|
||||
|
||||
|
||||
class WeComSettingSerializer(serializers.Serializer):
|
||||
WECOM_CORPID = serializers.CharField(max_length=256, required=True, label='corpid')
|
||||
WECOM_AGENTID = serializers.CharField(max_length=256, required=True, label='agentid')
|
||||
WECOM_SECRET = serializers.CharField(max_length=256, required=False, label='secret', write_only=True)
|
||||
AUTH_WECOM = serializers.BooleanField(default=False, label=_('Enable WeCom Auth'))
|
||||
|
||||
|
||||
class DingTalkSettingSerializer(serializers.Serializer):
|
||||
DINGTALK_AGENTID = serializers.CharField(max_length=256, required=True, label='AgentId')
|
||||
DINGTALK_APPKEY = serializers.CharField(max_length=256, required=True, label='AppKey')
|
||||
DINGTALK_APPSECRET = serializers.CharField(max_length=256, required=False, label='AppSecret', write_only=True)
|
||||
AUTH_DINGTALK = serializers.BooleanField(default=False, label=_('Enable DingTalk Auth'))
|
||||
|
||||
|
||||
class FeiShuSettingSerializer(serializers.Serializer):
|
||||
FEISHU_APP_ID = serializers.CharField(max_length=256, required=True, label='App ID')
|
||||
FEISHU_APP_SECRET = serializers.CharField(max_length=256, required=False, label='App Secret', write_only=True)
|
||||
AUTH_FEISHU = serializers.BooleanField(default=False, label=_('Enable FeiShu Auth'))
|
||||
|
||||
|
||||
class SettingsSerializer(
|
||||
BasicSettingSerializer,
|
||||
EmailSettingSerializer,
|
||||
EmailContentSettingSerializer,
|
||||
LDAPSettingSerializer,
|
||||
TerminalSettingSerializer,
|
||||
SecuritySettingSerializer,
|
||||
WeComSettingSerializer,
|
||||
DingTalkSettingSerializer,
|
||||
FeiShuSettingSerializer,
|
||||
EmailSettingSerializer,
|
||||
EmailContentSettingSerializer,
|
||||
OtherSettingSerializer,
|
||||
OIDCSettingSerializer,
|
||||
KeycloakSettingSerializer,
|
||||
CASSettingSerializer,
|
||||
RadiusSettingSerializer,
|
||||
CleaningSerializer
|
||||
):
|
||||
|
||||
# encrypt_fields 现在使用 write_only 来判断了
|
||||
pass
|
||||
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
|
||||
class TerminalSettingSerializer(serializers.Serializer):
|
||||
SORT_BY_CHOICES = (
|
||||
('hostname', _('Hostname')),
|
||||
('ip', _('IP'))
|
||||
)
|
||||
|
||||
PAGE_SIZE_CHOICES = (
|
||||
('all', _('All')),
|
||||
('auto', _('Auto')),
|
||||
('10', '10'),
|
||||
('15', '15'),
|
||||
('25', '25'),
|
||||
('50', '50'),
|
||||
)
|
||||
TERMINAL_PASSWORD_AUTH = serializers.BooleanField(required=False, label=_('Password auth'))
|
||||
TERMINAL_PUBLIC_KEY_AUTH = serializers.BooleanField(
|
||||
required=False, label=_('Public key auth'),
|
||||
help_text=_('Tips: If use other auth method, like AD/LDAP, you should disable this to '
|
||||
'avoid being able to log in after deleting')
|
||||
)
|
||||
TERMINAL_ASSET_LIST_SORT_BY = serializers.ChoiceField(SORT_BY_CHOICES, required=False, label=_('List sort by'))
|
||||
TERMINAL_ASSET_LIST_PAGE_SIZE = serializers.ChoiceField(PAGE_SIZE_CHOICES, required=False,
|
||||
label=_('List page size'))
|
||||
TERMINAL_SESSION_KEEP_DURATION = serializers.IntegerField(
|
||||
min_value=1, max_value=99999, required=True, label=_('Session keep duration'),
|
||||
help_text=_('Unit: days, Session, record, command will be delete if more than duration, only in database')
|
||||
)
|
||||
TERMINAL_TELNET_REGEX = serializers.CharField(
|
||||
allow_blank=True, max_length=1024, required=False, label=_('Telnet login regex'),
|
||||
help_text=_("The login success message varies with devices. "
|
||||
"if you cannot log in to the device through Telnet, set this parameter")
|
||||
)
|
||||
TERMINAL_RDP_ADDR = serializers.CharField(
|
||||
required=False, label=_("RDP address"),
|
||||
max_length=1024,
|
||||
allow_blank=True,
|
||||
help_text=_('RDP visit address, eg: dev.jumpserver.org:3389')
|
||||
)
|
|
@ -92,8 +92,8 @@ def import_ldap_user():
|
|||
def import_ldap_user_periodic():
|
||||
if not settings.AUTH_LDAP:
|
||||
return
|
||||
task_name = 'import_ldap_user_periodic'
|
||||
if not settings.AUTH_LDAP_SYNC_IS_PERIODIC:
|
||||
task_name = sys._getframe().f_code.co_name
|
||||
disable_celery_periodic_task(task_name)
|
||||
return
|
||||
|
||||
|
@ -104,7 +104,7 @@ def import_ldap_user_periodic():
|
|||
interval = None
|
||||
crontab = settings.AUTH_LDAP_SYNC_CRONTAB
|
||||
tasks = {
|
||||
'import_ldap_user_periodic': {
|
||||
task_name: {
|
||||
'task': import_ldap_user.name,
|
||||
'interval': interval,
|
||||
'crontab': crontab,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# SECURITY WARNING: keep the secret key used in production secret!
|
||||
# 加密秘钥 生产环境中请修改为随机字符串,请勿外泄, 可使用命令生成
|
||||
# 加密密钥 生产环境中请修改为随机字符串,请勿外泄, 可使用命令生成
|
||||
# $ cat /dev/urandom | tr -dc A-Za-z0-9 | head -c 49;echo
|
||||
SECRET_KEY:
|
||||
|
||||
|
|
Loading…
Reference in New Issue