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:
fit2bot
2023-06-30 15:54:06 +08:00
committed by GitHub
parent 6962430e6a
commit bbbd011cc2
14 changed files with 570 additions and 400 deletions

View File

@@ -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,)

View File

@@ -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__':

View File

@@ -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')
}
}
},
}

View File

@@ -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')

View File

@@ -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

View File

@@ -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 = [

View File

@@ -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)

View File

@@ -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