Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#129 add community requested source and destination objects #207

Open
wants to merge 41 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
84918ab
feat: Adding new Source-Fields to ACLStandard Rule
rvveber Sep 2, 2024
1dd426c
feat: Adding new Destination-Fields to ACLExtended Rule
rvveber Sep 2, 2024
6400e68
feat: Adding Database Constraint for ACLStandard Rule, so that at max…
rvveber Sep 2, 2024
a2e6bee
feat: Adding Database Constraint for ACLExtended Rule, so that at max…
rvveber Sep 2, 2024
2bfba2f
feat: Adding Database Constraint for ACLExtended Rule, so that at max…
rvveber Sep 2, 2024
410bc9c
refactor: Re-order; Adapt Comments; Use Constants
rvveber Sep 2, 2024
1b960c9
feat(view): Adding new Source fields to Standard Rule View Set
rvveber Sep 2, 2024
a220574
feat(view): Adding new Source fields to Extended Rule View Set
rvveber Sep 2, 2024
0585eba
feat(view): Adding new Destination fields to Extended Rule View Set
rvveber Sep 2, 2024
493c825
feat(view): Adding new Source Fields to ACL Standard Rule Template
rvveber Sep 2, 2024
bb74eef
feat(view): Adding new Source fields to ACL Extended Rule Template
rvveber Sep 2, 2024
556b4ca
feat(view): Adding new Destination fields to ACL Extended Rule Template
rvveber Sep 2, 2024
7bed2a3
feat(view): Adding new Source Fields to the Views of ACLStandardRule
rvveber Sep 2, 2024
7fbcdd2
feat(view): Adding new Source Fields to the Views of ACLExtendedRule
rvveber Sep 2, 2024
450e6ea
feat(view): Adding new Destination Fields to the Views of ACLExtended…
rvveber Sep 2, 2024
a262b31
feat(form): Adding new Sources to the ACLStandardRule creation form
rvveber Sep 2, 2024
2cca885
feat(form): ACLStandardRule: Instruct new Sources to be displayed as …
rvveber Sep 2, 2024
10a4e75
feat(form): ACLStandardRule: Change validation to support multiple so…
rvveber Sep 2, 2024
187c6f5
feat(form): Adding new Sources to the ACLExtendedRule creation form
rvveber Sep 2, 2024
a58d69e
feat(form): ACLExtendedRule: Instruct new Sources to be displayed as …
rvveber Sep 2, 2024
998a4b2
feat(form): ACLExtendedRule: Change validation to support multiple so…
rvveber Sep 2, 2024
73bac7c
feat(form): Adding new Destinations to the ACLExtendedRule creation form
rvveber Sep 2, 2024
59f3a90
feat(form): ACLExtendedRule: Instruct new Destinations to be displaye…
rvveber Sep 2, 2024
934df46
feat(form): ACLExtendedRule: Change validation to support multiple de…
rvveber Sep 2, 2024
90dd003
fix(table): Fix error when sorting host in InterfaceAssignment
rvveber Sep 2, 2024
ef61d6f
feat(table): ACLStandardRule: Changing Source Prefix to a single Sour…
rvveber Sep 2, 2024
556a9e3
feat(table): ACLExtendedRule: Changing Source Prefix to a single Sour…
rvveber Sep 2, 2024
b98606f
feat(table): ACLExtendedRule: Changing Destination Prefix to a single…
rvveber Sep 2, 2024
636b24a
feat(filter): ACLStandardRule: Adding new Sources to the filter
rvveber Sep 2, 2024
062a535
feat(filter): ACLStandardRule: Instruct new Sources to be displayed a…
rvveber Sep 2, 2024
dee2969
feat(filter): ACLExtendedRule: Adding new Sources to the filter
rvveber Sep 2, 2024
2758296
feat(filter): ACLExtendedRule: Instruct new Sources to be displayed a…
rvveber Sep 2, 2024
c6ca5d7
feat(filter): ACLExtendedRule: Adding new Destinations to the filter
rvveber Sep 2, 2024
c512099
feat(filter): ACLExtendedRule: Instruct new Destinations to be displa…
rvveber Sep 2, 2024
516841e
feat(serializer): ACLStandardRule: Adding new Source Fields to serial…
rvveber Sep 2, 2024
1ddadf3
feat(serializer): ACLStandardRule: Change validation to support multi…
rvveber Sep 2, 2024
4342b8c
feat(serializer): ACLExtendedRule: Adding new Source Fields to serial…
rvveber Sep 2, 2024
15de961
feat(serializer): ACLExtendedRule: Change validation to support multi…
rvveber Sep 2, 2024
df06833
feat(serializer): ACLExtendedRule: Adding new Destination Fields to s…
rvveber Sep 2, 2024
3f7df5d
feat(serializer): ACLExtendedRule: Change validation to support multi…
rvveber Sep 2, 2024
c0d5ab6
feat(migration): Adding migration for the new sources and destinations
rvveber Oct 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
160 changes: 137 additions & 23 deletions netbox_acls/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from django.contrib.contenttypes.models import ContentType
from drf_spectacular.utils import extend_schema_field
from ipam.api.serializers import PrefixSerializer
from ipam.api.serializers import PrefixSerializer, IPRangeSerializer, IPAddressSerializer, AggregateSerializer, ServiceSerializer
from netbox.api.fields import ContentTypeField
from netbox.api.serializers import NetBoxModelSerializer
from rest_framework import serializers
Expand All @@ -27,14 +27,20 @@
"ACLExtendedRuleSerializer",
]


# Sets a standard error message for ACL rules with an action of remark, but no remark set.
error_message_no_remark = "Action is set to remark, you MUST add a remark."
# Sets a standard error message for ACL rules with an action of remark, but no source_prefix is set.
error_message_action_remark_source_prefix_set = "Action is set to remark, Source Prefix CANNOT be set."
# Sets a standard error message for ACL rules with an action of remark, but no source/destination is set.
error_message_action_remark_source_set = "Action is set to remark, Source CANNOT be set."
error_message_action_remark_destination_set = "Action is set to remark, Destination CANNOT be set."
# Sets a standard error message for ACL rules with an action not set to remark, but no remark is set.
error_message_remark_without_action_remark = "CANNOT set remark unless action is set to remark."
# Sets a standard error message for ACL rules no associated to an ACL of the same type.
error_message_acl_type = "Provided parent Access List is not of right type."
# Sets a standard error message for ACL rules when more than one IP/Host sources are set.
error_message_sources_more_than_one = "Only one IP/Host related Source can be specified."
# Sets a standard error message for ACL rules when more than one IP/Host destinations are set.
error_message_destinations_more_than_one = "Only one IP/Host related Destination can be specified."


class AccessListSerializer(NetBoxModelSerializer):
Expand Down Expand Up @@ -190,6 +196,30 @@ class ACLStandardRuleSerializer(NetBoxModelSerializer):
default=None,
nested=True
)
source_iprange = IPRangeSerializer(
required=False,
allow_null=True,
default=None,
nested=True
)
source_ipaddress = IPAddressSerializer(
required=False,
allow_null=True,
default=None,
nested=True
)
source_aggregate = AggregateSerializer(
required=False,
allow_null=True,
default=None,
nested=True
)
source_service = ServiceSerializer(
required=False,
allow_null=True,
default=None,
nested=True
)

class Meta:
"""
Expand All @@ -211,28 +241,39 @@ class Meta:
"custom_fields",
"last_updated",
"source_prefix",
"source_iprange",
"source_ipaddress",
"source_aggregate",
"source_service",
)
brief_fields = ("id", "url", "display")

def validate(self, data):
"""
Validate the ACLStandardRule django model's inputs before allowing it to update the instance:
- Check if action set to remark, but no remark set.
- Check if action set to remark, but source_prefix set.
- Check if action set to remark, but source set.
- Check not more than one source is set.
"""
error_message = {}

sources = ["source_prefix", "source_iprange", "source_ipaddress", "source_aggregate", "source_service"]

if data.get("action") == "remark":
# Check if action set to remark, but no remark set.
if data.get("remark") is None:
error_message["remark"] = [
error_message_no_remark,
]
# Check if action set to remark, but source_prefix set.
if data.get("source_prefix"):
error_message["source_prefix"] = [
error_message_action_remark_source_prefix_set,
]
# Check if action set to remark, but source set.
if any(data.get(source) for source in sources):
for source in sources:
error_message[source] = [error_message_action_remark_source_set]

# Check not more than one source is set.
if sum(bool(data.get(source)) for source in sources) > 1:
for source in sources:
error_message[source] = [error_message_sources_more_than_one]

if error_message:
raise serializers.ValidationError(error_message)
Expand All @@ -249,18 +290,68 @@ class ACLExtendedRuleSerializer(NetBoxModelSerializer):
view_name="plugins-api:netbox_acls-api:aclextendedrule-detail",
)
access_list = NestedAccessListSerializer()

source_prefix = PrefixSerializer(
required=False,
allow_null=True,
default=None,
nested=True
)
source_iprange = IPRangeSerializer(
required=False,
allow_null=True,
default=None,
nested=True
)
source_ipaddress = IPAddressSerializer(
required=False,
allow_null=True,
default=None,
nested=True
)
source_aggregate = AggregateSerializer(
required=False,
allow_null=True,
default=None,
nested=True
)
source_service = ServiceSerializer(
required=False,
allow_null=True,
default=None,
nested=True
)

destination_prefix = PrefixSerializer(
required=False,
allow_null=True,
default=None,
nested=True
)
destination_iprange = IPRangeSerializer(
required=False,
allow_null=True,
default=None,
nested=True
)
destination_ipaddress = IPAddressSerializer(
required=False,
allow_null=True,
default=None,
nested=True
)
destination_aggregate = AggregateSerializer(
required=False,
allow_null=True,
default=None,
nested=True
)
destination_service = ServiceSerializer(
required=False,
allow_null=True,
default=None,
nested=True
)

class Meta:
"""
Expand All @@ -280,9 +371,20 @@ class Meta:
"created",
"custom_fields",
"last_updated",

"source_prefix",
"source_ports",
"source_iprange",
"source_ipaddress",
"source_aggregate",
"source_service",

"destination_prefix",
"destination_iprange",
"destination_ipaddress",
"destination_aggregate",
"destination_service",

"source_ports",
"destination_ports",
"protocol",
"remark",
Expand All @@ -292,36 +394,38 @@ def validate(self, data):
"""
Validate the ACLExtendedRule django model's inputs before allowing it to update the instance:
- Check if action set to remark, but no remark set.
- Check if action set to remark, but source_prefix set.
- Check if action set to remark, but source set.
- Check if action set to remark, but destination set.
- Check if action set to remark, but source_ports set.
- Check if action set to remark, but destination_prefix set.
- Check if action set to remark, but destination_ports set.
- Check if action set to remark, but protocol set.
- Check if action set to remark, but protocol set.
- Check not more than one source is set.
- Check not more than one destination is set.
"""
error_message = {}

sources = ["source_prefix", "source_iprange", "source_ipaddress", "source_aggregate", "source_service"]
destinations = ["destination_prefix", "destination_iprange", "destination_ipaddress", "destination_aggregate", "destination_service"]

if data.get("action") == "remark":
# Check if action set to remark, but no remark set.
if data.get("remark") is None:
error_message["remark"] = [
error_message_no_remark,
]
# Check if action set to remark, but source_prefix set.
if data.get("source_prefix"):
error_message["source_prefix"] = [
error_message_action_remark_source_prefix_set,
]
# Check if action set to remark, but source set.
if any(data.get(source) for source in sources):
for source in sources:
error_message[source] = [error_message_action_remark_source_set]
# Check if action set to remark, but destination set.
if any(data.get(destination) for destination in destinations):
for destination in destinations:
error_message[destination] = [error_message_action_remark_destination_set]
# Check if action set to remark, but source_ports set.
if data.get("source_ports"):
error_message["source_ports"] = [
"Action is set to remark, Source Ports CANNOT be set.",
]
# Check if action set to remark, but destination_prefix set.
if data.get("destination_prefix"):
error_message["destination_prefix"] = [
"Action is set to remark, Destination Prefix CANNOT be set.",
]
# Check if action set to remark, but destination_ports set.
if data.get("destination_ports"):
error_message["destination_ports"] = [
Expand All @@ -332,6 +436,16 @@ def validate(self, data):
error_message["protocol"] = [
"Action is set to remark, Protocol CANNOT be set.",
]

# Check not more than one source is set.
if sum(bool(data.get(source)) for source in sources) > 1:
for source in sources:
error_message[source] = [error_message_sources_more_than_one]

# Check not more than one destination is set.
if sum(bool(data.get(destination)) for destination in destinations) > 1:
for destination in destinations:
error_message[destination] = [error_message_destinations_more_than_one]

if error_message:
raise serializers.ValidationError(error_message)
Expand Down
6 changes: 3 additions & 3 deletions netbox_acls/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class ACLStandardRuleViewSet(NetBoxModelViewSet):
queryset = models.ACLStandardRule.objects.prefetch_related(
"access_list",
"tags",
"source_prefix",
"source_prefix", "source_iprange", "source_ipaddress", "source_aggregate", "source_service"
)
serializer_class = ACLStandardRuleSerializer
filterset_class = filtersets.ACLStandardRuleFilterSet
Expand All @@ -74,8 +74,8 @@ class ACLExtendedRuleViewSet(NetBoxModelViewSet):
queryset = models.ACLExtendedRule.objects.prefetch_related(
"access_list",
"tags",
"source_prefix",
"destination_prefix",
"source_prefix", "source_iprange", "source_ipaddress", "source_aggregate", "source_service",
"destination_prefix", "destination_iprange", "destination_ipaddress", "destination_aggregate", "destination_service",
)
serializer_class = ACLExtendedRuleSerializer
filterset_class = filtersets.ACLExtendedRuleFilterSet
45 changes: 43 additions & 2 deletions netbox_acls/filtersets.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,17 @@ class Meta:
"""

model = ACLStandardRule
fields = ("id", "access_list", "index", "action")
fields = (
"id",
"access_list",
"index",
"action",
"source_prefix",
"source_iprange",
"source_ipaddress",
"source_aggregate",
"source_service",
)

def search(self, queryset, name, value):
"""
Expand All @@ -191,6 +201,11 @@ def search(self, queryset, name, value):
Q(access_list__name__icontains=value)
| Q(index__icontains=value)
| Q(action__icontains=value)
| Q(source_prefix__icontains=value)
| Q(source_iprange__icontains=value)
| Q(source_ipaddress__icontains=value)
| Q(source_aggregate__icontains=value)
| Q(source_service__icontains=value)
)
return queryset.filter(query)

Expand All @@ -206,7 +221,23 @@ class Meta:
"""

model = ACLExtendedRule
fields = ("id", "access_list", "index", "action", "protocol")
fields = (
"id",
"access_list",
"index",
"action",
"protocol",
"source_prefix",
"source_iprange",
"source_ipaddress",
"source_aggregate",
"source_service",
"destination_prefix",
"destination_iprange",
"destination_ipaddress",
"destination_aggregate",
"destination_service"
)

def search(self, queryset, name, value):
"""
Expand All @@ -217,5 +248,15 @@ def search(self, queryset, name, value):
| Q(index__icontains=value)
| Q(action__icontains=value)
| Q(protocol__icontains=value)
| Q(source_prefix__icontains=value)
| Q(source_iprange__icontains=value)
| Q(source_ipaddress__icontains=value)
| Q(source_aggregate__icontains=value)
| Q(source_service__icontains=value)
| Q(destination_prefix__icontains=value)
| Q(destination_iprange__icontains=value)
| Q(destination_ipaddress__icontains=value)
| Q(destination_aggregate__icontains=value)
| Q(destination_service__icontains=value)
)
return queryset.filter(query)
Loading