Skip to content

Commit 91e5d9c

Browse files
authored
Merge pull request #85 from Onemind-Services-LLC/housekeeping/cleanup
2 parents f2eba68 + d2a91f6 commit 91e5d9c

File tree

11 files changed

+144
-88
lines changed

11 files changed

+144
-88
lines changed

.devcontainer/docker-compose.override.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ services:
55
dockerfile: Dockerfile-plugin_dev
66
context: .
77
ports:
8-
- 8000:8080
8+
- "8000:8080"
99
volumes:
1010
- ../:/opt/netbox/netbox/netbox-acls
1111
- ~/.gitconfig:/home/vscode/.gitconfig:z,ro

.devcontainer/initializers/cables.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# ```
44
# termination_x_name -> name of interface
55
# termination_x_device -> name of the device interface belongs to
6-
# termination_x_class -> required if different than 'Interface' which is the default
6+
# termination_x_class -> required if different from 'Interface' which is the default
77
# ```
88
#
99
# Supported termination classes: Interface, ConsolePort, ConsoleServerPort, FrontPort, RearPort, PowerPort, PowerOutlet

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,3 +161,5 @@ cython_debug/
161161

162162
# VS Code
163163
.vscode/
164+
# JetBrains
165+
.idea/

CONTRIBUTING.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
## Reporting Bugs
44

55
* First, ensure that you're running the [latest stable version](https://github.com/netbox-community/netbox/releases)
6-
of NetBox or this plugin [latest stable version](https://github.com/ryanmerolle/netbox-acls/releases).
6+
of NetBox or this plugin is at [latest stable version](https://github.com/ryanmerolle/netbox-acls/releases).
77
If you're running an older version, it's possible that the bug has already been fixed
8-
or you are running a version of the plugin not tested with the NetBox version
8+
or, you are running a version of the plugin not tested with the NetBox version
99
you are running [Compatibility Matrix](./README.md#compatibility).
1010

1111
* Next, check the GitHub [issues list](https://github.com/ryanmerolle/netbox-acls/issues)

README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ Based on the NetBox plugin tutorial by [jeremystretch](https://github.com/jeremy
1919
- [demo repository](https://github.com/netbox-community/netbox-plugin-demo)
2020
- [tutorial](https://github.com/netbox-community/netbox-plugin-tutorial)
2121

22-
All credit should go to Jeremy. Thanks Jeremy!
22+
All credit should go to Jeremy. Thanks, Jeremy!
2323

2424
This project just looks to build on top of this framework and model presented.
2525

@@ -69,12 +69,12 @@ PLUGINS_CONFIG = {
6969
To develop this plugin further one can use the included .devcontainer configuration. This configuration creates a docker container which includes a fully working netbox installation. Currently it should work when using WSL 2. For this to work make sure you have Docker Desktop installed and the WSL 2 integrations activated.
7070

7171
1. In the WSL terminal, enter `code` to run Visual studio code.
72-
1. Install the devcontainer extension "ms-vscode-remote.remote-containers"
73-
1. Press Ctrl+Shift+P and use the "Dev Container: Clone Repository in Container Volume" function to clone this repository. This will take a while depending on your computer
74-
1. If you'd like the netbox instance to be prepopulated run `make Makefile example_initializers` and `make Makefile load_initializers`
75-
1. Start the netbox instance using `make Makefile all`
72+
2. Install the devcontainer extension "ms-vscode-remote.remote-containers"
73+
3. Press Ctrl+Shift+P and use the "Dev Container: Clone Repository in Container Volume" function to clone this repository. This will take a while depending on your computer
74+
4. If you'd like the netbox instance to be prepopulated run `make Makefile example_initializers` and `make Makefile load_initializers`
75+
5. Start the netbox instance using `make Makefile all`
7676

77-
Your netbox instance will be served under 0.0.0.0:8000 so it should now be available under localhost:8000.
77+
Your netbox instance will be served under 0.0.0.0:8000, so it should now be available under localhost:8000.
7878

7979
## Screenshots
8080

netbox_acls/api/serializers.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from ipam.api.serializers import NestedPrefixSerializer
1010
from netbox.api.fields import ContentTypeField
1111
from netbox.api.serializers import NetBoxModelSerializer
12+
from netbox.constants import NESTED_SERIALIZER_PREFIX
1213
from rest_framework import serializers
1314
from utilities.api import get_serializer_for_model
1415

@@ -82,7 +83,10 @@ class Meta:
8283

8384
@swagger_serializer_method(serializer_or_field=serializers.DictField)
8485
def get_assigned_object(self, obj):
85-
serializer = get_serializer_for_model(obj.assigned_object, prefix="Nested")
86+
serializer = get_serializer_for_model(
87+
obj.assigned_object,
88+
prefix=NESTED_SERIALIZER_PREFIX,
89+
)
8690
context = {"request": self.context["request"]}
8791
return serializer(obj.assigned_object, context=context).data
8892

@@ -96,6 +100,7 @@ def validate(self, data):
96100

97101
# Check that the GFK object is valid.
98102
if "assigned_object_type" in data and "assigned_object_id" in data:
103+
# TODO: This can removed after https://github.com/netbox-community/netbox/issues/10221 is fixed.
99104
try:
100105
assigned_object = data[ # noqa: F841
101106
"assigned_object_type"
@@ -161,21 +166,25 @@ class Meta:
161166

162167
@swagger_serializer_method(serializer_or_field=serializers.DictField)
163168
def get_assigned_object(self, obj):
164-
serializer = get_serializer_for_model(obj.assigned_object, prefix="Nested")
169+
serializer = get_serializer_for_model(
170+
obj.assigned_object,
171+
prefix=NESTED_SERIALIZER_PREFIX,
172+
)
165173
context = {"request": self.context["request"]}
166174
return serializer(obj.assigned_object, context=context).data
167175

168176
def validate(self, data):
169177
"""
170-
Validate the AccessList django model model's inputs before allowing it to update the instance.
178+
Validate the AccessList django model's inputs before allowing it to update the instance.
171179
- Check that the GFK object is valid.
172180
- Check that the associated interface's parent host has the selected ACL defined.
173181
"""
174182
error_message = {}
175183
acl_host = data["access_list"].assigned_object
176184

177-
# Check that the GFK object is vlaid.
185+
# Check that the GFK object is valid.
178186
if "assigned_object_type" in data and "assigned_object_id" in data:
187+
# TODO: This can removed after https://github.com/netbox-community/netbox/issues/10221 is fixed.
179188
try:
180189
assigned_object = data[ # noqa: F841
181190
"assigned_object_type"
@@ -200,6 +209,8 @@ def validate(self, data):
200209
.get_object_for_this_type(id=data["assigned_object_id"])
201210
.virtual_machine
202211
)
212+
else:
213+
interface_host = None
203214
# Check that the associated interface's parent host has the selected ACL defined.
204215
if acl_host != interface_host:
205216
error_acl_not_assigned_to_host = (
@@ -253,7 +264,7 @@ class Meta:
253264

254265
def validate(self, data):
255266
"""
256-
Validate the ACLStandardRule django model model's inputs before allowing it to update the instance:
267+
Validate the ACLStandardRule django model's inputs before allowing it to update the instance:
257268
- Check if action set to remark, but no remark set.
258269
- Check if action set to remark, but source_prefix set.
259270
"""
@@ -322,7 +333,7 @@ class Meta:
322333

323334
def validate(self, data):
324335
"""
325-
Validate the ACLExtendedRule django model model's inputs before allowing it to update the instance:
336+
Validate the ACLExtendedRule django model's inputs before allowing it to update the instance:
326337
- Check if action set to remark, but no remark set.
327338
- Check if action set to remark, but source_prefix set.
328339
- Check if action set to remark, but source_ports set.

netbox_acls/choices.py

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,12 @@ class ACLAssignmentDirectionChoices(ChoiceSet):
5151
Defines the direction of the application of the ACL on an associated interface.
5252
"""
5353

54+
DIRECTION_INGRESS = "ingress"
55+
DIRECTION_EGRESS = "egress"
56+
5457
CHOICES = [
55-
("ingress", "Ingress", "blue"),
56-
("egress", "Egress", "purple"),
58+
(DIRECTION_INGRESS, "Ingress", "blue"),
59+
(DIRECTION_EGRESS, "Egress", "purple"),
5760
]
5861

5962

@@ -62,9 +65,12 @@ class ACLTypeChoices(ChoiceSet):
6265
Defines the choices availble for the Access Lists plugin specific to ACL type.
6366
"""
6467

68+
TYPE_STANDARD = "standard"
69+
TYPE_EXTENDED = "extended"
70+
6571
CHOICES = [
66-
("extended", "Extended", "purple"),
67-
("standard", "Standard", "blue"),
72+
(TYPE_EXTENDED, "Extended", "purple"),
73+
(TYPE_STANDARD, "Standard", "blue"),
6874
]
6975

7076

@@ -73,8 +79,12 @@ class ACLProtocolChoices(ChoiceSet):
7379
Defines the choices availble for the Access Lists plugin specific to ACL Rule protocol.
7480
"""
7581

82+
PROTOCOL_ICMP = "icmp"
83+
PROTOCOL_TCP = "tcp"
84+
PROTOCOL_UDP = "udp"
85+
7686
CHOICES = [
77-
("icmp", "ICMP", "purple"),
78-
("tcp", "TCP", "blue"),
79-
("udp", "UDP", "orange"),
87+
(PROTOCOL_ICMP, "ICMP", "purple"),
88+
(PROTOCOL_TCP, "TCP", "blue"),
89+
(PROTOCOL_UDP, "UDP", "orange"),
8090
]

netbox_acls/forms/models.py

Lines changed: 47 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
VMInterface,
2323
)
2424

25+
from ..choices import ACLTypeChoices
2526
from ..models import (
2627
AccessList,
2728
ACLExtendedRule,
@@ -236,8 +237,12 @@ def clean(self):
236237
"name": [error_same_acl_name],
237238
}
238239
# Check if Access List has no existing rules before change the Access List's type.
239-
if (acl_type == "extended" and self.instance.aclstandardrules.exists()) or (
240-
acl_type == "standard" and self.instance.aclextendedrules.exists()
240+
if (
241+
acl_type == ACLTypeChoices.TYPE_EXTENDED
242+
and self.instance.aclstandardrules.exists()
243+
) or (
244+
acl_type == ACLTypeChoices.TYPE_STANDARD
245+
and self.instance.aclextendedrules.exists()
241246
):
242247
error_message["type"] = [
243248
"This ACL has ACL rules associated, CANNOT change ACL type.",
@@ -312,10 +317,6 @@ class ACLInterfaceAssignmentForm(NetBoxModelForm):
312317
),
313318
)
314319
comments = CommentField()
315-
tags = DynamicModelMultipleChoiceField(
316-
queryset=Tag.objects.all(),
317-
required=False,
318-
)
319320

320321
def __init__(self, *args, **kwargs):
321322

@@ -355,7 +356,7 @@ def clean(self):
355356
"""
356357
Validates form inputs before submitting:
357358
- Check if both interface and vminterface are set.
358-
- Check if neither interface or vminterface are set.
359+
- Check if neither interface nor vminterface are set.
359360
- Check that an interface's parent device/virtual_machine is assigned to the Access List.
360361
- Check that an interface's parent device/virtual_machine is assigned to the Access List.
361362
- Check for duplicate entry. (Because of GFK)
@@ -367,7 +368,6 @@ def clean(self):
367368
direction = cleaned_data.get("direction")
368369
interface = cleaned_data.get("interface")
369370
vminterface = cleaned_data.get("vminterface")
370-
assigned_object = cleaned_data.get("assigned_object")
371371

372372
# Check if both interface and vminterface are set.
373373
if interface and vminterface:
@@ -403,40 +403,42 @@ def clean(self):
403403
).pk
404404
access_list_host = AccessList.objects.get(pk=access_list.pk).assigned_object
405405

406-
# Check that an interface's parent device/virtual_machine is assigned to the Access List.
407-
if access_list_host != host:
408-
error_acl_not_assigned_to_host = "Access List not present on selected host."
409-
error_message |= {
410-
"access_list": [error_acl_not_assigned_to_host],
411-
assigned_object_type: [error_acl_not_assigned_to_host],
412-
host_type: [error_acl_not_assigned_to_host],
413-
}
414-
# Check for duplicate entry.
415-
if ACLInterfaceAssignment.objects.filter(
416-
access_list=access_list,
417-
assigned_object_id=assigned_object_id,
418-
assigned_object_type=assigned_object_type_id,
419-
direction=direction,
420-
).exists():
421-
error_duplicate_entry = "An ACL with this name is already associated to this interface & direction."
422-
error_message |= {
423-
"access_list": [error_duplicate_entry],
424-
"direction": [error_duplicate_entry],
425-
assigned_object_type: [error_duplicate_entry],
426-
}
427-
# Check that the interface does not have an existing ACL applied in the direction already.
428-
if ACLInterfaceAssignment.objects.filter(
429-
assigned_object_id=assigned_object_id,
430-
assigned_object_type=assigned_object_type_id,
431-
direction=direction,
432-
).exists():
433-
error_interface_already_assigned = (
434-
"Interfaces can only have 1 Access List assigned in each direction."
435-
)
436-
error_message |= {
437-
"direction": [error_interface_already_assigned],
438-
assigned_object_type: [error_interface_already_assigned],
439-
}
406+
# Check that an interface's parent device/virtual_machine is assigned to the Access List.
407+
if access_list_host != host:
408+
error_acl_not_assigned_to_host = (
409+
"Access List not present on selected host."
410+
)
411+
error_message |= {
412+
"access_list": [error_acl_not_assigned_to_host],
413+
assigned_object_type: [error_acl_not_assigned_to_host],
414+
host_type: [error_acl_not_assigned_to_host],
415+
}
416+
# Check for duplicate entry.
417+
if ACLInterfaceAssignment.objects.filter(
418+
access_list=access_list,
419+
assigned_object_id=assigned_object_id,
420+
assigned_object_type=assigned_object_type_id,
421+
direction=direction,
422+
).exists():
423+
error_duplicate_entry = "An ACL with this name is already associated to this interface & direction."
424+
error_message |= {
425+
"access_list": [error_duplicate_entry],
426+
"direction": [error_duplicate_entry],
427+
assigned_object_type: [error_duplicate_entry],
428+
}
429+
# Check that the interface does not have an existing ACL applied in the direction already.
430+
if ACLInterfaceAssignment.objects.filter(
431+
assigned_object_id=assigned_object_id,
432+
assigned_object_type=assigned_object_type_id,
433+
direction=direction,
434+
).exists():
435+
error_interface_already_assigned = (
436+
"Interfaces can only have 1 Access List assigned in each direction."
437+
)
438+
error_message |= {
439+
"direction": [error_interface_already_assigned],
440+
assigned_object_type: [error_interface_already_assigned],
441+
}
440442

441443
if error_message:
442444
raise forms.ValidationError(error_message)
@@ -460,7 +462,7 @@ class ACLStandardRuleForm(NetBoxModelForm):
460462
access_list = DynamicModelChoiceField(
461463
queryset=AccessList.objects.all(),
462464
query_params={
463-
"type": "standard",
465+
"type": ACLTypeChoices.TYPE_STANDARD,
464466
},
465467
help_text=mark_safe(
466468
"<b>*Note:</b> This field will only display Standard ACLs.",
@@ -473,10 +475,6 @@ class ACLStandardRuleForm(NetBoxModelForm):
473475
help_text=help_text_acl_rule_logic,
474476
label="Source Prefix",
475477
)
476-
tags = DynamicModelMultipleChoiceField(
477-
queryset=Tag.objects.all(),
478-
required=False,
479-
)
480478

481479
fieldsets = (
482480
("Access List Details", ("access_list", "description", "tags")),
@@ -542,17 +540,14 @@ class ACLExtendedRuleForm(NetBoxModelForm):
542540
access_list = DynamicModelChoiceField(
543541
queryset=AccessList.objects.all(),
544542
query_params={
545-
"type": "extended",
543+
"type": ACLTypeChoices.TYPE_EXTENDED,
546544
},
547545
help_text=mark_safe(
548546
"<b>*Note:</b> This field will only display Extended ACLs.",
549547
),
550548
label="Access List",
551549
)
552-
tags = DynamicModelMultipleChoiceField(
553-
queryset=Tag.objects.all(),
554-
required=False,
555-
)
550+
556551
source_prefix = DynamicModelChoiceField(
557552
queryset=Prefix.objects.all(),
558553
required=False,

netbox_acls/models/access_list_rules.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from django.urls import reverse
99
from netbox.models import NetBoxModel
1010

11-
from ..choices import ACLProtocolChoices, ACLRuleActionChoices
11+
from ..choices import ACLProtocolChoices, ACLRuleActionChoices, ACLTypeChoices
1212
from .access_lists import AccessList
1313

1414
__all__ = (
@@ -86,7 +86,7 @@ class ACLStandardRule(ACLRule):
8686
on_delete=models.CASCADE,
8787
to=AccessList,
8888
verbose_name="Standard Access List",
89-
limit_choices_to={"type": "standard"},
89+
limit_choices_to={"type": ACLTypeChoices.TYPE_STANDARD},
9090
related_name="aclstandardrules",
9191
)
9292

netbox_acls/template_content.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ def right_page(self):
3131
elif ctype.model == "vminterface":
3232
parent_type = "virtual_machine"
3333
parent_id = obj.virtual_machine.pk
34+
else:
35+
parent_type = None
36+
parent_id = None
3437

3538
return self.render(
3639
"inc/assigned_interface/access_lists.html",

0 commit comments

Comments
 (0)