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
|
@on_transaction_commit
|
||||||
def on_system_user_update(instance: SystemUser, created, **kwargs):
|
def on_system_user_update(instance: SystemUser, created, **kwargs):
|
||||||
"""
|
"""
|
||||||
当系统用户更新时,可能更新了秘钥,用户名等,这时要自动推送系统用户到资产上,
|
当系统用户更新时,可能更新了密钥,用户名等,这时要自动推送系统用户到资产上,
|
||||||
其实应该当 用户名,密码,秘钥 sudo等更新时再推送,这里偷个懒,
|
其实应该当 用户名,密码,密钥 sudo等更新时再推送,这里偷个懒,
|
||||||
这里直接取了 instance.assets 因为nodes和系统用户发生变化时,会自动将nodes下的资产
|
这里直接取了 instance.assets 因为nodes和系统用户发生变化时,会自动将nodes下的资产
|
||||||
关联到上面
|
关联到上面
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -5,14 +5,12 @@ from django.utils import timezone
|
||||||
from celery import shared_task
|
from celery import shared_task
|
||||||
|
|
||||||
from ops.celery.decorator import (
|
from ops.celery.decorator import (
|
||||||
register_as_period_task, after_app_shutdown_clean_periodic
|
register_as_period_task
|
||||||
)
|
)
|
||||||
from .models import UserLoginLog, OperateLog
|
from .models import UserLoginLog, OperateLog
|
||||||
from common.utils import get_log_keep_day
|
from common.utils import get_log_keep_day
|
||||||
|
|
||||||
|
|
||||||
@shared_task
|
|
||||||
@after_app_shutdown_clean_periodic
|
|
||||||
def clean_login_log_period():
|
def clean_login_log_period():
|
||||||
now = timezone.now()
|
now = timezone.now()
|
||||||
days = get_log_keep_day('LOGIN_LOG_KEEP_DAYS')
|
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()
|
UserLoginLog.objects.filter(datetime__lt=expired_day).delete()
|
||||||
|
|
||||||
|
|
||||||
@shared_task
|
|
||||||
@after_app_shutdown_clean_periodic
|
|
||||||
def clean_operation_log_period():
|
def clean_operation_log_period():
|
||||||
now = timezone.now()
|
now = timezone.now()
|
||||||
days = get_log_keep_day('OPERATE_LOG_KEEP_DAYS')
|
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()
|
OperateLog.objects.filter(datetime__lt=expired_day).delete()
|
||||||
|
|
||||||
|
|
||||||
@shared_task
|
|
||||||
def clean_ftp_log_period():
|
def clean_ftp_log_period():
|
||||||
now = timezone.now()
|
now = timezone.now()
|
||||||
days = get_log_keep_day('FTP_LOG_KEEP_DAYS')
|
days = get_log_keep_day('FTP_LOG_KEEP_DAYS')
|
||||||
|
|
|
@ -51,7 +51,8 @@ class UserLoginView(mixins.AuthMixin, FormView):
|
||||||
|
|
||||||
if settings.AUTH_OPENID:
|
if settings.AUTH_OPENID:
|
||||||
auth_type = 'OIDC'
|
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:
|
else:
|
||||||
openid_auth_url = None
|
openid_auth_url = None
|
||||||
|
|
||||||
|
@ -64,16 +65,13 @@ class UserLoginView(mixins.AuthMixin, FormView):
|
||||||
if not any([openid_auth_url, cas_auth_url]):
|
if not any([openid_auth_url, cas_auth_url]):
|
||||||
return None
|
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
|
auth_url = openid_auth_url
|
||||||
|
|
||||||
elif settings.LOGIN_REDIRECT_TO_BACKEND == 'CAS' and cas_auth_url:
|
if settings.LOGIN_REDIRECT_TO_BACKEND or not settings.LOGIN_REDIRECT_MSG_ENABLED:
|
||||||
auth_url = cas_auth_url
|
|
||||||
|
|
||||||
else:
|
|
||||||
auth_url = openid_auth_url or cas_auth_url
|
|
||||||
|
|
||||||
if settings.LOGIN_REDIRECT_TO_BACKEND:
|
|
||||||
redirect_url = auth_url
|
redirect_url = auth_url
|
||||||
else:
|
else:
|
||||||
message_data = {
|
message_data = {
|
||||||
|
|
|
@ -179,13 +179,14 @@ class Config(dict):
|
||||||
'AUTH_OPENID_CLIENT_SECRET': 'client-secret',
|
'AUTH_OPENID_CLIENT_SECRET': 'client-secret',
|
||||||
'AUTH_OPENID_SHARE_SESSION': True,
|
'AUTH_OPENID_SHARE_SESSION': True,
|
||||||
'AUTH_OPENID_IGNORE_SSL_VERIFICATION': True,
|
'AUTH_OPENID_IGNORE_SSL_VERIFICATION': True,
|
||||||
|
|
||||||
# OpenID 新配置参数 (version >= 1.5.9)
|
# OpenID 新配置参数 (version >= 1.5.9)
|
||||||
'AUTH_OPENID_PROVIDER_ENDPOINT': 'https://op-example.com/',
|
'AUTH_OPENID_PROVIDER_ENDPOINT': 'https://oidc.example.com/',
|
||||||
'AUTH_OPENID_PROVIDER_AUTHORIZATION_ENDPOINT': 'https://op-example.com/authorize',
|
'AUTH_OPENID_PROVIDER_AUTHORIZATION_ENDPOINT': 'https://oidc.example.com/authorize',
|
||||||
'AUTH_OPENID_PROVIDER_TOKEN_ENDPOINT': 'https://op-example.com/token',
|
'AUTH_OPENID_PROVIDER_TOKEN_ENDPOINT': 'https://oidc.example.com/token',
|
||||||
'AUTH_OPENID_PROVIDER_JWKS_ENDPOINT': 'https://op-example.com/jwks',
|
'AUTH_OPENID_PROVIDER_JWKS_ENDPOINT': 'https://oidc.example.com/jwks',
|
||||||
'AUTH_OPENID_PROVIDER_USERINFO_ENDPOINT': 'https://op-example.com/userinfo',
|
'AUTH_OPENID_PROVIDER_USERINFO_ENDPOINT': 'https://oidc.example.com/userinfo',
|
||||||
'AUTH_OPENID_PROVIDER_END_SESSION_ENDPOINT': 'https://op-example.com/logout',
|
'AUTH_OPENID_PROVIDER_END_SESSION_ENDPOINT': 'https://oidc.example.com/logout',
|
||||||
'AUTH_OPENID_PROVIDER_SIGNATURE_ALG': 'HS256',
|
'AUTH_OPENID_PROVIDER_SIGNATURE_ALG': 'HS256',
|
||||||
'AUTH_OPENID_PROVIDER_SIGNATURE_KEY': None,
|
'AUTH_OPENID_PROVIDER_SIGNATURE_KEY': None,
|
||||||
'AUTH_OPENID_SCOPES': 'openid profile email',
|
'AUTH_OPENID_SCOPES': 'openid profile email',
|
||||||
|
@ -194,10 +195,13 @@ class Config(dict):
|
||||||
'AUTH_OPENID_USE_STATE': True,
|
'AUTH_OPENID_USE_STATE': True,
|
||||||
'AUTH_OPENID_USE_NONCE': True,
|
'AUTH_OPENID_USE_NONCE': True,
|
||||||
'AUTH_OPENID_ALWAYS_UPDATE_USER': 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,
|
'AUTH_OPENID_REALM_NAME': None,
|
||||||
|
|
||||||
|
# Raidus 认证
|
||||||
'AUTH_RADIUS': False,
|
'AUTH_RADIUS': False,
|
||||||
'RADIUS_SERVER': 'localhost',
|
'RADIUS_SERVER': 'localhost',
|
||||||
'RADIUS_PORT': 1812,
|
'RADIUS_PORT': 1812,
|
||||||
|
@ -205,8 +209,9 @@ class Config(dict):
|
||||||
'RADIUS_ENCRYPT_PASSWORD': True,
|
'RADIUS_ENCRYPT_PASSWORD': True,
|
||||||
'OTP_IN_RADIUS': False,
|
'OTP_IN_RADIUS': False,
|
||||||
|
|
||||||
|
# Cas 认证
|
||||||
'AUTH_CAS': False,
|
'AUTH_CAS': False,
|
||||||
'CAS_SERVER_URL': "http://host/cas/",
|
'CAS_SERVER_URL': "https://example.com/cas/",
|
||||||
'CAS_ROOT_PROXIED_AS': '',
|
'CAS_ROOT_PROXIED_AS': '',
|
||||||
'CAS_LOGOUT_COMPLETELY': True,
|
'CAS_LOGOUT_COMPLETELY': True,
|
||||||
'CAS_VERSION': 3,
|
'CAS_VERSION': 3,
|
||||||
|
@ -218,24 +223,31 @@ class Config(dict):
|
||||||
'AUTH_SSO': False,
|
'AUTH_SSO': False,
|
||||||
'AUTH_SSO_AUTHKEY_TTL': 60 * 15,
|
'AUTH_SSO_AUTHKEY_TTL': 60 * 15,
|
||||||
|
|
||||||
|
# 企业微信
|
||||||
'AUTH_WECOM': False,
|
'AUTH_WECOM': False,
|
||||||
'WECOM_CORPID': '',
|
'WECOM_CORPID': '',
|
||||||
'WECOM_AGENTID': '',
|
'WECOM_AGENTID': '',
|
||||||
'WECOM_SECRET': '',
|
'WECOM_SECRET': '',
|
||||||
|
|
||||||
|
# 钉钉
|
||||||
'AUTH_DINGTALK': False,
|
'AUTH_DINGTALK': False,
|
||||||
'DINGTALK_AGENTID': '',
|
'DINGTALK_AGENTID': '',
|
||||||
'DINGTALK_APPKEY': '',
|
'DINGTALK_APPKEY': '',
|
||||||
'DINGTALK_APPSECRET': '',
|
'DINGTALK_APPSECRET': '',
|
||||||
|
|
||||||
|
# 飞书
|
||||||
'AUTH_FEISHU': False,
|
'AUTH_FEISHU': False,
|
||||||
'FEISHU_APP_ID': '',
|
'FEISHU_APP_ID': '',
|
||||||
'FEISHU_APP_SECRET': '',
|
'FEISHU_APP_SECRET': '',
|
||||||
|
|
||||||
|
'LOGIN_REDIRECT_TO_BACKEND': '', # 'OPENID / CAS
|
||||||
|
'LOGIN_REDIRECT_MSG_ENABLED': True,
|
||||||
|
|
||||||
'OTP_VALID_WINDOW': 2,
|
'OTP_VALID_WINDOW': 2,
|
||||||
'OTP_ISSUER_NAME': 'JumpServer',
|
'OTP_ISSUER_NAME': 'JumpServer',
|
||||||
'EMAIL_SUFFIX': 'jumpserver.org',
|
'EMAIL_SUFFIX': 'example.com',
|
||||||
|
|
||||||
|
# Terminal配置
|
||||||
'TERMINAL_PASSWORD_AUTH': True,
|
'TERMINAL_PASSWORD_AUTH': True,
|
||||||
'TERMINAL_PUBLIC_KEY_AUTH': True,
|
'TERMINAL_PUBLIC_KEY_AUTH': True,
|
||||||
'TERMINAL_HEARTBEAT_INTERVAL': 20,
|
'TERMINAL_HEARTBEAT_INTERVAL': 20,
|
||||||
|
@ -245,7 +257,9 @@ class Config(dict):
|
||||||
'TERMINAL_HOST_KEY': '',
|
'TERMINAL_HOST_KEY': '',
|
||||||
'TERMINAL_TELNET_REGEX': '',
|
'TERMINAL_TELNET_REGEX': '',
|
||||||
'TERMINAL_COMMAND_STORAGE': {},
|
'TERMINAL_COMMAND_STORAGE': {},
|
||||||
|
'TERMINAL_RDP_ADDR': '',
|
||||||
|
|
||||||
|
# 安全配置
|
||||||
'SECURITY_MFA_AUTH': 0, # 0 不开启 1 全局开启 2 管理员开启
|
'SECURITY_MFA_AUTH': 0, # 0 不开启 1 全局开启 2 管理员开启
|
||||||
'SECURITY_COMMAND_EXECUTION': True,
|
'SECURITY_COMMAND_EXECUTION': True,
|
||||||
'SECURITY_SERVICE_ACCOUNT_REGISTRATION': True,
|
'SECURITY_SERVICE_ACCOUNT_REGISTRATION': True,
|
||||||
|
@ -262,58 +276,60 @@ class Config(dict):
|
||||||
'SECURITY_PASSWORD_SPECIAL_CHAR': False,
|
'SECURITY_PASSWORD_SPECIAL_CHAR': False,
|
||||||
'SECURITY_LOGIN_CHALLENGE_ENABLED': False,
|
'SECURITY_LOGIN_CHALLENGE_ENABLED': False,
|
||||||
'SECURITY_LOGIN_CAPTCHA_ENABLED': True,
|
'SECURITY_LOGIN_CAPTCHA_ENABLED': True,
|
||||||
'SECURITY_DATA_CRYPTO_ALGO': 'aes',
|
|
||||||
'SECURITY_INSECURE_COMMAND': False,
|
'SECURITY_INSECURE_COMMAND': False,
|
||||||
'SECURITY_INSECURE_COMMAND_LEVEL': 5,
|
'SECURITY_INSECURE_COMMAND_LEVEL': 5,
|
||||||
'SECURITY_INSECURE_COMMAND_EMAIL_RECEIVER': '',
|
'SECURITY_INSECURE_COMMAND_EMAIL_RECEIVER': '',
|
||||||
'SECURITY_LUNA_REMEMBER_AUTH': True,
|
'SECURITY_LUNA_REMEMBER_AUTH': True,
|
||||||
'SECURITY_WATERMARK_ENABLED': True,
|
'SECURITY_WATERMARK_ENABLED': True,
|
||||||
|
'SECURITY_MFA_VERIFY_TTL': 3600,
|
||||||
'SECURITY_SESSION_SHARE': True,
|
'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_BIND_HOST': '0.0.0.0',
|
||||||
'HTTP_LISTEN_PORT': 8080,
|
'HTTP_LISTEN_PORT': 8080,
|
||||||
'WS_LISTEN_PORT': 8070,
|
'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,
|
'LOGIN_LOG_KEEP_DAYS': 200,
|
||||||
'TASK_LOG_KEEP_DAYS': 90,
|
'TASK_LOG_KEEP_DAYS': 90,
|
||||||
'OPERATE_LOG_KEEP_DAYS': 200,
|
'OPERATE_LOG_KEEP_DAYS': 200,
|
||||||
'FTP_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,
|
'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):
|
def compatible_auth_openid_of_key(self):
|
||||||
|
@ -324,6 +340,9 @@ class Config(dict):
|
||||||
构造出新配置中标准OpenID协议中所需的Endpoint即可
|
构造出新配置中标准OpenID协议中所需的Endpoint即可
|
||||||
(Keycloak说明文档参考: https://www.keycloak.org/docs/latest/securing_apps/)
|
(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:
|
if not self.AUTH_OPENID:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
|
@ -72,14 +72,9 @@ TERMINAL_HOST_KEY = CONFIG.TERMINAL_HOST_KEY
|
||||||
TERMINAL_HEADER_TITLE = CONFIG.TERMINAL_HEADER_TITLE
|
TERMINAL_HEADER_TITLE = CONFIG.TERMINAL_HEADER_TITLE
|
||||||
TERMINAL_TELNET_REGEX = CONFIG.TERMINAL_TELNET_REGEX
|
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
|
# Asset user auth external backend, default AuthBook backend
|
||||||
BACKEND_ASSET_USER_AUTH_VAULT = False
|
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_SINGLE_ASSET_TO_UNGROUP_NODE = CONFIG.PERM_SINGLE_ASSET_TO_UNGROUP_NODE
|
||||||
PERM_EXPIRED_CHECK_PERIODIC = CONFIG.PERM_EXPIRED_CHECK_PERIODIC
|
PERM_EXPIRED_CHECK_PERIODIC = CONFIG.PERM_EXPIRED_CHECK_PERIODIC
|
||||||
WINDOWS_SSH_DEFAULT_SHELL = CONFIG.WINDOWS_SSH_DEFAULT_SHELL
|
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
|
SECURITY_SESSION_SHARE = CONFIG.SECURITY_SESSION_SHARE
|
||||||
|
|
||||||
LOGIN_REDIRECT_TO_BACKEND = CONFIG.LOGIN_REDIRECT_TO_BACKEND
|
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
|
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 channels.generic.websocket import JsonWebsocketConsumer
|
||||||
|
|
||||||
from common.utils import get_logger
|
from common.utils import get_logger
|
||||||
from .models import SiteMessage
|
|
||||||
from .site_msg import SiteMessageUtil
|
from .site_msg import SiteMessageUtil
|
||||||
from .signals_handler import new_site_msg_chan
|
from .signals_handler import new_site_msg_chan
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ class BaseHost(Host):
|
||||||
if host_data.get('username'):
|
if host_data.get('username'):
|
||||||
self.set_variable('ansible_user', host_data['username'])
|
self.set_variable('ansible_user', host_data['username'])
|
||||||
|
|
||||||
# 添加密码和秘钥
|
# 添加密码和密钥
|
||||||
if host_data.get('password'):
|
if host_data.get('password'):
|
||||||
self.set_variable('ansible_ssh_pass', host_data['password'])
|
self.set_variable('ansible_ssh_pass', host_data['password'])
|
||||||
if host_data.get('private_key'):
|
if host_data.get('private_key'):
|
||||||
|
|
|
@ -159,7 +159,7 @@ class PeriodTaskFormMixin(forms.Form):
|
||||||
)
|
)
|
||||||
interval = forms.IntegerField(
|
interval = forms.IntegerField(
|
||||||
required=False, initial=24,
|
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):
|
def get_initial_for_field(self, field, field_name):
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
from .common import *
|
from .settings import *
|
||||||
from .ldap import *
|
from .ldap import *
|
||||||
from .wecom import *
|
from .wecom import *
|
||||||
from .dingtalk import *
|
from .dingtalk import *
|
||||||
from .feishu 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):
|
class Setting(models.Model):
|
||||||
name = models.CharField(max_length=128, unique=True, verbose_name=_("Name"))
|
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")
|
category = models.CharField(max_length=128, default="default")
|
||||||
encrypted = models.BooleanField(default=False)
|
encrypted = models.BooleanField(default=False)
|
||||||
enabled = models.BooleanField(verbose_name=_("Enabled"), default=True)
|
enabled = models.BooleanField(verbose_name=_("Enabled"), default=True)
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
#
|
#
|
||||||
|
|
||||||
|
from .basic import *
|
||||||
|
from .auth import *
|
||||||
from .email import *
|
from .email import *
|
||||||
from .ldap import *
|
|
||||||
from .public import *
|
from .public import *
|
||||||
from .settings 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
|
# coding: utf-8
|
||||||
#
|
#
|
||||||
|
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
__all__ = ['MailTestSerializer']
|
__all__ = ['MailTestSerializer', 'EmailSettingSerializer', 'EmailContentSettingSerializer']
|
||||||
|
|
||||||
|
|
||||||
class MailTestSerializer(serializers.Serializer):
|
class MailTestSerializer(serializers.Serializer):
|
||||||
|
@ -15,3 +16,56 @@ class MailTestSerializer(serializers.Serializer):
|
||||||
EMAIL_RECIPIENT = serializers.CharField(required=False, allow_blank=True)
|
EMAIL_RECIPIENT = serializers.CharField(required=False, allow_blank=True)
|
||||||
EMAIL_USE_SSL = serializers.BooleanField(default=False)
|
EMAIL_USE_SSL = serializers.BooleanField(default=False)
|
||||||
EMAIL_USE_TLS = 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
|
# coding: utf-8
|
||||||
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from .basic import BasicSettingSerializer
|
||||||
from rest_framework import serializers
|
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__ = [
|
__all__ = [
|
||||||
'BasicSettingSerializer', 'EmailSettingSerializer', 'EmailContentSettingSerializer',
|
'SettingsSerializer',
|
||||||
'LDAPSettingSerializer', 'TerminalSettingSerializer', 'SecuritySettingSerializer',
|
|
||||||
'SettingsSerializer', 'WeComSettingSerializer', 'DingTalkSettingSerializer',
|
|
||||||
'FeiShuSettingSerializer',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
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(
|
class SettingsSerializer(
|
||||||
BasicSettingSerializer,
|
BasicSettingSerializer,
|
||||||
EmailSettingSerializer,
|
|
||||||
EmailContentSettingSerializer,
|
|
||||||
LDAPSettingSerializer,
|
LDAPSettingSerializer,
|
||||||
TerminalSettingSerializer,
|
TerminalSettingSerializer,
|
||||||
SecuritySettingSerializer,
|
SecuritySettingSerializer,
|
||||||
WeComSettingSerializer,
|
WeComSettingSerializer,
|
||||||
DingTalkSettingSerializer,
|
DingTalkSettingSerializer,
|
||||||
FeiShuSettingSerializer,
|
FeiShuSettingSerializer,
|
||||||
|
EmailSettingSerializer,
|
||||||
|
EmailContentSettingSerializer,
|
||||||
|
OtherSettingSerializer,
|
||||||
|
OIDCSettingSerializer,
|
||||||
|
KeycloakSettingSerializer,
|
||||||
|
CASSettingSerializer,
|
||||||
|
RadiusSettingSerializer,
|
||||||
|
CleaningSerializer
|
||||||
):
|
):
|
||||||
|
|
||||||
# encrypt_fields 现在使用 write_only 来判断了
|
# encrypt_fields 现在使用 write_only 来判断了
|
||||||
pass
|
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():
|
def import_ldap_user_periodic():
|
||||||
if not settings.AUTH_LDAP:
|
if not settings.AUTH_LDAP:
|
||||||
return
|
return
|
||||||
|
task_name = 'import_ldap_user_periodic'
|
||||||
if not settings.AUTH_LDAP_SYNC_IS_PERIODIC:
|
if not settings.AUTH_LDAP_SYNC_IS_PERIODIC:
|
||||||
task_name = sys._getframe().f_code.co_name
|
|
||||||
disable_celery_periodic_task(task_name)
|
disable_celery_periodic_task(task_name)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@ def import_ldap_user_periodic():
|
||||||
interval = None
|
interval = None
|
||||||
crontab = settings.AUTH_LDAP_SYNC_CRONTAB
|
crontab = settings.AUTH_LDAP_SYNC_CRONTAB
|
||||||
tasks = {
|
tasks = {
|
||||||
'import_ldap_user_periodic': {
|
task_name: {
|
||||||
'task': import_ldap_user.name,
|
'task': import_ldap_user.name,
|
||||||
'interval': interval,
|
'interval': interval,
|
||||||
'crontab': crontab,
|
'crontab': crontab,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# SECURITY WARNING: keep the secret key used in production secret!
|
# SECURITY WARNING: keep the secret key used in production secret!
|
||||||
# 加密秘钥 生产环境中请修改为随机字符串,请勿外泄, 可使用命令生成
|
# 加密密钥 生产环境中请修改为随机字符串,请勿外泄, 可使用命令生成
|
||||||
# $ cat /dev/urandom | tr -dc A-Za-z0-9 | head -c 49;echo
|
# $ cat /dev/urandom | tr -dc A-Za-z0-9 | head -c 49;echo
|
||||||
SECRET_KEY:
|
SECRET_KEY:
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue