Merge pull request #3283 from jumpserver/dev

Dev
pull/3299/head
老广 2019-09-25 17:23:00 +08:00 committed by GitHub
commit 91f64eccda
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 79 additions and 56 deletions

View File

@ -14,6 +14,10 @@ __all__ = [
'AssetCreateForm', 'AssetUpdateForm', 'AssetBulkUpdateForm', 'ProtocolForm',
]
HELP_TEXTS_ASSET_HOSTNAME = _(
'Only Numbers、letters、 chinese and characters ( {} ) are allowed'
).format(" ".join(['.', '_', '@']))
class ProtocolForm(forms.Form):
name = forms.ChoiceField(
@ -68,8 +72,7 @@ class AssetCreateForm(OrgModelForm):
'nodes': _("Node"),
}
help_texts = {
'hostname': _('Only Numbers, letters, and characters ( {} ) '
'are allowed').format(" ".join(['.', '_', '@'])),
'hostname': HELP_TEXTS_ASSET_HOSTNAME,
'admin_user': _(
'root or other NOPASSWD sudo privilege user existed in asset,'
'If asset is windows or other set any one, more see admin user left menu'
@ -116,8 +119,7 @@ class AssetUpdateForm(OrgModelForm):
'nodes': _("Node"),
}
help_texts = {
'hostname': _('Only Numbers, letters, and characters ( {} ) '
'are allowed').format(" ".join(['.', '_', '@'])),
'hostname': HELP_TEXTS_ASSET_HOSTNAME,
'admin_user': _(
'root or other NOPASSWD sudo privilege user existed in asset,'
'If asset is windows or other set any one, more see admin user left menu'

View File

@ -257,10 +257,6 @@ class NodeAssetsMixin:
@lazyproperty
def assets_amount(self):
"""
获取节点下所有资产数量速度太慢所以需要重写使用cache等方案
:return:
"""
amount = self.tree().assets_amount(self.key)
return amount

View File

@ -94,7 +94,7 @@ class AssetSerializer(BulkOrgResourceModelSerializer):
@staticmethod
def validate_hostname(hostname):
pattern = r"^[\._@a-zA-Z0-9-]+$"
pattern = r"^[\._@\w-]+$"
res = re.match(pattern, hostname)
if res is None:
msg = _("* The hostname contains characters that are not allowed")

View File

@ -26,10 +26,6 @@ def get_system_user_by_id(id):
class TreeService(Tree):
tag_sep = ' / '
cache_key = '_NODE_FULL_TREE'
cache_time = 3600
has_empty_node = False
has_ungrouped_node = False
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@ -43,13 +39,17 @@ class TreeService(Tree):
from orgs.utils import tmp_to_root_org
with tmp_to_root_org():
all_nodes = Node.objects.all()
all_nodes = list(Node.objects.all().values("key", "value"))
all_nodes.sort(key=lambda x: len(x["key"].split(":")))
tree = cls()
tree.create_node(tag='', identifier='')
for node in all_nodes:
key = node["key"]
value = node["value"]
parent_key = ":".join(key.split(":")[:-1])
tree.create_node(
tag=node.value, identifier=node.key,
parent=node.parent_key,
tag=value, identifier=key,
parent=parent_key,
)
tree.init_assets()
return tree

View File

@ -36,3 +36,4 @@ class SessionAuditSerializer(serializers.ModelSerializer):
class Meta:
model = Session
fields = '__all__'

View File

@ -9,7 +9,8 @@ from rest_framework.renderers import JSONRenderer
from jumpserver.utils import current_request
from common.utils import get_request_ip, get_logger, get_syslogger
from users.models import User
from terminal.models import Session
from terminal.models import Session, Command
from terminal.backends.command.serializers import SessionCommandSerializer
from . import models
from . import serializers
@ -88,6 +89,9 @@ def on_audits_log_create(sender, instance=None, **kwargs):
elif sender == Session:
category = "host_session_log"
serializer = serializers.SessionAuditSerializer
elif sender == Command:
category = "session_command_log"
serializer = SessionCommandSerializer
else:
return

View File

@ -225,4 +225,4 @@ class lazyproperty:
else:
value = self.func(instance)
setattr(instance, self.func.__name__, value)
return value
return value

View File

@ -286,7 +286,7 @@ LOGGING = {
'handlers': ['console', 'file'],
'level': "INFO",
},
'jms_audits': {
'jms.audits': {
'handlers': ['syslog'],
'level': 'INFO'
},

View File

@ -190,7 +190,7 @@ class IndexView(PermissionsMixin, TemplateView):
class LunaView(View):
def get(self, request):
msg = _("<div>Luna is a separately deployed program, you need to deploy Luna, coco, configure nginx for url distribution,</div> "
msg = _("<div>Luna is a separately deployed program, you need to deploy Luna, koko, configure nginx for url distribution,</div> "
"</div>If you see this page, prove that you are not accessing the nginx listening port. Good luck.</div>")
return HttpResponse(msg)

Binary file not shown.

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Jumpserver 0.3.3\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-09-24 11:11+0800\n"
"POT-Creation-Date: 2019-09-25 15:11+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: ibuler <ibuler@qq.com>\n"
"Language-Team: Jumpserver team<ibuler@qq.com>\n"
@ -112,7 +112,7 @@ msgstr "资产"
#: applications/templates/applications/remote_app_detail.html:53
#: applications/templates/applications/remote_app_list.html:20
#: applications/templates/applications/user_remote_app_list.html:16
#: assets/forms/asset.py:20 assets/forms/domain.py:73 assets/forms/user.py:74
#: assets/forms/asset.py:24 assets/forms/domain.py:73 assets/forms/user.py:74
#: assets/forms/user.py:94 assets/models/base.py:28 assets/models/cluster.py:18
#: assets/models/cmd_filter.py:20 assets/models/domain.py:20
#: assets/models/group.py:20 assets/models/label.py:18
@ -576,14 +576,18 @@ msgstr "更新节点资产硬件信息: {}"
msgid "Test if the assets under the node are connectable: {}"
msgstr "测试节点下资产是否可连接: {}"
#: assets/forms/asset.py:24 assets/models/asset.py:140
#: assets/forms/asset.py:18
msgid "Only Numbers、letters、 chinese and characters ( {} ) are allowed"
msgstr "只允许包含数字、字母、中文和特殊字符( {} "
#: assets/forms/asset.py:28 assets/models/asset.py:140
#: assets/models/domain.py:50
#: assets/templates/assets/domain_gateway_list.html:69
#: settings/templates/settings/replay_storage_create.html:59
msgid "Port"
msgstr "端口"
#: assets/forms/asset.py:55 assets/models/asset.py:145
#: assets/forms/asset.py:59 assets/models/asset.py:145
#: assets/models/user.py:110 assets/templates/assets/asset_detail.html:190
#: assets/templates/assets/asset_detail.html:198
#: assets/templates/assets/system_user_assets.html:83
@ -594,7 +598,7 @@ msgstr "端口"
msgid "Nodes"
msgstr "节点"
#: assets/forms/asset.py:58 assets/forms/asset.py:106
#: assets/forms/asset.py:62 assets/forms/asset.py:109
#: assets/models/asset.py:149 assets/models/cluster.py:19
#: assets/models/user.py:68 assets/templates/assets/asset_detail.html:76
#: templates/_nav.html:44 xpack/plugins/cloud/models.py:161
@ -603,7 +607,7 @@ msgstr "节点"
msgid "Admin user"
msgstr "管理用户"
#: assets/forms/asset.py:61 assets/forms/asset.py:109 assets/forms/asset.py:150
#: assets/forms/asset.py:65 assets/forms/asset.py:112 assets/forms/asset.py:152
#: assets/templates/assets/asset_create.html:48
#: assets/templates/assets/asset_create.html:50
#: assets/templates/assets/asset_list.html:85
@ -611,7 +615,7 @@ msgstr "管理用户"
msgid "Label"
msgstr "标签"
#: assets/forms/asset.py:64 assets/forms/asset.py:112
#: assets/forms/asset.py:68 assets/forms/asset.py:115
#: assets/models/asset.py:144 assets/models/domain.py:26
#: assets/models/domain.py:52 assets/templates/assets/asset_detail.html:80
#: assets/templates/assets/user_asset_list.html:53
@ -619,8 +623,8 @@ msgstr "标签"
msgid "Domain"
msgstr "网域"
#: assets/forms/asset.py:68 assets/forms/asset.py:103 assets/forms/asset.py:116
#: assets/forms/asset.py:153 assets/models/node.py:403
#: assets/forms/asset.py:72 assets/forms/asset.py:106 assets/forms/asset.py:119
#: assets/forms/asset.py:155 assets/models/node.py:413
#: assets/templates/assets/asset_create.html:42
#: perms/forms/asset_permission.py:82 perms/forms/asset_permission.py:89
#: perms/templates/perms/asset_permission_list.html:53
@ -635,11 +639,7 @@ msgstr "网域"
msgid "Node"
msgstr "节点"
#: assets/forms/asset.py:71 assets/forms/asset.py:119
msgid "Only Numbers, letters, and characters ( {} ) are allowed"
msgstr "只允许包含数字,字母,特殊字符( {} "
#: assets/forms/asset.py:74 assets/forms/asset.py:122
#: assets/forms/asset.py:77 assets/forms/asset.py:124
msgid ""
"root or other NOPASSWD sudo privilege user existed in asset,If asset is "
"windows or other set any one, more see admin user left menu"
@ -647,16 +647,16 @@ msgstr ""
"root或其他拥有NOPASSWD: ALL权限的用户, 如果是windows或其它硬件可以随意设置一"
"个, 更多信息查看左侧 `管理用户` 菜单"
#: assets/forms/asset.py:77 assets/forms/asset.py:125
#: assets/forms/asset.py:80 assets/forms/asset.py:127
msgid "Windows 2016 RDP protocol is different, If is window 2016, set it"
msgstr "Windows 2016的RDP协议与之前不同如果是请设置"
#: assets/forms/asset.py:78 assets/forms/asset.py:126
#: assets/forms/asset.py:81 assets/forms/asset.py:128
msgid ""
"If your have some network not connect with each other, you can set domain"
msgstr "如果有多个的互相隔离的网络,设置资产属于的网域,使用网域网关跳转登录"
#: assets/forms/asset.py:133 assets/forms/asset.py:137
#: assets/forms/asset.py:135 assets/forms/asset.py:139
#: assets/forms/domain.py:17 assets/forms/label.py:15
#: perms/templates/perms/asset_permission_asset.html:78
#: xpack/plugins/change_auth_plan/forms.py:55
@ -1107,7 +1107,7 @@ msgstr "默认资产组"
msgid "User"
msgstr "用户"
#: assets/models/label.py:19 assets/models/node.py:394
#: assets/models/label.py:19 assets/models/node.py:404
#: assets/templates/assets/label_list.html:15 settings/models.py:30
msgid "Value"
msgstr "值"
@ -1116,19 +1116,19 @@ msgstr "值"
msgid "Category"
msgstr "分类"
#: assets/models/node.py:230
#: assets/models/node.py:163
msgid "New node"
msgstr "新节点"
#: assets/models/node.py:318
#: assets/models/node.py:328
msgid "ungrouped"
msgstr "未分组"
#: assets/models/node.py:320
#: assets/models/node.py:330
msgid "empty"
msgstr "空"
#: assets/models/node.py:393
#: assets/models/node.py:403
msgid "Key"
msgstr "键"
@ -1182,7 +1182,7 @@ msgstr "Shell"
msgid "Login mode"
msgstr "登录模式"
#: assets/models/user.py:168 assets/templates/assets/user_asset_list.html:52
#: assets/models/user.py:162 assets/templates/assets/user_asset_list.html:52
#: audits/models.py:20 audits/templates/audits/ftp_log_list.html:52
#: audits/templates/audits/ftp_log_list.html:75
#: perms/forms/asset_permission.py:85 perms/forms/remote_app_permission.py:40
@ -2733,13 +2733,12 @@ msgstr "仪表盘"
#: jumpserver/views.py:193
msgid ""
"<div>Luna is a separately deployed program, you need to deploy Luna, coco, "
"<div>Luna is a separately deployed program, you need to deploy Luna, koko, "
"configure nginx for url distribution,</div> </div>If you see this page, "
"prove that you are not accessing the nginx listening port. Good luck.</div>"
msgstr ""
"<div>Luna是单独部署的一个程序你需要部署lunacoco配置nginx做url分发, </"
"div><div>如果你看到了这个页面证明你访问的不是nginx监听的端口祝你好运</"
"div>"
"<div>Luna是单独部署的一个程序你需要部署lunakoko, </div><div>如果你看到了"
"这个页面证明你访问的不是nginx监听的端口祝你好运</div>"
#: ops/api/celery.py:54
msgid "Waiting task start"
@ -3916,7 +3915,7 @@ msgstr "您确定删除吗?"
msgid "Search no entry matched in ou {}"
msgstr "在ou:{}中没有匹配条目"
#: settings/utils.py:120
#: settings/utils.py:122
msgid "The user source is not LDAP"
msgstr "用户来源不是LDAP"

View File

@ -15,7 +15,7 @@ logger = get_logger(__file__)
class JMSBaseInventory(BaseInventory):
windows_ssh_default_ssh = settings.WINDOWS_SSH_DEFAULT_SHELL
windows_ssh_default_shell = settings.WINDOWS_SSH_DEFAULT_SHELL
def convert_to_ansible(self, asset, run_as_admin=False):
info = {
@ -35,7 +35,7 @@ class JMSBaseInventory(BaseInventory):
if asset.is_windows():
info["vars"].update({
"ansible_connection": "ssh",
"ansible_shell_type": self.windows_ssh_default_ssh,
"ansible_shell_type": self.windows_ssh_default_shell,
})
for label in asset.labels.all():
info["vars"].update({

View File

@ -36,7 +36,7 @@ class UserNodeTreeMixin:
assets_amount = self.tree.assets_amount(node.key)
if assets_amount == 0 and node.key != Node.empty_key:
continue
node._assets_amount = assets_amount
node.assets_amount = assets_amount
data = ParserNode.parse_node_to_tree_node(node)
_queryset.append(data)
return _queryset

View File

@ -93,6 +93,8 @@ class LDAPUtil:
user_item = self._ldap_entry_to_user_item(entry)
user = self.get_user_by_username(user_item['username'])
user_item['existing'] = bool(user)
if user_item in user_items:
continue
user_items.append(user_item)
return user_items

View File

@ -26,7 +26,7 @@ logger = get_logger(__name__)
class SessionViewSet(OrgBulkModelViewSet):
queryset = Session.objects.all()
serializer_class = serializers.SessionSerializer
permission_classes = (IsOrgAdminOrAppUser | IsOrgAuditor, )
permission_classes = (IsOrgAdminOrAppUser, )
filter_fields = [
"user", "asset", "system_user", "remote_addr",
"protocol", "terminal", "is_finished",
@ -53,6 +53,11 @@ class SessionViewSet(OrgBulkModelViewSet):
serializer.validated_data["system_user"] = _system_user.name
return super().perform_create(serializer)
def get_permissions(self):
if self.request.method.lower() in ['get']:
self.permission_classes = (IsOrgAdminOrAppUser | IsOrgAuditor, )
return super().get_permissions()
class SessionReplayViewSet(viewsets.ViewSet):
serializer_class = serializers.ReplaySerializer

View File

@ -4,6 +4,7 @@ import os
import uuid
from django.db import models
from django.db.models.signals import post_save
from django.utils.translation import ugettext_lazy as _
from django.utils import timezone
from django.conf import settings
@ -267,7 +268,16 @@ class Task(models.Model):
db_table = "terminal_task"
class CommandManager(models.Manager):
def bulk_create(self, objs, **kwargs):
resp = super().bulk_create(objs, **kwargs)
for i in objs:
post_save.send(i.__class__, instance=i, created=True)
return resp
class Command(AbstractSessionCommand):
objects = CommandManager()
class Meta:
db_table = "terminal_command"

View File

@ -41,7 +41,7 @@
</table>
<div id="actions" class="hide">
{% if type == "online" %}
{% if type == "online" and request.user.can_admin_current_org %}
<div class="input-group">
<select class="form-control m-b" style="width: auto" id="slct_bulk_update">
<option value="terminate">{% trans 'Terminate selected' %}</option>
@ -140,7 +140,7 @@ function initTable() {
replayBtn = replayBtn.replace("disabled", "")
}
var termBtn = '<a class="btn btn-xs btn-danger btn-term" disabled value="sessionID" terminal="terminalID" >{% trans "Terminate" %}</a>';
if ("{{ request.user.is_org_admin }}" === "True") {
if ("{{ request.user.can_admin_current_org }}" === "True") {
termBtn = termBtn.replace("disabled", "")
.replace("sessionID", cellData)
.replace("terminalID", rowData.terminal)

View File

@ -135,4 +135,4 @@ class WebTerminalView(View):
class WebSFTPView(View):
def get(self, request, *args, **kwargs):
return redirect('/coco/elfinder/sftp/?' + request.GET.urlencode())
return redirect('/koko/elfinder/sftp/?' + request.GET.urlencode())

6
jms
View File

@ -205,6 +205,10 @@ def parse_service(s):
]
if s == 'all':
return all_services
elif s == "web":
return ['gunicorn', 'flower']
elif s == "task":
return ["celery_ansible", "celery_default", "beat"]
elif s == 'gunicorn':
return ['gunicorn', 'flower']
elif s == "celery":
@ -474,7 +478,7 @@ if __name__ == '__main__':
)
parser.add_argument(
"service", type=str, default="all", nargs="?",
choices=("all", "gunicorn", "celery", "beat", "celery,beat", "flower"),
choices=("all", "web", "task", "gunicorn", "celery", "beat", "celery,beat", "flower"),
help="The service to start",
)
parser.add_argument('-d', '--daemon', nargs="?", const=1)