mirror of https://github.com/jumpserver/jumpserver
parent
dcf113b87c
commit
4b72099053
|
@ -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):
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue