perf: 连接方式新增 guide 模式 (#11237)

Co-authored-by: ibuler <ibuler@qq.com>
pull/11240/head
fit2bot 2023-08-09 22:59:53 +08:00 committed by GitHub
parent dcf113b87c
commit 4b72099053
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 62 additions and 73 deletions

View File

@ -221,8 +221,11 @@ class Asset(NodesRelationMixin, AbsConnectivity, JSONFilterMixin, JMSOrgBaseMode
return self.address return self.address
def get_target_ssh_port(self): def get_target_ssh_port(self):
protocol = self.protocols.all().filter(name='ssh').first() return self.get_protocol_port('ssh')
return protocol.port if protocol else 22
def get_protocol_port(self, protocol):
protocol = self.protocols.all().filter(name=protocol).first()
return protocol.port if protocol else 0
@property @property
def is_valid(self): def is_valid(self):

View File

@ -126,12 +126,16 @@ class RDPFileClientProtocolURLMixin:
return filename, content return filename, content
@staticmethod @staticmethod
def get_connect_filename(prefix_name): def escape_name(name):
prefix_name = prefix_name.replace('/', '_') name = name.replace('/', '_')
prefix_name = prefix_name.replace('\\', '_') name = name.replace('\\', '_')
prefix_name = prefix_name.replace('.', '_') name = name.replace('.', '_')
name = urllib.parse.quote(name)
return name
def get_connect_filename(self, prefix_name):
filename = f'{prefix_name}-jumpserver' filename = f'{prefix_name}-jumpserver'
filename = urllib.parse.quote(filename) filename = self.escape_name(filename)
return filename return filename
@staticmethod @staticmethod
@ -145,28 +149,29 @@ class RDPFileClientProtocolURLMixin:
connect_method_dict = ConnectMethodUtil.get_connect_method( connect_method_dict = ConnectMethodUtil.get_connect_method(
token.connect_method, token.protocol, _os token.connect_method, token.protocol, _os
) )
asset = token.asset
if connect_method_dict is None: if connect_method_dict is None:
raise ValueError('Connect method not support: {}'.format(connect_method_name)) raise ValueError('Connect method not support: {}'.format(connect_method_name))
endpoint = self.get_smart_endpoint( account = token.account or token.input_username
protocol=connect_method_dict['endpoint_protocol'], datetime = timezone.localtime(timezone.now()).strftime('%Y-%m-%d_%H:%M:%S')
asset=token.asset name = account + '@' + str(asset) + '[' + datetime + ']'
)
data = { data = {
'id': str(token.id), 'version': 2,
'name': f'{endpoint.host}-{str(token.id)[:18]}', 'id': str(token.id), # 兼容老的,未来几个版本删掉
'value': token.value, # 兼容老的,未来几个版本删掉
'name': self.escape_name(name),
'protocol': token.protocol, 'protocol': token.protocol,
'host': endpoint.host, 'token': {
'port': endpoint.get_port(token.asset, token.protocol), 'id': str(token.id),
'username': f'JMS-{str(token.id)}',
'value': token.value, 'value': token.value,
'command': '', },
'file': {} 'file': {},
'command': ''
} }
if connect_method_name == NativeClient.mstsc or connect_method_dict['type'] == 'applet': if connect_method_name == NativeClient.mstsc or connect_method_dict['type'] == 'applet':
filename, content = self.get_rdp_file_info(token) filename, content = self.get_rdp_file_info(token)
filename = urllib.parse.unquote(filename)
data.update({ data.update({
'protocol': 'rdp', 'protocol': 'rdp',
'file': { 'file': {
@ -175,8 +180,26 @@ class RDPFileClientProtocolURLMixin:
} }
}) })
else: else:
cmd = NativeClient.get_launch_command(connect_method_name, token, endpoint) endpoint = self.get_smart_endpoint(
data.update({'command': cmd}) protocol=connect_method_dict['endpoint_protocol'],
asset=asset
)
data.update({
'asset': {
'id': str(asset.id),
'category': asset.category,
'type': asset.type,
'name': asset.name,
'address': asset.address,
'info': {
**asset.spec_info,
}
},
'endpoint': {
'host': endpoint.host,
'port': endpoint.get_port(token.asset, token.protocol),
}
})
return data return data
def get_smart_endpoint(self, protocol, asset=None): def get_smart_endpoint(self, protocol, asset=None):

View File

@ -1,18 +1,10 @@
from ..hands import *
from .base import BaseService from .base import BaseService
from ..hands import *
__all__ = ['FlowerService'] __all__ = ['FlowerService']
class FlowerService(BaseService): class FlowerService(BaseService):
def __init__(self, **kwargs):
super().__init__(**kwargs)
@property
def db_file(self):
return os.path.join(BASE_DIR, 'data', 'flower.db')
@property @property
def cmd(self): def cmd(self):
print("\n- Start Flower as Task Monitor") print("\n- Start Flower as Task Monitor")
@ -24,11 +16,9 @@ class FlowerService(BaseService):
'-A', 'ops', '-A', 'ops',
'flower', 'flower',
'-logging=info', '-logging=info',
'-db={}'.format(self.db_file),
'--url_prefix=/core/flower', '--url_prefix=/core/flower',
'--auto_refresh=False', '--auto_refresh=False',
'--max_tasks=1000', '--max_tasks=1000',
'--persistent=True',
'--state_save_interval=600000' '--state_save_interval=600000'
] ]
return cmd return cmd

View File

@ -26,34 +26,29 @@ class WebMethod(TextChoices):
class NativeClient(TextChoices): class NativeClient(TextChoices):
# Koko # Koko
ssh = 'ssh', 'SSH CLI' ssh_client = 'ssh_client', _('SSH Client')
sftp = 'sftp', 'SFTP CLI' ssh_guide = 'ssh_guide', _('SSH Guide')
putty = 'putty', 'PuTTY' sftp_client = 'sftp_client', _('SFTP Client')
xshell = 'xshell', 'Xshell'
# Magnus # Magnus
db_guide = 'db_guide', _('DB Guide')
db_client = 'db_client', _('DB Client') db_client = 'db_client', _('DB Client')
# Razor # Razor
mstsc = 'mstsc', 'Remote Desktop' mstsc = 'mstsc', _('Remote Desktop')
@classmethod @classmethod
def get_native_clients(cls): def get_native_clients(cls):
# native client 关注的是 endpoint 的 protocol, # native client 关注的是 endpoint 的 protocol,
# 比如 telnet mysql, koko 都支持,到那时暴露的是 ssh 协议 # 比如 telnet mysql, koko 都支持,到那时暴露的是 ssh 协议
clients = { clients = {
Protocol.ssh: { Protocol.ssh: [cls.ssh_client, cls.ssh_guide],
'default': [cls.ssh], Protocol.sftp: [cls.sftp_client],
'windows': [cls.putty],
},
Protocol.sftp: [cls.sftp],
Protocol.rdp: [cls.mstsc], Protocol.rdp: [cls.mstsc],
Protocol.mysql: [cls.db_client], Protocol.mysql: [cls.db_client, cls.db_guide],
Protocol.mariadb: [cls.db_client], Protocol.mariadb: [cls.db_client, cls.db_guide],
Protocol.redis: [cls.db_client], Protocol.redis: [cls.db_client, cls.db_guide],
Protocol.mongodb: [cls.db_client], Protocol.mongodb: [cls.db_client, cls.db_guide],
Protocol.oracle: [cls.db_client], Protocol.oracle: [cls.db_client, cls.db_guide],
Protocol.postgresql: [cls.db_client], Protocol.postgresql: [cls.db_client, cls.db_guide],
} }
return clients return clients
@ -97,28 +92,6 @@ class NativeClient(TextChoices):
}) })
return methods return methods
@classmethod
def get_launch_command(cls, name, token, endpoint, os='windows'):
username = f'JMS-{token.id}'
commands = {
cls.ssh: f'ssh {username}@{endpoint.host} -p {endpoint.ssh_port}',
cls.sftp: f'sftp {username}@{endpoint.host} -P {endpoint.ssh_port}',
cls.putty: f'putty.exe -ssh {username}@{endpoint.host} -P {endpoint.ssh_port}',
cls.xshell: f'xshell.exe -url ssh://{username}:{token.value}@{endpoint.host}:{endpoint.ssh_port}',
# 前端自己处理了
# cls.mysql: 'mysql -h {hostname} -P {port} -u {username} -p',
# cls.psql: {
# 'default': 'psql -h {hostname} -p {port} -U {username} -W',
# 'windows': 'psql /h {hostname} /p {port} /U {username} -W',
# },
# cls.sqlplus: 'sqlplus {username}/{password}@{hostname}:{port}',
# cls.redis: 'redis-cli -h {hostname} -p {port} -a {password}',
}
command = commands.get(name)
if isinstance(command, dict):
command = command.get(os, command.get('default'))
return command
class AppletMethod: class AppletMethod:
@classmethod @classmethod