Skip to content

#129 add community requested source and destination objects #207

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

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
e97b5af
feat: Adding new Source-Fields to ACLStandard Rule
rvveber Sep 2, 2024
426ad54
feat: Adding new Destination-Fields to ACLExtended Rule
rvveber Sep 2, 2024
04351fb
feat: Adding Database Constraint for ACLStandard Rule, so that at max…
rvveber Sep 2, 2024
a84cd18
feat: Adding Database Constraint for ACLExtended Rule, so that at max…
rvveber Sep 2, 2024
0bc9cf2
feat: Adding Database Constraint for ACLExtended Rule, so that at max…
rvveber Sep 2, 2024
675a72d
refactor: Re-order; Adapt Comments; Use Constants
rvveber Sep 2, 2024
d513e54
feat(view): Adding new Source fields to Standard Rule View Set
rvveber Sep 2, 2024
19f325e
feat(view): Adding new Source fields to Extended Rule View Set
rvveber Sep 2, 2024
baf9961
feat(view): Adding new Destination fields to Extended Rule View Set
rvveber Sep 2, 2024
ba1d4cf
feat(view): Adding new Source Fields to ACL Standard Rule Template
rvveber Sep 2, 2024
5bea6ad
feat(view): Adding new Source fields to ACL Extended Rule Template
rvveber Sep 2, 2024
fa55c0e
feat(view): Adding new Destination fields to ACL Extended Rule Template
rvveber Sep 2, 2024
d38a9c6
feat(view): Adding new Source Fields to the Views of ACLStandardRule
rvveber Sep 2, 2024
2b4a237
feat(view): Adding new Source Fields to the Views of ACLExtendedRule
rvveber Sep 2, 2024
11912b5
feat(view): Adding new Destination Fields to the Views of ACLExtended…
rvveber Sep 2, 2024
7adb987
feat(form): Adding new Sources to the ACLStandardRule creation form
rvveber Sep 2, 2024
87515f4
feat(form): ACLStandardRule: Instruct new Sources to be displayed as …
rvveber Sep 2, 2024
d290ae1
feat(form): ACLStandardRule: Change validation to support multiple so…
rvveber Sep 2, 2024
8d35acb
feat(form): Adding new Sources to the ACLExtendedRule creation form
rvveber Sep 2, 2024
00bc0ac
feat(form): ACLExtendedRule: Instruct new Sources to be displayed as …
rvveber Sep 2, 2024
1179ccd
feat(form): ACLExtendedRule: Change validation to support multiple so…
rvveber Sep 2, 2024
72ef307
feat(form): Adding new Destinations to the ACLExtendedRule creation form
rvveber Sep 2, 2024
ccfb3fa
feat(form): ACLExtendedRule: Instruct new Destinations to be displaye…
rvveber Sep 2, 2024
d15398d
feat(form): ACLExtendedRule: Change validation to support multiple de…
rvveber Sep 2, 2024
fa63c80
fix(table): Fix error when sorting host in InterfaceAssignment
rvveber Sep 2, 2024
4c5b49b
feat(table): ACLStandardRule: Changing Source Prefix to a single Sour…
rvveber Sep 2, 2024
91431da
feat(table): ACLExtendedRule: Changing Source Prefix to a single Sour…
rvveber Sep 2, 2024
5c0f39f
feat(table): ACLExtendedRule: Changing Destination Prefix to a single…
rvveber Sep 2, 2024
668551e
feat(filter): ACLStandardRule: Adding new Sources to the filter
rvveber Sep 2, 2024
c8a19b6
feat(filter): ACLStandardRule: Instruct new Sources to be displayed a…
rvveber Sep 2, 2024
8d1f698
feat(filter): ACLExtendedRule: Adding new Sources to the filter
rvveber Sep 2, 2024
ef91bdc
feat(filter): ACLExtendedRule: Instruct new Sources to be displayed a…
rvveber Sep 2, 2024
834ab7d
feat(filter): ACLExtendedRule: Adding new Destinations to the filter
rvveber Sep 2, 2024
f8cd877
feat(filter): ACLExtendedRule: Instruct new Destinations to be displa…
rvveber Sep 2, 2024
dca8e47
feat(serializer): ACLStandardRule: Adding new Source Fields to serial…
rvveber Sep 2, 2024
659c2d6
feat(serializer): ACLStandardRule: Change validation to support multi…
rvveber Sep 2, 2024
70e7b9d
feat(serializer): ACLExtendedRule: Adding new Source Fields to serial…
rvveber Sep 2, 2024
bcbd7f1
feat(serializer): ACLExtendedRule: Change validation to support multi…
rvveber Sep 2, 2024
ea1dd2c
feat(serializer): ACLExtendedRule: Adding new Destination Fields to s…
rvveber Sep 2, 2024
18f87c7
feat(serializer): ACLExtendedRule: Change validation to support multi…
rvveber Sep 2, 2024
7558f08
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