mirror of
https://github.com/lucaspalomodevelop/netbox-acls.git
synced 2026-03-12 23:27:23 +00:00
Merge pull request #85 from Onemind-Services-LLC/housekeeping/cleanup
This commit is contained in:
commit
91e5d9c1c2
@ -5,7 +5,7 @@ services:
|
|||||||
dockerfile: Dockerfile-plugin_dev
|
dockerfile: Dockerfile-plugin_dev
|
||||||
context: .
|
context: .
|
||||||
ports:
|
ports:
|
||||||
- 8000:8080
|
- "8000:8080"
|
||||||
volumes:
|
volumes:
|
||||||
- ../:/opt/netbox/netbox/netbox-acls
|
- ../:/opt/netbox/netbox/netbox-acls
|
||||||
- ~/.gitconfig:/home/vscode/.gitconfig:z,ro
|
- ~/.gitconfig:/home/vscode/.gitconfig:z,ro
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
# ```
|
# ```
|
||||||
# termination_x_name -> name of interface
|
# termination_x_name -> name of interface
|
||||||
# termination_x_device -> name of the device interface belongs to
|
# termination_x_device -> name of the device interface belongs to
|
||||||
# termination_x_class -> required if different than 'Interface' which is the default
|
# termination_x_class -> required if different from 'Interface' which is the default
|
||||||
# ```
|
# ```
|
||||||
#
|
#
|
||||||
# Supported termination classes: Interface, ConsolePort, ConsoleServerPort, FrontPort, RearPort, PowerPort, PowerOutlet
|
# Supported termination classes: Interface, ConsolePort, ConsoleServerPort, FrontPort, RearPort, PowerPort, PowerOutlet
|
||||||
|
|||||||
2
.gitignore
vendored
2
.gitignore
vendored
@ -161,3 +161,5 @@ cython_debug/
|
|||||||
|
|
||||||
# VS Code
|
# VS Code
|
||||||
.vscode/
|
.vscode/
|
||||||
|
# JetBrains
|
||||||
|
.idea/
|
||||||
@ -3,9 +3,9 @@
|
|||||||
## Reporting Bugs
|
## Reporting Bugs
|
||||||
|
|
||||||
* First, ensure that you're running the [latest stable version](https://github.com/netbox-community/netbox/releases)
|
* First, ensure that you're running the [latest stable version](https://github.com/netbox-community/netbox/releases)
|
||||||
of NetBox or this plugin [latest stable version](https://github.com/ryanmerolle/netbox-acls/releases).
|
of NetBox or this plugin is at [latest stable version](https://github.com/ryanmerolle/netbox-acls/releases).
|
||||||
If you're running an older version, it's possible that the bug has already been fixed
|
If you're running an older version, it's possible that the bug has already been fixed
|
||||||
or you are running a version of the plugin not tested with the NetBox version
|
or, you are running a version of the plugin not tested with the NetBox version
|
||||||
you are running [Compatibility Matrix](./README.md#compatibility).
|
you are running [Compatibility Matrix](./README.md#compatibility).
|
||||||
|
|
||||||
* Next, check the GitHub [issues list](https://github.com/ryanmerolle/netbox-acls/issues)
|
* Next, check the GitHub [issues list](https://github.com/ryanmerolle/netbox-acls/issues)
|
||||||
|
|||||||
12
README.md
12
README.md
@ -19,7 +19,7 @@ Based on the NetBox plugin tutorial by [jeremystretch](https://github.com/jeremy
|
|||||||
- [demo repository](https://github.com/netbox-community/netbox-plugin-demo)
|
- [demo repository](https://github.com/netbox-community/netbox-plugin-demo)
|
||||||
- [tutorial](https://github.com/netbox-community/netbox-plugin-tutorial)
|
- [tutorial](https://github.com/netbox-community/netbox-plugin-tutorial)
|
||||||
|
|
||||||
All credit should go to Jeremy. Thanks Jeremy!
|
All credit should go to Jeremy. Thanks, Jeremy!
|
||||||
|
|
||||||
This project just looks to build on top of this framework and model presented.
|
This project just looks to build on top of this framework and model presented.
|
||||||
|
|
||||||
@ -69,12 +69,12 @@ PLUGINS_CONFIG = {
|
|||||||
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.
|
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.
|
||||||
|
|
||||||
1. In the WSL terminal, enter `code` to run Visual studio code.
|
1. In the WSL terminal, enter `code` to run Visual studio code.
|
||||||
1. Install the devcontainer extension "ms-vscode-remote.remote-containers"
|
2. Install the devcontainer extension "ms-vscode-remote.remote-containers"
|
||||||
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
|
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
|
||||||
1. If you'd like the netbox instance to be prepopulated run `make Makefile example_initializers` and `make Makefile load_initializers`
|
4. If you'd like the netbox instance to be prepopulated run `make Makefile example_initializers` and `make Makefile load_initializers`
|
||||||
1. Start the netbox instance using `make Makefile all`
|
5. Start the netbox instance using `make Makefile all`
|
||||||
|
|
||||||
Your netbox instance will be served under 0.0.0.0:8000 so it should now be available under localhost:8000.
|
Your netbox instance will be served under 0.0.0.0:8000, so it should now be available under localhost:8000.
|
||||||
|
|
||||||
## Screenshots
|
## Screenshots
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,7 @@ from drf_yasg.utils import swagger_serializer_method
|
|||||||
from ipam.api.serializers import NestedPrefixSerializer
|
from ipam.api.serializers import NestedPrefixSerializer
|
||||||
from netbox.api.fields import ContentTypeField
|
from netbox.api.fields import ContentTypeField
|
||||||
from netbox.api.serializers import NetBoxModelSerializer
|
from netbox.api.serializers import NetBoxModelSerializer
|
||||||
|
from netbox.constants import NESTED_SERIALIZER_PREFIX
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from utilities.api import get_serializer_for_model
|
from utilities.api import get_serializer_for_model
|
||||||
|
|
||||||
@ -82,7 +83,10 @@ class AccessListSerializer(NetBoxModelSerializer):
|
|||||||
|
|
||||||
@swagger_serializer_method(serializer_or_field=serializers.DictField)
|
@swagger_serializer_method(serializer_or_field=serializers.DictField)
|
||||||
def get_assigned_object(self, obj):
|
def get_assigned_object(self, obj):
|
||||||
serializer = get_serializer_for_model(obj.assigned_object, prefix="Nested")
|
serializer = get_serializer_for_model(
|
||||||
|
obj.assigned_object,
|
||||||
|
prefix=NESTED_SERIALIZER_PREFIX,
|
||||||
|
)
|
||||||
context = {"request": self.context["request"]}
|
context = {"request": self.context["request"]}
|
||||||
return serializer(obj.assigned_object, context=context).data
|
return serializer(obj.assigned_object, context=context).data
|
||||||
|
|
||||||
@ -96,6 +100,7 @@ class AccessListSerializer(NetBoxModelSerializer):
|
|||||||
|
|
||||||
# Check that the GFK object is valid.
|
# Check that the GFK object is valid.
|
||||||
if "assigned_object_type" in data and "assigned_object_id" in data:
|
if "assigned_object_type" in data and "assigned_object_id" in data:
|
||||||
|
# TODO: This can removed after https://github.com/netbox-community/netbox/issues/10221 is fixed.
|
||||||
try:
|
try:
|
||||||
assigned_object = data[ # noqa: F841
|
assigned_object = data[ # noqa: F841
|
||||||
"assigned_object_type"
|
"assigned_object_type"
|
||||||
@ -161,21 +166,25 @@ class ACLInterfaceAssignmentSerializer(NetBoxModelSerializer):
|
|||||||
|
|
||||||
@swagger_serializer_method(serializer_or_field=serializers.DictField)
|
@swagger_serializer_method(serializer_or_field=serializers.DictField)
|
||||||
def get_assigned_object(self, obj):
|
def get_assigned_object(self, obj):
|
||||||
serializer = get_serializer_for_model(obj.assigned_object, prefix="Nested")
|
serializer = get_serializer_for_model(
|
||||||
|
obj.assigned_object,
|
||||||
|
prefix=NESTED_SERIALIZER_PREFIX,
|
||||||
|
)
|
||||||
context = {"request": self.context["request"]}
|
context = {"request": self.context["request"]}
|
||||||
return serializer(obj.assigned_object, context=context).data
|
return serializer(obj.assigned_object, context=context).data
|
||||||
|
|
||||||
def validate(self, data):
|
def validate(self, data):
|
||||||
"""
|
"""
|
||||||
Validate the AccessList django model model's inputs before allowing it to update the instance.
|
Validate the AccessList django model's inputs before allowing it to update the instance.
|
||||||
- Check that the GFK object is valid.
|
- Check that the GFK object is valid.
|
||||||
- Check that the associated interface's parent host has the selected ACL defined.
|
- Check that the associated interface's parent host has the selected ACL defined.
|
||||||
"""
|
"""
|
||||||
error_message = {}
|
error_message = {}
|
||||||
acl_host = data["access_list"].assigned_object
|
acl_host = data["access_list"].assigned_object
|
||||||
|
|
||||||
# Check that the GFK object is vlaid.
|
# Check that the GFK object is valid.
|
||||||
if "assigned_object_type" in data and "assigned_object_id" in data:
|
if "assigned_object_type" in data and "assigned_object_id" in data:
|
||||||
|
# TODO: This can removed after https://github.com/netbox-community/netbox/issues/10221 is fixed.
|
||||||
try:
|
try:
|
||||||
assigned_object = data[ # noqa: F841
|
assigned_object = data[ # noqa: F841
|
||||||
"assigned_object_type"
|
"assigned_object_type"
|
||||||
@ -200,6 +209,8 @@ class ACLInterfaceAssignmentSerializer(NetBoxModelSerializer):
|
|||||||
.get_object_for_this_type(id=data["assigned_object_id"])
|
.get_object_for_this_type(id=data["assigned_object_id"])
|
||||||
.virtual_machine
|
.virtual_machine
|
||||||
)
|
)
|
||||||
|
else:
|
||||||
|
interface_host = None
|
||||||
# Check that the associated interface's parent host has the selected ACL defined.
|
# Check that the associated interface's parent host has the selected ACL defined.
|
||||||
if acl_host != interface_host:
|
if acl_host != interface_host:
|
||||||
error_acl_not_assigned_to_host = (
|
error_acl_not_assigned_to_host = (
|
||||||
@ -253,7 +264,7 @@ class ACLStandardRuleSerializer(NetBoxModelSerializer):
|
|||||||
|
|
||||||
def validate(self, data):
|
def validate(self, data):
|
||||||
"""
|
"""
|
||||||
Validate the ACLStandardRule django model model's inputs before allowing it to update the instance:
|
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 no remark set.
|
||||||
- Check if action set to remark, but source_prefix set.
|
- Check if action set to remark, but source_prefix set.
|
||||||
"""
|
"""
|
||||||
@ -322,7 +333,7 @@ class ACLExtendedRuleSerializer(NetBoxModelSerializer):
|
|||||||
|
|
||||||
def validate(self, data):
|
def validate(self, data):
|
||||||
"""
|
"""
|
||||||
Validate the ACLExtendedRule django model model's inputs before allowing it to update the instance:
|
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 no remark set.
|
||||||
- Check if action set to remark, but source_prefix set.
|
- Check if action set to remark, but source_prefix set.
|
||||||
- Check if action set to remark, but source_ports set.
|
- Check if action set to remark, but source_ports set.
|
||||||
|
|||||||
@ -51,9 +51,12 @@ class ACLAssignmentDirectionChoices(ChoiceSet):
|
|||||||
Defines the direction of the application of the ACL on an associated interface.
|
Defines the direction of the application of the ACL on an associated interface.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
DIRECTION_INGRESS = "ingress"
|
||||||
|
DIRECTION_EGRESS = "egress"
|
||||||
|
|
||||||
CHOICES = [
|
CHOICES = [
|
||||||
("ingress", "Ingress", "blue"),
|
(DIRECTION_INGRESS, "Ingress", "blue"),
|
||||||
("egress", "Egress", "purple"),
|
(DIRECTION_EGRESS, "Egress", "purple"),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@ -62,9 +65,12 @@ class ACLTypeChoices(ChoiceSet):
|
|||||||
Defines the choices availble for the Access Lists plugin specific to ACL type.
|
Defines the choices availble for the Access Lists plugin specific to ACL type.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
TYPE_STANDARD = "standard"
|
||||||
|
TYPE_EXTENDED = "extended"
|
||||||
|
|
||||||
CHOICES = [
|
CHOICES = [
|
||||||
("extended", "Extended", "purple"),
|
(TYPE_EXTENDED, "Extended", "purple"),
|
||||||
("standard", "Standard", "blue"),
|
(TYPE_STANDARD, "Standard", "blue"),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@ -73,8 +79,12 @@ class ACLProtocolChoices(ChoiceSet):
|
|||||||
Defines the choices availble for the Access Lists plugin specific to ACL Rule protocol.
|
Defines the choices availble for the Access Lists plugin specific to ACL Rule protocol.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
PROTOCOL_ICMP = "icmp"
|
||||||
|
PROTOCOL_TCP = "tcp"
|
||||||
|
PROTOCOL_UDP = "udp"
|
||||||
|
|
||||||
CHOICES = [
|
CHOICES = [
|
||||||
("icmp", "ICMP", "purple"),
|
(PROTOCOL_ICMP, "ICMP", "purple"),
|
||||||
("tcp", "TCP", "blue"),
|
(PROTOCOL_TCP, "TCP", "blue"),
|
||||||
("udp", "UDP", "orange"),
|
(PROTOCOL_UDP, "UDP", "orange"),
|
||||||
]
|
]
|
||||||
|
|||||||
@ -22,6 +22,7 @@ from virtualization.models import (
|
|||||||
VMInterface,
|
VMInterface,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from ..choices import ACLTypeChoices
|
||||||
from ..models import (
|
from ..models import (
|
||||||
AccessList,
|
AccessList,
|
||||||
ACLExtendedRule,
|
ACLExtendedRule,
|
||||||
@ -236,8 +237,12 @@ class AccessListForm(NetBoxModelForm):
|
|||||||
"name": [error_same_acl_name],
|
"name": [error_same_acl_name],
|
||||||
}
|
}
|
||||||
# Check if Access List has no existing rules before change the Access List's type.
|
# Check if Access List has no existing rules before change the Access List's type.
|
||||||
if (acl_type == "extended" and self.instance.aclstandardrules.exists()) or (
|
if (
|
||||||
acl_type == "standard" and self.instance.aclextendedrules.exists()
|
acl_type == ACLTypeChoices.TYPE_EXTENDED
|
||||||
|
and self.instance.aclstandardrules.exists()
|
||||||
|
) or (
|
||||||
|
acl_type == ACLTypeChoices.TYPE_STANDARD
|
||||||
|
and self.instance.aclextendedrules.exists()
|
||||||
):
|
):
|
||||||
error_message["type"] = [
|
error_message["type"] = [
|
||||||
"This ACL has ACL rules associated, CANNOT change ACL type.",
|
"This ACL has ACL rules associated, CANNOT change ACL type.",
|
||||||
@ -312,10 +317,6 @@ class ACLInterfaceAssignmentForm(NetBoxModelForm):
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
comments = CommentField()
|
comments = CommentField()
|
||||||
tags = DynamicModelMultipleChoiceField(
|
|
||||||
queryset=Tag.objects.all(),
|
|
||||||
required=False,
|
|
||||||
)
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
|
||||||
@ -355,7 +356,7 @@ class ACLInterfaceAssignmentForm(NetBoxModelForm):
|
|||||||
"""
|
"""
|
||||||
Validates form inputs before submitting:
|
Validates form inputs before submitting:
|
||||||
- Check if both interface and vminterface are set.
|
- Check if both interface and vminterface are set.
|
||||||
- Check if neither interface or vminterface are set.
|
- Check if neither interface nor vminterface are set.
|
||||||
- Check that an interface's parent device/virtual_machine is assigned to the Access List.
|
- Check that an interface's parent device/virtual_machine is assigned to the Access List.
|
||||||
- Check that an interface's parent device/virtual_machine is assigned to the Access List.
|
- Check that an interface's parent device/virtual_machine is assigned to the Access List.
|
||||||
- Check for duplicate entry. (Because of GFK)
|
- Check for duplicate entry. (Because of GFK)
|
||||||
@ -367,7 +368,6 @@ class ACLInterfaceAssignmentForm(NetBoxModelForm):
|
|||||||
direction = cleaned_data.get("direction")
|
direction = cleaned_data.get("direction")
|
||||||
interface = cleaned_data.get("interface")
|
interface = cleaned_data.get("interface")
|
||||||
vminterface = cleaned_data.get("vminterface")
|
vminterface = cleaned_data.get("vminterface")
|
||||||
assigned_object = cleaned_data.get("assigned_object")
|
|
||||||
|
|
||||||
# Check if both interface and vminterface are set.
|
# Check if both interface and vminterface are set.
|
||||||
if interface and vminterface:
|
if interface and vminterface:
|
||||||
@ -403,40 +403,42 @@ class ACLInterfaceAssignmentForm(NetBoxModelForm):
|
|||||||
).pk
|
).pk
|
||||||
access_list_host = AccessList.objects.get(pk=access_list.pk).assigned_object
|
access_list_host = AccessList.objects.get(pk=access_list.pk).assigned_object
|
||||||
|
|
||||||
# Check that an interface's parent device/virtual_machine is assigned to the Access List.
|
# Check that an interface's parent device/virtual_machine is assigned to the Access List.
|
||||||
if access_list_host != host:
|
if access_list_host != host:
|
||||||
error_acl_not_assigned_to_host = "Access List not present on selected host."
|
error_acl_not_assigned_to_host = (
|
||||||
error_message |= {
|
"Access List not present on selected host."
|
||||||
"access_list": [error_acl_not_assigned_to_host],
|
)
|
||||||
assigned_object_type: [error_acl_not_assigned_to_host],
|
error_message |= {
|
||||||
host_type: [error_acl_not_assigned_to_host],
|
"access_list": [error_acl_not_assigned_to_host],
|
||||||
}
|
assigned_object_type: [error_acl_not_assigned_to_host],
|
||||||
# Check for duplicate entry.
|
host_type: [error_acl_not_assigned_to_host],
|
||||||
if ACLInterfaceAssignment.objects.filter(
|
}
|
||||||
access_list=access_list,
|
# Check for duplicate entry.
|
||||||
assigned_object_id=assigned_object_id,
|
if ACLInterfaceAssignment.objects.filter(
|
||||||
assigned_object_type=assigned_object_type_id,
|
access_list=access_list,
|
||||||
direction=direction,
|
assigned_object_id=assigned_object_id,
|
||||||
).exists():
|
assigned_object_type=assigned_object_type_id,
|
||||||
error_duplicate_entry = "An ACL with this name is already associated to this interface & direction."
|
direction=direction,
|
||||||
error_message |= {
|
).exists():
|
||||||
"access_list": [error_duplicate_entry],
|
error_duplicate_entry = "An ACL with this name is already associated to this interface & direction."
|
||||||
"direction": [error_duplicate_entry],
|
error_message |= {
|
||||||
assigned_object_type: [error_duplicate_entry],
|
"access_list": [error_duplicate_entry],
|
||||||
}
|
"direction": [error_duplicate_entry],
|
||||||
# Check that the interface does not have an existing ACL applied in the direction already.
|
assigned_object_type: [error_duplicate_entry],
|
||||||
if ACLInterfaceAssignment.objects.filter(
|
}
|
||||||
assigned_object_id=assigned_object_id,
|
# Check that the interface does not have an existing ACL applied in the direction already.
|
||||||
assigned_object_type=assigned_object_type_id,
|
if ACLInterfaceAssignment.objects.filter(
|
||||||
direction=direction,
|
assigned_object_id=assigned_object_id,
|
||||||
).exists():
|
assigned_object_type=assigned_object_type_id,
|
||||||
error_interface_already_assigned = (
|
direction=direction,
|
||||||
"Interfaces can only have 1 Access List assigned in each direction."
|
).exists():
|
||||||
)
|
error_interface_already_assigned = (
|
||||||
error_message |= {
|
"Interfaces can only have 1 Access List assigned in each direction."
|
||||||
"direction": [error_interface_already_assigned],
|
)
|
||||||
assigned_object_type: [error_interface_already_assigned],
|
error_message |= {
|
||||||
}
|
"direction": [error_interface_already_assigned],
|
||||||
|
assigned_object_type: [error_interface_already_assigned],
|
||||||
|
}
|
||||||
|
|
||||||
if error_message:
|
if error_message:
|
||||||
raise forms.ValidationError(error_message)
|
raise forms.ValidationError(error_message)
|
||||||
@ -460,7 +462,7 @@ class ACLStandardRuleForm(NetBoxModelForm):
|
|||||||
access_list = DynamicModelChoiceField(
|
access_list = DynamicModelChoiceField(
|
||||||
queryset=AccessList.objects.all(),
|
queryset=AccessList.objects.all(),
|
||||||
query_params={
|
query_params={
|
||||||
"type": "standard",
|
"type": ACLTypeChoices.TYPE_STANDARD,
|
||||||
},
|
},
|
||||||
help_text=mark_safe(
|
help_text=mark_safe(
|
||||||
"<b>*Note:</b> This field will only display Standard ACLs.",
|
"<b>*Note:</b> This field will only display Standard ACLs.",
|
||||||
@ -473,10 +475,6 @@ class ACLStandardRuleForm(NetBoxModelForm):
|
|||||||
help_text=help_text_acl_rule_logic,
|
help_text=help_text_acl_rule_logic,
|
||||||
label="Source Prefix",
|
label="Source Prefix",
|
||||||
)
|
)
|
||||||
tags = DynamicModelMultipleChoiceField(
|
|
||||||
queryset=Tag.objects.all(),
|
|
||||||
required=False,
|
|
||||||
)
|
|
||||||
|
|
||||||
fieldsets = (
|
fieldsets = (
|
||||||
("Access List Details", ("access_list", "description", "tags")),
|
("Access List Details", ("access_list", "description", "tags")),
|
||||||
@ -542,17 +540,14 @@ class ACLExtendedRuleForm(NetBoxModelForm):
|
|||||||
access_list = DynamicModelChoiceField(
|
access_list = DynamicModelChoiceField(
|
||||||
queryset=AccessList.objects.all(),
|
queryset=AccessList.objects.all(),
|
||||||
query_params={
|
query_params={
|
||||||
"type": "extended",
|
"type": ACLTypeChoices.TYPE_EXTENDED,
|
||||||
},
|
},
|
||||||
help_text=mark_safe(
|
help_text=mark_safe(
|
||||||
"<b>*Note:</b> This field will only display Extended ACLs.",
|
"<b>*Note:</b> This field will only display Extended ACLs.",
|
||||||
),
|
),
|
||||||
label="Access List",
|
label="Access List",
|
||||||
)
|
)
|
||||||
tags = DynamicModelMultipleChoiceField(
|
|
||||||
queryset=Tag.objects.all(),
|
|
||||||
required=False,
|
|
||||||
)
|
|
||||||
source_prefix = DynamicModelChoiceField(
|
source_prefix = DynamicModelChoiceField(
|
||||||
queryset=Prefix.objects.all(),
|
queryset=Prefix.objects.all(),
|
||||||
required=False,
|
required=False,
|
||||||
|
|||||||
@ -8,7 +8,7 @@ from django.db import models
|
|||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from netbox.models import NetBoxModel
|
from netbox.models import NetBoxModel
|
||||||
|
|
||||||
from ..choices import ACLProtocolChoices, ACLRuleActionChoices
|
from ..choices import ACLProtocolChoices, ACLRuleActionChoices, ACLTypeChoices
|
||||||
from .access_lists import AccessList
|
from .access_lists import AccessList
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
@ -86,7 +86,7 @@ class ACLStandardRule(ACLRule):
|
|||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
to=AccessList,
|
to=AccessList,
|
||||||
verbose_name="Standard Access List",
|
verbose_name="Standard Access List",
|
||||||
limit_choices_to={"type": "standard"},
|
limit_choices_to={"type": ACLTypeChoices.TYPE_STANDARD},
|
||||||
related_name="aclstandardrules",
|
related_name="aclstandardrules",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -31,6 +31,9 @@ class ACLInterfaceAssignments(PluginTemplateExtension):
|
|||||||
elif ctype.model == "vminterface":
|
elif ctype.model == "vminterface":
|
||||||
parent_type = "virtual_machine"
|
parent_type = "virtual_machine"
|
||||||
parent_id = obj.virtual_machine.pk
|
parent_id = obj.virtual_machine.pk
|
||||||
|
else:
|
||||||
|
parent_type = None
|
||||||
|
parent_id = None
|
||||||
|
|
||||||
return self.render(
|
return self.render(
|
||||||
"inc/assigned_interface/access_lists.html",
|
"inc/assigned_interface/access_lists.html",
|
||||||
|
|||||||
@ -6,7 +6,7 @@ Specifically, all the various interactions with a client.
|
|||||||
from django.db.models import Count
|
from django.db.models import Count
|
||||||
from netbox.views import generic
|
from netbox.views import generic
|
||||||
|
|
||||||
from . import filtersets, forms, models, tables
|
from . import choices, filtersets, forms, models, tables
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
"AccessListView",
|
"AccessListView",
|
||||||
@ -48,15 +48,22 @@ class AccessListView(generic.ObjectView):
|
|||||||
"""
|
"""
|
||||||
Depending on the Access List type, the list view will return the required ACL Rule using the previous defined tables in tables.py.
|
Depending on the Access List type, the list view will return the required ACL Rule using the previous defined tables in tables.py.
|
||||||
"""
|
"""
|
||||||
if instance.type == "extended":
|
|
||||||
table = tables.ACLExtendedRuleTable(instance.aclextendedrules.all())
|
|
||||||
elif instance.type == "standard":
|
|
||||||
table = tables.ACLStandardRuleTable(instance.aclstandardrules.all())
|
|
||||||
table.configure(request)
|
|
||||||
|
|
||||||
return {
|
if instance.type == choices.ACLTypeChoices.TYPE_EXTENDED:
|
||||||
"rules_table": table,
|
table = tables.ACLExtendedRuleTable(instance.aclextendedrules.all())
|
||||||
}
|
elif instance.type == choices.ACLTypeChoices.TYPE_STANDARD:
|
||||||
|
table = tables.ACLStandardRuleTable(instance.aclstandardrules.all())
|
||||||
|
else:
|
||||||
|
table = None
|
||||||
|
|
||||||
|
if table:
|
||||||
|
table.columns.hide("access_list")
|
||||||
|
table.configure(request)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"rules_table": table,
|
||||||
|
}
|
||||||
|
return {}
|
||||||
|
|
||||||
|
|
||||||
class AccessListListView(generic.ObjectListView):
|
class AccessListListView(generic.ObjectListView):
|
||||||
@ -84,7 +91,7 @@ class AccessListEditView(generic.ObjectEditView):
|
|||||||
|
|
||||||
class AccessListDeleteView(generic.ObjectDeleteView):
|
class AccessListDeleteView(generic.ObjectDeleteView):
|
||||||
"""
|
"""
|
||||||
Defines the delete view for the AccessLists django model.
|
Defines delete view for the AccessLists django model.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
queryset = models.AccessList.objects.all()
|
queryset = models.AccessList.objects.all()
|
||||||
@ -129,10 +136,20 @@ class ACLInterfaceAssignmentEditView(generic.ObjectEditView):
|
|||||||
form = forms.ACLInterfaceAssignmentForm
|
form = forms.ACLInterfaceAssignmentForm
|
||||||
template_name = "netbox_acls/aclinterfaceassignment_edit.html"
|
template_name = "netbox_acls/aclinterfaceassignment_edit.html"
|
||||||
|
|
||||||
|
def get_extra_addanother_params(self, request):
|
||||||
|
"""
|
||||||
|
Returns a dictionary of additional parameters to be passed to the "Add Another" button.
|
||||||
|
"""
|
||||||
|
|
||||||
|
return {
|
||||||
|
"access_list": request.GET.get("access_list") or request.POST.get("access_list"),
|
||||||
|
"direction": request.GET.get("direction") or request.POST.get("direction"),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class ACLInterfaceAssignmentDeleteView(generic.ObjectDeleteView):
|
class ACLInterfaceAssignmentDeleteView(generic.ObjectDeleteView):
|
||||||
"""
|
"""
|
||||||
Defines the delete view for the ACLInterfaceAssignments django model.
|
Defines delete view for the ACLInterfaceAssignments django model.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
queryset = models.ACLInterfaceAssignment.objects.all()
|
queryset = models.ACLInterfaceAssignment.objects.all()
|
||||||
@ -176,10 +193,19 @@ class ACLStandardRuleEditView(generic.ObjectEditView):
|
|||||||
queryset = models.ACLStandardRule.objects.all()
|
queryset = models.ACLStandardRule.objects.all()
|
||||||
form = forms.ACLStandardRuleForm
|
form = forms.ACLStandardRuleForm
|
||||||
|
|
||||||
|
def get_extra_addanother_params(self, request):
|
||||||
|
"""
|
||||||
|
Returns a dictionary of additional parameters to be passed to the "Add Another" button.
|
||||||
|
"""
|
||||||
|
|
||||||
|
return {
|
||||||
|
"access_list": request.GET.get("access_list") or request.POST.get("access_list"),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class ACLStandardRuleDeleteView(generic.ObjectDeleteView):
|
class ACLStandardRuleDeleteView(generic.ObjectDeleteView):
|
||||||
"""
|
"""
|
||||||
Defines the delete view for the ACLStandardRules django model.
|
Defines delete view for the ACLStandardRules django model.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
queryset = models.ACLStandardRule.objects.all()
|
queryset = models.ACLStandardRule.objects.all()
|
||||||
@ -223,10 +249,19 @@ class ACLExtendedRuleEditView(generic.ObjectEditView):
|
|||||||
queryset = models.ACLExtendedRule.objects.all()
|
queryset = models.ACLExtendedRule.objects.all()
|
||||||
form = forms.ACLExtendedRuleForm
|
form = forms.ACLExtendedRuleForm
|
||||||
|
|
||||||
|
def get_extra_addanother_params(self, request):
|
||||||
|
"""
|
||||||
|
Returns a dictionary of additional parameters to be passed to the "Add Another" button.
|
||||||
|
"""
|
||||||
|
|
||||||
|
return {
|
||||||
|
"access_list": request.GET.get("access_list") or request.POST.get("access_list"),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class ACLExtendedRuleDeleteView(generic.ObjectDeleteView):
|
class ACLExtendedRuleDeleteView(generic.ObjectDeleteView):
|
||||||
"""
|
"""
|
||||||
Defines the delete view for the ACLExtendedRules django model.
|
Defines delete view for the ACLExtendedRules django model.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
queryset = models.ACLExtendedRule.objects.all()
|
queryset = models.ACLExtendedRule.objects.all()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user