示例#1
0
class IPAddressSerializer(BonkTriggerMixin, HistorySerializerMixin):
    id = serializers.CharField(required=False)
    tags = serializers.DictField(required=False)
    state = serializers.ChoiceField(required=True, choices=['allocated', 'reserved', 'quarantine'])
    vrf = serializers.IntegerField(required=True, validators=[validate_vrf])
    ip = serializers.IPAddressField(required=True)
    name = serializers.CharField(required=True, validators=[validate_fqdn])
    dhcp_mac = serializers.ListField(child=serializers.CharField(validators=[validate_mac]), required=False)
    reference = serializers.CharField(required=False)
    permissions = PermissionsSerializer(required=False)
    ttl = serializers.IntegerField(required=False, validators=[validate_ttl])

    class Meta(RethinkSerializer.Meta):
        table_name = 'ip_address'
        slug_field = 'vrf_ip'
        indices = [
            'ip',
            'name',
            ('vrf_ip', (r.row['vrf'], r.row['ip'])),
            ('permissions_read', r.row['permissions']['read'], {'multi': True}),
            ('permissions_create', r.row['permissions']['create'], {'multi': True}),
            ('permissions_write', r.row['permissions']['write'], {'multi': True}),
        ]
        unique_together = [
            ('vrf', 'ip'),
        ]

    def create_link(self, instance):
        return reverse('bonk:address_detail', kwargs={
                'vrf': instance['vrf'],
                'ip': instance['ip'],
            }, request=self.context.get('request'))

    @classmethod
    def filter_by_prefix(cls, prefix, reql=False):
        return cls.filter(lambda a:
            r.ip_prefix_contains(
                r.ip_prefix(prefix['network'], prefix['length']),
                r.ip_address(a['ip'])
            ),
        reql=reql)

    def validate_name(self, value):
        possibles = []
        for part in value.split(".")[:0:-1]:
            suffix = "" if len(possibles) == 0 else ("." + possibles[-1])
            possibles.append(part + suffix)
        try:
            zone = DNSZoneSerializer.filter(lambda zone: r.expr(possibles).contains(zone['name']), reql=True).order_by(r.desc(r.row['name'].count())).nth(0).run(self.conn)
        except r.errors.ReqlNonExistenceError:
            raise serializers.ValidationError("no zone matching %s could be found" % value)
        if 'request' in self.context and not self.context['request'].user.is_superuser:
            user_groups = set(self.context['request'].user.groups.all().values_list('name', flat=True))
            if self.instance is not None and len(user_groups.intersection(set(
                    self.instance.get('permissions', {}).get('write', [])
                ))) > 0:
                pass
            elif len(user_groups.intersection(set(
                    zone.get('permissions', {}).get('create', [])
                    + zone.get('permissions', {}).get('write', [])
                ))) == 0:
                raise serializers.ValidationError("you do not have permission to create names in %s" % zone['name'])
        try:
            ip_address = IPAddressSerializer.get(name=value)
            if self.instance is None or ip_address['id'] != self.instance['id']:
                raise serializers.ValidationError("%r is already in use by %s" % (value, ip_address['ip']))
        except RethinkObjectNotFound:
            pass
        return value

    def validate(self, data):
        data = super(IPAddressSerializer, self).validate(data)
        full = self.get_updated_object(data)
        try:
            prefix = IPPrefixSerializer.get_by_ip(full['vrf'], full['ip'])
        except RethinkObjectNotFound:
            raise serializers.ValidationError("no prefix found for IP %s" % full['ip'])
        return data
示例#2
0
class IPPrefixDDNSSerializer(DDNSSerializer):
    zone = serializers.CharField(required=True)
    server = serializers.IPAddressField(required=True)
示例#3
0
class IPPrefixSerializer(BonkTriggerMixin, HistorySerializerMixin):
    id = serializers.CharField(required=False)
    tags = serializers.DictField(required=False)
    vrf = serializers.IntegerField(required=True, validators=[validate_vrf])
    network = serializers.IPAddressField(required=True)
    length = serializers.IntegerField(required=True)
    asn = serializers.IntegerField(required=False)
    name = serializers.CharField(required=False)
    state = serializers.ChoiceField(required=True, choices=['allocated', 'reserved', 'quarantine'])
    permissions = PermissionsSerializer(required=False)
    gateway = serializers.IPAddressField(required=False)
    dhcp = IPPrefixDHCPSerializer(required=False)
    ddns = IPPrefixDDNSSerializer(required=False)
    reference = serializers.CharField(required=False)
    inventory_id = serializers.CharField(required=False)

    class Meta(RethinkSerializer.Meta):
        table_name = 'ip_prefix'
        slug_field = 'vrf_network_length'
        indices = [
            'name',
            ('vrf_network_length', (r.row['vrf'], r.row['network'], r.row['length'])),
            ('permissions_read', r.row['permissions']['read'], {'multi': True}),
            ('permissions_create', r.row['permissions']['create'], {'multi': True}),
            ('permissions_write', r.row['permissions']['write'], {'multi': True}),
        ]
        unique = [
            'name'
        ]
        unique_together = [
            ('vrf', 'network', 'length'),
        ]

    def create_link(self, instance):
        return reverse('bonk:prefix_detail', kwargs={
                'vrf': instance['vrf'],
                'network': instance['network'],
                'length': instance['length'],
            }, request=self.context.get('request'))

    @classmethod
    def filter_by_block(cls, block, reql=False):
        return cls.filter(lambda p:
            r.ip_prefix_contains(
                r.ip_prefix(block['network'], block['length']),
                r.ip_address(p['network'])
            ), reql=reql)

    @classmethod
    def get_by_ip(cls, vrf, ip, reql=False):
        query = cls.filter(lambda p:
                r.ip_prefix_contains(
                    r.ip_prefix(p['network'], p['length']),
                    r.ip_address(ip)
                ), reql=True) \
                .filter({'vrf': vrf}) \
                .order_by(r.desc("length")).nth(0)
        if reql:
            return query
        else:
            try:
                return query.run(get_connection())
            except r.errors.ReqlNonExistenceError:
                raise RethinkObjectNotFound("no prefix found for IP %s" % ip)

    def validate(self, data):
        data = super(IPPrefixSerializer, self).validate(data)
        full = self.get_updated_object(data)
        try:
            block = IPBlockSerializer.get_by_ip(full['vrf'], full['network'])
        except RethinkObjectNotFound:
            raise serializers.ValidationError("no block exists matching prefix %s/%d" % (full['network'], full['length']))
        if block['length'] > full['length']:
            raise serializers.ValidationError("prefix %s/%d exceeds block of %s/%d" % (full['network'], full['length'], block['network'], block['length']))
        if (self.instance is None
                and self.context['request'].user is not None
                and not self.context['request'].user.is_superuser
            ):
            allowed = set(
                block.get('permissions', {}).get('write', [])
                + block.get('permissions', {}).get('create', [])
            )
            groups = set(self.context['request'].user.groups.all().values_list('name', flat=True))
            if len(groups.intersection(allowed)) == 0:
                raise serializers.ValidationError("you do not have permissions to block %s/%d" % (block['network'], block['length']))
        underlappers = [x for x in self.filter_by_block(full) if x[self.Meta.pk_field] != full.get(self.Meta.pk_field, None)]
        if len(underlappers) > 0:
            raise serializers.ValidationError("prefix %s/%d overlaps with %r" % (full['network'], full['length'], underlappers))
        try:
            overlapper = IPPrefixSerializer.get_by_ip(full['vrf'], full['network'])
            if overlapper[self.Meta.pk_field] != full.get(self.Meta.pk_field, None):
                raise serializers.ValidationError("prefix %s/%d includes this prefix %s/%d" % (overlapper['network'], overlapper['length'], full['network'], full['length']))
        except RethinkObjectNotFound:
            pass
        network = netaddr.IPNetwork("%s/%d" % (full['network'], full['length']))
        if str(network.network) != full['network']:
            raise serializers.ValidationError("network is not the network address for %s/%d" % (full['network'], full['length']))
        return data

    def create(self, data):
        import bonk.tasks
        data = super(IPPrefixSerializer, self).create(data)
        block = IPBlockSerializer.get_by_ip(data['vrf'], data['network'])
        if 'announced_by' in block and data['state'] == 'allocated':
            bonk.tasks.trigger_prefix_create.apply_async((data, block))
        return data

    def update(self, instance, data):
        import bonk.tasks
        ret = super(IPPrefixSerializer, self).update(instance, data)
        block = IPBlockSerializer.get_by_ip(ret['vrf'], ret['network'])
        if 'announced_by' in block:
            if instance['state'] != 'allocated' and ret['state'] == 'allocated':
                bonk.tasks.trigger_prefix_create.apply_async((ret, block))
            elif instance['state'] == 'allocated' and ret['state'] != 'allocated':
                bonk.tasks.trigger_prefix_delete.apply_async((ret, block))
        return ret

    def delete(self):
        import bonk.tasks
        block = IPBlockSerializer.get_by_ip(self.instance['vrf'], self.instance['network'])
        if 'announced_by' in block and self.instance['state'] == 'allocated':
            bonk.tasks.trigger_prefix_delete.apply_async((self.instance, block))
        for address in IPAddressSerializer.filter_by_prefix(self.instance):
            ip = IPAddressSerializer(address)
            ip.delete()
        ret = super(IPPrefixSerializer, self).delete()
        return ret
示例#4
0
class DeviceCreateSerializer(serializers.ModelSerializer):
    customer = serializers.CharField(required=True,
                                     max_length=100,
                                     help_text="客户",
                                     error_messages={
                                         "blank": "请输入客户名",
                                         "required": "请输入客户名"
                                     })
    customer_token = serializers.CharField(max_length=30,
                                           required=True,
                                           help_text="商户编码",
                                           error_messages={
                                               "blank": "请输入商户编码",
                                               "required": "请输入商户编码"
                                           })
    main_record = serializers.CharField(max_length=100,
                                        required=True,
                                        help_text="主解析记录",
                                        error_messages={
                                            "blank": "请输入主记录",
                                            "required": "请输入主记录"
                                        })
    sub_record = serializers.CharField(max_length=100,
                                       required=True,
                                       help_text="副解析记录",
                                       error_messages={
                                           "blank": "请输入副记录",
                                           "required": "请输入副记录"
                                       })
    cdn_record = serializers.CharField(max_length=100,
                                       required=True,
                                       help_text="cdn解析记录",
                                       error_messages={
                                           "blank": "请输入cdn记录",
                                           "required": "请输入cdn记录"
                                       })
    main_ip = serializers.IPAddressField(required=True,
                                         help_text="主ip",
                                         error_messages={
                                             "blank": "请输入主ip",
                                             "required": "请输入主ip"
                                         })
    back_ip = serializers.IPAddressField(required=True,
                                         help_text="副ip",
                                         error_messages={
                                             "blank": "请输入副ip",
                                             "required": "请输入副ip"
                                         })
    apapa_ip = serializers.IPAddressField(required=False,
                                          allow_blank=True,
                                          allow_null=True,
                                          help_text="APAPAip")
    cdn_ip = serializers.IPAddressField(required=False,
                                        allow_blank=True,
                                        allow_null=True,
                                        help_text="CDNip")
    lan_ip = serializers.IPAddressField(read_only=False,
                                        allow_blank=True,
                                        allow_null=True,
                                        help_text='LANip')
    creater = serializers.CharField(max_length=30,
                                    required=True,
                                    help_text="搭建人",
                                    error_messages={
                                        "blank": "请输入创建人",
                                        "required": "请输入创建人"
                                    })

    def validate_custumer_token(self, custumer_token):
        if DeviceInfo.objects.filter(custumer_token=custumer_token).count():
            raise serializers.ValidationError("商户编码已经存在")
        return custumer_token

    def validate_main_ip(self, main_ip):
        if DeviceInfo.objects.filter(~Q(customer_token=self.instance),
                                     main_ip=main_ip):
            instance = DeviceInfo.objects.filter(
                ~Q(customer_token=self.instance), main_ip=main_ip)
            raise serializers.ValidationError("该ip和{}客户主ip冲突,请查看".format(
                instance[0].customer_token))
        if DeviceInfo.objects.filter(back_ip=main_ip):
            instance = DeviceInfo.objects.filter(back_ip=main_ip)
            raise serializers.ValidationError("该ip和{}客户副ip冲突,请查看".format(
                instance[0].customer_token))
        if DeviceInfo.objects.filter(apapa_ip=main_ip):
            instance = DeviceInfo.objects.filter(apapa_ip=main_ip)
            raise serializers.ValidationError("该ip和{}客户apapaip冲突,请查看".format(
                instance[0].customer_token))
        if DeviceInfo.objects.filter(cdn_ip=main_ip):
            instance = DeviceInfo.objects.filter(cdn_ip=main_ip)
            raise serializers.ValidationError("该ip和{}客户cdnip冲突,请查看".format(
                instance[0].customer_token))
        return main_ip

    def validate_back_ip(self, back_ip):
        if DeviceInfo.objects.filter(main_ip=back_ip):
            instance = DeviceInfo.objects.filter(main_ip=back_ip)
            raise serializers.ValidationError("该ip和{}客户主ip冲突,请查看".format(
                instance[0].customer_token))
        if DeviceInfo.objects.filter(~Q(customer_token=self.instance),
                                     back_ip=back_ip):
            instance = DeviceInfo.objects.filter(
                ~Q(customer_token=self.instance), back_ip=back_ip)
            raise serializers.ValidationError("该ip和{}客户副ip冲突,请查看".format(
                instance[0].customer_token))
        if DeviceInfo.objects.filter(apapa_ip=back_ip):
            instance = DeviceInfo.objects.filter(apapa_ip=back_ip)
            raise serializers.ValidationError("该ip和{}客户apapaip冲突,请查看".format(
                instance[0].customer_token))
        if DeviceInfo.objects.filter(cdn_ip=back_ip):
            instance = DeviceInfo.objects.filter(cdn_ip=back_ip)
            raise serializers.ValidationError("该ip和{}客户cdnip冲突,请查看".format(
                instance[0].customer_token))
        return back_ip

    def validate_apapa_ip(self, apapa_ip):
        if apapa_ip:
            if DeviceInfo.objects.filter(main_ip=apapa_ip):
                instance = DeviceInfo.objects.filter(main_ip=apapa_ip)
                raise serializers.ValidationError("该ip和{}客户主ip冲突,请查看".format(
                    instance[0].customer_token))
            if DeviceInfo.objects.filter(back_ip=apapa_ip):
                instance = DeviceInfo.objects.filter(back_ip=apapa_ip)
                raise serializers.ValidationError("该ip和{}客户副ip冲突,请查看".format(
                    instance[0].customer_token))
            if DeviceInfo.objects.filter(~Q(customer_token=self.instance),
                                         apapa_ip=apapa_ip):
                instance = DeviceInfo.objects.filter(
                    ~Q(customer_token=self.instance), apapa_ip=apapa_ip)
                raise serializers.ValidationError(
                    "该ip和{}客户apapaip冲突,请查看".format(instance[0].customer_token))
            if DeviceInfo.objects.filter(cdn_ip=apapa_ip):
                instance = DeviceInfo.objects.filter(cdn_ip=apapa_ip)
                raise serializers.ValidationError("该ip和{}客户cdnip冲突,请查看".format(
                    instance[0].customer_token))
            return apapa_ip

    def validate_cdn_ip(self, cdn_ip):
        if cdn_ip:
            if DeviceInfo.objects.filter(main_ip=cdn_ip):
                instance = DeviceInfo.objects.filter(main_ip=cdn_ip)
                raise serializers.ValidationError("该ip和{}客户主ip冲突,请查看".format(
                    instance[0].customer_token))
            if DeviceInfo.objects.filter(back_ip=cdn_ip):
                instance = DeviceInfo.objects.filter(back_ip=cdn_ip)
                raise serializers.ValidationError("该ip和{}客户副ip冲突,请查看".format(
                    instance[0].customer_token))
            if DeviceInfo.objects.filter(apapa_ip=cdn_ip):
                instance = DeviceInfo.objects.filter(apapa_ip=cdn_ip)
                raise serializers.ValidationError(
                    "该ip和{}客户apapaip冲突,请查看".format(instance[0].customer_token))
            if DeviceInfo.objects.filter(~Q(customer_token=self.instance),
                                         cdn_ip=cdn_ip):
                instance = DeviceInfo.objects.filter(
                    ~Q(customer_token=self.instance), cdn_ip=cdn_ip)
                raise serializers.ValidationError("该ip和{}客户cdnip冲突,请查看".format(
                    instance[0].customer_token))
            return cdn_ip

    class Meta:
        model = DeviceInfo
        fields = "__all__"
示例#5
0
class ConnectionRequestSerializerCreate(serializers.Serializer):
    ip_address = serializers.IPAddressField(protocol='both')
    node_identifier = serializers.CharField(max_length=VERIFY_KEY_LENGTH)
    port = serializers.IntegerField(allow_null=True,
                                    max_value=65535,
                                    min_value=0,
                                    required=False)
    protocol = serializers.ChoiceField(choices=PROTOCOL_CHOICES)

    def create(self, validated_data):
        """
        Process validated connection request
        """

        config_data = validated_data

        if config_data['node_type'] == BANK:
            create_bank_from_config_data(config_data=validated_data)

        if config_data['node_type'] == CONFIRMATION_VALIDATOR:
            create_validator_from_config_data(config_data=validated_data)

        return True

    @staticmethod
    def get_node_config(data):
        """
        Attempt to connect to node
        Return nodes config data after validation
        """

        ip_address = data['ip_address']
        protocol = data['protocol']

        try:
            address = format_address(ip_address=ip_address,
                                     port=data.get('port'),
                                     protocol=protocol)
            config_address = f'{address}/config'
            config_data = fetch(url=config_address, headers={})

            if config_data['node_type'] == BANK:
                config_serializer = BankConfigurationSerializer(
                    data=config_data)
            elif config_data['node_type'] == CONFIRMATION_VALIDATOR:
                config_serializer = ValidatorConfigurationSerializer(
                    data=config_data)
            elif config_data['node_type'] == PRIMARY_VALIDATOR:
                raise serializers.ValidationError(
                    'Unable to accept connection requests from primary validators'
                )
            else:
                raise serializers.ValidationError('Invalid node_type')

            config_node_identifier = config_data['node_identifier']
            signed_node_identifier = data['node_identifier']

            if config_node_identifier != signed_node_identifier:
                raise serializers.ValidationError(
                    f'Node config node_identifier of {config_node_identifier} does not match '
                    f'signed node_identifier of {signed_node_identifier}')

        except Exception as e:
            logger.exception(e)
            raise serializers.ValidationError(e)

        if config_serializer.is_valid():
            return config_data
        else:
            logger.exception(config_serializer.errors)
            raise serializers.ValidationError(config_serializer.errors)

    def update(self, instance, validated_data):
        raise RuntimeError('Method unavailable')

    def validate(self, data):
        """
        Attempt to connect to node
        """

        ip_address = data['ip_address']
        protocol = data['protocol']

        if Bank.objects.filter(ip_address=ip_address,
                               protocol=protocol).exists():
            raise serializers.ValidationError('Already connected to bank')

        if SelfConfiguration.objects.filter(ip_address=ip_address,
                                            protocol=protocol).exists():
            raise serializers.ValidationError('Unable to connect to self')

        if Validator.objects.filter(ip_address=ip_address,
                                    protocol=protocol).exists():
            raise serializers.ValidationError('Already connected to validator')

        return self.get_node_config(data)

    @staticmethod
    def validate_node_identifier(node_identifier):
        """
        Validate node_identifier length
        """

        if len(node_identifier) != VERIFY_KEY_LENGTH:
            raise serializers.ValidationError(
                f'node_identifier must be {VERIFY_KEY_LENGTH} characters long')

        if Bank.objects.filter(node_identifier=node_identifier).exists():
            raise serializers.ValidationError(
                'Bank with that node identifier already exists')

        if Validator.objects.filter(node_identifier=node_identifier).exists():
            raise serializers.ValidationError(
                'Validator with that node identifier already exists')

        return node_identifier
示例#6
0
class IPLocationSerializer(natrix_serializers.NatrixSerializer):
    """IP and Location information

    """
    ip = rest_serializers.IPAddressField()
    location = LocationSerializer(required=False, allow_null=True)
示例#7
0
class TerminalInfo(natrix_serializers.NatrixSerializer):
    mac = rest_serializers.CharField(max_length=32)
    ip = rest_serializers.IPAddressField()
示例#8
0
class UserSerializerrr(serializers.ModelSerializer):
    snippets = serializers.PrimaryKeyRelatedField(many=True, queryset=Snippet.objects.all())
    article_slugs = serializers.SlugRelatedField(read_only=True, slug_field='slug', many=True, source='articles')
    last_connected_ip = serializers.IPAddressField(help_text="i'm out of ideas", protocol='ipv4', read_only=True)
    last_connected_at = serializers.DateField(help_text="really?", read_only=True)

    other_stuff = serializers.SerializerMethodField(
        help_text="the decorator should determine the serializer class for this")

    hint_example = MethodFieldExampleSerializer()

    @swagger_serializer_method(serializer_or_field=OtherStuffSerializer)
    def get_other_stuff(self, obj):
        """
        method_field that uses a serializer internally.

        By using the decorator, we can tell drf-yasg how to represent this in Swagger
        :param obj:
        :return:
        """
        return OtherStuffSerializer().data

    help_text_example_1 = serializers.SerializerMethodField(
        help_text="help text on field is set, so this should appear in swagger"
    )

    @swagger_serializer_method(serializer_or_field=serializers.IntegerField(
        help_text="decorated instance help_text shouldn't appear in swagger because field has priority"))
    def get_help_text_example_1(self):
        """
        method docstring shouldn't appear in swagger because field has priority
        :return:
        """
        return 1

    help_text_example_2 = serializers.SerializerMethodField()

    @swagger_serializer_method(serializer_or_field=serializers.IntegerField(
        help_text="instance help_text is set, so should appear in swagger"))
    def get_help_text_example_2(self):
        """
        method docstring shouldn't appear in swagger because decorator has priority
        :return:
        """
        return 1

    help_text_example_3 = serializers.SerializerMethodField()

    @swagger_serializer_method(serializer_or_field=serializers.IntegerField())
    def get_help_text_example_3(self):
        """
        docstring is set so should appear in swagger as fallback
        :return:
        """
        return 1

    class Meta:
        model = User
        fields = ('id', 'username', 'email', 'articles', 'snippets',
                  'last_connected_ip', 'last_connected_at', 'article_slugs', 'other_stuff', 'hint_example',
                  'help_text_example_1', 'help_text_example_2', 'help_text_example_3')
示例#9
0
class InstanceSerializer(serializers.Serializer):
    id = serializers.CharField(read_only=True)
    url = CustomHyperlinkedIdentityField(view_name='instance-detail',
                                         lookup_field='id',
                                         lookup_url_kwarg='pk',
                                         parent_url_kwargs=['cloud_pk'])
    name = serializers.CharField()
    public_ips = serializers.ListField(serializers.IPAddressField())
    private_ips = serializers.ListField(serializers.IPAddressField())
    instance_type_id = ProviderPKRelatedField(
        label="Instance Type",
        queryset='compute.instance_types',
        display_fields=['name'],
        display_format="{0}",
        required=True)
    instance_type_url = CustomHyperlinkedIdentityField(
        view_name='instance_type-detail',
        lookup_field='instance_type_id',
        lookup_url_kwarg='pk',
        parent_url_kwargs=['cloud_pk'])
    image_id = ProviderPKRelatedField(label="Image",
                                      queryset='compute.images',
                                      display_fields=['name', 'id'],
                                      display_format="{0} ({1})",
                                      required=True)
    image_id_url = CustomHyperlinkedIdentityField(
        view_name='machine_image-detail',
        lookup_field='image_id',
        lookup_url_kwarg='pk',
        parent_url_kwargs=['cloud_pk'])
    key_pair_name = ProviderPKRelatedField(label="Keypair Name",
                                           queryset='security.key_pairs',
                                           display_fields=['id'],
                                           display_format="{0}",
                                           required=True)
    zone_id = PlacementZonePKRelatedField(label="Placement Zone",
                                          queryset='non_empty_value',
                                          display_fields=['id'],
                                          display_format="{0}",
                                          required=True)
    security_group_ids = ProviderPKRelatedField(
        label="Security Groups",
        queryset='security.security_groups',
        display_fields=['name'],
        display_format="{0}",
        many=True)
    user_data = serializers.CharField(write_only=True,
                                      style={'base_template': 'textarea.html'})

    def create(self, validated_data):
        provider = view_helpers.get_cloud_provider(self.context.get('view'))
        name = validated_data.get('name')
        image_id = validated_data.get('image_id')
        instance_type = validated_data.get('instance_type_id')
        kp_name = validated_data.get('key_pair_name')
        zone_id = validated_data.get('zone_id')
        security_group_ids = validated_data.get('security_group_ids')
        user_data = validated_data.get('user_data')
        try:
            return provider.compute.instances.create(
                name,
                image_id,
                instance_type,
                zone=zone_id,
                key_pair=kp_name,
                security_groups=security_group_ids,
                user_data=user_data)
        except Exception as e:
            raise serializers.ValidationError("{0}".format(e))

    def update(self, instance, validated_data):
        try:
            if instance.name != validated_data.get('name'):
                instance.name = validated_data.get('name')
            return instance
        except Exception as e:
            raise serializers.ValidationError("{0}".format(e))
示例#10
0
class CreateVirtualConfigSerializer(serializers.Serializer):
    domain = serializers.CharField(
        help_text='Domain name.',
        label='Domain',
        max_length=254,
        min_length=3,
        required=True
    )

    ip = serializers.IPAddressField(
        help_text='IP Address.',
        label='IP Address',
        required=True
    )

    port = serializers.ChoiceField(
        choices=[
            80,
            443
        ],
        help_text='Port.',
        label='Port',
        required=True
    )

    user = serializers.RegexField(
        help_text='System user name.',
        label='User',
        max_length=32,
        min_length=2,
        regex='^[a-z][a-z0-9]+$',
        required=True
    )

    def validate_domain(self, value):
        if not validators.domain(value):
            raise serializers.ValidationError(
                f"Domain '{value}' is invalid.",
                code='invalid'
            )

        return value

    def validate_ip(self, value):
        ip = ipaddress.ip_address(value)

        if ip.version == 4:
            file = str(ip).replace('.', '_')
        else:
            file = str(ip).replace(':', '_')

        if not os.path.exists(f"{SystemPath.ip_base_dir()}{file}"):
            raise serializers.ValidationError(
                f"System IP '{ip}' Address does not exist.",
                code='not_found'
            )

        return ip

    def validate_user(self, value):
        try:
            pwd.getpwnam(value).pw_uid
        except KeyError:
            raise serializers.ValidationError(
                f"System User '{value}' does not exist.",
                code='not_found'
            )

        return value

    def validate(self, attrs):
        domain = attrs.get('domain')

        user = attrs.get('user')

        port = attrs.get('port')

        if not os.path.exists(f"{NginxPath.conf_dir()}.isInstalled"):
            raise serializers.ValidationError(
                'Nginx Server has not yet been installed.',
                code='not_installed'
            )

        elif os.path.exists(f"{NginxPath.sites_dir()}{domain}.{port}.conf"):
            raise serializers.ValidationError(
                'Nginx Virtual Configuration already exists.',
                code='exists'
            )

        elif not os.path.exists(f"{WebPath.www_dir(user)}/{domain}"):
            raise serializers.ValidationError(
                f"Web Domain '{domain}' does not exist.",
                code='not_found'
            )

        return attrs

    def create(self, validated_data):
        validated_domain = validated_data['domain']

        validated_ip = validated_data['ip']

        validated_port = validated_data['port']

        validated_user = validated_data['user']

        path_config = f"{NginxPath.sites_dir()}{validated_domain}.{validated_port}.conf"

        path_config_enabled = f"{NginxPath.sites_enabled_dir()}{validated_domain}.{validated_port}.conf"

        ip = (str(validated_ip) if validated_ip.version == 4 else f"[{validated_ip}]")

        content = render_to_string(f"nginx/virtualhost_{validated_port}.tmpl") \
            .replace('[WEB-DOMAIN]', validated_domain) \
            .replace('[WEB-VHOST]', WebPath.www_dir(validated_user)) \
            .replace('[WEB-VHOST-SSL]', WebPath.ssl_dir(validated_user)) \
            .replace('[SYSTEM-IPADDRESS]', ip)

        handle = open(path_config, 'w')
        handle.write(content)
        handle.close()

        os.symlink(path_config, path_config_enabled)

        path_sites_conf = f"{NginxPath.sites_conf_dir()}{validated_domain}"

        if not os.path.exists(path_sites_conf):
            os.makedirs(path_sites_conf, 0o755)
            shutil.chown(path_sites_conf, user='******', group='root')

        return validated_data
示例#11
0
class ServerAutoReportSerializer(serializers.Serializer):
    """
    服务器同步序列化类
    """
    ip          = serializers.IPAddressField(required=True)
    hostname    = serializers.CharField(required=True, max_length=20)
    cpu         = serializers.CharField(required=True, max_length=50)
    mem         = serializers.CharField(required=True, max_length=20)
    disk        = serializers.CharField(required=True, max_length=200)
    os          = serializers.CharField(required=True, max_length=50)
    sn          = serializers.CharField(required=True, max_length=50)
    manufacturer= serializers.CharField(required=True)
    model_name  = serializers.CharField(required=True)
    uuid        = serializers.CharField(required=True, max_length=50)
    network     = serializers.JSONField(required=True)

    def validate_manufacturer(self, value):
        try:
            return Manufacturer.objects.get(vendor_name__exact=value)
        except Manufacturer.DoesNotExist:
            return self.create_manufacturer(value)

    def validate(self, attrs):
        manufacturer_obj = attrs["manufacturer"]
        try:
            attrs["model_name"] = manufacturer_obj.productmodel_set.get(model_name__exact=attrs["model_name"])
        except ProductModel.DoesNotExist:
            attrs["model_name"] = self.create_product_model(manufacturer_obj, attrs["model_name"])
        return attrs

    def create_server(self, validated_data):
        network = validated_data.pop("network")
        server_obj = Server.objects.create(**validated_data)
        self.check_server_network_device(server_obj, network)
        return server_obj

    def create(self, validated_data):
        uuid = validated_data["uuid"].lower()
        sn   = validated_data["sn"].lower()

        try:
            if sn == uuid or sn == "" or sn.startswith("vmware"):
                server_obj = Server.objects.get(uuid__icontains=uuid)
            else:
                server_obj = Server.objects.get(sn__icontains=sn)
        except Server.DoesNotExist:
            return self.create_server(validated_data)
        else:
            return self.update_server(server_obj, validated_data)

    def update_server(self, instance, validated_data):
        instance.hostname = validated_data.get("hostname", instance.hostname)
        instance.cpu = validated_data.get("cpu", instance.cpu)
        instance.ip = validated_data.get("ip", instance.ip)
        instance.mem = validated_data.get("mem", instance.mem)
        instance.disk = validated_data.get("disk", instance.disk)
        instance.os = validated_data.get("os", instance.os)
        instance.save()
        self.check_server_network_device(instance, validated_data["network"])
        return instance

    def check_server_network_device(self,server_obj, network):
        """
        检查批定服务器有没有这些网卡设备,并作关联
        """
        network_device_queryset = server_obj.networkdevice_set.all()
        current_network_device_queryset = []
        for device in network:
            try:
                network_device_obj = network_device_queryset.get(name__exact=device["name"])
            except NetworkDevice.DoesNotExist:
                network_device_obj = self.create_network_device(server_obj, device)
            self.check_ip(network_device_obj, device["ips"])
            current_network_device_queryset.append(network_device_obj)

        for network_device_obj in list(set(network_device_queryset) - set(current_network_device_queryset)):
            network_device_obj.delete()

    def check_ip(self, network_device_obj, ifnets):
        ip_queryset = network_device_obj.ip_set.all()
        current_ip_queryset = []
        for ifnet in ifnets:
            try:
                ip_obj = ip_queryset.get(ip_addr__exact=ifnet["ip_addr"])
            except IP.DoesNotExist:
                ip_obj = self.create_ip(network_device_obj, ifnet)
            current_ip_queryset.append(ip_obj)

        for ip_obj in list(set(ip_queryset) - set(current_ip_queryset)):
            ip_obj.delete()

    def create_ip(self, network_device_obj, ifnet):
        ifnet["device"] = network_device_obj
        return IP.objects.create(**ifnet)


    def create_network_device(self,server_obj, device):
        device.pop("ips")
        device["host"] = server_obj
        network_device_obj = NetworkDevice.objects.create(**device)
        return network_device_obj


    def create_manufacturer(self, vendor_name):
        return Manufacturer.objects.create(vendor_name=vendor_name)

    def create_product_model(self,manufacturer_obj, model_name):
        return ProductModel.objects.create(model_name=model_name, vendor=manufacturer_obj)

    def to_representation(self, instance):
        ret = {
            "hostname": instance.hostname,
            "ip": instance.ip
        }
        return ret
示例#12
0
class VirtualMachineSerializer(structure_serializers.BaseResourceSerializer):
    endpoints = InstanceEndpointsSerializer(many=True, read_only=True)

    service = serializers.HyperlinkedRelatedField(
        source='service_project_link.service',
        view_name='azure-detail',
        read_only=True,
        lookup_field='uuid')

    service_project_link = serializers.HyperlinkedRelatedField(
        view_name='azure-spl-detail',
        queryset=models.AzureServiceProjectLink.objects.all(),
        allow_null=True,
        required=False,
    )

    image = serializers.HyperlinkedRelatedField(
        view_name='azure-image-detail',
        lookup_field='uuid',
        queryset=models.Image.objects.all(),
        write_only=True)

    size = serializers.HyperlinkedRelatedField(view_name='azure-size-detail',
                                               lookup_field='uuid',
                                               queryset=SizeQueryset(),
                                               write_only=True)

    external_ips = serializers.ListField(
        child=serializers.IPAddressField(),
        read_only=True,
    )

    user_username = serializers.CharField(required=True)
    user_password = serializers.CharField(required=True,
                                          style={'input_type': 'password'})

    rdp = serializers.HyperlinkedIdentityField(
        view_name='azure-virtualmachine-rdp', lookup_field='uuid')

    class Meta(structure_serializers.BaseResourceSerializer.Meta):
        model = models.VirtualMachine
        view_name = 'azure-virtualmachine-detail'
        fields = structure_serializers.BaseResourceSerializer.Meta.fields + (
            'image',
            'size',
            'user_username',
            'user_password',
            'user_data',
            'rdp',
            'external_ips',
            'internal_ips',
            'runtime_state',
            'start_time',
            'cores',
            'ram',
            'disk',
            'image_name',
            'endpoints',
        )
        protected_fields = structure_serializers.BaseResourceSerializer.Meta.protected_fields + (
            'image', 'size', 'user_username', 'user_password', 'user_data')
        read_only_fields = structure_serializers.BaseResourceSerializer.Meta.read_only_fields + (
            'external_ips', 'internal_ips', 'runtime_state', 'start_time',
            'cores', 'ram', 'disk', 'image_name')

    def validate(self, attrs):
        attrs = super(VirtualMachineSerializer, self).validate(attrs)

        if not re.match(r'[a-zA-Z][a-zA-Z0-9-]{0,13}[a-zA-Z0-9]$',
                        attrs['name']):
            raise serializers.ValidationError({
                'name':
                _("The name can contain only letters, numbers, and hyphens. "
                  "The name must be shorter than 15 characters and start with "
                  "a letter and must end with a letter or a number.")
            })

        # passwords must contain characters from at least three of the following four categories:
        groups = (r'[a-z]', r'[A-Z]', r'[0-9]', r'[^a-zA-Z\d\s:]')
        password = attrs['user_password']
        if not 6 <= len(password) <= 72 or sum(
                bool(re.search(g, password)) for g in groups) < 3:
            raise serializers.ValidationError({
                'user_password':
                _("The supplied password must be 6-72 characters long "
                  "and contain 3 of the following: a lowercase character, "
                  "an uppercase character, a number, a special character.")
            })

        if re.match(r'Administrator|Admin', attrs['user_username'], re.I):
            raise serializers.ValidationError(
                {'user_username': _('Invalid administrator username.')})

        return attrs

    @transaction.atomic
    def create(self, validated_data):
        image = validated_data['image']
        validated_data['image_name'] = image.name
        size = validated_data['size']
        validated_data['cores'] = size.cores
        validated_data['ram'] = size.ram
        validated_data['disk'] = size.disk
        return super(VirtualMachineSerializer, self).create(validated_data)
示例#13
0
class RequestAssetPermTicketSerializer(serializers.ModelSerializer):
    actions = ActionsField(source='meta.actions',
                           choices=Action.DB_CHOICES,
                           default=Action.CONNECT)
    ips = serializers.ListField(child=serializers.IPAddressField(),
                                source='meta.ips',
                                default=list,
                                label=_('IP group'))
    hostname = serializers.CharField(max_length=256,
                                     source='meta.hostname',
                                     default='',
                                     allow_blank=True,
                                     label=_('Hostname'))
    system_user = serializers.CharField(max_length=256,
                                        source='meta.system_user',
                                        default='',
                                        allow_blank=True,
                                        label=_('System user'))
    date_start = serializers.DateTimeField(source='meta.date_start',
                                           allow_null=True,
                                           required=False,
                                           label=_('Date start'))
    date_expired = serializers.DateTimeField(source='meta.date_expired',
                                             allow_null=True,
                                             required=False,
                                             label=_('Date expired'))
    confirmed_assets = serializers.ListField(child=serializers.UUIDField(),
                                             source='meta.confirmed_assets',
                                             default=list,
                                             required=False,
                                             label=_('Confirmed assets'))
    confirmed_system_users = serializers.ListField(
        child=serializers.UUIDField(),
        source='meta.confirmed_system_users',
        default=list,
        required=False,
        label=_('Confirmed system user'))
    assets_waitlist_url = serializers.SerializerMethodField()
    system_users_waitlist_url = serializers.SerializerMethodField()

    class Meta:
        model = Ticket
        mini_fields = ['id', 'title']
        small_fields = [
            'status', 'action', 'date_created', 'date_updated',
            'system_users_waitlist_url', 'type', 'type_display',
            'action_display', 'ips', 'confirmed_assets', 'date_start',
            'date_expired', 'confirmed_system_users', 'hostname',
            'assets_waitlist_url', 'system_user', 'org_id', 'actions',
            'comment'
        ]
        m2m_fields = [
            'user', 'user_display', 'assignees', 'assignees_display',
            'assignee', 'assignee_display'
        ]

        fields = mini_fields + small_fields + m2m_fields
        read_only_fields = [
            'user_display',
            'assignees_display',
            'type',
            'user',
            'status',
            'date_created',
            'date_updated',
            'action',
            'id',
            'assignee',
            'assignee_display',
        ]
        extra_kwargs = {
            'status': {
                'label': _('Status')
            },
            'action': {
                'label': _('Action')
            },
            'user_display': {
                'label': _('User')
            },
            'org_id': {
                'required': True
            }
        }

    def validate(self, attrs):
        org_id = attrs.get('org_id')
        assignees = attrs.get('assignees')

        instance = self.instance
        if instance is not None:
            if org_id and not assignees:
                assignees = list(instance.assignees.all())
            elif assignees and not org_id:
                org_id = instance.org_id
            elif assignees and org_id:
                pass
            else:
                return attrs

        user = self.context['request'].user
        org = Organization.get_instance(org_id)
        if org is None:
            raise serializers.ValidationError(_('Invalid `org_id`'))

        q = Q(role=User.ROLE.ADMIN)
        if not org.is_default():
            q |= Q(m2m_org_members__role=ORG_ROLE.ADMIN,
                   orgs__id=org_id,
                   orgs__members=user)

        q &= Q(id__in=[assignee.id for assignee in assignees])
        count = User.objects.filter(q).distinct().count()
        if count != len(assignees):
            raise serializers.ValidationError(
                _('Field `assignees` must be organization admin or superuser'))
        return attrs

    def get_system_users_waitlist_url(self, instance: Ticket):
        if not self._is_assignee(instance):
            return None
        return reverse('api-assets:system-user-list')

    def get_assets_waitlist_url(self, instance: Ticket):
        if not self._is_assignee(instance):
            return None

        asset_api = reverse('api-assets:asset-list')
        query = ''

        meta = instance.meta
        hostname = meta.get('hostname')
        if hostname:
            query = '?search=%s' % hostname

        return asset_api + query

    def _recommend_assets(self, data, instance):
        confirmed_assets = data.get('confirmed_assets')
        if not confirmed_assets and self._is_assignee(instance):
            ips = data.get('ips')
            hostname = data.get('hostname')
            limit = 5

            q = Q(id=None)
            if ips:
                limit = len(ips) + 2
                q |= Q(ip__in=ips)
            if hostname:
                q |= Q(hostname__icontains=hostname)

            data['confirmed_assets'] = list(
                map(lambda x: str(x),
                    chain(
                        *Asset.objects.filter(q)[0:limit].values_list('id'))))

    def to_representation(self, instance):
        data = super().to_representation(instance)
        self._recommend_assets(data, instance)
        return data

    def _create_body(self, validated_data):
        meta = validated_data['meta']
        type = Ticket.TYPE.get(validated_data.get('type', ''))
        date_start = dt_parser(meta.get('date_start')).strftime(
            settings.DATETIME_DISPLAY_FORMAT)
        date_expired = dt_parser(meta.get('date_expired')).strftime(
            settings.DATETIME_DISPLAY_FORMAT)

        validated_data['body'] = _('''
        Type: {type}<br>
        User: {username}<br>
        Ip group: {ips}<br>
        Hostname: {hostname}<br>
        System user: {system_user}<br>
        Date start: {date_start}<br>
        Date expired: {date_expired}<br>
        ''').format(type=type,
                    username=validated_data.get('user', ''),
                    ips=', '.join(meta.get('ips', [])),
                    hostname=meta.get('hostname', ''),
                    system_user=meta.get('system_user', ''),
                    date_start=date_start,
                    date_expired=date_expired)

    def create(self, validated_data):
        # `type` 与 `user` 用户不可提交,
        validated_data['type'] = self.Meta.model.TYPE.REQUEST_ASSET_PERM
        validated_data['user'] = self.context['request'].user
        # `confirmed` 相关字段只能审批人修改,所以创建时直接清理掉
        self._pop_confirmed_fields()
        self._create_body(validated_data)
        return super().create(validated_data)

    def save(self, **kwargs):
        """
        做了一些数据转换
        """
        meta = self.validated_data.get('meta', {})

        org_id = self.validated_data.get('org_id')
        if org_id is not None and org_id == Organization.DEFAULT_ID:
            self.validated_data['org_id'] = ''

        # 时间的转换,好烦😭,可能有更好的办法吧
        date_start = meta.get('date_start')
        if date_start:
            meta['date_start'] = dt_formater(date_start)

        date_expired = meta.get('date_expired')
        if date_expired:
            meta['date_expired'] = dt_formater(date_expired)

        # UUID 的转换
        confirmed_system_users = meta.get('confirmed_system_users')
        if confirmed_system_users:
            meta['confirmed_system_users'] = [
                str(system_user) for system_user in confirmed_system_users
            ]

        confirmed_assets = meta.get('confirmed_assets')
        if confirmed_assets:
            meta['confirmed_assets'] = [
                str(asset) for asset in confirmed_assets
            ]

        with tmp_to_root_org():
            return super().save(**kwargs)

    def update(self, instance, validated_data):
        new_meta = validated_data['meta']
        if not self._is_assignee(instance):
            self._pop_confirmed_fields()

        # Json 字段保存的坑😭
        old_meta = instance.meta
        meta = {}
        meta.update(old_meta)
        meta.update(new_meta)
        validated_data['meta'] = meta

        return super().update(instance, validated_data)

    def _pop_confirmed_fields(self):
        meta = self.validated_data['meta']
        meta.pop('confirmed_assets', None)
        meta.pop('confirmed_system_users', None)

    def _is_assignee(self, obj: Ticket):
        user = self.context['request'].user
        return obj.is_assignee(user)
class LastSeenSerializer(serializers.Serializer):
    ip_of_seen = serializers.IPAddressField(required=True)
示例#15
0
class ParticipantSerializer(serializers.Serializer):
    name = serializers.CharField(max_length=50)
    ip_address = serializers.IPAddressField()
    session_id = serializers.CharField(max_length=50)
示例#16
0
class RadiusAccountingSerializer(serializers.ModelSerializer):
    framed_ip_address = serializers.IPAddressField(required=False,
                                                   allow_blank=True)
    framed_ipv6_address = serializers.IPAddressField(required=False,
                                                     allow_blank=True,
                                                     protocol='IPv6')
    session_time = serializers.IntegerField(required=False, default=0)
    stop_time = serializers.DateTimeField(required=False)
    update_time = serializers.DateTimeField(required=False)
    input_octets = serializers.IntegerField(required=False, default=0)
    output_octets = serializers.IntegerField(required=False, default=0)
    # this is needed otherwise serialize will ignore status_type from accounting packet
    # as it's not a model field
    status_type = serializers.ChoiceField(write_only=True,
                                          required=True,
                                          choices=STATUS_TYPE_CHOICES)

    def _disable_token_auth(self, user):
        try:
            radius_token = RadiusToken.objects.get(user__username=user)
        except RadiusToken.DoesNotExist:
            pass
        else:
            radius_token.can_auth = False
            radius_token.save()

    def run_validation(self, data):
        for field in ['session_time', 'input_octets', 'output_octets']:
            if data.get('status_type', None) == 'Start' and data[field] == '':
                data[field] = 0
        return super().run_validation(data)

    def validate(self, data):
        """
        We need to set some timestamps according to the accounting packet type
        * update_time: set everytime a Interim-Update / Stop packet is received
        * stop_time: set everytime a Stop packet is received
        * session_time: calculated if not present in the accounting packet
        :param data: accounting packet
        :return: Dict accounting packet
        """
        time = timezone.now()
        status_type = data.pop('status_type')
        if status_type == 'Interim-Update':
            data['update_time'] = time
        if status_type == 'Stop':
            data['update_time'] = time
            data['stop_time'] = time
            # disable radius_token auth capability
            self._disable_token_auth(data['username'])
        return data

    def create(self, validated_data):
        if app_settings.API_ACCOUNTING_AUTO_GROUP:
            username = validated_data.get('username', '')
            try:
                user = User.objects.get(username=username)
            except User.DoesNotExist:
                logging.warning(
                    _(f'No corresponding user found for username: {username}'))
            else:
                group = user.radiususergroup_set.order_by('priority').first()
                groupname = group.groupname if group else None
                validated_data.update(groupname=groupname)
        return super().create(validated_data)

    class Meta:
        model = RadiusAccounting
        fields = '__all__'
        read_only_fields = ('organization', )