mirror of https://github.com/jumpserver/jumpserver
				
				
				
			
		
			
				
	
	
		
			242 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			Python
		
	
	
			
		
		
	
	
			242 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			Python
		
	
	
# -*- coding: utf-8 -*-
 | 
						|
#
 | 
						|
from rest_framework import serializers
 | 
						|
from rest_framework.validators import UniqueValidator
 | 
						|
from urllib.parse import urlparse
 | 
						|
from django.utils.translation import ugettext_lazy as _
 | 
						|
from django.db.models import TextChoices
 | 
						|
 | 
						|
from common.drf.serializers import MethodSerializer
 | 
						|
from common.drf.fields import ReadableHiddenField, EncryptedField
 | 
						|
from ..models import ReplayStorage, CommandStorage
 | 
						|
from .. import const
 | 
						|
 | 
						|
 | 
						|
# Replay storage serializers
 | 
						|
# --------------------------
 | 
						|
def replay_storage_endpoint_format_validator(endpoint):
 | 
						|
    h = urlparse(endpoint)
 | 
						|
    if h.path:
 | 
						|
        raise serializers.ValidationError(_('Endpoint invalid: remove path `{}`').format(h.path))
 | 
						|
    return endpoint
 | 
						|
 | 
						|
 | 
						|
class ReplayStorageTypeBaseSerializer(serializers.Serializer):
 | 
						|
    BUCKET = serializers.CharField(
 | 
						|
        required=True, max_length=1024, label=_('Bucket'), allow_null=True
 | 
						|
    )
 | 
						|
    ACCESS_KEY = serializers.CharField(
 | 
						|
        max_length=1024, required=False, allow_blank=True,
 | 
						|
        label=_('Access key id'), allow_null=True,
 | 
						|
    )
 | 
						|
    SECRET_KEY = EncryptedField(
 | 
						|
        max_length=1024, required=False, allow_blank=True,
 | 
						|
        label=_('Access key secret'), allow_null=True,
 | 
						|
    )
 | 
						|
    ENDPOINT = serializers.CharField(
 | 
						|
        validators=[replay_storage_endpoint_format_validator],
 | 
						|
        required=True, max_length=1024, label=_('Endpoint'), allow_null=True,
 | 
						|
    )
 | 
						|
 | 
						|
 | 
						|
class ReplayStorageTypeS3Serializer(ReplayStorageTypeBaseSerializer):
 | 
						|
    endpoint_help_text = '''
 | 
						|
        S3 format: http://s3.{REGION_NAME}.amazonaws.com <br>
 | 
						|
        S3(China) format: http://s3.{REGION_NAME}.amazonaws.com.cn <br>
 | 
						|
        Such as: http://s3.cn-north-1.amazonaws.com.cn
 | 
						|
    '''
 | 
						|
    ENDPOINT = serializers.CharField(
 | 
						|
        validators=[replay_storage_endpoint_format_validator],
 | 
						|
        required=True, max_length=1024, label=_('Endpoint'), help_text=_(endpoint_help_text),
 | 
						|
        allow_null=True,
 | 
						|
    )
 | 
						|
 | 
						|
 | 
						|
class ReplayStorageTypeCephSerializer(ReplayStorageTypeBaseSerializer):
 | 
						|
    pass
 | 
						|
 | 
						|
 | 
						|
class ReplayStorageTypeSwiftSerializer(ReplayStorageTypeBaseSerializer):
 | 
						|
    class ProtocolChoices(TextChoices):
 | 
						|
        http = 'http', 'http'
 | 
						|
        https = 'https', 'https'
 | 
						|
 | 
						|
    REGION = serializers.CharField(
 | 
						|
        required=True, max_length=1024, label=_('Region'), allow_null=True
 | 
						|
    )
 | 
						|
    PROTOCOL = serializers.ChoiceField(
 | 
						|
        choices=ProtocolChoices.choices, default=ProtocolChoices.http.value, label=_('Protocol'),
 | 
						|
        allow_null=True,
 | 
						|
    )
 | 
						|
 | 
						|
 | 
						|
class ReplayStorageTypeOSSSerializer(ReplayStorageTypeBaseSerializer):
 | 
						|
    endpoint_help_text = '''
 | 
						|
        OSS format: http://{REGION_NAME}.aliyuncs.com <br>
 | 
						|
        Such as: http://oss-cn-hangzhou.aliyuncs.com
 | 
						|
    '''
 | 
						|
    ENDPOINT = serializers.CharField(
 | 
						|
        validators=[replay_storage_endpoint_format_validator],
 | 
						|
        max_length=1024, label=_('Endpoint'), help_text=_(endpoint_help_text), allow_null=True,
 | 
						|
    )
 | 
						|
 | 
						|
 | 
						|
class ReplayStorageTypeOBSSerializer(ReplayStorageTypeBaseSerializer):
 | 
						|
    endpoint_help_text = '''
 | 
						|
        OBS format: obs.{REGION_NAME}.myhuaweicloud.com <br>
 | 
						|
        Such as: obs.cn-north-4.myhuaweicloud.com
 | 
						|
    '''
 | 
						|
    ENDPOINT = serializers.CharField(
 | 
						|
        max_length=1024, label=_('Endpoint'), help_text=_(endpoint_help_text), allow_null=True,
 | 
						|
    )
 | 
						|
 | 
						|
 | 
						|
class ReplayStorageTypeCOSSerializer(ReplayStorageTypeS3Serializer):
 | 
						|
    endpoint_help_text = '''Such as: http://cos.{REGION_NAME}.myqcloud.com'''
 | 
						|
    ENDPOINT = serializers.CharField(
 | 
						|
        validators=[replay_storage_endpoint_format_validator],
 | 
						|
        required=True, max_length=1024, label=_('Endpoint'), help_text=_(endpoint_help_text),
 | 
						|
        allow_null=True,
 | 
						|
    )
 | 
						|
 | 
						|
 | 
						|
class ReplayStorageTypeAzureSerializer(serializers.Serializer):
 | 
						|
    class EndpointSuffixChoices(TextChoices):
 | 
						|
        china = 'core.chinacloudapi.cn', 'core.chinacloudapi.cn'
 | 
						|
        international = 'core.windows.net', 'core.windows.net'
 | 
						|
 | 
						|
    CONTAINER_NAME = serializers.CharField(
 | 
						|
        max_length=1024, label=_('Container name'), allow_null=True
 | 
						|
    )
 | 
						|
    ACCOUNT_NAME = serializers.CharField(max_length=1024, label=_('Account name'), allow_null=True)
 | 
						|
    ACCOUNT_KEY = EncryptedField(max_length=1024, label=_('Account key'), allow_null=True)
 | 
						|
    ENDPOINT_SUFFIX = serializers.ChoiceField(
 | 
						|
        choices=EndpointSuffixChoices.choices, default=EndpointSuffixChoices.china.value,
 | 
						|
        label=_('Endpoint suffix'), allow_null=True,
 | 
						|
    )
 | 
						|
 | 
						|
 | 
						|
# mapping
 | 
						|
replay_storage_type_serializer_classes_mapping = {
 | 
						|
    const.ReplayStorageType.s3.value: ReplayStorageTypeS3Serializer,
 | 
						|
    const.ReplayStorageType.ceph.value: ReplayStorageTypeCephSerializer,
 | 
						|
    const.ReplayStorageType.swift.value: ReplayStorageTypeSwiftSerializer,
 | 
						|
    const.ReplayStorageType.oss.value: ReplayStorageTypeOSSSerializer,
 | 
						|
    const.ReplayStorageType.azure.value: ReplayStorageTypeAzureSerializer,
 | 
						|
    const.ReplayStorageType.obs.value: ReplayStorageTypeOBSSerializer,
 | 
						|
    const.ReplayStorageType.cos.value: ReplayStorageTypeCOSSerializer
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
# Command storage serializers
 | 
						|
# ---------------------------
 | 
						|
def command_storage_es_host_format_validator(host):
 | 
						|
    h = urlparse(host)
 | 
						|
    default_error_msg = _('The address format is incorrect')
 | 
						|
    if h.scheme not in ['http', 'https']:
 | 
						|
        raise serializers.ValidationError(default_error_msg)
 | 
						|
    if ':' not in h.netloc:
 | 
						|
        raise serializers.ValidationError(default_error_msg)
 | 
						|
    _host, _port = h.netloc.rsplit(':', maxsplit=1)
 | 
						|
    if not _host:
 | 
						|
        error_msg = _('Host invalid')
 | 
						|
        raise serializers.ValidationError(error_msg)
 | 
						|
    if not _port.isdigit():
 | 
						|
        error_msg = _('Port invalid')
 | 
						|
        raise serializers.ValidationError(error_msg)
 | 
						|
    return host
 | 
						|
 | 
						|
 | 
						|
class CommandStorageTypeESSerializer(serializers.Serializer):
 | 
						|
    hosts_help_text = '''
 | 
						|
        Tip: If there are multiple hosts, use a comma (,) to separate them. <br>
 | 
						|
        (eg: http://www.jumpserver.a.com:9100, http://www.jumpserver.b.com:9100)
 | 
						|
    '''
 | 
						|
    HOSTS = serializers.ListField(
 | 
						|
        child=serializers.CharField(validators=[command_storage_es_host_format_validator]),
 | 
						|
        label=_('Hosts'), help_text=_(hosts_help_text), allow_null=True
 | 
						|
    )
 | 
						|
    INDEX_BY_DATE = serializers.BooleanField(
 | 
						|
        default=False, label=_('Index by date'),
 | 
						|
        help_text=_('Whether to create an index by date')
 | 
						|
    )
 | 
						|
    INDEX = serializers.CharField(
 | 
						|
        max_length=1024, default='jumpserver', label=_('Index'), allow_null=True
 | 
						|
    )
 | 
						|
    DOC_TYPE = ReadableHiddenField(default='_doc', label=_('Doc type'), allow_null=True)
 | 
						|
    IGNORE_VERIFY_CERTS = serializers.BooleanField(
 | 
						|
        default=False, label=_('Ignore Certificate Verification'),
 | 
						|
        source='OTHER.IGNORE_VERIFY_CERTS', allow_null=True,
 | 
						|
    )
 | 
						|
 | 
						|
 | 
						|
# mapping
 | 
						|
command_storage_type_serializer_classes_mapping = {
 | 
						|
    const.CommandStorageType.es.value: CommandStorageTypeESSerializer
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
# BaseStorageSerializer
 | 
						|
class BaseStorageSerializer(serializers.ModelSerializer):
 | 
						|
    storage_type_serializer_classes_mapping = {}
 | 
						|
    meta = MethodSerializer()
 | 
						|
 | 
						|
    class Meta:
 | 
						|
        model = None
 | 
						|
        fields = ['id', 'name', 'type', 'meta', 'is_default', 'comment']
 | 
						|
 | 
						|
    def validate_meta(self, meta):
 | 
						|
        _meta = self.instance.meta if self.instance else {}
 | 
						|
        _meta.update(meta)
 | 
						|
        return _meta
 | 
						|
 | 
						|
    def get_meta_serializer(self):
 | 
						|
        default_serializer = serializers.Serializer(read_only=True)
 | 
						|
 | 
						|
        if isinstance(self.instance, self.__class__.Meta.model):
 | 
						|
            _type = self.instance.type
 | 
						|
        else:
 | 
						|
            _type = self.context['request'].query_params.get('type')
 | 
						|
 | 
						|
        if _type:
 | 
						|
            serializer_class = self.storage_type_serializer_classes_mapping.get(_type)
 | 
						|
        else:
 | 
						|
            serializer_class = default_serializer
 | 
						|
 | 
						|
        if not serializer_class:
 | 
						|
            serializer_class = default_serializer
 | 
						|
 | 
						|
        if isinstance(serializer_class, type):
 | 
						|
            serializer = serializer_class()
 | 
						|
        else:
 | 
						|
            serializer = serializer_class
 | 
						|
        return serializer
 | 
						|
 | 
						|
    def save(self, **kwargs):
 | 
						|
        instance = super().save(**kwargs)
 | 
						|
        if self.validated_data.get('is_default', False):
 | 
						|
            instance.set_to_default()
 | 
						|
        return instance
 | 
						|
 | 
						|
 | 
						|
# CommandStorageSerializer
 | 
						|
class CommandStorageSerializer(BaseStorageSerializer):
 | 
						|
    storage_type_serializer_classes_mapping = command_storage_type_serializer_classes_mapping
 | 
						|
 | 
						|
    class Meta(BaseStorageSerializer.Meta):
 | 
						|
        model = CommandStorage
 | 
						|
        extra_kwargs = {
 | 
						|
            'name': {'validators': [UniqueValidator(queryset=CommandStorage.objects.all())]}
 | 
						|
        }
 | 
						|
 | 
						|
 | 
						|
# ReplayStorageSerializer
 | 
						|
class ReplayStorageSerializer(BaseStorageSerializer):
 | 
						|
    storage_type_serializer_classes_mapping = replay_storage_type_serializer_classes_mapping
 | 
						|
 | 
						|
    class Meta(BaseStorageSerializer.Meta):
 | 
						|
        model = ReplayStorage
 | 
						|
        extra_kwargs = {
 | 
						|
            'name': {'validators': [UniqueValidator(queryset=ReplayStorage.objects.all())]}
 | 
						|
        }
 |