diff --git a/apps/assets/models/authbook.py b/apps/assets/models/authbook.py index a040bbd0d..94e4f4cf4 100644 --- a/apps/assets/models/authbook.py +++ b/apps/assets/models/authbook.py @@ -78,7 +78,7 @@ class AuthBook(AssetUser): if host == self.asset.hostname: _connectivity = self.UNREACHABLE - for host in value.get('contacted', {}).keys(): + for host in value.get('contacted', []): if host == self.asset.hostname: _connectivity = self.REACHABLE diff --git a/apps/assets/templates/assets/_asset_user_view_auth_modal.html b/apps/assets/templates/assets/_asset_user_view_auth_modal.html new file mode 100644 index 000000000..07ac34ce5 --- /dev/null +++ b/apps/assets/templates/assets/_asset_user_view_auth_modal.html @@ -0,0 +1,140 @@ +{% extends '_modal.html' %} +{% load i18n %} +{% load static %} +{% block modal_id %}asset_user_auth_view{% endblock %} +{% block modal_title%}{% trans "Asset user auth" %}{% endblock %} +{% block modal_body %} + +
+
+ +
+ + {% trans "Need otp auth for view auth" %} +
+ +
+ +
+ + +{% endblock %} +{% block modal_button %} + +{% endblock %} diff --git a/apps/assets/templates/assets/admin_user_assets.html b/apps/assets/templates/assets/admin_user_assets.html index c893ead80..328b21579 100644 --- a/apps/assets/templates/assets/admin_user_assets.html +++ b/apps/assets/templates/assets/admin_user_assets.html @@ -85,6 +85,7 @@ {% include 'assets/_asset_user_auth_modal.html' %} + {% include 'assets/_asset_user_view_auth_modal.html' %} {% endblock %} {% block custom_foot_js %} {% endblock %} diff --git a/apps/assets/templates/assets/asset_asset_user_list.html b/apps/assets/templates/assets/asset_asset_user_list.html index 9a330ce77..ef192d790 100644 --- a/apps/assets/templates/assets/asset_asset_user_list.html +++ b/apps/assets/templates/assets/asset_asset_user_list.html @@ -2,10 +2,6 @@ {% load common_tags %} {% load static %} {% load i18n %} - -{% block custom_head_css_js %} -{% endblock %} - {% block content %}
@@ -87,6 +83,7 @@
{% include 'assets/_asset_user_auth_modal.html' %} + {% include 'assets/_asset_user_view_auth_modal.html' %} {% endblock %} {% block custom_foot_js %} {% endblock %} \ No newline at end of file diff --git a/apps/assets/templates/assets/system_user_asset.html b/apps/assets/templates/assets/system_user_asset.html index 082e13fd8..f5df32bf5 100644 --- a/apps/assets/templates/assets/system_user_asset.html +++ b/apps/assets/templates/assets/system_user_asset.html @@ -133,6 +133,7 @@ {% include 'assets/_asset_user_auth_modal.html' %} + {% include 'assets/_asset_user_view_auth_modal.html' %} {% endblock %} {% block custom_foot_js %} {% endblock %} diff --git a/apps/authentication/api/auth.py b/apps/authentication/api/auth.py index 2d9cfe367..42c196c51 100644 --- a/apps/authentication/api/auth.py +++ b/apps/authentication/api/auth.py @@ -2,6 +2,7 @@ # import uuid +import time from django.core.cache import cache from django.urls import reverse @@ -10,10 +11,11 @@ from django.utils.translation import ugettext as _ from rest_framework.permissions import AllowAny from rest_framework.response import Response +from rest_framework.generics import CreateAPIView from rest_framework.views import APIView from common.utils import get_logger, get_request_ip -from common.permissions import IsOrgAdminOrAppUser +from common.permissions import IsOrgAdminOrAppUser, IsValidUser from orgs.mixins import RootOrgViewMixin from users.serializers import UserSerializer from users.models import User @@ -23,12 +25,13 @@ from users.utils import ( check_user_valid, check_otp_code, increase_login_failed_count, is_block_login, clean_failed_count ) - +from ..serializers import OtpVerifySerializer from ..signals import post_auth_success, post_auth_failed logger = get_logger(__name__) __all__ = [ 'UserAuthApi', 'UserConnectionTokenApi', 'UserOtpAuthApi', + 'UserOtpVerifyApi', ] @@ -179,3 +182,20 @@ class UserOtpAuthApi(RootOrgViewMixin, APIView): sender=self.__class__, username=username, request=self.request, reason=reason ) + + +class UserOtpVerifyApi(CreateAPIView): + permission_classes = (IsValidUser,) + serializer_class = OtpVerifySerializer + + def create(self, request, *args, **kwargs): + serializer = self.get_serializer(data=request.data) + serializer.is_valid(raise_exception=True) + code = serializer.validated_data["code"] + + if request.user.check_otp(code): + request.session["OTP_LAST_VERIFY_TIME"] = int(time.time()) + return Response({"ok": "1"}) + else: + return Response({"error": "Code not valid"}, status=400) + diff --git a/apps/authentication/serializers.py b/apps/authentication/serializers.py index cf4968a56..2033b3e44 100644 --- a/apps/authentication/serializers.py +++ b/apps/authentication/serializers.py @@ -14,3 +14,7 @@ class AccessKeySerializer(serializers.ModelSerializer): model = AccessKey fields = ['id', 'secret'] read_only_fields = ['id', 'secret'] + + +class OtpVerifySerializer(serializers.Serializer): + code = serializers.CharField(max_length=6, min_length=6) diff --git a/apps/authentication/urls/api_urls.py b/apps/authentication/urls/api_urls.py index b22c49884..85f3aa522 100644 --- a/apps/authentication/urls/api_urls.py +++ b/apps/authentication/urls/api_urls.py @@ -16,5 +16,6 @@ urlpatterns = [ path('connection-token/', api.UserConnectionTokenApi.as_view(), name='connection-token'), path('otp/auth/', api.UserOtpAuthApi.as_view(), name='user-otp-auth'), + path('otp/verify/', api.UserOtpVerifyApi.as_view(), name='user-otp-verify'), ] diff --git a/apps/common/permissions.py b/apps/common/permissions.py index 689444131..025d44ba3 100644 --- a/apps/common/permissions.py +++ b/apps/common/permissions.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- # +import time from rest_framework import permissions from django.contrib.auth.mixins import UserPassesTestMixin diff --git a/apps/common/utils/common.py b/apps/common/utils/common.py index dcd7daf16..79146c039 100644 --- a/apps/common/utils/common.py +++ b/apps/common/utils/common.py @@ -144,6 +144,7 @@ def is_uuid(seq): def get_request_ip(request): x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR', '').split(',') + if x_forwarded_for and x_forwarded_for[0]: login_ip = x_forwarded_for[0] else: diff --git a/apps/jumpserver/conf.py b/apps/jumpserver/conf.py index ee6dcdbfd..35254d1ca 100644 --- a/apps/jumpserver/conf.py +++ b/apps/jumpserver/conf.py @@ -194,7 +194,7 @@ class Config(dict): filename = os.path.join(self.root_path, filename) try: with open(filename, 'rt', encoding='utf8') as f: - obj = yaml.load(f) + obj = yaml.safe_load(f) except IOError as e: if silent and e.errno in (errno.ENOENT, errno.EISDIR): return False diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index 52ca4190e..4d188c93e 100644 Binary files a/apps/locale/zh/LC_MESSAGES/django.mo and b/apps/locale/zh/LC_MESSAGES/django.mo differ diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 17e132ca0..1f39462f8 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Jumpserver 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-04-29 12:22+0800\n" +"POT-Creation-Date: 2019-05-20 11:19+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: ibuler \n" "Language-Team: Jumpserver team\n" @@ -21,15 +21,15 @@ msgstr "" msgid "Please select assets that need to be updated" msgstr "请选择需要更新的资产" -#: assets/api/node.py:58 +#: assets/api/node.py:60 msgid "You can't update the root node name" msgstr "不能修改根节点名称" -#: assets/api/node.py:282 +#: assets/api/node.py:285 msgid "Update node asset hardware information: {}" msgstr "更新节点资产硬件信息: {}" -#: assets/api/node.py:296 +#: assets/api/node.py:299 msgid "Test if the assets under the node are connectable: {}" msgstr "测试节点下资产是否可连接: {}" @@ -45,7 +45,7 @@ msgstr "节点管理" #: assets/models/cluster.py:19 assets/models/user.py:91 #: assets/templates/assets/asset_detail.html:80 templates/_nav.html:24 #: xpack/plugins/cloud/models.py:124 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:67 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:65 #: xpack/plugins/orgs/templates/orgs/org_list.html:18 msgid "Admin user" msgstr "管理用户" @@ -81,8 +81,8 @@ msgstr "网域" #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:55 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:15 #: xpack/plugins/cloud/models.py:123 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:63 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:66 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:61 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:64 msgid "Node" msgstr "节点" @@ -136,7 +136,7 @@ msgstr "选择资产" #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:13 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:14 #: xpack/plugins/cloud/models.py:187 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:65 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:63 #: xpack/plugins/orgs/templates/orgs/org_list.html:16 msgid "Asset" msgstr "资产" @@ -188,9 +188,9 @@ msgstr "SSH网关,支持代理SSH,RDP和VNC" #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:61 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:12 #: xpack/plugins/cloud/models.py:49 xpack/plugins/cloud/models.py:119 -#: xpack/plugins/cloud/templates/cloud/account_detail.html:52 +#: xpack/plugins/cloud/templates/cloud/account_detail.html:50 #: xpack/plugins/cloud/templates/cloud/account_list.html:12 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:55 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:53 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:12 #: xpack/plugins/orgs/templates/orgs/org_detail.html:52 #: xpack/plugins/orgs/templates/orgs/org_list.html:12 @@ -200,9 +200,10 @@ msgstr "名称" #: assets/forms/domain.py:74 assets/forms/user.py:85 assets/forms/user.py:147 #: assets/models/base.py:27 #: assets/templates/assets/_asset_user_auth_modal.html:15 +#: assets/templates/assets/_asset_user_view_auth_modal.html:31 #: assets/templates/assets/admin_user_detail.html:60 #: assets/templates/assets/admin_user_list.html:27 -#: assets/templates/assets/asset_asset_user_list.html:48 +#: assets/templates/assets/asset_asset_user_list.html:44 #: assets/templates/assets/domain_gateway_list.html:71 #: assets/templates/assets/system_user_detail.html:62 #: assets/templates/assets/system_user_list.html:30 audits/models.py:94 @@ -233,6 +234,7 @@ msgstr "密码或密钥密码" #: assets/forms/user.py:26 assets/models/base.py:28 #: assets/serializers/asset_user.py:19 #: assets/templates/assets/_asset_user_auth_modal.html:21 +#: assets/templates/assets/_asset_user_view_auth_modal.html:37 #: authentication/forms.py:13 #: authentication/templates/authentication/login.html:67 #: authentication/templates/authentication/new_login.html:93 @@ -313,6 +315,7 @@ msgstr "IP" #: assets/models/asset.py:75 assets/templates/assets/_asset_list_modal.html:45 #: assets/templates/assets/_asset_user_auth_modal.html:9 +#: assets/templates/assets/_asset_user_view_auth_modal.html:25 #: assets/templates/assets/admin_user_assets.html:48 #: assets/templates/assets/asset_detail.html:60 #: assets/templates/assets/asset_list.html:92 @@ -461,8 +464,8 @@ msgstr "创建者" #: users/templates/users/user_group_detail.html:63 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:105 #: xpack/plugins/cloud/models.py:56 xpack/plugins/cloud/models.py:128 -#: xpack/plugins/cloud/templates/cloud/account_detail.html:68 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:79 +#: xpack/plugins/cloud/templates/cloud/account_detail.html:66 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:77 #: xpack/plugins/orgs/templates/orgs/org_detail.html:60 msgid "Date created" msgstr "创建日期" @@ -495,9 +498,9 @@ msgstr "创建日期" #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:117 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:19 #: xpack/plugins/cloud/models.py:54 xpack/plugins/cloud/models.py:125 -#: xpack/plugins/cloud/templates/cloud/account_detail.html:72 +#: xpack/plugins/cloud/templates/cloud/account_detail.html:70 #: xpack/plugins/cloud/templates/cloud/account_list.html:15 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:71 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:69 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:16 #: xpack/plugins/orgs/templates/orgs/org_detail.html:64 #: xpack/plugins/orgs/templates/orgs/org_list.html:22 @@ -513,7 +516,7 @@ msgstr "不可达" #: assets/models/asset.py:118 assets/models/base.py:39 #: assets/templates/assets/admin_user_assets.html:51 #: assets/templates/assets/admin_user_list.html:29 -#: assets/templates/assets/asset_asset_user_list.html:50 +#: assets/templates/assets/asset_asset_user_list.html:46 #: assets/templates/assets/asset_list.html:95 #: assets/templates/assets/system_user_asset.html:53 #: assets/templates/assets/system_user_list.html:34 @@ -584,7 +587,7 @@ msgid "Default" msgstr "默认" #: assets/models/cluster.py:36 assets/models/label.py:14 -#: users/models/user.py:475 +#: users/models/user.py:479 msgid "System" msgstr "系统" @@ -665,7 +668,7 @@ msgstr "每行一个命令" #: assets/models/cmd_filter.py:54 #: assets/templates/assets/admin_user_assets.html:52 #: assets/templates/assets/admin_user_list.html:33 -#: assets/templates/assets/asset_asset_user_list.html:52 +#: assets/templates/assets/asset_asset_user_list.html:48 #: assets/templates/assets/asset_list.html:96 #: assets/templates/assets/cmd_filter_list.html:28 #: assets/templates/assets/cmd_filter_rule_list.html:63 @@ -735,7 +738,7 @@ msgstr "默认资产组" #: terminal/templates/terminal/command_list.html:72 #: terminal/templates/terminal/session_list.html:33 #: terminal/templates/terminal/session_list.html:71 users/forms.py:283 -#: users/models/user.py:36 users/models/user.py:463 +#: users/models/user.py:36 users/models/user.py:467 #: users/templates/users/user_group_detail.html:78 #: users/templates/users/user_group_list.html:13 users/views/user.py:395 #: xpack/plugins/orgs/forms.py:26 @@ -757,7 +760,7 @@ msgstr "分类" msgid "Key" msgstr "键" -#: assets/models/node.py:128 +#: assets/models/node.py:133 msgid "New node" msgstr "新节点" @@ -975,6 +978,61 @@ msgstr "更新资产用户认证信息" msgid "Please input password" msgstr "请输入密码" +#: assets/templates/assets/_asset_user_view_auth_modal.html:5 +msgid "Asset user auth" +msgstr "资产用户信息" + +#: assets/templates/assets/_asset_user_view_auth_modal.html:14 +#: assets/templates/assets/_otp_verify_modal.html:8 audits/models.py:99 +#: audits/templates/audits/login_log_list.html:56 users/forms.py:142 +#: users/models/user.py:83 users/templates/users/first_login.html:45 +msgid "MFA" +msgstr "MFA" + +#: assets/templates/assets/_asset_user_view_auth_modal.html:17 +msgid "Need otp auth for view auth" +msgstr "需要二次认证来查看账号信息" + +#: assets/templates/assets/_asset_user_view_auth_modal.html:20 +#: assets/templates/assets/admin_user_detail.html:100 +#: assets/templates/assets/asset_detail.html:211 +#: assets/templates/assets/asset_list.html:637 +#: assets/templates/assets/cmd_filter_detail.html:106 +#: assets/templates/assets/system_user_asset.html:112 +#: assets/templates/assets/system_user_detail.html:182 +#: assets/templates/assets/system_user_list.html:144 +#: settings/templates/settings/terminal_setting.html:165 +#: templates/_modal.html:23 terminal/templates/terminal/session_detail.html:108 +#: users/templates/users/user_detail.html:388 +#: users/templates/users/user_detail.html:414 +#: users/templates/users/user_detail.html:437 +#: users/templates/users/user_detail.html:482 +#: users/templates/users/user_group_create_update.html:32 +#: users/templates/users/user_group_list.html:90 +#: users/templates/users/user_list.html:215 +#: users/templates/users/user_profile.html:238 +#: xpack/plugins/cloud/templates/cloud/account_create_update.html:34 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_create.html:36 +#: xpack/plugins/interface/templates/interface/interface.html:103 +#: xpack/plugins/orgs/templates/orgs/org_create_update.html:33 +msgid "Confirm" +msgstr "确认" + +#: assets/templates/assets/_asset_user_view_auth_modal.html:63 +msgid "Copy success" +msgstr "复制成功" + +#: assets/templates/assets/_asset_user_view_auth_modal.html:79 +msgid "Get auth info error" +msgstr "获取认证信息错误" + +#: assets/templates/assets/_asset_user_view_auth_modal.html:139 +#: assets/templates/assets/_user_asset_detail_modal.html:23 +#: settings/templates/settings/_ldap_list_users_modal.html:96 +#: templates/_modal.html:22 +msgid "Close" +msgstr "关闭" + #: assets/templates/assets/_gateway_test_modal.html:4 msgid "Test gateway test connection" msgstr "测试连接网关" @@ -987,6 +1045,10 @@ msgstr "SSH端口" msgid "If use nat, set the ssh real port" msgstr "如果使用了nat端口映射,请设置为ssh真实监听的端口" +#: assets/templates/assets/_otp_verify_modal.html:4 +msgid "MFA Confirm" +msgstr "确认" + #: assets/templates/assets/_system_user.html:37 #: assets/templates/assets/asset_create.html:16 #: assets/templates/assets/asset_update.html:21 @@ -1088,17 +1150,11 @@ msgid "Submit" msgstr "提交" #: assets/templates/assets/_user_asset_detail_modal.html:11 -#: assets/templates/assets/asset_asset_user_list.html:17 +#: assets/templates/assets/asset_asset_user_list.html:13 #: assets/templates/assets/asset_detail.html:20 assets/views/asset.py:187 msgid "Asset detail" msgstr "资产详情" -#: assets/templates/assets/_user_asset_detail_modal.html:23 -#: settings/templates/settings/_ldap_list_users_modal.html:96 -#: templates/_modal.html:22 -msgid "Close" -msgstr "关闭" - #: assets/templates/assets/admin_user_assets.html:18 #: assets/templates/assets/admin_user_detail.html:18 #: assets/templates/assets/cmd_filter_detail.html:19 @@ -1140,41 +1196,47 @@ msgid "Quick update" msgstr "快速更新" #: assets/templates/assets/admin_user_assets.html:70 -#: assets/templates/assets/asset_asset_user_list.html:71 +#: assets/templates/assets/asset_asset_user_list.html:67 #: assets/templates/assets/asset_detail.html:179 msgid "Test connective" msgstr "测试可连接性" #: assets/templates/assets/admin_user_assets.html:73 -#: assets/templates/assets/admin_user_assets.html:115 -#: assets/templates/assets/asset_asset_user_list.html:74 -#: assets/templates/assets/asset_asset_user_list.html:122 +#: assets/templates/assets/admin_user_assets.html:118 +#: assets/templates/assets/asset_asset_user_list.html:70 +#: assets/templates/assets/asset_asset_user_list.html:119 #: assets/templates/assets/asset_detail.html:182 #: assets/templates/assets/system_user_asset.html:75 -#: assets/templates/assets/system_user_asset.html:165 +#: assets/templates/assets/system_user_asset.html:166 #: assets/templates/assets/system_user_detail.html:151 msgid "Test" msgstr "测试" #: assets/templates/assets/admin_user_assets.html:116 -#: assets/templates/assets/asset_asset_user_list.html:120 -#: assets/templates/assets/system_user_asset.html:167 +#: assets/templates/assets/asset_asset_user_list.html:117 +#: assets/templates/assets/system_user_asset.html:169 msgid "Update auth" msgstr "更新认证" -#: assets/templates/assets/admin_user_assets.html:192 -#: assets/templates/assets/asset_asset_user_list.html:176 +#: assets/templates/assets/admin_user_assets.html:117 +#: assets/templates/assets/asset_asset_user_list.html:118 +#: assets/templates/assets/system_user_asset.html:167 +msgid "View auth" +msgstr "查看认证" + +#: assets/templates/assets/admin_user_assets.html:196 +#: assets/templates/assets/asset_asset_user_list.html:162 #: assets/templates/assets/asset_detail.html:311 -#: assets/templates/assets/system_user_asset.html:351 +#: assets/templates/assets/system_user_asset.html:353 #: users/templates/users/user_detail.html:307 #: users/templates/users/user_detail.html:334 #: xpack/plugins/interface/views.py:34 msgid "Update successfully!" msgstr "更新成功" -#: assets/templates/assets/admin_user_assets.html:195 -#: assets/templates/assets/asset_asset_user_list.html:179 -#: assets/templates/assets/system_user_asset.html:354 +#: assets/templates/assets/admin_user_assets.html:199 +#: assets/templates/assets/asset_asset_user_list.html:165 +#: assets/templates/assets/system_user_asset.html:356 msgid "Update failed!" msgstr "更新失败" @@ -1205,11 +1267,11 @@ msgstr "更新失败" #: users/templates/users/user_profile.html:187 #: users/templates/users/user_profile.html:196 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:29 -#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:54 -#: xpack/plugins/cloud/templates/cloud/account_detail.html:25 -#: xpack/plugins/cloud/templates/cloud/account_list.html:38 +#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:55 +#: xpack/plugins/cloud/templates/cloud/account_detail.html:23 +#: xpack/plugins/cloud/templates/cloud/account_list.html:39 #: xpack/plugins/orgs/templates/orgs/org_detail.html:25 -#: xpack/plugins/orgs/templates/orgs/org_list.html:85 +#: xpack/plugins/orgs/templates/orgs/org_list.html:87 msgid "Update" msgstr "更新" @@ -1239,13 +1301,13 @@ msgstr "更新" #: users/templates/users/user_list.html:91 #: users/templates/users/user_list.html:95 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:33 -#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:56 -#: xpack/plugins/cloud/templates/cloud/account_detail.html:29 -#: xpack/plugins/cloud/templates/cloud/account_list.html:40 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:32 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:54 +#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:57 +#: xpack/plugins/cloud/templates/cloud/account_detail.html:27 +#: xpack/plugins/cloud/templates/cloud/account_list.html:41 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:30 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:55 #: xpack/plugins/orgs/templates/orgs/org_detail.html:29 -#: xpack/plugins/orgs/templates/orgs/org_list.html:87 +#: xpack/plugins/orgs/templates/orgs/org_list.html:89 msgid "Delete" msgstr "删除" @@ -1260,30 +1322,6 @@ msgstr "替换资产的管理员" msgid "Select nodes" msgstr "选择节点" -#: assets/templates/assets/admin_user_detail.html:100 -#: assets/templates/assets/asset_detail.html:211 -#: assets/templates/assets/asset_list.html:637 -#: assets/templates/assets/cmd_filter_detail.html:106 -#: assets/templates/assets/system_user_asset.html:112 -#: assets/templates/assets/system_user_detail.html:182 -#: assets/templates/assets/system_user_list.html:144 -#: settings/templates/settings/terminal_setting.html:165 -#: templates/_modal.html:23 terminal/templates/terminal/session_detail.html:108 -#: users/templates/users/user_detail.html:388 -#: users/templates/users/user_detail.html:414 -#: users/templates/users/user_detail.html:437 -#: users/templates/users/user_detail.html:482 -#: users/templates/users/user_group_create_update.html:32 -#: users/templates/users/user_group_list.html:90 -#: users/templates/users/user_list.html:215 -#: users/templates/users/user_profile.html:238 -#: xpack/plugins/cloud/templates/cloud/account_create_update.html:34 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_create.html:36 -#: xpack/plugins/interface/templates/interface/interface.html:103 -#: xpack/plugins/orgs/templates/orgs/org_create_update.html:33 -msgid "Confirm" -msgstr "确认" - #: assets/templates/assets/admin_user_list.html:10 msgid "" "Admin users are asset (charged server) on the root, or have NOPASSWD: ALL " @@ -1313,26 +1351,26 @@ msgstr "创建管理用户" msgid "Ratio" msgstr "比例" -#: assets/templates/assets/asset_asset_user_list.html:20 +#: assets/templates/assets/asset_asset_user_list.html:16 #: assets/templates/assets/asset_detail.html:23 assets/views/asset.py:68 msgid "Asset user list" msgstr "资产用户列表" -#: assets/templates/assets/asset_asset_user_list.html:28 +#: assets/templates/assets/asset_asset_user_list.html:24 msgid "Asset users of" msgstr "资产用户" -#: assets/templates/assets/asset_asset_user_list.html:49 +#: assets/templates/assets/asset_asset_user_list.html:45 msgid "Password version" msgstr "密码版本" -#: assets/templates/assets/asset_asset_user_list.html:51 +#: assets/templates/assets/asset_asset_user_list.html:47 #: assets/templates/assets/cmd_filter_detail.html:73 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:109 msgid "Date updated" msgstr "更新日期" -#: assets/templates/assets/asset_asset_user_list.html:64 +#: assets/templates/assets/asset_asset_user_list.html:60 #: assets/templates/assets/asset_detail.html:148 #: terminal/templates/terminal/session_detail.html:81 #: users/templates/users/user_detail.html:138 @@ -1672,7 +1710,7 @@ msgid "Push system user now" msgstr "立刻推送系统" #: assets/templates/assets/system_user_asset.html:84 -#: assets/templates/assets/system_user_asset.html:163 +#: assets/templates/assets/system_user_asset.html:164 #: assets/templates/assets/system_user_detail.html:142 msgid "Push" msgstr "推送" @@ -1948,12 +1986,6 @@ msgstr "登录城市" msgid "User agent" msgstr "Agent" -#: audits/models.py:99 audits/templates/audits/login_log_list.html:56 -#: users/forms.py:142 users/models/user.py:83 -#: users/templates/users/first_login.html:45 -msgid "MFA" -msgstr "MFA" - #: audits/models.py:100 audits/templates/audits/login_log_list.html:57 #: xpack/plugins/change_auth_plan/models.py:413 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:15 @@ -1965,7 +1997,7 @@ msgstr "原因" #: audits/models.py:101 audits/templates/audits/login_log_list.html:58 #: xpack/plugins/cloud/models.py:171 xpack/plugins/cloud/models.py:188 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:70 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:67 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:65 msgid "Status" msgstr "状态" @@ -2003,7 +2035,7 @@ msgstr "选择用户" #: terminal/templates/terminal/command_list.html:60 #: terminal/templates/terminal/session_list.html:61 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:52 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:50 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:48 msgid "Search" msgstr "搜索" @@ -2013,7 +2045,7 @@ msgstr "搜索" #: ops/templates/ops/task_detail.html:56 #: terminal/templates/terminal/session_list.html:70 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:64 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:62 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:60 msgid "ID" msgstr "ID" @@ -2063,25 +2095,25 @@ msgstr "登录日志" msgid "Command execution log" msgstr "命令执行" -#: authentication/api/auth.py:46 +#: authentication/api/auth.py:49 #: authentication/templates/authentication/login.html:52 #: authentication/templates/authentication/new_login.html:77 msgid "Log in frequently and try again later" msgstr "登录频繁, 稍后重试" -#: authentication/api/auth.py:64 +#: authentication/api/auth.py:67 msgid "The user {} password has expired, please update." msgstr "用户 {} 密码已经过期,请更新。" -#: authentication/api/auth.py:83 +#: authentication/api/auth.py:86 msgid "Please carry seed value and conduct MFA secondary certification" msgstr "请携带seed值, 进行MFA二次认证" -#: authentication/api/auth.py:163 +#: authentication/api/auth.py:166 msgid "Please verify the user name and password first" msgstr "请先进行用户名和密码验证" -#: authentication/api/auth.py:168 +#: authentication/api/auth.py:171 msgid "MFA certification failed" msgstr "MFA认证失败" @@ -2415,7 +2447,7 @@ msgid "Become" msgstr "Become" #: ops/models/adhoc.py:166 users/templates/users/user_group_detail.html:59 -#: xpack/plugins/cloud/templates/cloud/account_detail.html:64 +#: xpack/plugins/cloud/templates/cloud/account_detail.html:62 #: xpack/plugins/orgs/templates/orgs/org_detail.html:56 msgid "Create by" msgstr "创建者" @@ -2661,8 +2693,8 @@ msgstr "版本" #: ops/templates/ops/task_list.html:63 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:137 -#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:52 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:52 +#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:53 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:53 msgid "Run" msgstr "执行" @@ -2828,7 +2860,7 @@ msgstr "创建授权规则" #: perms/templates/perms/asset_permission_list.html:59 #: perms/templates/perms/asset_permission_list.html:73 #: users/templates/users/user_list.html:28 xpack/plugins/cloud/models.py:53 -#: xpack/plugins/cloud/templates/cloud/account_detail.html:60 +#: xpack/plugins/cloud/templates/cloud/account_detail.html:58 #: xpack/plugins/cloud/templates/cloud/account_list.html:14 msgid "Validity" msgstr "有效" @@ -3283,8 +3315,8 @@ msgstr "端点后缀" #: settings/templates/settings/replay_storage_create.html:136 #: xpack/plugins/cloud/models.py:186 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:83 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:64 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:81 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:62 msgid "Region" msgstr "地域" @@ -3999,7 +4031,7 @@ msgstr "复制你的公钥到这里" msgid "Select users" msgstr "选择用户" -#: users/models/user.py:35 users/models/user.py:471 +#: users/models/user.py:35 users/models/user.py:475 msgid "Administrator" msgstr "管理员" @@ -4045,7 +4077,7 @@ msgstr "最后更新密码日期" msgid "User auth from {}, go there change password" msgstr "用户认证源来自 {}, 请去相应系统修改密码" -#: users/models/user.py:474 +#: users/models/user.py:478 msgid "Administrator is the super user of system" msgstr "Administrator是初始的超级管理员" @@ -4064,7 +4096,7 @@ msgstr "安全令牌验证" #: users/templates/users/_base_otp.html:44 users/templates/users/_user.html:13 #: users/templates/users/user_profile_update.html:51 #: xpack/plugins/cloud/models.py:120 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:59 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:57 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:13 msgid "Account" msgstr "账户" @@ -4947,7 +4979,7 @@ msgid "Run plan manually" msgstr "手动执行计划" #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:179 -#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:101 +#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:102 msgid "Execute failed" msgstr "执行失败" @@ -5033,7 +5065,7 @@ msgid "Unavailable" msgstr "无效" #: xpack/plugins/cloud/models.py:50 -#: xpack/plugins/cloud/templates/cloud/account_detail.html:56 +#: xpack/plugins/cloud/templates/cloud/account_detail.html:54 #: xpack/plugins/cloud/templates/cloud/account_list.html:13 msgid "Provider" msgstr "云服务商" @@ -5059,7 +5091,7 @@ msgid "Instances" msgstr "实例" #: xpack/plugins/cloud/models.py:126 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:75 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:73 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:17 msgid "Date last sync" msgstr "最后同步日期" @@ -5078,7 +5110,7 @@ msgstr "" #: xpack/plugins/cloud/models.py:173 xpack/plugins/cloud/models.py:189 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:71 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:68 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:66 msgid "Date sync" msgstr "同步日期" @@ -5095,8 +5127,8 @@ msgid "Sync instance task history" msgstr "同步实例任务历史" #: xpack/plugins/cloud/models.py:185 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:91 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:63 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:89 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:61 msgid "Instance" msgstr "实例" @@ -5116,7 +5148,7 @@ msgstr "AWS (国际)" msgid "Qcloud" msgstr "腾讯云" -#: xpack/plugins/cloud/templates/cloud/account_detail.html:22 +#: xpack/plugins/cloud/templates/cloud/account_detail.html:20 #: xpack/plugins/cloud/views.py:72 msgid "Account detail" msgstr "账户详情" @@ -5134,23 +5166,23 @@ msgstr "加载中..." msgid "Load failed" msgstr "加载失败" -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:22 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:20 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:25 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:23 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:21 #: xpack/plugins/cloud/views.py:122 msgid "Sync task detail" msgstr "同步任务详情" -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:25 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:23 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:28 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:26 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:24 #: xpack/plugins/cloud/views.py:137 msgid "Sync task history" msgstr "同步历史列表" -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:28 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:26 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:31 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:29 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:27 #: xpack/plugins/cloud/views.py:188 msgid "Sync instance list" msgstr "同步实例列表" @@ -5183,7 +5215,7 @@ msgstr "执行次数" msgid "Instance count" msgstr "实例个数" -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:92 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:93 msgid "Sync success" msgstr "同步成功" @@ -5267,6 +5299,7 @@ msgid "This will restore default Settings of the interface !!!" msgstr "您确定要恢复默认初始化吗?" #: xpack/plugins/interface/templates/interface/interface.html:107 +#: xpack/plugins/interface/views.py:53 msgid "Restore default successfully." msgstr "恢复默认成功!" @@ -5279,13 +5312,9 @@ msgid "Interface" msgstr "界面" #: xpack/plugins/interface/views.py:49 -msgid "It is already in the default setting state!" +msgid "It is already in the default setting state!" msgstr "当前已经是初始化状态!" -#: xpack/plugins/interface/views.py:53 -msgid "Restore default successfully!" -msgstr "恢复默认成功!" - #: xpack/plugins/license/meta.py:11 xpack/plugins/license/models.py:94 #: xpack/plugins/license/templates/license/license_detail.html:50 #: xpack/plugins/license/templates/license/license_detail.html:55 @@ -5423,6 +5452,22 @@ msgstr "创建组织" msgid "Update org" msgstr "更新组织" +#~ msgid "Monitor" +#~ msgstr "监控" + +#, fuzzy +#~| msgid "Select user" +#~ msgid "Select time" +#~ msgstr "选择用户" + +#, fuzzy +#~| msgid "Select Asset" +#~ msgid "Select host" +#~ msgstr "选择资产" + +#~ msgid "Restore default successfully!" +#~ msgstr "恢复默认成功!" + #~ msgid "Beijing Duizhan Tech, Inc." #~ msgstr "北京堆栈科技有限公司" @@ -5453,9 +5498,6 @@ msgstr "更新组织" #~ "object has no attribute 'keys'" #~ msgstr "导入 {} 个用户成功; 导入 {} 这些用户失败,因为对象没有属性'keys'" -#~ msgid "Monitor" -#~ msgstr "监控" - #~ msgid "Invalid private key" #~ msgstr "ssh密钥不合法" @@ -5549,9 +5591,6 @@ msgstr "更新组织" #~ "Are you sure to remove authentication information for the system user ?" #~ msgstr "你确定清除该系统用户的认证信息吗 ?" -#~ msgid "Clear auth" -#~ msgstr "清除认证信息" - #~ msgid "success" #~ msgstr "成功" diff --git a/apps/ops/ansible/callback.py b/apps/ops/ansible/callback.py index 02004285a..694bb9e27 100644 --- a/apps/ops/ansible/callback.py +++ b/apps/ops/ansible/callback.py @@ -124,6 +124,9 @@ class AdHocResultCallback(CallbackMixin, CallbackModule, CMDCallBackModule): def display_ok_hosts(self): pass + def display_failed_stderr(self): + pass + class CommandResultCallback(AdHocResultCallback): """ diff --git a/apps/ops/ansible/runner.py b/apps/ops/ansible/runner.py index 4c8f87888..5f25ee2c4 100644 --- a/apps/ops/ansible/runner.py +++ b/apps/ops/ansible/runner.py @@ -1,8 +1,11 @@ # ~*~ coding: utf-8 ~*~ import os +import shutil from collections import namedtuple +from ansible import context +from ansible.module_utils.common.collections import ImmutableDict from ansible.executor.task_queue_manager import TaskQueueManager from ansible.vars.manager import VariableManager from ansible.parsing.dataloader import DataLoader @@ -33,29 +36,18 @@ Options = namedtuple('Options', [ def get_default_options(): - options = Options( - listtags=False, - listtasks=False, - listhosts=False, + options = dict( syntax=False, timeout=30, connection='ssh', - module_path='', forks=10, remote_user='root', private_key_file=None, - ssh_common_args="", - ssh_extra_args="", - sftp_extra_args="", - scp_extra_args="", become=None, become_method=None, become_user=None, - verbosity=None, - extra_vars=[], + verbosity=1, check=False, - playbook_path='/etc/ansible/', - passwords=None, diff=False, gathering='implicit', remote_tmp='/tmp/.ansible' @@ -108,9 +100,9 @@ class PlayBookRunner: inventory=self.inventory, variable_manager=self.variable_manager, loader=self.loader, - options=self.options, - passwords=self.passwords + passwords={"conn_pass": self.passwords} ) + context.CLIARGS = ImmutableDict(self.options) if executor._tqm: executor._tqm._stdout_callback = self.results_callback @@ -185,11 +177,10 @@ class AdHocRunner: return cleaned_tasks def update_options(self, options): + _options = {k: v for k, v in self.default_options.items()} if options and isinstance(options, dict): - options = self.__class__.default_options._replace(**options) - else: - options = self.__class__.default_options - return options + _options.update(options) + return _options def run(self, tasks, pattern, play_name='Ansible Ad-hoc', gather_facts='no'): """ @@ -202,6 +193,7 @@ class AdHocRunner: self.check_pattern(pattern) self.results_callback = self.get_result_callback() cleaned_tasks = self.clean_tasks(tasks) + context.CLIARGS = ImmutableDict(self.options) play_source = dict( name=play_name, @@ -220,9 +212,8 @@ class AdHocRunner: inventory=self.inventory, variable_manager=self.variable_manager, loader=self.loader, - options=self.options, stdout_callback=self.results_callback, - passwords=self.options.passwords, + passwords={"conn_pass": self.options.get("password", "")} ) try: tqm.run(play) @@ -230,8 +221,9 @@ class AdHocRunner: except Exception as e: raise AnsibleError(e) finally: - tqm.cleanup() - self.loader.cleanup_all_tmp_files() + if tqm is not None: + tqm.cleanup() + shutil.rmtree(C.DEFAULT_LOCAL_TMP, True) class CommandRunner(AdHocRunner): diff --git a/apps/ops/ansible/test_runner.py b/apps/ops/ansible/test_runner.py index 07c9051f3..e38168a6c 100644 --- a/apps/ops/ansible/test_runner.py +++ b/apps/ops/ansible/test_runner.py @@ -15,7 +15,7 @@ class TestAdHocRunner(unittest.TestCase): host_data = [ { "hostname": "testserver", - "ip": "192.168.244.168", + "ip": "192.168.244.185", "port": 22, "username": "root", "password": "redhat", diff --git a/apps/ops/inventory.py b/apps/ops/inventory.py index e4f11bec1..002b6fbda 100644 --- a/apps/ops/inventory.py +++ b/apps/ops/inventory.py @@ -35,7 +35,6 @@ class JMSBaseInventory(BaseInventory): info["vars"].update({ label.name: label.value }) - info["groups"].append("{}:{}".format(label.name, label.value)) if asset.domain: info["vars"].update({ "domain": asset.domain.name, diff --git a/apps/static/js/jumpserver.js b/apps/static/js/jumpserver.js index 50f78187c..b3a2bd35e 100644 --- a/apps/static/js/jumpserver.js +++ b/apps/static/js/jumpserver.js @@ -715,9 +715,12 @@ String.prototype.format = function(args) { return result; }; -function setCookie(key, value) { +function setCookie(key, value, time) { var expires = new Date(); - expires.setTime(expires.getTime() + (24 * 60 * 60 * 1000)); + if (!time) { + time = expires.getTime() + (24 * 60 * 60 * 1000); + } + expires.setTime(time); document.cookie = key + '=' + value + ';expires=' + expires.toUTCString() + ';path=/'; } diff --git a/apps/static/js/plugins/clipboard/clipboard.min.js b/apps/static/js/plugins/clipboard/clipboard.min.js new file mode 100755 index 000000000..4e2a012a6 --- /dev/null +++ b/apps/static/js/plugins/clipboard/clipboard.min.js @@ -0,0 +1,7 @@ +/*! + * clipboard.js v1.5.5 + * https://zenorocha.github.io/clipboard.js + * + * Licensed MIT © Zeno Rocha + */ +!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,e.Clipboard=t()}}(function(){var t,e,n;return function t(e,n,r){function o(a,c){if(!n[a]){if(!e[a]){var s="function"==typeof require&&require;if(!c&&s)return s(a,!0);if(i)return i(a,!0);var u=new Error("Cannot find module '"+a+"'");throw u.code="MODULE_NOT_FOUND",u}var l=n[a]={exports:{}};e[a][0].call(l.exports,function(t){var n=e[a][1][t];return o(n?n:t)},l,l.exports,t,e,n,r)}return n[a].exports}for(var i="function"==typeof require&&require,a=0;ar;r++)n[r].fn.apply(n[r].ctx,e);return this},off:function(t,e){var n=this.e||(this.e={}),r=n[t],o=[];if(r&&e)for(var i=0,a=r.length;a>i;i++)r[i].fn!==e&&r[i].fn._!==e&&o.push(r[i]);return o.length?n[t]=o:delete n[t],this}},e.exports=r},{}],8:[function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}function o(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}n.__esModule=!0;var i=function(){function t(t,e){for(var n=0;n