Unverified Commit 9f235207 authored by 老广's avatar 老广 Committed by GitHub

Merge pull request #1068 from jumpserver/dev

merge dev to master
parents 240faee2 63f1ec83
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
.env .env
env env
env* env*
venv
dist dist
build build
*.egg *.egg
......
...@@ -12,7 +12,7 @@ Jumpserver是全球首款完全开源的堡垒机,使用GNU GPL v2.0开源协 ...@@ -12,7 +12,7 @@ Jumpserver是全球首款完全开源的堡垒机,使用GNU GPL v2.0开源协
Jumpserver使用Python / Django 进行开发,遵循 Web 2.0 规范,配备了业界领先的 Web Terminal 解决方案,交互界面美观、用户体验好。 Jumpserver使用Python / Django 进行开发,遵循 Web 2.0 规范,配备了业界领先的 Web Terminal 解决方案,交互界面美观、用户体验好。
Jumpserver采纳分布式架构,支持多机房跨区域部署,中心节点提供 API,各机房部署登录节点,可横向扩展、无并发访问限制。 Jumpserver采纳分布式架构,支持多机房跨区域部署,中心节点提供 API,各机房部署登录节点,可横向扩展、无并发限制。
改变世界,从一点点开始。 改变世界,从一点点开始。
...@@ -52,7 +52,7 @@ Jumpserver采纳分布式架构,支持多机房跨区域部署,中心节点 ...@@ -52,7 +52,7 @@ Jumpserver采纳分布式架构,支持多机房跨区域部署,中心节点
### License & Copyright ### License & Copyright
Copyright (c) 2014-2017 Beijing Duizhan Tech, Inc., All rights reserved. Copyright (c) 2014-2018 Beijing Duizhan Tech, Inc., All rights reserved.
Licensed under The GNU General Public License version 2 (GPLv2) (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at Licensed under The GNU General Public License version 2 (GPLv2) (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
......
...@@ -18,10 +18,12 @@ from rest_framework.views import APIView ...@@ -18,10 +18,12 @@ from rest_framework.views import APIView
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework_bulk import BulkModelViewSet from rest_framework_bulk import BulkModelViewSet
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.shortcuts import get_object_or_404
from common.utils import get_logger, get_object_or_none from common.utils import get_logger, get_object_or_none
from ..hands import IsSuperUser from ..hands import IsSuperUser
from ..models import Node from ..models import Node
from ..tasks import update_assets_hardware_info_util, test_asset_connectability_util
from .. import serializers from .. import serializers
...@@ -29,7 +31,8 @@ logger = get_logger(__file__) ...@@ -29,7 +31,8 @@ logger = get_logger(__file__)
__all__ = [ __all__ = [
'NodeViewSet', 'NodeChildrenApi', 'NodeViewSet', 'NodeChildrenApi',
'NodeAddAssetsApi', 'NodeRemoveAssetsApi', 'NodeAddAssetsApi', 'NodeRemoveAssetsApi',
'NodeAddChildrenApi', 'NodeAddChildrenApi', 'RefreshNodeHardwareInfoApi',
'TestNodeConnectiveApi'
] ]
...@@ -117,3 +120,31 @@ class NodeRemoveAssetsApi(generics.UpdateAPIView): ...@@ -117,3 +120,31 @@ class NodeRemoveAssetsApi(generics.UpdateAPIView):
instance = self.get_object() instance = self.get_object()
if instance != Node.root(): if instance != Node.root():
instance.assets.remove(*tuple(assets)) instance.assets.remove(*tuple(assets))
class RefreshNodeHardwareInfoApi(APIView):
permission_classes = (IsSuperUser,)
model = Node
def get(self, request, *args, **kwargs):
node_id = kwargs.get('pk')
node = get_object_or_404(self.model, id=node_id)
assets = node.assets.all()
# task_name = _("Refresh node assets hardware info: {}".format(node.name))
task_name = _("更新节点资产硬件信息: {}".format(node.name))
update_assets_hardware_info_util.delay(assets, task_name=task_name)
return Response({"msg": "Task created"})
class TestNodeConnectiveApi(APIView):
permission_classes = (IsSuperUser,)
model = Node
def get(self, request, *args, **kwargs):
node_id = kwargs.get('pk')
node = get_object_or_404(self.model, id=node_id)
assets = node.assets.all()
task_name = _("测试节点下资产是否可连接: {}".format(node.name))
test_asset_connectability_util.delay(assets, task_name=task_name)
return Response({"msg": "Task created"})
...@@ -40,23 +40,22 @@ class SystemUserViewSet(BulkModelViewSet): ...@@ -40,23 +40,22 @@ class SystemUserViewSet(BulkModelViewSet):
permission_classes = (IsSuperUserOrAppUser,) permission_classes = (IsSuperUserOrAppUser,)
class SystemUserAuthInfoApi(generics.RetrieveAPIView): class SystemUserAuthInfoApi(generics.RetrieveUpdateAPIView):
""" """
Get system user auth info Get system user auth info
""" """
queryset = SystemUser.objects.all() queryset = SystemUser.objects.all()
permission_classes = (IsSuperUserOrAppUser,) permission_classes = (IsSuperUserOrAppUser,)
serializer_class = serializers.SystemUserAuthSerializer
def retrieve(self, request, *args, **kwargs): def update(self, request, *args, **kwargs):
system_user = self.get_object() password = request.data.pop("password", None)
data = { private_key = request.data.pop("private_key", None)
'id': system_user.id, instance = self.get_object()
'name': system_user.name,
'username': system_user.username, if password or private_key:
'password': system_user.password, instance.set_auth(password=password, private_key=private_key)
'private_key': system_user.private_key, return super().update(request, *args, **kwargs)
}
return Response(data)
class SystemUserPushApi(generics.RetrieveAPIView): class SystemUserPushApi(generics.RetrieveAPIView):
......
...@@ -35,10 +35,10 @@ class AssetCreateForm(forms.ModelForm): ...@@ -35,10 +35,10 @@ class AssetCreateForm(forms.ModelForm):
'ip': '* required', 'ip': '* required',
'port': '* required', 'port': '* required',
'admin_user': _( 'admin_user': _(
'Admin user is a privilege user exist on this asset,' 'root or other NOPASSWD sudo privilege user existed in asset,'
'Example: root or other NOPASSWD sudo privilege user' 'If asset is windows or other set any one, more see admin user left menu'
'If asset not support ansible, set any one' ),
) 'platform': _("* required Must set exact system platform, Windows, Linux ...")
} }
...@@ -67,10 +67,10 @@ class AssetUpdateForm(forms.ModelForm): ...@@ -67,10 +67,10 @@ class AssetUpdateForm(forms.ModelForm):
'port': '* required', 'port': '* required',
'cluster': '* required', 'cluster': '* required',
'admin_user': _( 'admin_user': _(
'Admin user is a privilege user exist on this asset,' 'root or other NOPASSWD sudo privilege user existed in asset,'
'Example: root or other NOPASSWD sudo privilege user' 'If asset is windows or other set any one, more see admin user left menu'
'If asset not support ansible, set any one' ),
) 'platform': _("* required Must set exact system platform, Windows, Linux ...")
} }
...@@ -102,7 +102,7 @@ class AssetBulkUpdateForm(forms.ModelForm): ...@@ -102,7 +102,7 @@ class AssetBulkUpdateForm(forms.ModelForm):
class Meta: class Meta:
model = Asset model = Asset
fields = [ fields = [
'assets', 'port', 'admin_user', 'labels', 'nodes', 'assets', 'port', 'admin_user', 'labels', 'nodes', 'platform'
] ]
widgets = { widgets = {
'labels': forms.SelectMultiple( 'labels': forms.SelectMultiple(
......
...@@ -36,6 +36,21 @@ class SystemUserSerializer(serializers.ModelSerializer): ...@@ -36,6 +36,21 @@ class SystemUserSerializer(serializers.ModelSerializer):
return len(obj.assets) return len(obj.assets)
class SystemUserAuthSerializer(serializers.ModelSerializer):
"""
系统用户认证信息
"""
password = serializers.CharField(max_length=1024)
private_key = serializers.CharField(max_length=4096)
class Meta:
model = SystemUser
fields = [
"id", "name", "username", "protocol",
"password", "private_key",
]
class AssetSystemUserSerializer(serializers.ModelSerializer): class AssetSystemUserSerializer(serializers.ModelSerializer):
""" """
查看授权的资产系统用户的数据结构,这个和AssetSerializer不同,字段少 查看授权的资产系统用户的数据结构,这个和AssetSerializer不同,字段少
......
...@@ -21,7 +21,7 @@ def update_asset_hardware_info_on_created(asset): ...@@ -21,7 +21,7 @@ def update_asset_hardware_info_on_created(asset):
def test_asset_conn_on_created(asset): def test_asset_conn_on_created(asset):
logger.debug("Test asset `{}` connectability".format(asset)) logger.debug("Test asset `{}` connectability".format(asset))
test_asset_connectability_util.delay(asset) test_asset_connectability_util.delay([asset])
def set_asset_root_node(asset): def set_asset_root_node(asset):
......
# ~*~ coding: utf-8 ~*~ # ~*~ coding: utf-8 ~*~
import json import json
import re import re
import os
from celery import shared_task from celery import shared_task
from django.core.cache import cache from django.core.cache import cache
...@@ -20,6 +21,7 @@ TIMEOUT = 60 ...@@ -20,6 +21,7 @@ TIMEOUT = 60
logger = get_logger(__file__) logger = get_logger(__file__)
CACHE_MAX_TIME = 60*60*60 CACHE_MAX_TIME = 60*60*60
disk_pattern = re.compile(r'^hd|sd|xvd|vd') disk_pattern = re.compile(r'^hd|sd|xvd|vd')
PERIOD_TASK = os.environ.get("PERIOD_TASK", "on")
@shared_task @shared_task
...@@ -89,7 +91,8 @@ def update_assets_hardware_info_util(assets, task_name=None): ...@@ -89,7 +91,8 @@ def update_assets_hardware_info_util(assets, task_name=None):
""" """
from ops.utils import update_or_create_ansible_task from ops.utils import update_or_create_ansible_task
if task_name is None: if task_name is None:
task_name = _("Update some assets hardware info") # task_name = _("Update some assets hardware info")
task_name = _("更新资产硬件信息")
tasks = const.UPDATE_ASSETS_HARDWARE_TASKS tasks = const.UPDATE_ASSETS_HARDWARE_TASKS
hostname_list = [asset.hostname for asset in assets if asset.is_active and asset.is_unixlike()] hostname_list = [asset.hostname for asset in assets if asset.is_active and asset.is_unixlike()]
task, created = update_or_create_ansible_task( task, created = update_or_create_ansible_task(
...@@ -105,7 +108,8 @@ def update_assets_hardware_info_util(assets, task_name=None): ...@@ -105,7 +108,8 @@ def update_assets_hardware_info_util(assets, task_name=None):
@shared_task @shared_task
def update_asset_hardware_info_manual(asset): def update_asset_hardware_info_manual(asset):
task_name = _("Update asset hardware info") # task_name = _("Update asset hardware info")
task_name = _("更新资产硬件信息")
return update_assets_hardware_info_util([asset], task_name=task_name) return update_assets_hardware_info_util([asset], task_name=task_name)
...@@ -118,8 +122,13 @@ def update_assets_hardware_info_period(): ...@@ -118,8 +122,13 @@ def update_assets_hardware_info_period():
Update asset hardware period task Update asset hardware period task
:return: :return:
""" """
if PERIOD_TASK != "on":
logger.debug("Period task disabled, update assets hardware info pass")
return
from ops.utils import update_or_create_ansible_task from ops.utils import update_or_create_ansible_task
task_name = _("Update assets hardware info period") # task_name = _("Update assets hardware info period")
task_name = _("定期更新资产硬件信息")
hostname_list = [ hostname_list = [
asset.hostname for asset in Asset.objects.all() asset.hostname for asset in Asset.objects.all()
if asset.is_active and asset.is_unixlike() if asset.is_active and asset.is_unixlike()
...@@ -190,25 +199,32 @@ def test_admin_user_connectability_period(): ...@@ -190,25 +199,32 @@ def test_admin_user_connectability_period():
""" """
A period task that update the ansible task period A period task that update the ansible task period
""" """
if PERIOD_TASK != "on":
logger.debug("Period task disabled, test admin user connectability pass")
return
admin_users = AdminUser.objects.all() admin_users = AdminUser.objects.all()
for admin_user in admin_users: for admin_user in admin_users:
task_name = _("Test admin user connectability period: {}".format(admin_user.name)) # task_name = _("Test admin user connectability period: {}".format(admin_user.name))
task_name = _("定期测试管理账号可连接性: {}".format(admin_user.name))
test_admin_user_connectability_util(admin_user, task_name) test_admin_user_connectability_util(admin_user, task_name)
@shared_task @shared_task
def test_admin_user_connectability_manual(admin_user): def test_admin_user_connectability_manual(admin_user):
task_name = _("Test admin user connectability: {}").format(admin_user.name) # task_name = _("Test admin user connectability: {}").format(admin_user.name)
task_name = _("测试管理行号可连接性: {}").format(admin_user.name)
return test_admin_user_connectability_util.delay(admin_user, task_name) return test_admin_user_connectability_util.delay(admin_user, task_name)
@shared_task @shared_task
def test_asset_connectability_util(asset, task_name=None): def test_asset_connectability_util(assets, task_name=None):
from ops.utils import update_or_create_ansible_task from ops.utils import update_or_create_ansible_task
if task_name is None: if task_name is None:
task_name = _("Test asset connectability") # task_name = _("Test assets connectability")
hosts = [asset.hostname] task_name = _("测试资产可连接性")
hosts = [asset.hostname for asset in assets if asset.is_active and asset.is_unixlike()]
if not hosts: if not hosts:
logger.info("No hosts, passed") logger.info("No hosts, passed")
return {} return {}
...@@ -219,18 +235,17 @@ def test_asset_connectability_util(asset, task_name=None): ...@@ -219,18 +235,17 @@ def test_asset_connectability_util(asset, task_name=None):
) )
result = task.run() result = task.run()
summary = result[1] summary = result[1]
if summary.get('dark'): for k in summary.get('dark'):
cache.set(const.ASSET_ADMIN_CONN_CACHE_KEY.format(asset.hostname), 0, cache.set(const.ASSET_ADMIN_CONN_CACHE_KEY.format(k), 0, CACHE_MAX_TIME)
CACHE_MAX_TIME)
else: for k in summary.get('contacted'):
cache.set(const.ASSET_ADMIN_CONN_CACHE_KEY.format(asset.hostname), 1, cache.set(const.ASSET_ADMIN_CONN_CACHE_KEY.format(k), 1, CACHE_MAX_TIME)
CACHE_MAX_TIME)
return summary return summary
@shared_task @shared_task
def test_asset_connectability_manual(asset): def test_asset_connectability_manual(asset):
summary = test_asset_connectability_util(asset) summary = test_asset_connectability_util([asset])
if summary.get('dark'): if summary.get('dark'):
return False, summary['dark'] return False, summary['dark']
...@@ -287,9 +302,14 @@ def test_system_user_connectability_manual(system_user): ...@@ -287,9 +302,14 @@ def test_system_user_connectability_manual(system_user):
@after_app_ready_start @after_app_ready_start
@after_app_shutdown_clean @after_app_shutdown_clean
def test_system_user_connectability_period(): def test_system_user_connectability_period():
if PERIOD_TASK != "on":
logger.debug("Period task disabled, test system user connectability pass")
return
system_users = SystemUser.objects.all() system_users = SystemUser.objects.all()
for system_user in system_users: for system_user in system_users:
task_name = _("test system user connectability period: {}".format(system_user)) # task_name = _("Test system user connectability period: {}".format(system_user))
task_name = _("定期测试系统用户可连接性: {}".format(system_user))
test_system_user_connectability_util(system_user, task_name) test_system_user_connectability_util(system_user, task_name)
...@@ -366,7 +386,9 @@ def push_system_user_util(system_users, assets, task_name): ...@@ -366,7 +386,9 @@ def push_system_user_util(system_users, assets, task_name):
def get_node_push_system_user_task_name(system_user, node): def get_node_push_system_user_task_name(system_user, node):
return _("Push system user to node: {} => {}").format(
# return _("Push system user to node: {} => {}").format(
return _("推送系统用户到节点资产: {} => {}").format(
system_user.name, system_user.name,
node.value node.value
) )
...@@ -404,7 +426,8 @@ def push_node_system_users_to_asset(node, assets): ...@@ -404,7 +426,8 @@ def push_node_system_users_to_asset(node, assets):
system_users.extend(list(n.systemuser_set.all())) system_users.extend(list(n.systemuser_set.all()))
if system_users: if system_users:
task_name = _("Push system users to node: {}").format(node.value) # task_name = _("Push system users to node: {}").format(node.value)
task_name = _("推送节点系统用户到新加入资产中: {}").format(node.value)
push_system_user_util.delay(system_users, assets, task_name) push_system_user_util.delay(system_users, assets, task_name)
......
...@@ -5,7 +5,8 @@ ...@@ -5,7 +5,8 @@
{% block help_message %} {% block help_message %}
<div class="alert alert-info help-message"> <div class="alert alert-info help-message">
管理用户是 服务器上已存在的特权用户,Jumpserver使用该用户来 `推送系统用户`、`获取资产硬件信息`等。 管理用户是服务器的root,或拥有 NOPASSWD: ALL sudo权限的用户,Jumpserver使用该用户来 `推送系统用户`、`获取资产硬件信息`等。
Windows或其它硬件可以随意设置一个
</div> </div>
{% endblock %} {% endblock %}
......
...@@ -155,6 +155,7 @@ ...@@ -155,6 +155,7 @@
</span> </span>
</td> </td>
</tr> </tr>
{% if asset.is_unixlike %}
<tr> <tr>
<td>{% trans 'Refresh hardware' %}:</td> <td>{% trans 'Refresh hardware' %}:</td>
<td> <td>
...@@ -171,6 +172,7 @@ ...@@ -171,6 +172,7 @@
</span> </span>
</td> </td>
</tr> </tr>
{% endif %}
</tbody> </tbody>
</table> </table>
</div> </div>
......
...@@ -119,6 +119,8 @@ ...@@ -119,6 +119,8 @@
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li id="menu_asset_create" class="btn-create-asset" tabindex="-1"><a>{% trans 'Create asset' %}</a></li> <li id="menu_asset_create" class="btn-create-asset" tabindex="-1"><a>{% trans 'Create asset' %}</a></li>
<li id="menu_asset_add" class="btn-add-asset" data-toggle="modal" data-target="#asset_list_modal" tabindex="0"><a>{% trans 'Add asset' %}</a></li> <li id="menu_asset_add" class="btn-add-asset" data-toggle="modal" data-target="#asset_list_modal" tabindex="0"><a>{% trans 'Add asset' %}</a></li>
<li id="menu_refresh_hardware_info" class="btn-refresh-hardware" tabindex="-1"><a>{% trans 'Refresh node hardware info' %}</a></li>
<li id="menu_test_connective" class="btn-test-connective" tabindex="-1"><a>{% trans 'Test node connective' %}</a></li>
<li class="divider"></li> <li class="divider"></li>
<li id="m_create" tabindex="-1" onclick="addTreeNode();"><a>{% trans 'Add node' %}</a></li> <li id="m_create" tabindex="-1" onclick="addTreeNode();"><a>{% trans 'Add node' %}</a></li>
<li id="m_del" tabindex="-1" onclick="editTreeNode();"><a>{% trans 'Rename node' %}</a></li> <li id="m_del" tabindex="-1" onclick="editTreeNode();"><a>{% trans 'Rename node' %}</a></li>
...@@ -476,6 +478,49 @@ $(document).ready(function(){ ...@@ -476,6 +478,49 @@ $(document).ready(function(){
} }
window.open(url, '_self'); window.open(url, '_self');
}) })
.on('click', '.btn-refresh-hardware', function () {
var url = "{% url 'api-assets:node-refresh-hardware-info' pk=DEFAULT_PK %}";
var nodes = zTree.getSelectedNodes();
var current_node;
if (nodes && nodes.length ===1 ){
current_node = nodes[0];
} else {
return null;
}
var the_url = url.replace("{{ DEFAULT_PK }}", current_node.id);
function success() {
rMenu.css({"visibility" : "hidden"});
}
APIUpdateAttr({
url: the_url,
method: "GET",
success_message: "更新硬件信息任务下发成功",
success: success
});
})
.on('click', '.btn-test-connective', function () {
var url = "{% url 'api-assets:node-test-connective' pk=DEFAULT_PK %}";
var nodes = zTree.getSelectedNodes();
var current_node;
if (nodes && nodes.length ===1 ){
current_node = nodes[0];
} else {
return null;
}
var the_url = url.replace("{{ DEFAULT_PK }}", current_node.id);
function success() {
rMenu.css({"visibility" : "hidden"});
}
APIUpdateAttr({
url: the_url,
method: "GET",
success_message: "测试可连接性任务下发成功",
success: success
});
})
.on('click', '.btn_asset_delete', function () { .on('click', '.btn_asset_delete', function () {
var $this = $(this); var $this = $(this);
var $data_table = $("#asset_list_table").DataTable(); var $data_table = $("#asset_list_table").DataTable();
......
...@@ -3,8 +3,10 @@ ...@@ -3,8 +3,10 @@
{% block help_message %} {% block help_message %}
<div class="alert alert-info help-message"> <div class="alert alert-info help-message">
系统用户是 用户登录资产(服务器)时使用的用户,如 web, sa, dba等具有特殊功能的用户。系统用户创建时,如果选择了自动推送 系统用户是 Jumpserver跳转登录资产时使用的用户,可以理解为登录资产用户,如 web, sa, dba(`ssh web@some-host`), 而不是使用某个用户的用户名跳转登录服务器(`ssh xiaoming@some-host`);
Jumpserver会使用ansible自动推送系统用户到资产中,如果资产(交换机、windows)不支持ansible, 请手动填写账号密码。 简单来说是 用户使用自己的用户名登录Jumpserver, Jumpserver使用系统用户登录资产。
系统用户创建时,如果选择了自动推送 Jumpserver会使用ansible自动推送系统用户到资产中,如果资产(交换机、windows)不支持ansible, 请手动填写账号密码。
目前还不支持Windows的自动推送
</div> </div>
{% endblock %} {% endblock %}
......
...@@ -47,6 +47,8 @@ urlpatterns = [ ...@@ -47,6 +47,8 @@ urlpatterns = [
url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/children/add/$', api.NodeAddChildrenApi.as_view(), name='node-add-children'), url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/children/add/$', api.NodeAddChildrenApi.as_view(), name='node-add-children'),
url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/assets/add/$', api.NodeAddAssetsApi.as_view(), name='node-add-assets'), url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/assets/add/$', api.NodeAddAssetsApi.as_view(), name='node-add-assets'),
url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/assets/remove/$', api.NodeRemoveAssetsApi.as_view(), name='node-remove-assets'), url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/assets/remove/$', api.NodeRemoveAssetsApi.as_view(), name='node-remove-assets'),
url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/refresh-hardware-info/$', api.RefreshNodeHardwareInfoApi.as_view(), name='node-refresh-hardware-info'),
url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/test-connective/$', api.TestNodeConnectiveApi.as_view(), name='node-test-connective'),
] ]
urlpatterns += router.urls urlpatterns += router.urls
......
...@@ -8,7 +8,7 @@ msgid "" ...@@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Jumpserver 0.3.3\n" "Project-Id-Version: Jumpserver 0.3.3\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-03-07 21:18+0800\n" "POT-Creation-Date: 2018-03-14 18:11+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: ibuler <ibuler@qq.com>\n" "Last-Translator: ibuler <ibuler@qq.com>\n"
"Language-Team: Jumpserver team<ibuler@qq.com>\n" "Language-Team: Jumpserver team<ibuler@qq.com>\n"
...@@ -17,14 +17,22 @@ msgstr "" ...@@ -17,14 +17,22 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
#: assets/api/node.py:55 #: assets/api/node.py:58
msgid "New node {}" msgid "New node {}"
msgstr "新节点 {}" msgstr "新节点 {}"
#: assets/api/node.py:134
msgid "更新节点资产硬件信息: {}"
msgstr ""
#: assets/api/node.py:147
msgid "测试节点下资产是否可连接: {}"
msgstr ""
#: assets/forms/asset.py:23 assets/forms/asset.py:54 assets/forms/user.py:125 #: assets/forms/asset.py:23 assets/forms/asset.py:54 assets/forms/user.py:125
#: assets/models/asset.py:53 assets/models/user.py:218 #: assets/models/asset.py:53 assets/models/user.py:218
#: assets/templates/assets/asset_detail.html:181 #: assets/templates/assets/asset_detail.html:183
#: assets/templates/assets/asset_detail.html:189 #: assets/templates/assets/asset_detail.html:191
#: assets/templates/assets/system_user_detail.html:166 #: assets/templates/assets/system_user_detail.html:166
msgid "Nodes" msgid "Nodes"
msgstr "节点管理" msgstr "节点管理"
...@@ -38,21 +46,25 @@ msgstr "管理用户" ...@@ -38,21 +46,25 @@ msgstr "管理用户"
#: assets/forms/asset.py:29 assets/forms/asset.py:60 assets/models/asset.py:81 #: assets/forms/asset.py:29 assets/forms/asset.py:60 assets/models/asset.py:81
#: assets/templates/assets/asset_create.html:32 #: assets/templates/assets/asset_create.html:32
#: assets/templates/assets/asset_detail.html:218 #: assets/templates/assets/asset_detail.html:220
#: assets/templates/assets/asset_update.html:37 templates/_nav.html:26 #: assets/templates/assets/asset_update.html:37 templates/_nav.html:26
msgid "Labels" msgid "Labels"
msgstr "标签管理" msgstr "标签管理"
#: assets/forms/asset.py:38 assets/forms/asset.py:70 #: assets/forms/asset.py:38 assets/forms/asset.py:70
msgid "" msgid ""
"Admin user is a privilege user exist on this asset,Example: root or other " "root or other NOPASSWD sudo privilege user existed in asset,If asset is "
"NOPASSWD sudo privilege userIf asset not support ansible, set any one" "windows or other set any one, more see admin user left menu"
msgstr "" msgstr ""
"管理用户是资产上已经存在的特权用户,如 root或者其它有NOPASSWD的用户, 如果资产" "root或其他拥有NOPASSWD: ALL权限的用户, 如果是windows或其它硬件可以随意设置一"
"不支持ansible, 任意设置一个即可" "个, 更多信息查看左侧 `管理用户` 菜单"
#: assets/forms/asset.py:41 assets/forms/asset.py:73
msgid "* required Must set exact system platform, Windows, Linux ..."
msgstr "* required 必须准确设置操作系统平台,如Windows, Linux ..."
#: assets/forms/asset.py:80 assets/forms/asset.py:84 assets/forms/label.py:15 #: assets/forms/asset.py:80 assets/forms/asset.py:84 assets/forms/label.py:15
#: perms/templates/perms/asset_permission_asset.html:88 users/forms.py:242 #: perms/templates/perms/asset_permission_asset.html:88 users/forms.py:244
msgid "Select assets" msgid "Select assets"
msgstr "选择资产" msgstr "选择资产"
...@@ -73,9 +85,9 @@ msgid "Select nodes" ...@@ -73,9 +85,9 @@ msgid "Select nodes"
msgstr "选择节点" msgstr "选择节点"
#: assets/forms/label.py:13 assets/models/asset.py:153 #: assets/forms/label.py:13 assets/models/asset.py:153
#: assets/templates/assets/admin_user_list.html:24 #: assets/templates/assets/admin_user_list.html:25
#: assets/templates/assets/label_list.html:16 #: assets/templates/assets/label_list.html:16
#: assets/templates/assets/system_user_list.html:26 perms/models.py:17 #: assets/templates/assets/system_user_list.html:28 perms/models.py:17
#: terminal/backends/command/models.py:11 terminal/models.py:123 #: terminal/backends/command/models.py:11 terminal/models.py:123
#: terminal/templates/terminal/command_list.html:40 #: terminal/templates/terminal/command_list.html:40
#: terminal/templates/terminal/command_list.html:73 #: terminal/templates/terminal/command_list.html:73
...@@ -89,7 +101,7 @@ msgid "Password or private key passphrase" ...@@ -89,7 +101,7 @@ msgid "Password or private key passphrase"
msgstr "密码或密钥密码" msgstr "密码或密钥密码"
#: assets/forms/user.py:25 assets/models/user.py:30 common/forms.py:113 #: assets/forms/user.py:25 assets/models/user.py:30 common/forms.py:113
#: users/forms.py:16 users/forms.py:24 users/templates/users/login.html:59 #: users/forms.py:16 users/forms.py:25 users/templates/users/login.html:59
#: users/templates/users/reset_password.html:52 #: users/templates/users/reset_password.html:52
#: users/templates/users/user_create.html:11 #: users/templates/users/user_create.html:11
#: users/templates/users/user_password_update.html:40 #: users/templates/users/user_password_update.html:40
...@@ -113,10 +125,10 @@ msgstr "密码和私钥, 必须输入一个" ...@@ -113,10 +125,10 @@ msgstr "密码和私钥, 必须输入一个"
#: assets/forms/user.py:79 assets/forms/user.py:120 assets/models/cluster.py:18 #: assets/forms/user.py:79 assets/forms/user.py:120 assets/models/cluster.py:18
#: assets/models/group.py:20 assets/models/label.py:17 assets/models/user.py:28 #: assets/models/group.py:20 assets/models/label.py:17 assets/models/user.py:28
#: assets/templates/assets/admin_user_detail.html:56 #: assets/templates/assets/admin_user_detail.html:56
#: assets/templates/assets/admin_user_list.html:22 #: assets/templates/assets/admin_user_list.html:23
#: assets/templates/assets/label_list.html:14 #: assets/templates/assets/label_list.html:14
#: assets/templates/assets/system_user_detail.html:58 #: assets/templates/assets/system_user_detail.html:58
#: assets/templates/assets/system_user_list.html:24 common/models.py:26 #: assets/templates/assets/system_user_list.html:26 common/models.py:26
#: common/templates/common/terminal_setting.html:67 #: common/templates/common/terminal_setting.html:67
#: common/templates/common/terminal_setting.html:85 ops/models.py:31 #: common/templates/common/terminal_setting.html:85 ops/models.py:31
#: ops/templates/ops/task_detail.html:56 ops/templates/ops/task_list.html:34 #: ops/templates/ops/task_detail.html:56 ops/templates/ops/task_list.html:34
...@@ -136,9 +148,9 @@ msgstr "名称" ...@@ -136,9 +148,9 @@ msgstr "名称"
#: assets/forms/user.py:80 assets/forms/user.py:121 assets/models/user.py:29 #: assets/forms/user.py:80 assets/forms/user.py:121 assets/models/user.py:29
#: assets/templates/assets/admin_user_detail.html:60 #: assets/templates/assets/admin_user_detail.html:60
#: assets/templates/assets/admin_user_list.html:23 #: assets/templates/assets/admin_user_list.html:24
#: assets/templates/assets/system_user_detail.html:62 #: assets/templates/assets/system_user_detail.html:62
#: assets/templates/assets/system_user_list.html:25 #: assets/templates/assets/system_user_list.html:27
#: perms/templates/perms/asset_permission_user.html:55 users/forms.py:14 #: perms/templates/perms/asset_permission_user.html:55 users/forms.py:14
#: users/models/authentication.py:45 users/models/user.py:34 #: users/models/authentication.py:45 users/models/user.py:34
#: users/templates/users/_select_user_modal.html:14 #: users/templates/users/_select_user_modal.html:14
...@@ -285,10 +297,10 @@ msgstr "创建日期" ...@@ -285,10 +297,10 @@ msgstr "创建日期"
#: assets/models/asset.py:84 assets/models/cluster.py:29 #: assets/models/asset.py:84 assets/models/cluster.py:29
#: assets/models/group.py:23 assets/models/label.py:21 assets/models/user.py:33 #: assets/models/group.py:23 assets/models/label.py:21 assets/models/user.py:33
#: assets/templates/assets/admin_user_detail.html:72 #: assets/templates/assets/admin_user_detail.html:72
#: assets/templates/assets/admin_user_list.html:28 #: assets/templates/assets/admin_user_list.html:29
#: assets/templates/assets/asset_detail.html:125 #: assets/templates/assets/asset_detail.html:125
#: assets/templates/assets/system_user_detail.html:100 #: assets/templates/assets/system_user_detail.html:100
#: assets/templates/assets/system_user_list.html:30 common/models.py:30 #: assets/templates/assets/system_user_list.html:32 common/models.py:30
#: ops/models.py:37 perms/models.py:24 perms/models.py:81 #: ops/models.py:37 perms/models.py:24 perms/models.py:81
#: perms/templates/perms/asset_permission_detail.html:98 terminal/models.py:26 #: perms/templates/perms/asset_permission_detail.html:98 terminal/models.py:26
#: terminal/templates/terminal/terminal_detail.html:63 users/models/group.py:15 #: terminal/templates/terminal/terminal_detail.html:63 users/models/group.py:15
...@@ -358,7 +370,7 @@ msgstr "默认资产组" ...@@ -358,7 +370,7 @@ msgstr "默认资产组"
#: terminal/templates/terminal/command_list.html:32 #: terminal/templates/terminal/command_list.html:32
#: terminal/templates/terminal/command_list.html:72 #: terminal/templates/terminal/command_list.html:72
#: terminal/templates/terminal/session_list.html:33 #: terminal/templates/terminal/session_list.html:33
#: terminal/templates/terminal/session_list.html:71 users/forms.py:190 #: terminal/templates/terminal/session_list.html:71 users/forms.py:192
#: users/models/user.py:30 users/models/user.py:254 #: users/models/user.py:30 users/models/user.py:254
#: users/templates/users/user_group_detail.html:78 #: users/templates/users/user_group_detail.html:78
#: users/templates/users/user_group_list.html:13 users/views/user.py:333 #: users/templates/users/user_group_list.html:13 users/views/user.py:333
...@@ -424,45 +436,41 @@ msgstr "系统用户" ...@@ -424,45 +436,41 @@ msgstr "系统用户"
msgid "%(value)s is not an even number" msgid "%(value)s is not an even number"
msgstr "%(value)s is not an even number" msgstr "%(value)s is not an even number"
#: assets/tasks.py:92 #: assets/tasks.py:95 assets/tasks.py:112
msgid "Update some assets hardware info" msgid "更新资产硬件信息"
msgstr "更新一些资产硬件信息" msgstr ""
#: assets/tasks.py:108
msgid "Update asset hardware info"
msgstr "更新资产硬件信息"
#: assets/tasks.py:122 #: assets/tasks.py:131
msgid "Update assets hardware info period" msgid "定期更新资产硬件信息"
msgstr "定期更新资产硬件信息" msgstr ""
#: assets/tasks.py:195 #: assets/tasks.py:209
msgid "Test admin user connectability period: {}" msgid "定期测试管理账号可连接性: {}"
msgstr "定期测试管理用户可连接性: {}" msgstr ""
#: assets/tasks.py:201 #: assets/tasks.py:216
msgid "Test admin user connectability: {}" msgid "测试管理行号可连接性: {}"
msgstr "测试管理用户可连接性: {}" msgstr ""
#: assets/tasks.py:210 #: assets/tasks.py:226
msgid "Test asset connectability" msgid "测试资产可连接性"
msgstr "测试资产可连接性" msgstr ""
#: assets/tasks.py:281 #: assets/tasks.py:296
msgid "Test system user connectability: {}" msgid "Test system user connectability: {}"
msgstr "测试系统用户可连接性: {}" msgstr "测试系统用户可连接性: {}"
#: assets/tasks.py:292 #: assets/tasks.py:312
msgid "test system user connectability period: {}" msgid "定期测试系统用户可连接性: {}"
msgstr "测试系统用户可连接性: {}" msgstr ""
#: assets/tasks.py:369 #: assets/tasks.py:391
msgid "Push system user to node: {} => {}" msgid "推送系统用户到节点资产: {} => {}"
msgstr "推送系统用户到节点: {}->{}" msgstr ""
#: assets/tasks.py:407 #: assets/tasks.py:430
msgid "Push system users to node: {}" msgid "推送节点系统用户到新加入资产中: {}"
msgstr "推送系统用户到节点: {}" msgstr ""
#: assets/templates/assets/_asset_group_bulk_update_modal.html:5 #: assets/templates/assets/_asset_group_bulk_update_modal.html:5
msgid "Update asset group" msgid "Update asset group"
...@@ -548,21 +556,21 @@ msgstr "激活中" ...@@ -548,21 +556,21 @@ msgstr "激活中"
#: assets/templates/assets/_asset_list_modal.html:24 #: assets/templates/assets/_asset_list_modal.html:24
#: assets/templates/assets/admin_user_assets.html:54 #: assets/templates/assets/admin_user_assets.html:54
#: assets/templates/assets/admin_user_list.html:25 #: assets/templates/assets/admin_user_list.html:26
#: assets/templates/assets/asset_detail.html:357 #: assets/templates/assets/asset_detail.html:359
#: assets/templates/assets/asset_list.html:90 #: assets/templates/assets/asset_list.html:90
#: assets/templates/assets/system_user_asset.html:52 #: assets/templates/assets/system_user_asset.html:52
#: assets/templates/assets/system_user_list.html:27 #: assets/templates/assets/system_user_list.html:29
#: users/templates/users/user_granted_asset.html:47 #: users/templates/users/user_granted_asset.html:47
#: users/templates/users/user_group_granted_asset.html:47 #: users/templates/users/user_group_granted_asset.html:47
msgid "Reachable" msgid "Reachable"
msgstr "可连接" msgstr "可连接"
#: assets/templates/assets/_asset_list_modal.html:25 #: assets/templates/assets/_asset_list_modal.html:25
#: assets/templates/assets/admin_user_list.html:29 #: assets/templates/assets/admin_user_list.html:30
#: assets/templates/assets/asset_list.html:91 #: assets/templates/assets/asset_list.html:91
#: assets/templates/assets/label_list.html:17 #: assets/templates/assets/label_list.html:17
#: assets/templates/assets/system_user_list.html:31 #: assets/templates/assets/system_user_list.html:33
#: ops/templates/ops/adhoc_history.html:59 ops/templates/ops/task_adhoc.html:61 #: ops/templates/ops/adhoc_history.html:59 ops/templates/ops/task_adhoc.html:61
#: ops/templates/ops/task_history.html:62 ops/templates/ops/task_list.html:41 #: ops/templates/ops/task_history.html:62 ops/templates/ops/task_list.html:41
#: perms/templates/perms/asset_permission_list.html:72 #: perms/templates/perms/asset_permission_list.html:72
...@@ -625,12 +633,12 @@ msgstr "提交" ...@@ -625,12 +633,12 @@ msgstr "提交"
#: assets/templates/assets/_asset_list_modal.html:79 #: assets/templates/assets/_asset_list_modal.html:79
#: assets/templates/assets/admin_user_detail.html:24 #: assets/templates/assets/admin_user_detail.html:24
#: assets/templates/assets/admin_user_list.html:84 #: assets/templates/assets/admin_user_list.html:85
#: assets/templates/assets/asset_detail.html:24 #: assets/templates/assets/asset_detail.html:24
#: assets/templates/assets/asset_list.html:166 #: assets/templates/assets/asset_list.html:168
#: assets/templates/assets/label_list.html:38 #: assets/templates/assets/label_list.html:38
#: assets/templates/assets/system_user_detail.html:26 #: assets/templates/assets/system_user_detail.html:26
#: assets/templates/assets/system_user_list.html:85 #: assets/templates/assets/system_user_list.html:87
#: perms/templates/perms/asset_permission_detail.html:30 #: perms/templates/perms/asset_permission_detail.html:30
#: perms/templates/perms/asset_permission_list.html:121 #: perms/templates/perms/asset_permission_list.html:121
#: terminal/templates/terminal/terminal_detail.html:16 #: terminal/templates/terminal/terminal_detail.html:16
...@@ -644,12 +652,12 @@ msgstr "更新" ...@@ -644,12 +652,12 @@ msgstr "更新"
#: assets/templates/assets/_asset_list_modal.html:80 #: assets/templates/assets/_asset_list_modal.html:80
#: assets/templates/assets/admin_user_detail.html:28 #: assets/templates/assets/admin_user_detail.html:28
#: assets/templates/assets/admin_user_list.html:85 #: assets/templates/assets/admin_user_list.html:86
#: assets/templates/assets/asset_detail.html:28 #: assets/templates/assets/asset_detail.html:28
#: assets/templates/assets/asset_list.html:167 #: assets/templates/assets/asset_list.html:169
#: assets/templates/assets/label_list.html:39 #: assets/templates/assets/label_list.html:39
#: assets/templates/assets/system_user_detail.html:30 #: assets/templates/assets/system_user_detail.html:30
#: assets/templates/assets/system_user_list.html:86 #: assets/templates/assets/system_user_list.html:88
#: ops/templates/ops/task_list.html:71 #: ops/templates/ops/task_list.html:71
#: perms/templates/perms/asset_permission_detail.html:34 #: perms/templates/perms/asset_permission_detail.html:34
#: perms/templates/perms/asset_permission_list.html:122 #: perms/templates/perms/asset_permission_list.html:122
...@@ -743,12 +751,12 @@ msgid "Quick update" ...@@ -743,12 +751,12 @@ msgid "Quick update"
msgstr "快速更新" msgstr "快速更新"
#: assets/templates/assets/admin_user_assets.html:72 #: assets/templates/assets/admin_user_assets.html:72
#: assets/templates/assets/asset_detail.html:167 #: assets/templates/assets/asset_detail.html:168
msgid "Test connective" msgid "Test connective"
msgstr "测试可连接性" msgstr "测试可连接性"
#: assets/templates/assets/admin_user_assets.html:75 #: assets/templates/assets/admin_user_assets.html:75
#: assets/templates/assets/asset_detail.html:170 #: assets/templates/assets/asset_detail.html:171
#: assets/templates/assets/system_user_asset.html:81 #: assets/templates/assets/system_user_asset.html:81
#: assets/templates/assets/system_user_detail.html:147 #: assets/templates/assets/system_user_detail.html:147
msgid "Test" msgid "Test"
...@@ -763,10 +771,10 @@ msgid "Replace node assets admin user with this" ...@@ -763,10 +771,10 @@ msgid "Replace node assets admin user with this"
msgstr "替换资产的管理员" msgstr "替换资产的管理员"
#: assets/templates/assets/admin_user_detail.html:100 #: assets/templates/assets/admin_user_detail.html:100
#: assets/templates/assets/asset_detail.html:198 #: assets/templates/assets/asset_detail.html:200
#: assets/templates/assets/asset_list.html:541 #: assets/templates/assets/asset_list.html:586
#: assets/templates/assets/system_user_detail.html:183 #: assets/templates/assets/system_user_detail.html:183
#: assets/templates/assets/system_user_list.html:135 templates/_modal.html:16 #: assets/templates/assets/system_user_list.html:137 templates/_modal.html:16
#: terminal/templates/terminal/session_detail.html:108 #: terminal/templates/terminal/session_detail.html:108
#: users/templates/users/user_detail.html:339 #: users/templates/users/user_detail.html:339
#: users/templates/users/user_detail.html:364 #: users/templates/users/user_detail.html:364
...@@ -778,18 +786,18 @@ msgstr "替换资产的管理员" ...@@ -778,18 +786,18 @@ msgstr "替换资产的管理员"
msgid "Confirm" msgid "Confirm"
msgstr "确认" msgstr "确认"
#: assets/templates/assets/admin_user_list.html:14 #: assets/templates/assets/admin_user_list.html:15
#: assets/views/admin_user.py:48 #: assets/views/admin_user.py:48
msgid "Create admin user" msgid "Create admin user"
msgstr "创建管理用户" msgstr "创建管理用户"
#: assets/templates/assets/admin_user_list.html:26 #: assets/templates/assets/admin_user_list.html:27
#: assets/templates/assets/system_user_list.html:28 #: assets/templates/assets/system_user_list.html:30
msgid "Unreachable" msgid "Unreachable"
msgstr "不可达" msgstr "不可达"
#: assets/templates/assets/admin_user_list.html:27 #: assets/templates/assets/admin_user_list.html:28
#: assets/templates/assets/system_user_list.html:29 #: assets/templates/assets/system_user_list.html:31
#: ops/templates/ops/adhoc_history.html:54 #: ops/templates/ops/adhoc_history.html:54
#: ops/templates/ops/task_history.html:57 #: ops/templates/ops/task_history.html:57
msgid "Ratio" msgid "Ratio"
...@@ -833,15 +841,15 @@ msgstr "创建日期" ...@@ -833,15 +841,15 @@ msgstr "创建日期"
msgid "Quick modify" msgid "Quick modify"
msgstr "快速修改" msgstr "快速修改"
#: assets/templates/assets/asset_detail.html:159 #: assets/templates/assets/asset_detail.html:160
msgid "Refresh hardware" msgid "Refresh hardware"
msgstr "更新硬件信息" msgstr "更新硬件信息"
#: assets/templates/assets/asset_detail.html:162 #: assets/templates/assets/asset_detail.html:163
msgid "Refresh" msgid "Refresh"
msgstr "刷新" msgstr "刷新"
#: assets/templates/assets/asset_detail.html:299 #: assets/templates/assets/asset_detail.html:301
#: users/templates/users/user_detail.html:273 #: users/templates/users/user_detail.html:273
msgid "Update successfully!" msgid "Update successfully!"
msgstr "更新成功" msgstr "更新成功"
...@@ -869,28 +877,36 @@ msgstr "从节点移除" ...@@ -869,28 +877,36 @@ msgstr "从节点移除"
msgid "Add asset" msgid "Add asset"
msgstr "添加资产到节点" msgstr "添加资产到节点"
#: assets/templates/assets/asset_list.html:122
msgid "Refresh node hardware info"
msgstr "更新节点资产硬件信息"
#: assets/templates/assets/asset_list.html:123 #: assets/templates/assets/asset_list.html:123
msgid "Test node connective"
msgstr "测试节点资产可连接性"
#: assets/templates/assets/asset_list.html:125
msgid "Add node" msgid "Add node"
msgstr "新建节点" msgstr "新建节点"
#: assets/templates/assets/asset_list.html:124 #: assets/templates/assets/asset_list.html:126
msgid "Rename node" msgid "Rename node"
msgstr "重命名节点" msgstr "重命名节点"
#: assets/templates/assets/asset_list.html:126 #: assets/templates/assets/asset_list.html:128
msgid "Delete node" msgid "Delete node"
msgstr "删除节点" msgstr "删除节点"
#: assets/templates/assets/asset_list.html:201 #: assets/templates/assets/asset_list.html:203
msgid "Create node failed" msgid "Create node failed"
msgstr "创建节点失败" msgstr "创建节点失败"
#: assets/templates/assets/asset_list.html:214 #: assets/templates/assets/asset_list.html:216
msgid "Have child node, cancel" msgid "Have child node, cancel"
msgstr "存在子节点,不能删除" msgstr "存在子节点,不能删除"
#: assets/templates/assets/asset_list.html:536 #: assets/templates/assets/asset_list.html:581
#: assets/templates/assets/system_user_list.html:130 #: assets/templates/assets/system_user_list.html:132
#: users/templates/users/user_detail.html:334 #: users/templates/users/user_detail.html:334
#: users/templates/users/user_detail.html:359 #: users/templates/users/user_detail.html:359
#: users/templates/users/user_group_list.html:81 #: users/templates/users/user_group_list.html:81
...@@ -898,20 +914,20 @@ msgstr "存在子节点,不能删除" ...@@ -898,20 +914,20 @@ msgstr "存在子节点,不能删除"
msgid "Are you sure?" msgid "Are you sure?"
msgstr "你确认吗?" msgstr "你确认吗?"
#: assets/templates/assets/asset_list.html:537 #: assets/templates/assets/asset_list.html:582
msgid "This will delete the selected assets !!!" msgid "This will delete the selected assets !!!"
msgstr "删除选择资产" msgstr "删除选择资产"
#: assets/templates/assets/asset_list.html:545 #: assets/templates/assets/asset_list.html:590
msgid "Asset Deleted." msgid "Asset Deleted."
msgstr "已被删除" msgstr "已被删除"
#: assets/templates/assets/asset_list.html:546 #: assets/templates/assets/asset_list.html:591
#: assets/templates/assets/asset_list.html:551 #: assets/templates/assets/asset_list.html:596
msgid "Asset Delete" msgid "Asset Delete"
msgstr "删除" msgstr "删除"
#: assets/templates/assets/asset_list.html:550 #: assets/templates/assets/asset_list.html:595
msgid "Asset Deleting failed." msgid "Asset Deleting failed."
msgstr "删除失败" msgstr "删除失败"
...@@ -974,25 +990,25 @@ msgstr "Uid" ...@@ -974,25 +990,25 @@ msgstr "Uid"
msgid "Add to node" msgid "Add to node"
msgstr "添加到节点" msgstr "添加到节点"
#: assets/templates/assets/system_user_list.html:16 #: assets/templates/assets/system_user_list.html:18
#: assets/views/system_user.py:45 #: assets/views/system_user.py:45
msgid "Create system user" msgid "Create system user"
msgstr "创建系统用户" msgstr "创建系统用户"
#: assets/templates/assets/system_user_list.html:131 #: assets/templates/assets/system_user_list.html:133
msgid "This will delete the selected System Users !!!" msgid "This will delete the selected System Users !!!"
msgstr "删除选择系统用户" msgstr "删除选择系统用户"
#: assets/templates/assets/system_user_list.html:139 #: assets/templates/assets/system_user_list.html:141
msgid "System Users Deleted." msgid "System Users Deleted."
msgstr "已被删除" msgstr "已被删除"
#: assets/templates/assets/system_user_list.html:140 #: assets/templates/assets/system_user_list.html:142
#: assets/templates/assets/system_user_list.html:145 #: assets/templates/assets/system_user_list.html:147
msgid "System Users Delete" msgid "System Users Delete"
msgstr "删除系统用户" msgstr "删除系统用户"
#: assets/templates/assets/system_user_list.html:144 #: assets/templates/assets/system_user_list.html:146
msgid "System Users Deleting failed." msgid "System Users Deleting failed."
msgstr "系统用户删除失败" msgstr "系统用户删除失败"
...@@ -1211,7 +1227,7 @@ msgid "" ...@@ -1211,7 +1227,7 @@ msgid ""
msgstr "设置终端命令存储,default是默认用的存储方式" msgstr "设置终端命令存储,default是默认用的存储方式"
#: common/forms.py:165 common/templates/common/terminal_setting.html:81 #: common/forms.py:165 common/templates/common/terminal_setting.html:81
#: terminal/forms.py:34 terminal/models.py:21 #: terminal/forms.py:35 terminal/models.py:21
msgid "Replay storage" msgid "Replay storage"
msgstr "录像存储" msgstr "录像存储"
...@@ -1532,7 +1548,7 @@ msgstr "日期" ...@@ -1532,7 +1548,7 @@ msgstr "日期"
msgid "Run" msgid "Run"
msgstr "执行" msgstr "执行"
#: ops/templates/ops/task_list.html:125 #: ops/templates/ops/task_list.html:123
msgid "Task start: " msgid "Task start: "
msgstr "任务开始: " msgstr "任务开始: "
...@@ -1598,7 +1614,7 @@ msgstr "添加" ...@@ -1598,7 +1614,7 @@ msgstr "添加"
msgid "Add asset group to this permission" msgid "Add asset group to this permission"
msgstr "添加资产组" msgstr "添加资产组"
#: perms/templates/perms/asset_permission_asset.html:116 users/forms.py:245 #: perms/templates/perms/asset_permission_asset.html:116 users/forms.py:247
msgid "Select asset groups" msgid "Select asset groups"
msgstr "选择资产组" msgstr "选择资产组"
...@@ -1627,7 +1643,7 @@ msgstr "资产组数量" ...@@ -1627,7 +1643,7 @@ msgstr "资产组数量"
msgid "System user count" msgid "System user count"
msgstr "系统用户数量" msgstr "系统用户数量"
#: perms/templates/perms/asset_permission_detail.html:144 users/forms.py:248 #: perms/templates/perms/asset_permission_detail.html:144 users/forms.py:250
msgid "Select system users" msgid "Select system users"
msgstr "选择系统用户" msgstr "选择系统用户"
...@@ -1815,13 +1831,18 @@ msgstr "输出" ...@@ -1815,13 +1831,18 @@ msgstr "输出"
msgid "Session" msgid "Session"
msgstr "会话" msgstr "会话"
#: terminal/forms.py:44 #: terminal/forms.py:31
msgid "Coco ssh listen port" msgid "Command can store in server db or ES, default to server, more see docs"
msgstr "SSH 监听端口" msgstr ""
"命令支持存储到服务器端数据库、ES中,默认存储的服务器端数据库,更多查看文档"
#: terminal/forms.py:45 #: terminal/forms.py:36
msgid "Coco http/ws listen port" msgid ""
msgstr "Http/Websocket 监听端口" "Replay file can store in server disk, AWS S3, Aliyun OSS, default to server, "
"more see docs"
msgstr ""
"录像文件支持存储到服务器端硬盘、AWS S3、 阿里云 OSS 中,默认存储到服务器端硬"
"盘, 更多查看文档"
#: terminal/models.py:17 #: terminal/models.py:17
msgid "Remote Address" msgid "Remote Address"
...@@ -1948,12 +1969,10 @@ msgid "Terminal detail" ...@@ -1948,12 +1969,10 @@ msgid "Terminal detail"
msgstr "终端详情" msgstr "终端详情"
#: terminal/templates/terminal/terminal_detail.html:51 #: terminal/templates/terminal/terminal_detail.html:51
#: terminal/templates/terminal/terminal_list.html:31
msgid "SSH port" msgid "SSH port"
msgstr "SSH端口" msgstr "SSH端口"
#: terminal/templates/terminal/terminal_detail.html:55 #: terminal/templates/terminal/terminal_detail.html:55
#: terminal/templates/terminal/terminal_list.html:32
msgid "Http port" msgid "Http port"
msgstr "HTTP端口" msgstr "HTTP端口"
...@@ -2061,51 +2080,59 @@ msgstr "" ...@@ -2061,51 +2080,59 @@ msgstr ""
msgid "Invalid token or cache refreshed." msgid "Invalid token or cache refreshed."
msgstr "" msgstr ""
#: users/forms.py:43 users/templates/users/user_detail.html:187 #: users/forms.py:28 users/models/user.py:38
#: users/templates/users/_select_user_modal.html:15
#: users/templates/users/user_detail.html:87
#: users/templates/users/user_list.html:25
#: users/templates/users/user_profile.html:55
msgid "Role"
msgstr "角色"
#: users/forms.py:45 users/templates/users/user_detail.html:187
msgid "Join user groups" msgid "Join user groups"
msgstr "添加到用户组" msgstr "添加到用户组"
#: users/forms.py:74 #: users/forms.py:76
msgid "Old password" msgid "Old password"
msgstr "原来密码" msgstr "原来密码"
#: users/forms.py:79 #: users/forms.py:81
msgid "New password" msgid "New password"
msgstr "新密码" msgstr "新密码"
#: users/forms.py:84 #: users/forms.py:86
msgid "Confirm password" msgid "Confirm password"
msgstr "确认密码" msgstr "确认密码"
#: users/forms.py:94 #: users/forms.py:96
msgid "Old password error" msgid "Old password error"
msgstr "原来密码错误" msgstr "原来密码错误"
#: users/forms.py:102 #: users/forms.py:104
msgid "Password does not match" msgid "Password does not match"
msgstr "密码不一致" msgstr "密码不一致"
#: users/forms.py:114 #: users/forms.py:116
msgid "ssh public key" msgid "ssh public key"
msgstr "ssh公钥" msgstr "ssh公钥"
#: users/forms.py:115 #: users/forms.py:117
msgid "ssh-rsa AAAA..." msgid "ssh-rsa AAAA..."
msgstr "" msgstr ""
#: users/forms.py:116 #: users/forms.py:118
msgid "Paste your id_rsa.pub here." msgid "Paste your id_rsa.pub here."
msgstr "复制你的公钥到这里" msgstr "复制你的公钥到这里"
#: users/forms.py:129 #: users/forms.py:131
msgid "Public key should not be the same as your old one." msgid "Public key should not be the same as your old one."
msgstr "不能和原来的密钥相同" msgstr "不能和原来的密钥相同"
#: users/forms.py:133 users/serializers.py:42 #: users/forms.py:135 users/serializers.py:42
msgid "Not a valid ssh public key" msgid "Not a valid ssh public key"
msgstr "ssh密钥不合法" msgstr "ssh密钥不合法"
#: users/forms.py:147 users/forms.py:152 users/forms.py:164 users/forms.py:194 #: users/forms.py:149 users/forms.py:154 users/forms.py:166 users/forms.py:196
msgid "Select users" msgid "Select users"
msgstr "选择用户" msgstr "选择用户"
...@@ -2146,13 +2173,6 @@ msgstr "应用程序" ...@@ -2146,13 +2173,6 @@ msgstr "应用程序"
msgid "Email" msgid "Email"
msgstr "邮件" msgstr "邮件"
#: users/models/user.py:38 users/templates/users/_select_user_modal.html:15
#: users/templates/users/user_detail.html:87
#: users/templates/users/user_list.html:25
#: users/templates/users/user_profile.html:55
msgid "Role"
msgstr "角色"
#: users/models/user.py:39 #: users/models/user.py:39
msgid "Avatar" msgid "Avatar"
msgstr "头像" msgstr "头像"
...@@ -2648,5 +2668,53 @@ msgstr "密码更新" ...@@ -2648,5 +2668,53 @@ msgstr "密码更新"
msgid "Public key update" msgid "Public key update"
msgstr "密钥更新" msgstr "密钥更新"
#~ msgid "Test node assets connective: {}"
#~ msgstr "测试节点资产可连接性"
#~ msgid ""
#~ "Admin user is a privilege user exist on this asset,Example: root or other "
#~ "NOPASSWD sudo privilege userIf asset not support ansible, set any one"
#~ msgstr ""
#~ "管理用户是资产上已经存在的特权用户,如 root或者其它有NOPASSWD的用户, 如果"
#~ "资产是Windows或交换机, 任意设置一个即可"
#~ msgid "Refresh node assets hardware info: {}"
#~ msgstr "更新一些资产硬件信息: {}"
#~ msgid "Update some assets hardware info"
#~ msgstr "更新一些资产硬件信息"
#~ msgid "Update asset hardware info"
#~ msgstr "更新资产硬件信息"
#~ msgid "Update assets hardware info period"
#~ msgstr "定期更新资产硬件信息"
#~ msgid "Test admin user connectability period: {}"
#~ msgstr "定期测试管理用户可连接性: {}"
#~ msgid "Test admin user connectability: {}"
#~ msgstr "测试管理用户可连接性: {}"
#, fuzzy
#~| msgid "Test asset connectability"
#~ msgid "Test assets connectability"
#~ msgstr "测试资产可连接性"
#~ msgid "Test system user connectability period: {}"
#~ msgstr "测试系统用户可连接性: {}"
#~ msgid "Push system user to node: {} => {}"
#~ msgstr "推送系统用户到节点: {}->{}"
#~ msgid "Push system users to node: {}"
#~ msgstr "推送系统用户到节点: {}"
#~ msgid "Coco ssh listen port"
#~ msgstr "SSH 监听端口"
#~ msgid "Coco http/ws listen port"
#~ msgstr "Http/Websocket 监听端口"
#~ msgid "Create asset permission " #~ msgid "Create asset permission "
#~ msgstr "创建资产权限" #~ msgstr "创建资产权限"
...@@ -27,7 +27,14 @@ sys.path.append(PROJECT_DIR) ...@@ -27,7 +27,14 @@ sys.path.append(PROJECT_DIR)
try: try:
from config import config as CONFIG from config import config as CONFIG
except ImportError: except ImportError:
CONFIG = type('_', (), {'__getattr__': lambda arg1, arg2: None})() msg = """
Error: No config file found.
You can run `cp config_example.py config.py`, and edit it.
"""
raise ImportError(msg)
# CONFIG = type('_', (), {'__getattr__': lambda arg1, arg2: None})()
# Quick-start development settings - unsuitable for production # Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.10/howto/deployment/checklist/ # See https://docs.djangoproject.com/en/1.10/howto/deployment/checklist/
...@@ -177,7 +184,7 @@ LOGGING = { ...@@ -177,7 +184,7 @@ LOGGING = {
'level': 'DEBUG', 'level': 'DEBUG',
'class': 'logging.FileHandler', 'class': 'logging.FileHandler',
'formatter': 'main', 'formatter': 'main',
'filename': os.path.join(CONFIG.LOG_DIR, 'jumpserver.log') 'filename': os.path.join(PROJECT_DIR, 'logs', 'jumpserver.log')
}, },
'ansible_logs': { 'ansible_logs': {
'level': 'DEBUG', 'level': 'DEBUG',
......
...@@ -234,7 +234,7 @@ class AdHoc(models.Model): ...@@ -234,7 +234,7 @@ class AdHoc(models.Model):
result = runner.run(self.tasks, self.pattern, self.task.name) result = runner.run(self.tasks, self.pattern, self.task.name)
return result.results_raw, result.results_summary return result.results_raw, result.results_summary
except AnsibleError as e: except AnsibleError as e:
logger.error("Failed run adhoc {}, {}".format(self.task.name, e)) logger.warn("Failed run adhoc {}, {}".format(self.task.name, e))
pass pass
@become.setter @become.setter
......
...@@ -112,9 +112,7 @@ $(document).ready(function() { ...@@ -112,9 +112,7 @@ $(document).ready(function() {
alert(data) alert(data)
}; };
var success = function () { var success = function () {
setTimeout(function () { alert("任务开始执行,重定向到任务详情页面,多刷新几次查看结果")
console.log("ok")
}, 1000);
window.location = "{% url 'ops:task-detail' pk=DEFAULT_PK %}".replace('{{ DEFAULT_PK }}', uid); window.location = "{% url 'ops:task-detail' pk=DEFAULT_PK %}".replace('{{ DEFAULT_PK }}', uid);
}; };
APIUpdateAttr({ APIUpdateAttr({
......
...@@ -432,4 +432,10 @@ div.dataTables_wrapper div.dataTables_filter { ...@@ -432,4 +432,10 @@ div.dataTables_wrapper div.dataTables_filter {
font-size: 12px !important; font-size: 12px !important;
} }
.ellipsis {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
...@@ -125,9 +125,9 @@ ...@@ -125,9 +125,9 @@
{% for data in week_asset_hot_ten %} {% for data in week_asset_hot_ten %}
<div class="timeline-item"> <div class="timeline-item">
<div class="row"> <div class="row">
<div class="col-xs-5 date"> <div class="col-xs-5 date ellipsis">
<i class="fa fa-info-circle"></i> <i class="fa fa-info-circle"></i>
<strong>{{ data.asset }}</strong> <strong data-toggle="tooltip" title="{{ data.asset }}">{{ data.asset }}</strong>
<br/> <br/>
<small class="text-navy">{{ data.total }}次</small> <small class="text-navy">{{ data.total }}次</small>
</div> </div>
...@@ -213,9 +213,9 @@ ...@@ -213,9 +213,9 @@
{% for data in week_user_hot_ten %} {% for data in week_user_hot_ten %}
<div class="timeline-item"> <div class="timeline-item">
<div class="row"> <div class="row">
<div class="col-xs-5 date"> <div class="col-xs-5 date ellipsis">
<i class="fa fa-info-circle"></i> <i class="fa fa-info-circle"></i>
<strong>{{ data.user }}</strong> <strong data-toggle="tooltip" title="{{ data.user }}">{{ data.user }}</strong>
<br/> <br/>
<small class="text-navy">{{ data.total }}次</small> <small class="text-navy">{{ data.total }}次</small>
</div> </div>
...@@ -245,7 +245,8 @@ $(document).ready(function(){ ...@@ -245,7 +245,8 @@ $(document).ready(function(){
$('#show').click(function(){ $('#show').click(function(){
$('#show').css('display', 'none'); $('#show').css('display', 'none');
$('#more').css('display', 'block'); $('#more').css('display', 'block');
}) });
$("[data-toggle='tooltip']").tooltip();
}); });
require.config({ require.config({
paths: { paths: {
......
...@@ -4,7 +4,6 @@ from collections import OrderedDict ...@@ -4,7 +4,6 @@ from collections import OrderedDict
import logging import logging
import os import os
import uuid import uuid
import boto3 # AWS S3 sdk
from django.core.cache import cache from django.core.cache import cache
from django.shortcuts import get_object_or_404, redirect from django.shortcuts import get_object_or_404, redirect
...@@ -13,6 +12,8 @@ from django.core.files.storage import default_storage ...@@ -13,6 +12,8 @@ from django.core.files.storage import default_storage
from django.http import HttpResponseNotFound from django.http import HttpResponseNotFound
from django.conf import settings from django.conf import settings
import jms_storage
from rest_framework import viewsets, serializers from rest_framework import viewsets, serializers
from rest_framework.views import APIView, Response from rest_framework.views import APIView, Response
from rest_framework.permissions import AllowAny from rest_framework.permissions import AllowAny
...@@ -282,36 +283,20 @@ class SessionReplayViewSet(viewsets.ViewSet): ...@@ -282,36 +283,20 @@ class SessionReplayViewSet(viewsets.ViewSet):
url = default_storage.url(path) url = default_storage.url(path)
return redirect(url) return redirect(url)
else: else:
config = settings.TERMINAL_REPLAY_STORAGE.items() configs = settings.TERMINAL_REPLAY_STORAGE.items()
if config: if not configs:
for name, value in config: return HttpResponseNotFound()
if value.get("TYPE", '') == "s3":
client, bucket = self.s3Client(value) for name, config in configs:
try: client = jms_storage.init(config)
date = self.session.date_start.strftime('%Y-%m-%d') date = self.session.date_start.strftime('%Y-%m-%d')
file_path = os.path.join(date, str(self.session.id) + '.replay.gz')
client.head_object(Bucket=bucket, target_path = default_storage.base_location + '/' + path
Key=os.path.join(date, str(self.session.id) + '.replay.gz'))
client.download_file(bucket, os.path.join(date, str(self.session.id) + '.replay.gz'), if client and client.has_file(file_path) and \
default_storage.base_location + '/' + path) client.download_file(file_path, target_path):
return redirect(default_storage.url(path)) return redirect(default_storage.url(path))
except: return HttpResponseNotFound()
pass
return HttpResponseNotFound()
def s3Client(self, config):
bucket = config.get("BUCKET", "jumpserver")
REGION = config.get("REGION", None)
ACCESS_KEY = config.get("ACCESS_KEY", None)
SECRET_KEY = config.get("SECRET_KEY", None)
if ACCESS_KEY and REGION and SECRET_KEY:
s3 = boto3.client('s3',
region_name=REGION,
aws_access_key_id=ACCESS_KEY,
aws_secret_access_key=SECRET_KEY)
else:
s3 = boto3.client('s3')
return s3, bucket
class TerminalConfig(APIView): class TerminalConfig(APIView):
......
...@@ -27,20 +27,20 @@ def get_all_replay_storage(): ...@@ -27,20 +27,20 @@ def get_all_replay_storage():
class TerminalForm(forms.ModelForm): class TerminalForm(forms.ModelForm):
command_storage = forms.ChoiceField( command_storage = forms.ChoiceField(
choices=get_all_command_storage(), choices=get_all_command_storage(),
label=_("Command storage") label=_("Command storage"),
help_text=_("Command can store in server db or ES, default to server, more see docs"),
) )
replay_storage = forms.ChoiceField( replay_storage = forms.ChoiceField(
choices=get_all_replay_storage(), choices=get_all_replay_storage(),
label=_("Replay storage") label=_("Replay storage"),
help_text=_("Replay file can store in server disk, AWS S3, Aliyun OSS, default to server, more see docs"),
) )
class Meta: class Meta:
model = Terminal model = Terminal
fields = [ fields = [
'name', 'remote_addr', 'ssh_port', 'http_port', 'comment', 'name', 'remote_addr', 'comment',
'command_storage', 'replay_storage', 'command_storage', 'replay_storage',
] ]
help_texts = { help_texts = {
'ssh_port': _("Coco ssh listen port"),
'http_port': _("Coco http/ws listen port"),
} }
...@@ -28,8 +28,8 @@ ...@@ -28,8 +28,8 @@
</th> </th>
<th class="text-center">{% trans 'Name' %}</th> <th class="text-center">{% trans 'Name' %}</th>
<th class="text-center">{% trans 'Addr' %}</th> <th class="text-center">{% trans 'Addr' %}</th>
<th class="text-center">{% trans 'SSH port' %}</th> {# <th class="text-center">{% trans 'SSH port' %}</th>#}
<th class="text-center">{% trans 'Http port' %}</th> {# <th class="text-center">{% trans 'Http port' %}</th>#}
<th class="text-center">{% trans 'Session' %}</th> <th class="text-center">{% trans 'Session' %}</th>
<th class="text-center">{% trans 'Active' %}</th> <th class="text-center">{% trans 'Active' %}</th>
<th class="text-center">{% trans 'Alive' %}</th> <th class="text-center">{% trans 'Alive' %}</th>
...@@ -53,21 +53,21 @@ function initTable() { ...@@ -53,21 +53,21 @@ function initTable() {
var detail_btn = '<a href="{% url "terminal:terminal-detail" pk=DEFAULT_PK %}">' + cellData + '</a>'; var detail_btn = '<a href="{% url "terminal:terminal-detail" pk=DEFAULT_PK %}">' + cellData + '</a>';
$(td).html(detail_btn.replace('{{ DEFAULT_PK }}', rowData.id)); $(td).html(detail_btn.replace('{{ DEFAULT_PK }}', rowData.id));
}}, }},
{targets: 6, createdCell: function (td, cellData) { {targets: 4, createdCell: function (td, cellData) {
if (!cellData) { if (!cellData) {
$(td).html('<i class="fa fa-times text-danger"></i>') $(td).html('<i class="fa fa-times text-danger"></i>')
} else { } else {
$(td).html('<i class="fa fa-check text-navy"></i>') $(td).html('<i class="fa fa-check text-navy"></i>')
} }
}}, }},
{targets: 7, createdCell: function (td, cellData) { {targets: 5, createdCell: function (td, cellData) {
if (!cellData) { if (!cellData) {
$(td).html('<i class="fa fa-circle text-danger"></i>') $(td).html('<i class="fa fa-circle text-danger"></i>')
} else { } else {
$(td).html('<i class="fa fa-circle text-navy"></i>') $(td).html('<i class="fa fa-circle text-navy"></i>')
} }
}}, }},
{targets: 8, createdCell: function (td, cellData, rowData) { {targets: 6, createdCell: function (td, cellData, rowData) {
var update_btn = '<a href="{% url "terminal:terminal-update" pk=DEFAULT_PK %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>' var update_btn = '<a href="{% url "terminal:terminal-update" pk=DEFAULT_PK %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'
.replace('{{ DEFAULT_PK }}', cellData); .replace('{{ DEFAULT_PK }}', cellData);
var delete_btn = '<a class="btn btn-xs btn-danger m-l-xs btn-del" data-id="{{ DEFAULT_PK }}" data-name="99991938">{% trans "Delete" %}</a>' var delete_btn = '<a class="btn btn-xs btn-danger m-l-xs btn-del" data-id="{{ DEFAULT_PK }}" data-name="99991938">{% trans "Delete" %}</a>'
...@@ -88,7 +88,7 @@ function initTable() { ...@@ -88,7 +88,7 @@ function initTable() {
}} }}
], ],
ajax_url: '{% url "api-terminal:terminal-list" %}', ajax_url: '{% url "api-terminal:terminal-list" %}',
columns: [{data: function(){return ""}}, {data: "name" }, {data: "remote_addr" }, {data: "ssh_port"}, {data: "http_port"}, columns: [{data: function(){return ""}}, {data: "name" }, {data: "remote_addr" },
{data: "session_online"}, {data: "is_active" }, {data: 'is_alive'}, {data: "id"}], {data: "session_online"}, {data: "is_active" }, {data: 'is_alive'}, {data: "id"}],
op_html: $('#actions').html() op_html: $('#actions').html()
}; };
......
...@@ -10,8 +10,8 @@ ...@@ -10,8 +10,8 @@
<p class="alert alert-danger" id="modal-error" style="display: none"></p> <p class="alert alert-danger" id="modal-error" style="display: none"></p>
{% bootstrap_field form.name layout="horizontal" %} {% bootstrap_field form.name layout="horizontal" %}
{% bootstrap_field form.remote_addr layout="horizontal" %} {% bootstrap_field form.remote_addr layout="horizontal" %}
{% bootstrap_field form.ssh_port layout="horizontal" %} {# {% bootstrap_field form.ssh_port layout="horizontal" %}#}
{% bootstrap_field form.http_port layout="horizontal" %} {# {% bootstrap_field form.http_port layout="horizontal" %}#}
{% bootstrap_field form.command_storage layout="horizontal" %} {% bootstrap_field form.command_storage layout="horizontal" %}
{% bootstrap_field form.replay_storage layout="horizontal" %} {% bootstrap_field form.replay_storage layout="horizontal" %}
{% bootstrap_field form.comment layout="horizontal" %} {% bootstrap_field form.comment layout="horizontal" %}
......
...@@ -33,8 +33,8 @@ ...@@ -33,8 +33,8 @@
<h3>{% trans 'Info' %}</h3> <h3>{% trans 'Info' %}</h3>
{% bootstrap_field form.name layout="horizontal" %} {% bootstrap_field form.name layout="horizontal" %}
{% bootstrap_field form.remote_addr layout="horizontal" %} {% bootstrap_field form.remote_addr layout="horizontal" %}
{% bootstrap_field form.ssh_port layout="horizontal" %} {# {% bootstrap_field form.ssh_port layout="horizontal" %}#}
{% bootstrap_field form.http_port layout="horizontal" %} {# {% bootstrap_field form.http_port layout="horizontal" %}#}
{% bootstrap_field form.command_storage layout="horizontal" %} {% bootstrap_field form.command_storage layout="horizontal" %}
{% bootstrap_field form.replay_storage layout="horizontal" %} {% bootstrap_field form.replay_storage layout="horizontal" %}
......
...@@ -180,15 +180,23 @@ class UserConnectionTokenApi(APIView): ...@@ -180,15 +180,23 @@ class UserConnectionTokenApi(APIView):
'asset': asset_id, 'asset': asset_id,
'system_user': system_user_id 'system_user': system_user_id
} }
cache.set(token, value, timeout=3600) cache.set(token, value, timeout=20)
return Response({"token": token}, status=201) return Response({"token": token}, status=201)
def get(self, request): def get(self, request):
token = request.query_params.get('token') token = request.query_params.get('token')
user_only = request.query_params.get('user-only', None)
value = cache.get(token, None) value = cache.get(token, None)
if value:
cache.delete(token)
return Response(value)
if not value:
return Response('', status=404)
if not user_only:
return Response(value)
else:
return Response({'user': value['user']})
def get_permissions(self):
if self.request.query_params.get('user-only', None):
self.permission_classes = (AllowAny,)
return super().get_permissions()
...@@ -20,10 +20,12 @@ class UserLoginForm(AuthenticationForm): ...@@ -20,10 +20,12 @@ class UserLoginForm(AuthenticationForm):
class UserCreateUpdateForm(forms.ModelForm): class UserCreateUpdateForm(forms.ModelForm):
role_choices = ((i, n) for i, n in User.ROLE_CHOICES if i != User.ROLE_APP)
password = forms.CharField( password = forms.CharField(
label=_('Password'), widget=forms.PasswordInput, label=_('Password'), widget=forms.PasswordInput,
max_length=128, strip=False, required=False, max_length=128, strip=False, required=False,
) )
role = forms.ChoiceField(choices=role_choices, required=True, initial=User.ROLE_USER, label=_("Role"))
class Meta: class Meta:
model = User model = User
......
...@@ -4,14 +4,17 @@ ...@@ -4,14 +4,17 @@
商业支持 商业支持
~~~~~~~~~~~ ~~~~~~~~~~~
https://market.aliyun.com/products/53690006/cmgj026011.html `阿里云市场购买: <https://market.aliyun.com/products/53690006/cmgj026011.html>`_
QQ群
QQ 群
~~~~~~~~ ~~~~~~~~
群1: 390139816 群1: 390139816 (推荐)
群2: 399218702
群3: 552054376 群2: 399218702 (满)
群3: 552054376 (满)
Github Github
...@@ -29,10 +32,10 @@ http://www.jumpserver.org ...@@ -29,10 +32,10 @@ http://www.jumpserver.org
Demo Demo
~~~~~~~~ ~~~~~~~~
http://demo.jumpserver.org:8080 http://demo.jumpserver.org
邮件 邮件
~~~~~~~~ ~~~~~~~~
ibuler#fit2cloud.com (#替换为@) support@fit2cloud.com (#替换为@)
\ No newline at end of file \ No newline at end of file
FAQ FAQ
+++++++++++++++++++++ ==========
\ No newline at end of file
1. Windows 无法连接
::
(1). 如果白屏 可能是nginx设置的不对,也可能运行guacamole的docker容器有问题,总之请求到不了guacamole
(2). 如果显示没有权限 可能是你在 终端管理里没有接受 guacamole的注册,请接受一下,如果还是不行,就删除刚才的注册,重启guacamole的docker重新注册
(3). 如果显示未知问题 可能是你的资产填写的端口不对,或者授权的系统用户的协议不是rdp
2. 用户、系统用户、管理用户的关系
::
用户:每个公司的同事创建一个用户账号,用来登录Jumpserver
系统用户:使用来登录到服务器的用户,如 web, dba, root等
管理用户:是服务器上已存在的特权用户,Ansible用来获取硬件信息, 如 root, 或者其它拥有 sudo NOPASSWD: ALL权限的用户
...@@ -19,3 +19,4 @@ Jumpserver 文档 ...@@ -19,3 +19,4 @@ Jumpserver 文档
contributor contributor
contact contact
snapshot snapshot
faq
简介
============
Jumpserver是混合云下更好用的堡垒机, 分布式架构设计无限扩展,轻松对接混合云资产,支持使用云存储(AWS S3, ES等)存储录像、命令
Jumpserver颠覆传统堡垒机, 无主机和并发数量限制,支持水平扩容,FIT2CLOUD提供完备的商业服务支持,用户无后顾之忧
Jumpserver拥有极致的用户体验, 极致UI体验,容器化的部署方式,部署过程方便快捷,可持续升级
组件说明
++++++++++++++++++++++++
Jumpserver
```````````
现指Jumpserver管理后台,是核心组件(Core), 使用 Django Class Based View 风格开发,支持Restful API。
`Github <https://github.com/jumpserver/jumpserver.git>`_
Coco
````````
实现了SSH Server 和 Web Terminal Server的组件,提供ssh和websocket接口, 使用 Paramiko 和 Flask 开发。
`Github <https://github.com/jumpserver/coco.git>`__
Luna
````````
现在是Web Terminal前端,计划前端页面都由该项目提供,Jumpserver只提供API,不再负责后台渲染html等。
`Github <https://github.com/jumpserver/luna.git>`__
Guacamole
```````````
Apache 跳板机项目,Jumpserver使用其组件实现RDP功能,Jumpserver并没有修改其代码而是添加了额外的插件,支持Jumpserver调用
Jumpserver-python-sdk
```````````````````````
Jumpserver API Python SDK,Coco目前使用该SDK与Jumpserver API交互
`Github <https://github.com/jumpserver/jumpserver-python-sdk.git>`__
组件架构图
++++++++++++++++++++++++
.. image:: _static/img/structure.png
:alt: 组件架构图
快速安装 快速安装
========================== ==========================
Jumpserver 封装了一个 All in one Docker,可以快速启动。该镜像集成了所有需要的组件,可以使用外置 Database 和 Redis Jumpserver 封装了一个 All in one Docker,可以快速启动。该镜像集成了所需要的组件(Windows组件未暂未集成),也支持使用外置 Database 和 Redis
Tips: 不建议在生产中使用 Tips: 不建议在生产中使用, 生产中请使用 详细安装 `详细安装 <https://docs.docker.com/install/>`_
Docker 安装见: `Docker官方安装文档 <https://docs.docker.com/install/>`_ Docker 安装见: `Docker官方安装文档 <https://docs.docker.com/install/>`_
...@@ -18,9 +18,12 @@ Docker 安装见: `Docker官方安装文档 <https://docs.docker.com/install/>`_ ...@@ -18,9 +18,12 @@ Docker 安装见: `Docker官方安装文档 <https://docs.docker.com/install/>`_
访问 访问
``````````````` ```````````````
浏览器访问: http://localhost:8080 浏览器访问: http://<容器所在服务器IP>:8080
SSH访问: ssh -p 2222 <容器所在服务器IP>
XShell等工具请添加connection连接
SSH访问: ssh -p 2222 localhost
额外环境变量 额外环境变量
...@@ -33,9 +36,9 @@ SSH访问: ssh -p 2222 localhost ...@@ -33,9 +36,9 @@ SSH访问: ssh -p 2222 localhost
- DB_PASSWORD = xxxx - DB_PASSWORD = xxxx
- DB_NAME = jumpserver - DB_NAME = jumpserver
- REDIS_HOST = '' - REDIS_HOST = <redis-host>
- REDIS_PORT = '' - REDIS_PORT = <redis-port>
- REDIS_PASSWORD = '' - REDIS_PASSWORD = <
:: ::
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
:: ::
$ yum -y install wget sqlite-devel xz gcc automake zlib-devel openssl-devel epel-release $ yum -y install wget sqlite-devel xz gcc automake zlib-devel openssl-devel epel-release git
**1.2 编译安装** **1.2 编译安装**
...@@ -222,22 +222,33 @@ Luna 已改为纯前端,需要 Nginx 来运行访问 ...@@ -222,22 +222,33 @@ Luna 已改为纯前端,需要 Nginx 来运行访问
.. code:: shell .. code:: shell
# 注意:这里一定要改写一下本机的IP地址, 否则会出错
docker run -d \ docker run -d \
-p 8081:8080 \ -p 8081:8080 -v /opt/guacamole/key:/config/guacamole/key \
-e JUMPSERVER_KEY_DIR=/config/guacamole/key \
-e JUMPSERVER_SERVER=http://<填写本机的IP地址>:8080 \ -e JUMPSERVER_SERVER=http://<填写本机的IP地址>:8080 \
registry.jumpserver.org/public/guacamole:latest registry.jumpserver.org/public/guacamole:latest
这里所需要注意的是 guacamole 暴露出来的端口是 8081,若与主机上其他端口冲突请自定义一下。 这里所需要注意的是 guacamole 暴露出来的端口是 8081,若与主机上其他端口冲突请自定义一下。
修改 JUMPSERVER SERVER 的配置,填上 Jumpserver 的内网地址 再次强调:修改 JUMPSERVER_SERVER 环境变量的配置,填上 Jumpserver 的内网地址, 这时
去 Jumpserver-会话管理-终端管理 接受[Gua]开头的一个注册
六. 配置 Nginx 整合各组件 六. 配置 Nginx 整合各组件
~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~
6.1 安装 Nginx 根据喜好选择安装方式和版本 6.1 安装 Nginx 根据喜好选择安装方式和版本
6.2 配置文件 .. code:: shell
yum -y install nginx
6.2 准备配置文件 修改 /etc/nginx/nginx.conf
:: ::
...@@ -287,4 +298,10 @@ Luna 已改为纯前端,需要 Nginx 来运行访问 ...@@ -287,4 +298,10 @@ Luna 已改为纯前端,需要 Nginx 来运行访问
6.3 运行 Nginx 6.3 运行 Nginx
::
nginx -t
service nginx start
6.4 访问 http://192.168.244.144 6.4 访问 http://192.168.244.144
...@@ -61,6 +61,7 @@ pytz==2017.3 ...@@ -61,6 +61,7 @@ pytz==2017.3
PyYAML==3.12 PyYAML==3.12
redis==2.10.6 redis==2.10.6
requests==2.18.4 requests==2.18.4
jms-storage==0.0.13
s3transfer==0.1.13 s3transfer==0.1.13
simplejson==3.13.2 simplejson==3.13.2
six==1.11.0 six==1.11.0
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment