mirror of https://github.com/jumpserver/jumpserver
pref: 后端返回 connect types
parent
4591b03e17
commit
04ee7ee0e7
|
@ -2,13 +2,11 @@ from django.shortcuts import get_object_or_404
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
from rest_framework import status
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.generics import ListAPIView
|
||||
from rest_framework.request import Request
|
||||
from rest_framework.response import Response
|
||||
|
||||
from assets.models import Asset
|
||||
from common.drf.api import JMSBulkModelViewSet
|
||||
from common.permissions import IsValidUser
|
||||
from common.permissions import IsValidUserOrConnectionToken
|
||||
from orgs.utils import tmp_to_root_org
|
||||
from terminal import serializers
|
||||
|
@ -98,15 +96,3 @@ class EndpointRuleViewSet(JMSBulkModelViewSet):
|
|||
search_fields = filterset_fields
|
||||
serializer_class = serializers.EndpointRuleSerializer
|
||||
queryset = EndpointRule.objects.all()
|
||||
|
||||
|
||||
class ConnectMethodListApi(ListAPIView):
|
||||
permission_classes = (IsValidUser,)
|
||||
|
||||
# serializer_class = serializers.ProtocolConnectMethodsSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
protocol = self.request.query_params.get('protocol')
|
||||
if not protocol:
|
||||
return []
|
||||
return Protocol.objects.filter(name=protocol)
|
||||
|
|
|
@ -1,26 +1,24 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
import logging
|
||||
import uuid
|
||||
|
||||
from django.core.cache import cache
|
||||
from rest_framework import generics
|
||||
from rest_framework.views import APIView, Response
|
||||
from rest_framework import status
|
||||
from django.conf import settings
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from rest_framework import generics
|
||||
from rest_framework import status
|
||||
from rest_framework.views import APIView, Response
|
||||
|
||||
from common.exceptions import JMSException
|
||||
from common.drf.api import JMSBulkModelViewSet
|
||||
from common.utils import get_object_or_none, get_request_ip
|
||||
from common.exceptions import JMSException
|
||||
from common.permissions import IsValidUser
|
||||
from common.permissions import WithBootstrapToken
|
||||
from terminal.models import Terminal
|
||||
from terminal import serializers
|
||||
from terminal import exceptions
|
||||
from terminal.const import TerminalType
|
||||
from terminal.models import Terminal
|
||||
|
||||
__all__ = [
|
||||
'TerminalViewSet', 'TerminalConfig',
|
||||
'TerminalRegistrationApi',
|
||||
'TerminalViewSet', 'TerminalConfig',
|
||||
'TerminalRegistrationApi', 'ConnectMethodListApi'
|
||||
]
|
||||
logger = logging.getLogger(__file__)
|
||||
|
||||
|
@ -72,3 +70,22 @@ class TerminalRegistrationApi(generics.CreateAPIView):
|
|||
data = {"error": "service account registration disabled"}
|
||||
return Response(data=data, status=status.HTTP_400_BAD_REQUEST)
|
||||
return super().create(request, *args, **kwargs)
|
||||
|
||||
|
||||
class ConnectMethodListApi(generics.ListAPIView):
|
||||
serializer_class = serializers.ConnectMethodSerializer
|
||||
permission_classes = [IsValidUser]
|
||||
|
||||
def get_queryset(self):
|
||||
user_agent = self.request.META['HTTP_USER_AGENT'].lower()
|
||||
if 'macintosh' in user_agent:
|
||||
os = 'macos'
|
||||
elif 'windows' in user_agent:
|
||||
os = 'windows'
|
||||
else:
|
||||
os = 'linux'
|
||||
return TerminalType.get_protocols_connect_methods(os)
|
||||
|
||||
def list(self, request, *args, **kwargs):
|
||||
queryset = self.get_queryset()
|
||||
return Response(queryset)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
from collections import defaultdict
|
||||
|
||||
from django.db.models import TextChoices
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
@ -43,24 +44,12 @@ class ComponentLoad(TextChoices):
|
|||
return set(dict(cls.choices).keys())
|
||||
|
||||
|
||||
class TerminalType(TextChoices):
|
||||
koko = 'koko', 'KoKo'
|
||||
guacamole = 'guacamole', 'Guacamole'
|
||||
omnidb = 'omnidb', 'OmniDB'
|
||||
xrdp = 'xrdp', 'Xrdp'
|
||||
lion = 'lion', 'Lion'
|
||||
core = 'core', 'Core'
|
||||
celery = 'celery', 'Celery'
|
||||
magnus = 'magnus', 'Magnus'
|
||||
razor = 'razor', 'Razor'
|
||||
tinker = 'tinker', 'Tinker'
|
||||
|
||||
@classmethod
|
||||
def types(cls):
|
||||
return set(dict(cls.choices).keys())
|
||||
class HttpMethod(TextChoices):
|
||||
web_gui = 'web_gui', 'Web GUI'
|
||||
web_cli = 'web_cli', 'Web CLI'
|
||||
|
||||
|
||||
class NativeClient:
|
||||
class NativeClient(TextChoices):
|
||||
# Koko
|
||||
ssh = 'ssh', 'ssh'
|
||||
putty = 'putty', 'PuTTY'
|
||||
|
@ -71,15 +60,42 @@ class NativeClient:
|
|||
psql = 'psql', 'psql'
|
||||
sqlplus = 'sqlplus', 'sqlplus'
|
||||
redis = 'redis-cli', 'redis-cli'
|
||||
mongodb = 'mongo', 'mongo'
|
||||
|
||||
# Razor
|
||||
mstsc = 'mstsc', 'Remote Desktop'
|
||||
|
||||
@classmethod
|
||||
def get_native_clients(cls, p, os='windows'):
|
||||
def get_native_clients(cls):
|
||||
clients = {
|
||||
''
|
||||
Protocol.ssh: {
|
||||
'default': [cls.ssh],
|
||||
'windows': [cls.putty],
|
||||
},
|
||||
Protocol.rdp: [cls.mstsc],
|
||||
Protocol.mysql: [cls.mysql],
|
||||
Protocol.oracle: [cls.sqlplus],
|
||||
Protocol.postgresql: [cls.psql],
|
||||
Protocol.redis: [cls.redis],
|
||||
Protocol.mongodb: [cls.mongodb],
|
||||
}
|
||||
return clients
|
||||
|
||||
@classmethod
|
||||
def get_native_methods(cls, os='windows'):
|
||||
clients_map = cls.get_native_clients()
|
||||
methods = defaultdict(list)
|
||||
|
||||
for protocol, _clients in clients_map.items():
|
||||
if isinstance(_clients, dict):
|
||||
_clients = _clients.get(os, _clients['default'])
|
||||
for client in _clients:
|
||||
methods[protocol].append({
|
||||
'value': client.value,
|
||||
'label': client.label,
|
||||
'type': 'native',
|
||||
})
|
||||
return methods
|
||||
|
||||
@classmethod
|
||||
def get_launch_command(cls, name, os='windows'):
|
||||
|
@ -104,33 +120,113 @@ class NativeClient:
|
|||
|
||||
class RemoteAppMethod:
|
||||
@classmethod
|
||||
def get_remote_app_methods(cls, protocol):
|
||||
def get_remote_app_methods(cls):
|
||||
from .models import Applet
|
||||
applets = Applet.objects.filter(protocol=protocol)
|
||||
return applets
|
||||
applets = Applet.objects.all()
|
||||
methods = defaultdict(list)
|
||||
for applet in applets:
|
||||
for protocol in applet.protocols:
|
||||
methods[protocol].append({
|
||||
'value': applet.name,
|
||||
'label': applet.display_name,
|
||||
'icon': applet.icon,
|
||||
'type': 'remote_app',
|
||||
})
|
||||
return methods
|
||||
|
||||
|
||||
class ConnectMethod(TextChoices):
|
||||
web_cli = 'web_cli', _('Web CLI')
|
||||
web_gui = 'web_gui', _('Web GUI')
|
||||
native_client = 'native_client', _('Native Client')
|
||||
remote_app = 'remote_app', _('Remote App')
|
||||
class TerminalType(TextChoices):
|
||||
koko = 'koko', 'KoKo'
|
||||
guacamole = 'guacamole', 'Guacamole'
|
||||
omnidb = 'omnidb', 'OmniDB'
|
||||
xrdp = 'xrdp', 'Xrdp'
|
||||
lion = 'lion', 'Lion'
|
||||
core = 'core', 'Core'
|
||||
celery = 'celery', 'Celery'
|
||||
magnus = 'magnus', 'Magnus'
|
||||
razor = 'razor', 'Razor'
|
||||
tinker = 'tinker', 'Tinker'
|
||||
|
||||
@classmethod
|
||||
def methods(cls):
|
||||
def types(cls):
|
||||
return set(dict(cls.choices).keys())
|
||||
|
||||
@classmethod
|
||||
def protocols(cls):
|
||||
return {
|
||||
Protocol.ssh: [cls.web_cli, cls.native_client],
|
||||
Protocol.rdp: ([cls.web_gui], [cls.native_client]),
|
||||
Protocol.vnc: [cls.web_gui],
|
||||
Protocol.telnet: [cls.web_cli, cls.native_client],
|
||||
|
||||
Protocol.mysql: [cls.web_cli, cls.web_gui, cls.native_client],
|
||||
Protocol.sqlserver: [cls.web_cli, cls.web_gui],
|
||||
Protocol.oracle: [cls.web_cli, cls.web_gui],
|
||||
Protocol.postgresql: [cls.web_cli, cls.web_gui],
|
||||
Protocol.redis: [cls.web_cli, cls.web_gui, cls.native_client],
|
||||
Protocol.mongodb: [cls.web_cli, cls.web_gui],
|
||||
|
||||
Protocol.k8s: [cls.web_cli],
|
||||
Protocol.http: [],
|
||||
cls.koko: {
|
||||
'http_method': HttpMethod.web_cli,
|
||||
'listen': [Protocol.ssh, Protocol.http],
|
||||
'support': [
|
||||
Protocol.ssh, Protocol.telnet,
|
||||
Protocol.mysql, Protocol.postgresql,
|
||||
Protocol.oracle, Protocol.sqlserver,
|
||||
Protocol.mariadb, Protocol.redis,
|
||||
Protocol.mongodb,
|
||||
],
|
||||
'match': 'm2m'
|
||||
},
|
||||
cls.omnidb: {
|
||||
'http_method': HttpMethod.web_gui,
|
||||
'listen': [Protocol.http],
|
||||
'support': [
|
||||
Protocol.mysql, Protocol.postgresql, Protocol.oracle,
|
||||
Protocol.sqlserver, Protocol.mariadb
|
||||
],
|
||||
'match': 'm2m'
|
||||
},
|
||||
cls.lion: {
|
||||
'http_method': HttpMethod.web_gui,
|
||||
'listen': [Protocol.http],
|
||||
'support': [Protocol.rdp, Protocol.vnc],
|
||||
'match': 'm2m'
|
||||
},
|
||||
cls.magnus: {
|
||||
'listen': [],
|
||||
'support': [
|
||||
Protocol.mysql, Protocol.postgresql, Protocol.oracle,
|
||||
Protocol.mariadb
|
||||
],
|
||||
'match': 'map'
|
||||
},
|
||||
cls.razor: {
|
||||
'listen': [Protocol.rdp],
|
||||
'support': [Protocol.rdp],
|
||||
'match': 'map'
|
||||
}
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def get_protocols_connect_methods(cls, os):
|
||||
methods = defaultdict(list)
|
||||
native_methods = NativeClient.get_native_methods(os)
|
||||
remote_app_methods = RemoteAppMethod.get_remote_app_methods()
|
||||
|
||||
for component, component_protocol in cls.protocols().items():
|
||||
component_methods = defaultdict(list)
|
||||
support = component_protocol['support']
|
||||
|
||||
for protocol in support:
|
||||
if component_protocol['match'] == 'map':
|
||||
listen = [protocol]
|
||||
else:
|
||||
listen = component_protocol['listen']
|
||||
|
||||
for listen_protocol in listen:
|
||||
if listen_protocol == Protocol.http:
|
||||
web_protocol = component_protocol['http_method']
|
||||
component_methods[protocol.value].append({
|
||||
'value': web_protocol.value,
|
||||
'label': web_protocol.label,
|
||||
'type': 'web',
|
||||
})
|
||||
|
||||
# Native method
|
||||
component_methods[protocol.value].extend(native_methods[listen_protocol])
|
||||
component_methods[protocol.value].extend(remote_app_methods[listen_protocol])
|
||||
|
||||
for protocol, _methods in component_methods.items():
|
||||
for method in _methods:
|
||||
method['component'] = component.value
|
||||
methods[protocol].extend(_methods)
|
||||
return methods
|
||||
|
|
|
@ -1,19 +1,16 @@
|
|||
import uuid
|
||||
import time
|
||||
import uuid
|
||||
|
||||
from django.utils import timezone
|
||||
from django.db import models
|
||||
from django.core.cache import cache
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.conf import settings
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from common.utils import get_logger, lazyproperty
|
||||
from users.models import User
|
||||
from orgs.utils import tmp_to_root_org
|
||||
from terminal.const import TerminalType as TypeChoices, ComponentLoad as StatusChoice
|
||||
from terminal.const import TerminalType as TypeChoices
|
||||
from users.models import User
|
||||
from ..session import Session
|
||||
|
||||
|
||||
logger = get_logger(__file__)
|
||||
|
||||
|
||||
|
@ -87,7 +84,8 @@ class Terminal(StorageMixin, TerminalStatusMixin, models.Model):
|
|||
remote_addr = models.CharField(max_length=128, blank=True, verbose_name=_('Remote Address'))
|
||||
command_storage = models.CharField(max_length=128, verbose_name=_("Command storage"), default='default')
|
||||
replay_storage = models.CharField(max_length=128, verbose_name=_("Replay storage"), default='default')
|
||||
user = models.OneToOneField(User, related_name='terminal', verbose_name='Application User', null=True, on_delete=models.CASCADE)
|
||||
user = models.OneToOneField(User, related_name='terminal', verbose_name='Application User', null=True,
|
||||
on_delete=models.CASCADE)
|
||||
is_deleted = models.BooleanField(default=False)
|
||||
date_created = models.DateTimeField(auto_now_add=True)
|
||||
comment = models.TextField(blank=True, verbose_name=_('Comment'))
|
||||
|
@ -160,4 +158,3 @@ class Terminal(StorageMixin, TerminalStatusMixin, models.Model):
|
|||
permissions = (
|
||||
('view_terminalconfig', _('Can view terminal config')),
|
||||
)
|
||||
|
||||
|
|
|
@ -136,4 +136,6 @@ class TerminalRegistrationSerializer(serializers.ModelSerializer):
|
|||
|
||||
|
||||
class ConnectMethodSerializer(serializers.Serializer):
|
||||
name = serializers.CharField(max_length=128)
|
||||
value = serializers.CharField(max_length=128)
|
||||
label = serializers.CharField(max_length=128)
|
||||
group = serializers.CharField(max_length=128)
|
||||
|
|
|
@ -31,7 +31,6 @@ router.register(r'applet-hosts', api.AppletHostViewSet, 'applet-host')
|
|||
router.register(r'applet-publications', api.AppletPublicationViewSet, 'applet-publication')
|
||||
router.register(r'applet-host-deployments', api.AppletHostDeploymentViewSet, 'applet-host-deployment')
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
path('my-sessions/', api.MySessionAPIView.as_view(), name='my-session'),
|
||||
path('terminal-registrations/', api.TerminalRegistrationApi.as_view(), name='terminal-registration'),
|
||||
|
@ -44,10 +43,13 @@ urlpatterns = [
|
|||
path('tasks/kill-session-for-ticket/', api.KillSessionForTicketAPI.as_view(), name='kill-session-for-ticket'),
|
||||
path('terminals/config/', api.TerminalConfig.as_view(), name='terminal-config'),
|
||||
path('commands/insecure-command/', api.InsecureCommandAlertAPI.as_view(), name="command-alert"),
|
||||
path('replay-storages/<uuid:pk>/test-connective/', api.ReplayStorageTestConnectiveApi.as_view(), name='replay-storage-test-connective'),
|
||||
path('command-storages/<uuid:pk>/test-connective/', api.CommandStorageTestConnectiveApi.as_view(), name='command-storage-test-connective'),
|
||||
path('replay-storages/<uuid:pk>/test-connective/', api.ReplayStorageTestConnectiveApi.as_view(),
|
||||
name='replay-storage-test-connective'),
|
||||
path('command-storages/<uuid:pk>/test-connective/', api.CommandStorageTestConnectiveApi.as_view(),
|
||||
name='command-storage-test-connective'),
|
||||
# components
|
||||
path('components/metrics/', api.ComponentsMetricsAPIView.as_view(), name='components-metrics'),
|
||||
path('components/connect-methods/', api.ConnectMethodListApi.as_view(), name='connect-methods'),
|
||||
]
|
||||
|
||||
old_version_urlpatterns = [
|
||||
|
@ -55,6 +57,3 @@ old_version_urlpatterns = [
|
|||
]
|
||||
|
||||
urlpatterns += router.urls + old_version_urlpatterns
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue