Compare commits

...

9 Commits
v5 ... v2.11.3

11 changed files with 129 additions and 87 deletions

View File

@@ -248,13 +248,16 @@ class SystemUser(BaseUser):
if user_id:
user = get_object_or_none(User, pk=user_id)
_username = self.username
if self.username_same_with_user:
if user and not username:
username = user.username
_username = user.username
else:
_username = username
# 加载某个资产的特殊配置认证信息
try:
self.load_asset_special_auth(asset, username)
self.load_asset_special_auth(asset, _username)
except Exception as e:
logger.error('Load special auth Error: ', e)
pass

View File

@@ -3,7 +3,7 @@
from django import forms
from django.conf import settings
from django.utils.translation import gettext_lazy as _
from django.utils.translation import ugettext_lazy as _
from captcha.fields import CaptchaField, CaptchaTextInput
@@ -23,12 +23,17 @@ class UserLoginForm(forms.Form):
max_length=1024, strip=False
)
auto_login = forms.BooleanField(
label=_("{} days auto login").format(days_auto_login or 1),
required=False, initial=False, widget=forms.CheckboxInput(
required=False, initial=False,
widget=forms.CheckboxInput(
attrs={'disabled': disable_days_auto_login}
)
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
auto_login_field = self.fields['auto_login']
auto_login_field.label = _("{} days auto login").format(self.days_auto_login or 1)
def confirm_login_allowed(self, user):
if not user.is_staff:
raise forms.ValidationError(

View File

@@ -44,14 +44,15 @@ class UserLoginView(mixins.AuthMixin, FormView):
# show jumpserver login page if request http://{JUMP-SERVER}/?admin=1
if self.request.GET.get("admin", 0):
return None
next_url = request.GET.get('next') or '/'
auth_type = ''
auth_url = ''
if settings.AUTH_OPENID:
auth_type = 'OIDC'
auth_url = reverse(settings.AUTH_OPENID_AUTH_LOGIN_URL_NAME)
auth_url = reverse(settings.AUTH_OPENID_AUTH_LOGIN_URL_NAME) + f'?next={next_url}'
elif settings.AUTH_CAS:
auth_type = 'CAS'
auth_url = reverse(settings.CAS_LOGIN_URL_NAME)
auth_url = reverse(settings.CAS_LOGIN_URL_NAME) + f'?next={next_url}'
if not auth_url:
return None

View File

@@ -6,7 +6,7 @@ import socket
import string
string_punctuation = '!#$%&()*+,-.:;<=>?@[]^_{}~'
string_punctuation = '!#$%&()*+,-.:;<=>?@[]^_~'
def random_datetime(date_start, date_end):

Binary file not shown.

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: JumpServer 0.3.3\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-06-16 17:47+0800\n"
"POT-Creation-Date: 2021-06-22 19:14+0800\n"
"PO-Revision-Date: 2021-05-20 10:54+0800\n"
"Last-Translator: ibuler <ibuler@qq.com>\n"
"Language-Team: JumpServer team<ibuler@qq.com>\n"
@@ -184,7 +184,7 @@ msgstr "格式为逗号分隔的字符串, * 表示匹配所有. "
#: users/templates/users/_select_user_modal.html:14
#: xpack/plugins/change_auth_plan/models.py:47
#: xpack/plugins/change_auth_plan/models.py:278
#: xpack/plugins/cloud/serializers.py:51
#: xpack/plugins/cloud/serializers.py:65
msgid "Username"
msgstr "用户名"
@@ -304,7 +304,7 @@ msgid "Cluster"
msgstr "集群"
#: applications/serializers/attrs/application_category/db.py:11
#: ops/models/adhoc.py:146 xpack/plugins/cloud/serializers.py:49
#: ops/models/adhoc.py:146 xpack/plugins/cloud/serializers.py:63
msgid "Host"
msgstr "主机"
@@ -314,7 +314,7 @@ msgstr "主机"
#: applications/serializers/attrs/application_type/oracle.py:11
#: applications/serializers/attrs/application_type/pgsql.py:11
#: assets/models/asset.py:188 assets/models/domain.py:53
#: xpack/plugins/cloud/serializers.py:50
#: xpack/plugins/cloud/serializers.py:64
msgid "Port"
msgstr "端口"
@@ -344,7 +344,7 @@ msgstr "目标URL"
#: xpack/plugins/change_auth_plan/models.py:68
#: xpack/plugins/change_auth_plan/models.py:190
#: xpack/plugins/change_auth_plan/models.py:285
#: xpack/plugins/cloud/serializers.py:53
#: xpack/plugins/cloud/serializers.py:67
msgid "Password"
msgstr "密码"
@@ -376,7 +376,7 @@ msgstr "不能删除根节点 ({})"
msgid "Deletion failed and the node contains assets"
msgstr "删除失败,节点包含资产"
#: assets/backends/db.py:110 assets/models/user.py:304 audits/models.py:39
#: assets/backends/db.py:110 assets/models/user.py:307 audits/models.py:39
#: perms/models/application_permission.py:31
#: perms/models/asset_permission.py:101 templates/_nav.html:45
#: terminal/backends/command/models.py:20
@@ -396,7 +396,7 @@ msgstr "系统用户(动态)"
#: assets/backends/db.py:233 assets/models/asset.py:196
#: assets/models/cluster.py:19 assets/models/user.py:67 templates/_nav.html:44
#: xpack/plugins/cloud/models.py:92 xpack/plugins/cloud/serializers.py:146
#: xpack/plugins/cloud/models.py:92 xpack/plugins/cloud/serializers.py:160
msgid "Admin user"
msgstr "管理用户"
@@ -715,7 +715,7 @@ msgstr "ssh私钥"
#: users/templates/users/user_asset_permission.html:41
#: users/templates/users/user_asset_permission.html:73
#: users/templates/users/user_asset_permission.html:158
#: xpack/plugins/cloud/models.py:89 xpack/plugins/cloud/serializers.py:147
#: xpack/plugins/cloud/models.py:89 xpack/plugins/cloud/serializers.py:161
msgid "Node"
msgstr "节点"
@@ -1422,12 +1422,12 @@ msgstr "您的密码已过期,先修改再登录"
msgid "Your password is invalid"
msgstr "您的密码无效"
#: authentication/forms.py:26
#: authentication/forms.py:35
msgid "{} days auto login"
msgstr "{} 天内自动登录"
#: authentication/forms.py:41 authentication/forms.py:54
#: authentication/forms.py:56 users/forms/profile.py:27
#: authentication/forms.py:46 authentication/forms.py:59
#: authentication/forms.py:61 users/forms/profile.py:27
msgid "MFA code"
msgstr "多因子认证验证码"
@@ -1632,19 +1632,19 @@ msgstr "请使用密码登录,然后绑定企业微信"
msgid "Binding DingTalk failed"
msgstr "绑定钉钉失败"
#: authentication/views/login.py:59
#: authentication/views/login.py:60
msgid "Redirecting"
msgstr "跳转中"
#: authentication/views/login.py:60
#: authentication/views/login.py:61
msgid "Redirecting to {} authentication"
msgstr "正在跳转到 {} 认证"
#: authentication/views/login.py:84
#: authentication/views/login.py:85
msgid "Please enable cookies and try again."
msgstr "设置你的浏览器支持cookie"
#: authentication/views/login.py:202
#: authentication/views/login.py:203
msgid ""
"Wait for <b>{}</b> confirm, You also can copy link to her/him <br/>\n"
" Don't close this page"
@@ -1652,15 +1652,15 @@ msgstr ""
"等待 <b>{}</b> 确认, 你也可以复制链接发给他/她 <br/>\n"
" 不要关闭本页面"
#: authentication/views/login.py:207
#: authentication/views/login.py:208
msgid "No ticket found"
msgstr "没有发现工单"
#: authentication/views/login.py:239
#: authentication/views/login.py:240
msgid "Logout success"
msgstr "退出登录成功"
#: authentication/views/login.py:240
#: authentication/views/login.py:241
msgid "Logout success, return login page"
msgstr "退出登录成功,返回到登录页面"
@@ -2195,13 +2195,13 @@ msgstr "欢迎使用JumpServer开源堡垒机"
msgid "Test success"
msgstr "测试成功"
#: settings/api/ldap.py:189
#: settings/api/ldap.py:197
msgid "Get ldap users is None"
msgstr "获取 LDAP 用户为 None"
#: settings/api/ldap.py:196
msgid "Imported {} users successfully"
msgstr "导入 {} 个用户成功"
#: settings/api/ldap.py:206
msgid "Imported {} users successfully (Organization: {})"
msgstr "成功导入 {} 个用户 ( 组织: {} )"
#: settings/models.py:123 users/templates/users/reset_password.html:29
msgid "Setting"
@@ -2543,100 +2543,100 @@ msgstr "启用企业微信认证"
msgid "Enable DingTalk Auth"
msgstr "启用钉钉认证"
#: settings/utils/ldap.py:417
#: settings/utils/ldap.py:416
msgid "Host or port is disconnected: {}"
msgstr "主机或端口不可连接: {}"
#: settings/utils/ldap.py:419
#: settings/utils/ldap.py:418
msgid "The port is not the port of the LDAP service: {}"
msgstr "端口不是LDAP服务端口: {}"
#: settings/utils/ldap.py:421
#: settings/utils/ldap.py:420
msgid "Please add certificate: {}"
msgstr "请添加证书"
#: settings/utils/ldap.py:423 settings/utils/ldap.py:450
#: settings/utils/ldap.py:480 settings/utils/ldap.py:508
#: settings/utils/ldap.py:422 settings/utils/ldap.py:449
#: settings/utils/ldap.py:479 settings/utils/ldap.py:507
msgid "Unknown error: {}"
msgstr "未知错误: {}"
#: settings/utils/ldap.py:437
#: settings/utils/ldap.py:436
msgid "Bind DN or Password incorrect"
msgstr "绑定DN或密码错误"
#: settings/utils/ldap.py:444
#: settings/utils/ldap.py:443
msgid "Please enter Bind DN: {}"
msgstr "请输入绑定DN: {}"
#: settings/utils/ldap.py:446
#: settings/utils/ldap.py:445
msgid "Please enter Password: {}"
msgstr "请输入密码: {}"
#: settings/utils/ldap.py:448
#: settings/utils/ldap.py:447
msgid "Please enter correct Bind DN and Password: {}"
msgstr "请输入正确的绑定DN和密码: {}"
#: settings/utils/ldap.py:466
#: settings/utils/ldap.py:465
msgid "Invalid User OU or User search filter: {}"
msgstr "不合法的用户OU或用户过滤器: {}"
#: settings/utils/ldap.py:497
#: settings/utils/ldap.py:496
msgid "LDAP User attr map not include: {}"
msgstr "LDAP属性映射没有包含: {}"
#: settings/utils/ldap.py:504
#: settings/utils/ldap.py:503
msgid "LDAP User attr map is not dict"
msgstr "LDAP属性映射不合法"
#: settings/utils/ldap.py:523
#: settings/utils/ldap.py:522
msgid "LDAP authentication is not enabled"
msgstr "LDAP认证没有启用"
#: settings/utils/ldap.py:541
#: settings/utils/ldap.py:540
msgid "Error (Invalid LDAP server): {}"
msgstr "错误 不合法的LDAP服务器地址: {}"
#: settings/utils/ldap.py:543
#: settings/utils/ldap.py:542
msgid "Error (Invalid Bind DN): {}"
msgstr "错误不合法的绑定DN: {}"
#: settings/utils/ldap.py:545
#: settings/utils/ldap.py:544
msgid "Error (Invalid LDAP User attr map): {}"
msgstr "错误不合法的LDAP属性映射: {}"
#: settings/utils/ldap.py:547
#: settings/utils/ldap.py:546
msgid "Error (Invalid User OU or User search filter): {}"
msgstr "错误不合法的用户OU或用户过滤器: {}"
#: settings/utils/ldap.py:549
#: settings/utils/ldap.py:548
msgid "Error (Not enabled LDAP authentication): {}"
msgstr "错误没有启用LDAP认证: {}"
#: settings/utils/ldap.py:551
#: settings/utils/ldap.py:550
msgid "Error (Unknown): {}"
msgstr "错误(未知): {}"
#: settings/utils/ldap.py:554
#: settings/utils/ldap.py:553
msgid "Succeed: Match {} s user"
msgstr "成功匹配 {} 个用户"
#: settings/utils/ldap.py:587
#: settings/utils/ldap.py:586
msgid "Authentication failed (configuration incorrect): {}"
msgstr "认证失败(配置错误): {}"
#: settings/utils/ldap.py:589
#: settings/utils/ldap.py:588
msgid "Authentication failed (before login check failed): {}"
msgstr "认证失败(登录前检查失败): {}"
#: settings/utils/ldap.py:591
#: settings/utils/ldap.py:590
msgid "Authentication failed (username or password incorrect): {}"
msgstr "认证失败 (用户名或密码不正确): {}"
#: settings/utils/ldap.py:593
#: settings/utils/ldap.py:592
msgid "Authentication failed (Unknown): {}"
msgstr "认证失败: (未知): {}"
#: settings/utils/ldap.py:596
#: settings/utils/ldap.py:595
msgid "Authentication success: {}"
msgstr "认证成功: {}"
@@ -2825,7 +2825,7 @@ msgstr "数据库应用"
msgid "Perms"
msgstr "权限管理"
#: templates/_nav.html:97 terminal/notifications.py:15
#: templates/_nav.html:97 terminal/notifications.py:16
msgid "Sessions"
msgstr "会话管理"
@@ -3280,11 +3280,11 @@ msgstr "命令存储"
msgid "Replay storage"
msgstr "录像存储"
#: terminal/notifications.py:35
#: terminal/notifications.py:50
msgid "Danger command alert"
msgstr "危险命令告警"
#: terminal/notifications.py:44
#: terminal/notifications.py:59
#, python-format
msgid ""
"\n"
@@ -3314,18 +3314,18 @@ msgstr ""
" <br>\n"
" "
#: terminal/notifications.py:79
#: terminal/notifications.py:94
#, python-format
msgid ""
"Insecure Command Alert: [%(name)s->%(login_from)s@%(remote_addr)s] $"
"%(command)s"
msgstr "危险命令告警: [%(name)s->%(login_from)s@%(remote_addr)s] $%(command)s"
#: terminal/notifications.py:97
#: terminal/notifications.py:112
msgid "Batch danger command alert"
msgstr "批量危险命令告警"
#: terminal/notifications.py:108
#: terminal/notifications.py:123
#, python-format
msgid ""
"\n"
@@ -3356,7 +3356,7 @@ msgstr ""
" ----------------- 命令 ---------------- <br>\n"
" "
#: terminal/notifications.py:133
#: terminal/notifications.py:148
#, python-format
msgid "Insecure Web Command Execution Alert: [%(name)s]"
msgstr "批量危险命令告警: [%(name)s]"
@@ -4057,7 +4057,7 @@ msgid "Security token validation"
msgstr "安全令牌验证"
#: users/templates/users/_base_otp.html:14 xpack/plugins/cloud/models.py:78
#: xpack/plugins/cloud/serializers.py:145
#: xpack/plugins/cloud/serializers.py:159
msgid "Account"
msgstr "账户"
@@ -4798,7 +4798,7 @@ msgstr "云服务商"
msgid "Cloud account"
msgstr "云账号"
#: xpack/plugins/cloud/models.py:81 xpack/plugins/cloud/serializers.py:126
#: xpack/plugins/cloud/models.py:81 xpack/plugins/cloud/serializers.py:140
msgid "Regions"
msgstr "地域"
@@ -4806,7 +4806,7 @@ msgstr "地域"
msgid "Hostname strategy"
msgstr "主机名策略"
#: xpack/plugins/cloud/models.py:95 xpack/plugins/cloud/serializers.py:149
#: xpack/plugins/cloud/models.py:95 xpack/plugins/cloud/serializers.py:163
msgid "Always update"
msgstr "总是更新"
@@ -4998,20 +4998,24 @@ msgstr ""
msgid "Subscription ID"
msgstr ""
#: xpack/plugins/cloud/serializers.py:124
#: xpack/plugins/cloud/serializers.py:49
msgid "This field is required"
msgstr "这个字段是必填项"
#: xpack/plugins/cloud/serializers.py:138
msgid "History count"
msgstr "执行次数"
#: xpack/plugins/cloud/serializers.py:125
#: xpack/plugins/cloud/serializers.py:139
msgid "Instance count"
msgstr "实例个数"
#: xpack/plugins/cloud/serializers.py:148
#: xpack/plugins/cloud/serializers.py:162
#: xpack/plugins/gathered_user/serializers.py:20
msgid "Periodic display"
msgstr "定时执行"
#: xpack/plugins/cloud/utils.py:64
#: xpack/plugins/cloud/utils.py:65
msgid "Account unavailable"
msgstr "账户无效"
@@ -5099,8 +5103,5 @@ msgstr "旗舰版"
msgid "Community edition"
msgstr "社区版"
#~ msgid "This field is required"
#~ msgstr "这个字段是必填项"
#~ msgid "Terminal command alert"
#~ msgstr "终端命令告警"

View File

@@ -15,6 +15,7 @@ from orgs.hands import set_current_org, Node, get_current_org
from perms.models import (AssetPermission, ApplicationPermission)
from users.models import UserGroup, User
from common.const.signals import PRE_REMOVE, POST_REMOVE
from common.decorator import on_transaction_commit
from common.signals import django_ready
from common.utils import get_logger
from common.utils.connection import RedisPubSub
@@ -167,3 +168,13 @@ def on_org_user_changed(action, instance, reverse, pk_set, **kwargs):
leaved_users = set(pk_set) - set(org.members.filter(id__in=user_pk_set).values_list('id', flat=True))
_clear_users_from_org(org, leaved_users)
@receiver(post_save, sender=User)
@on_transaction_commit
def on_user_created_set_default_org(sender, instance, created, **kwargs):
if not created:
return
if instance.orgs.count() > 0:
return
Organization.default().members.add(instance)

View File

@@ -7,8 +7,7 @@ from collections.abc import Iterable
from smtplib import SMTPSenderRefused
from rest_framework import generics
from rest_framework.views import Response, APIView
from django.conf import settings
from django.core.mail import send_mail, get_connection
from orgs.models import Organization
from django.utils.translation import ugettext_lazy as _
from ..utils import (
@@ -17,11 +16,12 @@ from ..utils import (
)
from ..tasks import sync_ldap_user
from common.permissions import IsOrgAdmin, IsSuperUser
from common.utils import get_logger
from common.utils import get_logger, is_uuid
from ..serializers import (
MailTestSerializer, LDAPTestConfigSerializer, LDAPUserSerializer,
PublicSettingSerializer, LDAPTestLoginSerializer, SettingsSerializer
)
from orgs.utils import current_org
from users.models import User
logger = get_logger(__file__)
@@ -170,6 +170,14 @@ class LDAPUserListApi(generics.ListAPIView):
class LDAPUserImportAPI(APIView):
permission_classes = (IsSuperUser,)
def get_org(self):
org_id = self.request.data.get('org_id')
if is_uuid(org_id):
org = Organization.objects.get(id=org_id)
else:
org = current_org
return org
def get_ldap_users(self):
username_list = self.request.data.get('username_list', [])
cache_police = self.request.query_params.get('cache_police', True)
@@ -188,12 +196,15 @@ class LDAPUserImportAPI(APIView):
if users is None:
return Response({'msg': _('Get ldap users is None')}, status=400)
errors = LDAPImportUtil().perform_import(users)
org = self.get_org()
errors = LDAPImportUtil().perform_import(users, org)
if errors:
return Response({'errors': errors}, status=400)
count = users if users is None else len(users)
return Response({'msg': _('Imported {} users successfully').format(count)})
return Response({
'msg': _('Imported {} users successfully (Organization: {})').format(count, org)
})
class LDAPCacheRefreshAPI(generics.RetrieveAPIView):

View File

@@ -362,20 +362,19 @@ class LDAPImportUtil(object):
)
return obj, created
def perform_import(self, users):
def perform_import(self, users, org=None):
logger.info('Start perform import ldap users, count: {}'.format(len(users)))
errors = []
instances = []
objs = []
for user in users:
try:
obj, created = self.update_or_create(user)
if created:
instances.append(obj)
objs.append(obj)
except Exception as e:
errors.append({user['username']: str(e)})
logger.error(e)
# 默认添加用户到 Default 组织
Organization.default().members.add(*instances)
if org and not org.is_root():
org.members.add(*objs)
logger.info('End perform import ldap users')
return errors

View File

@@ -32,14 +32,16 @@ class CommandAlertMixin:
db_setting = Setting.objects.filter(name='SECURITY_INSECURE_COMMAND_EMAIL_RECEIVER').first()
if db_setting:
emails = db_setting.value
emails = emails or settings.SECURITY_INSECURE_COMMAND_EMAIL_RECEIVER
else:
emails = settings.SECURITY_INSECURE_COMMAND_EMAIL_RECEIVER
emails = emails.split(',')
emails = [email.strip().strip('"') for email in emails]
users = User.objects.filter(email__in=emails)
subscription.users.add(*users)
subscription.receive_backends = [BACKEND.EMAIL]
subscription.save()
if users:
subscription.users.add(*users)
subscription.receive_backends = [BACKEND.EMAIL]
subscription.save()
class CommandAlertMessage(CommandAlertMixin, SystemMessage):

View File

@@ -0,0 +1,9 @@
#!/bin/bash
#
python ../apps/manage.py shell << EOF
from users.models import User
from orgs.models import Organization
unorgs_users = [user for user in User.objects.all() if user.orgs.count() == 0]
Organization.default().members.add(*unorgs_users)
EOF