Skip to content
Snippets Groups Projects
  • Sergios Aftsidis's avatar
    4df3eb2d
    Fix REST API issues · 4df3eb2d
    Sergios Aftsidis authored
    * Fix errors not allowing `PUT` method from the API
    * Validate `status`, to allow for status changes when using
    PUT (allow changing a `Route`  to `INACTIVE`, re-submitting
    `Route`s with `ERROR` state & more)
    * Move decision for whether to `commit_*` a `Route` from
    `post_save` to `update` since we need to know both the current
    `status` of the `Route` and the desired (new) to pick which
    `commit` we want
    * We need to expose `id`s in all REST API models since those are
    needed when creating relationships between those models
    * Register `MatchDscp` model (`Route` uses it)
    * Add REST API documentation
    * When creating / editing / deleting a `Route` from the API an
    asynchronous task is issued which uploads the required configuration
    on the flowspec device. Since this is asynchronous, the object
    must have a status of `PENDING` until this operation is completed.
    4df3eb2d
    History
    Fix REST API issues
    Sergios Aftsidis authored
    * Fix errors not allowing `PUT` method from the API
    * Validate `status`, to allow for status changes when using
    PUT (allow changing a `Route`  to `INACTIVE`, re-submitting
    `Route`s with `ERROR` state & more)
    * Move decision for whether to `commit_*` a `Route` from
    `post_save` to `update` since we need to know both the current
    `status` of the `Route` and the desired (new) to pick which
    `commit` we want
    * We need to expose `id`s in all REST API models since those are
    needed when creating relationships between those models
    * Register `MatchDscp` model (`Route` uses it)
    * Add REST API documentation
    * When creating / editing / deleting a `Route` from the API an
    asynchronous task is issued which uploads the required configuration
    on the flowspec device. Since this is asynchronous, the object
    must have a status of `PENDING` until this operation is completed.
serializers.py 2.88 KiB
"""
Serializers for flowspec models
"""
from rest_framework import serializers
from flowspec.models import (
    Route, MatchPort, ThenAction, FragmentType, MatchProtocol, MatchDscp)
from flowspec.validators import (
    clean_source, clean_destination, clean_expires, clean_status)


class RouteSerializer(serializers.HyperlinkedModelSerializer):
    """
    A serializer for `Route` objects
    """
    applier = serializers.CharField(source='applier_username', read_only=True)

    def validate_source(self, attrs, source):
        user = self.context.get('request').user
        source_ip = attrs.get('source')
        res = clean_source(user, source_ip)
        if res != source_ip:
            raise serializers.ValidationError(res)
        return attrs

    def validate_destination(self, attrs, source):
        user = self.context.get('request').user
        destination = attrs.get('destination')
        res = clean_destination(user, destination)
        if res != destination:
            raise serializers.ValidationError(res)
        return attrs

    def validate_expires(self, attrs, source):
        expires = attrs.get('expires')
        res = clean_expires(expires)
        if res != expires:
            raise serializers.ValidationError(res)
        return attrs

    def validate_status(self, attrs, source):
        status = attrs.get('status')
        res = clean_status(status)
        if res != status:
            raise serializers.ValidationError(res)
        return attrs

    class Meta:
        model = Route
        fields = (
            'name', 'id', 'comments', 'applier', 'source', 'sourceport',
            'destination', 'destinationport', 'port', 'dscp', 'fragmenttype',
            'icmpcode', 'packetlength', 'protocol', 'tcpflag', 'then', 'filed',
            'last_updated', 'status', 'expires', 'response', 'comments',
            'requesters_address')
        read_only_fields = (
            'requesters_address', 'response', 'last_updated', 'id', 'filed')


class PortSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = MatchPort
        fields = ('id', 'port', )
        read_only_fields = ('id', )


class ThenActionSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = ThenAction
        fields = ('id', 'action', 'action_value')
        read_only_fields = ('id', )


class FragmentTypeSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = FragmentType
        fields = ('id', 'fragmenttype', )
        read_only_fields = ('id', )


class MatchProtocolSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = MatchProtocol
        fields = ('id', 'protocol', )
        read_only_fields = ('id', )


class MatchDscpSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = MatchDscp
        fields = ('id', 'dscp', )
        read_only_fields = ('id', )