mirror of
https://github.com/jumpserver/jumpserver.git
synced 2026-01-29 21:51:31 +00:00
perf: 修改 protocol setting (#10875)
* feat: 新增账号配置 * perf: 修改 platform protocol define * perf: 修改 account config * perf: 修改协议设置 --------- Co-authored-by: ibuler <ibuler@qq.com>
This commit is contained in:
@@ -4,20 +4,20 @@ from rest_framework.decorators import action
|
||||
from rest_framework.response import Response
|
||||
|
||||
from assets.const import AllTypes
|
||||
from assets.models import Platform, Node, Asset
|
||||
from assets.serializers import PlatformSerializer
|
||||
from assets.models import Platform, Node, Asset, PlatformProtocol
|
||||
from assets.serializers import PlatformSerializer, PlatformProtocolSerializer
|
||||
from common.api import JMSModelViewSet
|
||||
from common.permissions import IsValidUser
|
||||
from common.serializers import GroupedChoiceSerializer
|
||||
|
||||
__all__ = ['AssetPlatformViewSet', 'PlatformAutomationMethodsApi']
|
||||
__all__ = ['AssetPlatformViewSet', 'PlatformAutomationMethodsApi', 'PlatformProtocolViewSet']
|
||||
|
||||
|
||||
class AssetPlatformViewSet(JMSModelViewSet):
|
||||
queryset = Platform.objects.all()
|
||||
serializer_classes = {
|
||||
'default': PlatformSerializer,
|
||||
'categories': GroupedChoiceSerializer
|
||||
'categories': GroupedChoiceSerializer,
|
||||
}
|
||||
filterset_fields = ['name', 'category', 'type']
|
||||
search_fields = ['name']
|
||||
@@ -25,7 +25,7 @@ class AssetPlatformViewSet(JMSModelViewSet):
|
||||
'categories': 'assets.view_platform',
|
||||
'type_constraints': 'assets.view_platform',
|
||||
'ops_methods': 'assets.view_platform',
|
||||
'filter_nodes_assets': 'assets.view_platform'
|
||||
'filter_nodes_assets': 'assets.view_platform',
|
||||
}
|
||||
|
||||
def get_queryset(self):
|
||||
@@ -61,6 +61,15 @@ class AssetPlatformViewSet(JMSModelViewSet):
|
||||
return Response(serializer.data)
|
||||
|
||||
|
||||
class PlatformProtocolViewSet(JMSModelViewSet):
|
||||
queryset = PlatformProtocol.objects.all()
|
||||
serializer_class = PlatformProtocolSerializer
|
||||
filterset_fields = ['name', 'platform__name']
|
||||
rbac_perms = {
|
||||
'*': 'assets.add_platform'
|
||||
}
|
||||
|
||||
|
||||
class PlatformAutomationMethodsApi(generics.ListAPIView):
|
||||
permission_classes = (IsValidUser,)
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
from django.db import models
|
||||
from django.db.models import TextChoices
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from jumpserver.utils import has_valid_xpack_license
|
||||
from .protocol import Protocol
|
||||
|
||||
|
||||
class Type:
|
||||
@@ -28,6 +29,12 @@ class Type:
|
||||
)
|
||||
|
||||
|
||||
class FillType(models.TextChoices):
|
||||
no = 'no', _('Disabled')
|
||||
basic = 'basic', _('Basic')
|
||||
script = 'script', _('Script')
|
||||
|
||||
|
||||
class BaseType(TextChoices):
|
||||
"""
|
||||
约束应该考虑代是对平台对限制,避免多余对选项,如: mysql 开启 ssh,
|
||||
@@ -57,6 +64,7 @@ class BaseType(TextChoices):
|
||||
|
||||
@classmethod
|
||||
def _parse_protocols(cls, protocol, tp):
|
||||
from .protocol import Protocol
|
||||
settings = Protocol.settings()
|
||||
choices = protocol.get('choices', [])
|
||||
if choices == '__self__':
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from common.db.models import ChoicesMixin
|
||||
from .base import FillType
|
||||
|
||||
__all__ = ['Protocol']
|
||||
|
||||
@@ -22,8 +24,7 @@ class Protocol(ChoicesMixin, models.TextChoices):
|
||||
mongodb = 'mongodb', 'MongoDB'
|
||||
|
||||
k8s = 'k8s', 'K8S'
|
||||
http = 'http', 'HTTP'
|
||||
_settings = None
|
||||
http = 'http', 'HTTP(s)'
|
||||
|
||||
@classmethod
|
||||
def device_protocols(cls):
|
||||
@@ -32,16 +33,40 @@ class Protocol(ChoicesMixin, models.TextChoices):
|
||||
'port': 22,
|
||||
'secret_types': ['password', 'ssh_key'],
|
||||
'setting': {
|
||||
'sftp_enabled': True,
|
||||
'sftp_home': '/tmp',
|
||||
'sftp_enabled': {
|
||||
'type': 'bool',
|
||||
'default': True,
|
||||
'label': _('SFTP enabled')
|
||||
},
|
||||
'sftp_home': {
|
||||
'type': 'str',
|
||||
'default': '/tmp',
|
||||
'label': _('SFTP home')
|
||||
},
|
||||
}
|
||||
},
|
||||
cls.rdp: {
|
||||
'port': 3389,
|
||||
'secret_types': ['password'],
|
||||
'setting': {
|
||||
'console': False,
|
||||
'security': 'any',
|
||||
'console': {
|
||||
'type': 'bool',
|
||||
'default': False,
|
||||
'label': _('Console'),
|
||||
'help_text': _("Connect to console session")
|
||||
},
|
||||
'security': {
|
||||
'type': 'choice',
|
||||
'choices': [('any', _('Any')), ('rdp', 'RDP'), ('tls', 'TLS'), ('nla', 'NLA')],
|
||||
'default': 'any',
|
||||
'label': _('Security'),
|
||||
'help_text': _("Security layer to use for the connection")
|
||||
},
|
||||
# 'ad_domain': {
|
||||
# 'type': 'str',
|
||||
# "required": False,
|
||||
# 'label': _('AD domain')
|
||||
# }
|
||||
}
|
||||
},
|
||||
cls.vnc: {
|
||||
@@ -56,7 +81,11 @@ class Protocol(ChoicesMixin, models.TextChoices):
|
||||
'port': 5985,
|
||||
'secret_types': ['password'],
|
||||
'setting': {
|
||||
'use_ssl': False,
|
||||
'use_ssl': {
|
||||
'type': 'bool',
|
||||
'default': False,
|
||||
'label': _('Use SSL')
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -105,7 +134,11 @@ class Protocol(ChoicesMixin, models.TextChoices):
|
||||
'required': True,
|
||||
'secret_types': ['password'],
|
||||
'setting': {
|
||||
'auth_username': True,
|
||||
'auth_username': {
|
||||
'type': 'bool',
|
||||
'default': False,
|
||||
'label': _('Auth username')
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -121,10 +154,28 @@ class Protocol(ChoicesMixin, models.TextChoices):
|
||||
cls.http: {
|
||||
'port': 80,
|
||||
'secret_types': ['password'],
|
||||
'label': 'HTTP(s)',
|
||||
'setting': {
|
||||
'username_selector': 'name=username',
|
||||
'password_selector': 'name=password',
|
||||
'submit_selector': 'id=login_button',
|
||||
'autofill': {
|
||||
'type': 'choice',
|
||||
'choices': FillType.choices,
|
||||
'default': 'basic',
|
||||
},
|
||||
'username_selector': {
|
||||
'type': 'str',
|
||||
'default': 'name=username',
|
||||
'label': _('Username selector')
|
||||
},
|
||||
'password_selector': {
|
||||
'type': 'str',
|
||||
'default': 'name=password',
|
||||
'label': _('Password selector')
|
||||
},
|
||||
'submit_selector': {
|
||||
'type': 'str',
|
||||
'default': 'type=submit',
|
||||
'label': _('Submit selector')
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from .base import BaseType
|
||||
@@ -53,9 +52,3 @@ class WebTypes(BaseType):
|
||||
return [
|
||||
cls.WEBSITE,
|
||||
]
|
||||
|
||||
|
||||
class FillType(models.TextChoices):
|
||||
no = 'no', _('Disabled')
|
||||
basic = 'basic', _('Basic')
|
||||
script = 'script', _('Script')
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from assets.const.web import FillType
|
||||
from assets.const import FillType
|
||||
from .common import Asset
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
from assets.const.web import FillType
|
||||
from assets.const import FillType
|
||||
from assets.models import Database, Web
|
||||
from common.serializers.fields import LabeledChoiceField
|
||||
|
||||
@@ -14,6 +14,7 @@ class DatabaseSpecSerializer(serializers.ModelSerializer):
|
||||
|
||||
class WebSpecSerializer(serializers.ModelSerializer):
|
||||
autofill = LabeledChoiceField(choices=FillType.choices, label=_('Autofill'))
|
||||
|
||||
class Meta:
|
||||
model = Web
|
||||
fields = [
|
||||
|
||||
@@ -1,48 +1,17 @@
|
||||
from django.db.models import QuerySet
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
from assets.const.web import FillType
|
||||
from common.serializers import WritableNestedModelSerializer, type_field_map
|
||||
from common.serializers import (
|
||||
WritableNestedModelSerializer, type_field_map, MethodSerializer,
|
||||
DictSerializer, create_serializer_class
|
||||
)
|
||||
from common.serializers.fields import LabeledChoiceField
|
||||
from common.utils import lazyproperty
|
||||
from ..const import Category, AllTypes
|
||||
from ..const import Category, AllTypes, Protocol
|
||||
from ..models import Platform, PlatformProtocol, PlatformAutomation
|
||||
|
||||
__all__ = ["PlatformSerializer", "PlatformOpsMethodSerializer"]
|
||||
|
||||
|
||||
class ProtocolSettingSerializer(serializers.Serializer):
|
||||
SECURITY_CHOICES = [
|
||||
("any", "Any"),
|
||||
("rdp", "RDP"),
|
||||
("tls", "TLS"),
|
||||
("nla", "NLA"),
|
||||
]
|
||||
# RDP
|
||||
console = serializers.BooleanField(required=False, default=False)
|
||||
security = serializers.ChoiceField(choices=SECURITY_CHOICES, default="any")
|
||||
|
||||
# SFTP
|
||||
sftp_enabled = serializers.BooleanField(default=True, label=_("SFTP enabled"))
|
||||
sftp_home = serializers.CharField(default="/tmp", label=_("SFTP home"))
|
||||
|
||||
# HTTP
|
||||
autofill = serializers.ChoiceField(default='basic', choices=FillType.choices, label=_("Autofill"))
|
||||
username_selector = serializers.CharField(
|
||||
default="", allow_blank=True, label=_("Username selector")
|
||||
)
|
||||
password_selector = serializers.CharField(
|
||||
default="", allow_blank=True, label=_("Password selector")
|
||||
)
|
||||
submit_selector = serializers.CharField(
|
||||
default="", allow_blank=True, label=_("Submit selector")
|
||||
)
|
||||
script = serializers.JSONField(default=list, label=_("Script"))
|
||||
# Redis
|
||||
auth_username = serializers.BooleanField(default=False, label=_("Auth with username"))
|
||||
|
||||
# WinRM
|
||||
use_ssl = serializers.BooleanField(default=False, label=_("Use SSL"))
|
||||
__all__ = ["PlatformSerializer", "PlatformOpsMethodSerializer", "PlatformProtocolSerializer"]
|
||||
|
||||
|
||||
class PlatformAutomationSerializer(serializers.ModelSerializer):
|
||||
@@ -76,7 +45,7 @@ class PlatformAutomationSerializer(serializers.ModelSerializer):
|
||||
|
||||
|
||||
class PlatformProtocolSerializer(serializers.ModelSerializer):
|
||||
setting = ProtocolSettingSerializer(required=False, allow_null=True)
|
||||
setting = MethodSerializer(required=False, label=_("Setting"))
|
||||
|
||||
class Meta:
|
||||
model = PlatformProtocol
|
||||
@@ -85,6 +54,47 @@ class PlatformProtocolSerializer(serializers.ModelSerializer):
|
||||
"required", "default", "public",
|
||||
"secret_types", "setting",
|
||||
]
|
||||
extra_kwargs = {
|
||||
"primary": {
|
||||
"help_text": _(
|
||||
"This protocol is primary, and it must be set when adding assets. "
|
||||
"Additionally, there can only be one primary protocol."
|
||||
)
|
||||
},
|
||||
"required": {
|
||||
"help_text": _("This protocol is required, and it must be set when adding assets.")
|
||||
},
|
||||
"default": {
|
||||
"help_text": _("This protocol is default, when adding assets, it will be displayed by default.")
|
||||
},
|
||||
"public": {
|
||||
"help_text": _("This protocol is public, asset will show this protocol to user")
|
||||
},
|
||||
}
|
||||
|
||||
def get_setting_serializer(self):
|
||||
request = self.context.get('request')
|
||||
default_field = DictSerializer()
|
||||
|
||||
if not request:
|
||||
return default_field
|
||||
|
||||
if self.instance and isinstance(self.instance, (QuerySet, list)):
|
||||
instance = self.instance[0]
|
||||
else:
|
||||
instance = self.instance
|
||||
|
||||
protocol = request.query_params.get('name', '')
|
||||
if instance and not protocol:
|
||||
protocol = instance.name
|
||||
|
||||
protocol_settings = Protocol.settings()
|
||||
setting_fields = protocol_settings.get(protocol, {}).get('setting')
|
||||
if not setting_fields:
|
||||
return default_field
|
||||
setting_fields = [{'name': k, **v} for k, v in setting_fields.items()]
|
||||
name = '{}ProtocolSettingSerializer'.format(protocol.capitalize())
|
||||
return create_serializer_class(name, setting_fields)()
|
||||
|
||||
def to_file_representation(self, data):
|
||||
return '{name}/{port}'.format(**data)
|
||||
|
||||
@@ -21,6 +21,7 @@ router.register(r'nodes', api.NodeViewSet, 'node')
|
||||
router.register(r'domains', api.DomainViewSet, 'domain')
|
||||
router.register(r'gateways', api.GatewayViewSet, 'gateway')
|
||||
router.register(r'favorite-assets', api.FavoriteAssetViewSet, 'favorite-asset')
|
||||
router.register(r'protocol-settings', api.PlatformProtocolViewSet, 'protocol-setting')
|
||||
|
||||
urlpatterns = [
|
||||
# path('assets/<uuid:pk>/gateways/', api.AssetGatewayListApi.as_view(), name='asset-gateway-list'),
|
||||
@@ -46,7 +47,8 @@ urlpatterns = [
|
||||
path('nodes/<uuid:pk>/tasks/', api.NodeTaskCreateApi.as_view(), name='node-task-create'),
|
||||
|
||||
path('gateways/<uuid:pk>/test-connective/', api.GatewayTestConnectionApi.as_view(), name='test-gateway-connective'),
|
||||
path('platform-automation-methods/', api.PlatformAutomationMethodsApi.as_view(), name='platform-automation-methods'),
|
||||
path('platform-automation-methods/', api.PlatformAutomationMethodsApi.as_view(),
|
||||
name='platform-automation-methods'),
|
||||
]
|
||||
|
||||
urlpatterns += router.urls
|
||||
|
||||
Reference in New Issue
Block a user